Merge "Merge "Improve performance of edge extension animation" into tm-dev am: 47aa2ca8aa am: e02a4598d5 am: 3c803c924f" into tm-qpr-dev-plus-aosp
This commit is contained in:
committed by
Android (Google) Code Review
commit
e5babdc40d
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.server.wm;
|
package com.android.server.wm;
|
||||||
|
|
||||||
|
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
|
||||||
import static android.util.TimeUtils.NANOS_PER_MS;
|
import static android.util.TimeUtils.NANOS_PER_MS;
|
||||||
import static android.view.Choreographer.CALLBACK_TRAVERSAL;
|
import static android.view.Choreographer.CALLBACK_TRAVERSAL;
|
||||||
import static android.view.Choreographer.getSfInstance;
|
import static android.view.Choreographer.getSfInstance;
|
||||||
@@ -26,14 +27,13 @@ import android.animation.Animator;
|
|||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
import android.animation.ValueAnimator;
|
import android.animation.ValueAnimator;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Insets;
|
import android.graphics.Insets;
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.hardware.power.Boost;
|
import android.hardware.power.Boost;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.PowerManagerInternal;
|
import android.os.PowerManagerInternal;
|
||||||
|
import android.os.Trace;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Choreographer;
|
import android.view.Choreographer;
|
||||||
@@ -50,6 +50,8 @@ import com.android.server.AnimationThread;
|
|||||||
import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
|
import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -83,6 +85,12 @@ class SurfaceAnimationRunner {
|
|||||||
private final PowerManagerInternal mPowerManagerInternal;
|
private final PowerManagerInternal mPowerManagerInternal;
|
||||||
private boolean mApplyScheduled;
|
private boolean mApplyScheduled;
|
||||||
|
|
||||||
|
// Executor to perform the edge extension.
|
||||||
|
// With two threads because in practice we will want to extend two surfaces in one animation,
|
||||||
|
// in which case we want to be able to parallelize those two extensions to cut down latency in
|
||||||
|
// starting the animation.
|
||||||
|
private final ExecutorService mEdgeExtensionExecutor = Executors.newFixedThreadPool(2);
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
final ArrayMap<SurfaceControl, RunningAnimation> mPendingAnimations = new ArrayMap<>();
|
final ArrayMap<SurfaceControl, RunningAnimation> mPendingAnimations = new ArrayMap<>();
|
||||||
@@ -173,7 +181,7 @@ class SurfaceAnimationRunner {
|
|||||||
|
|
||||||
// We must wait for t to be committed since otherwise the leash doesn't have the
|
// We must wait for t to be committed since otherwise the leash doesn't have the
|
||||||
// windows we want to screenshot and extend as children.
|
// windows we want to screenshot and extend as children.
|
||||||
t.addTransactionCommittedListener(Runnable::run, () -> {
|
t.addTransactionCommittedListener(mEdgeExtensionExecutor, () -> {
|
||||||
final WindowAnimationSpec animationSpec = a.asWindowAnimationSpec();
|
final WindowAnimationSpec animationSpec = a.asWindowAnimationSpec();
|
||||||
|
|
||||||
final Transaction edgeExtensionCreationTransaction = new Transaction();
|
final Transaction edgeExtensionCreationTransaction = new Transaction();
|
||||||
@@ -403,30 +411,17 @@ class SurfaceAnimationRunner {
|
|||||||
private void createExtensionSurface(SurfaceControl leash, Rect edgeBounds,
|
private void createExtensionSurface(SurfaceControl leash, Rect edgeBounds,
|
||||||
Rect extensionRect, int xPos, int yPos, String layerName,
|
Rect extensionRect, int xPos, int yPos, String layerName,
|
||||||
Transaction startTransaction) {
|
Transaction startTransaction) {
|
||||||
synchronized (mEdgeExtensionLock) {
|
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createExtensionSurface");
|
||||||
if (!mEdgeExtensions.containsKey(leash)) {
|
doCreateExtensionSurface(leash, edgeBounds, extensionRect, xPos, yPos, layerName,
|
||||||
// Animation leash has already been removed so we shouldn't perform any extension
|
startTransaction);
|
||||||
return;
|
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
||||||
}
|
|
||||||
createExtensionSurfaceLocked(leash, edgeBounds, extensionRect, xPos, yPos, layerName,
|
|
||||||
startTransaction);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createExtensionSurfaceLocked(SurfaceControl surfaceToExtend, Rect edgeBounds,
|
private void doCreateExtensionSurface(SurfaceControl leash, Rect edgeBounds,
|
||||||
Rect extensionRect, int xPos, int yPos, String layerName,
|
Rect extensionRect, int xPos, int yPos, String layerName,
|
||||||
Transaction startTransaction) {
|
Transaction startTransaction) {
|
||||||
final SurfaceControl edgeExtensionLayer = new SurfaceControl.Builder()
|
|
||||||
.setName(layerName)
|
|
||||||
.setParent(surfaceToExtend)
|
|
||||||
.setHidden(true)
|
|
||||||
.setCallsite("DefaultTransitionHandler#startAnimation")
|
|
||||||
.setOpaque(true)
|
|
||||||
.setBufferSize(extensionRect.width(), extensionRect.height())
|
|
||||||
.build();
|
|
||||||
|
|
||||||
SurfaceControl.LayerCaptureArgs captureArgs =
|
SurfaceControl.LayerCaptureArgs captureArgs =
|
||||||
new SurfaceControl.LayerCaptureArgs.Builder(surfaceToExtend)
|
new SurfaceControl.LayerCaptureArgs.Builder(leash /* surfaceToExtend */)
|
||||||
.setSourceCrop(edgeBounds)
|
.setSourceCrop(edgeBounds)
|
||||||
.setFrameScale(1)
|
.setFrameScale(1)
|
||||||
.setPixelFormat(PixelFormat.RGBA_8888)
|
.setPixelFormat(PixelFormat.RGBA_8888)
|
||||||
@@ -437,31 +432,76 @@ class SurfaceAnimationRunner {
|
|||||||
SurfaceControl.captureLayers(captureArgs);
|
SurfaceControl.captureLayers(captureArgs);
|
||||||
|
|
||||||
if (edgeBuffer == null) {
|
if (edgeBuffer == null) {
|
||||||
|
// The leash we are trying to screenshot may have been removed by this point, which is
|
||||||
|
// likely the reason for ending up with a null edgeBuffer, in which case we just want to
|
||||||
|
// return and do nothing.
|
||||||
Log.e("SurfaceAnimationRunner", "Failed to create edge extension - "
|
Log.e("SurfaceAnimationRunner", "Failed to create edge extension - "
|
||||||
+ "edge buffer is null");
|
+ "edge buffer is null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
android.graphics.BitmapShader shader =
|
final SurfaceControl edgeExtensionLayer = new SurfaceControl.Builder()
|
||||||
new android.graphics.BitmapShader(edgeBuffer.asBitmap(),
|
.setName(layerName)
|
||||||
android.graphics.Shader.TileMode.CLAMP,
|
.setHidden(true)
|
||||||
android.graphics.Shader.TileMode.CLAMP);
|
.setCallsite("DefaultTransitionHandler#startAnimation")
|
||||||
final Paint paint = new Paint();
|
.setOpaque(true)
|
||||||
paint.setShader(shader);
|
.setBufferSize(edgeBounds.width(), edgeBounds.height())
|
||||||
|
.build();
|
||||||
|
|
||||||
final Surface surface = new Surface(edgeExtensionLayer);
|
final Surface surface = new Surface(edgeExtensionLayer);
|
||||||
Canvas c = surface.lockHardwareCanvas();
|
surface.attachAndQueueBufferWithColorSpace(edgeBuffer.getHardwareBuffer(),
|
||||||
c.drawRect(extensionRect, paint);
|
edgeBuffer.getColorSpace());
|
||||||
surface.unlockCanvasAndPost(c);
|
|
||||||
surface.release();
|
surface.release();
|
||||||
|
|
||||||
startTransaction.setLayer(edgeExtensionLayer, Integer.MIN_VALUE);
|
final float scaleX = getScaleXForExtensionSurface(edgeBounds, extensionRect);
|
||||||
startTransaction.setPosition(edgeExtensionLayer, xPos, yPos);
|
final float scaleY = getScaleYForExtensionSurface(edgeBounds, extensionRect);
|
||||||
startTransaction.setVisibility(edgeExtensionLayer, true);
|
|
||||||
|
|
||||||
mEdgeExtensions.get(surfaceToExtend).add(edgeExtensionLayer);
|
synchronized (mEdgeExtensionLock) {
|
||||||
|
if (!mEdgeExtensions.containsKey(leash)) {
|
||||||
|
// The animation leash has already been removed, so we don't want to attach the
|
||||||
|
// edgeExtension layer and should immediately remove it instead.
|
||||||
|
startTransaction.remove(edgeExtensionLayer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
startTransaction.setScale(edgeExtensionLayer, scaleX, scaleY);
|
||||||
|
startTransaction.reparent(edgeExtensionLayer, leash);
|
||||||
|
startTransaction.setLayer(edgeExtensionLayer, Integer.MIN_VALUE);
|
||||||
|
startTransaction.setPosition(edgeExtensionLayer, xPos, yPos);
|
||||||
|
startTransaction.setVisibility(edgeExtensionLayer, true);
|
||||||
|
|
||||||
|
mEdgeExtensions.get(leash).add(edgeExtensionLayer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float getScaleXForExtensionSurface(Rect edgeBounds, Rect extensionRect) {
|
||||||
|
if (edgeBounds.width() == extensionRect.width()) {
|
||||||
|
// Top or bottom edge extension, no need to scale the X axis of the extension surface.
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (edgeBounds.width() == 1) {
|
||||||
|
// Left or right edge extension, scale the surface to be the extensionRect's width.
|
||||||
|
return extensionRect.width();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RuntimeException("Unexpected edgeBounds and extensionRect widths");
|
||||||
|
}
|
||||||
|
|
||||||
|
private float getScaleYForExtensionSurface(Rect edgeBounds, Rect extensionRect) {
|
||||||
|
if (edgeBounds.height() == extensionRect.height()) {
|
||||||
|
// Left or right edge extension, no need to scale the Y axis of the extension surface.
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (edgeBounds.height() == 1) {
|
||||||
|
// Top or bottom edge extension, scale the surface to be the extensionRect's height.
|
||||||
|
return extensionRect.height();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RuntimeException("Unexpected edgeBounds and extensionRect heights");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static final class RunningAnimation {
|
private static final class RunningAnimation {
|
||||||
final AnimationSpec mAnimSpec;
|
final AnimationSpec mAnimSpec;
|
||||||
final SurfaceControl mLeash;
|
final SurfaceControl mLeash;
|
||||||
|
|||||||
Reference in New Issue
Block a user