Merge "Fix issue with task snapshots being taken too late" into udc-dev

This commit is contained in:
Winson Chung
2023-05-23 17:05:51 +00:00
committed by Android (Google) Code Review
11 changed files with 90 additions and 25 deletions

View File

@@ -28,6 +28,7 @@ import android.hardware.HardwareBuffer;
import android.os.Build; import android.os.Build;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import android.os.SystemClock;
import android.view.Surface; import android.view.Surface;
import android.view.WindowInsetsController; import android.view.WindowInsetsController;
@@ -38,6 +39,9 @@ import android.view.WindowInsetsController;
public class TaskSnapshot implements Parcelable { public class TaskSnapshot implements Parcelable {
// Identifier of this snapshot // Identifier of this snapshot
private final long mId; private final long mId;
// The elapsed real time (in nanoseconds) when this snapshot was captured, not intended for use outside the
// process in which the snapshot was taken (ie. this is not parceled)
private final long mCaptureTime;
// Top activity in task when snapshot was taken // Top activity in task when snapshot was taken
private final ComponentName mTopActivityComponent; private final ComponentName mTopActivityComponent;
private final HardwareBuffer mSnapshot; private final HardwareBuffer mSnapshot;
@@ -65,7 +69,7 @@ public class TaskSnapshot implements Parcelable {
// Must be one of the named color spaces, otherwise, always use SRGB color space. // Must be one of the named color spaces, otherwise, always use SRGB color space.
private final ColorSpace mColorSpace; private final ColorSpace mColorSpace;
public TaskSnapshot(long id, public TaskSnapshot(long id, long captureTime,
@NonNull ComponentName topActivityComponent, HardwareBuffer snapshot, @NonNull ComponentName topActivityComponent, HardwareBuffer snapshot,
@NonNull ColorSpace colorSpace, int orientation, int rotation, Point taskSize, @NonNull ColorSpace colorSpace, int orientation, int rotation, Point taskSize,
Rect contentInsets, Rect letterboxInsets, boolean isLowResolution, Rect contentInsets, Rect letterboxInsets, boolean isLowResolution,
@@ -73,6 +77,7 @@ public class TaskSnapshot implements Parcelable {
@WindowInsetsController.Appearance int appearance, boolean isTranslucent, @WindowInsetsController.Appearance int appearance, boolean isTranslucent,
boolean hasImeSurface) { boolean hasImeSurface) {
mId = id; mId = id;
mCaptureTime = captureTime;
mTopActivityComponent = topActivityComponent; mTopActivityComponent = topActivityComponent;
mSnapshot = snapshot; mSnapshot = snapshot;
mColorSpace = colorSpace.getId() < 0 mColorSpace = colorSpace.getId() < 0
@@ -92,6 +97,7 @@ public class TaskSnapshot implements Parcelable {
private TaskSnapshot(Parcel source) { private TaskSnapshot(Parcel source) {
mId = source.readLong(); mId = source.readLong();
mCaptureTime = SystemClock.elapsedRealtimeNanos();
mTopActivityComponent = ComponentName.readFromParcel(source); mTopActivityComponent = ComponentName.readFromParcel(source);
mSnapshot = source.readTypedObject(HardwareBuffer.CREATOR); mSnapshot = source.readTypedObject(HardwareBuffer.CREATOR);
int colorSpaceId = source.readInt(); int colorSpaceId = source.readInt();
@@ -118,6 +124,14 @@ public class TaskSnapshot implements Parcelable {
return mId; return mId;
} }
/**
* @return The elapsed real time (in nanoseconds) when this snapshot was captured. This time is
* only valid in the process where this snapshot was taken.
*/
public long getCaptureTime() {
return mCaptureTime;
}
/** /**
* @return The top activity component for the task at the point this snapshot was taken. * @return The top activity component for the task at the point this snapshot was taken.
*/ */
@@ -268,6 +282,7 @@ public class TaskSnapshot implements Parcelable {
final int height = mSnapshot != null ? mSnapshot.getHeight() : 0; final int height = mSnapshot != null ? mSnapshot.getHeight() : 0;
return "TaskSnapshot{" return "TaskSnapshot{"
+ " mId=" + mId + " mId=" + mId
+ " mCaptureTime=" + mCaptureTime
+ " mTopActivityComponent=" + mTopActivityComponent.flattenToShortString() + " mTopActivityComponent=" + mTopActivityComponent.flattenToShortString()
+ " mSnapshot=" + mSnapshot + " (" + width + "x" + height + ")" + " mSnapshot=" + mSnapshot + " (" + width + "x" + height + ")"
+ " mColorSpace=" + mColorSpace.toString() + " mColorSpace=" + mColorSpace.toString()
@@ -296,6 +311,7 @@ public class TaskSnapshot implements Parcelable {
/** Builder for a {@link TaskSnapshot} object */ /** Builder for a {@link TaskSnapshot} object */
public static final class Builder { public static final class Builder {
private long mId; private long mId;
private long mCaptureTime;
private ComponentName mTopActivity; private ComponentName mTopActivity;
private HardwareBuffer mSnapshot; private HardwareBuffer mSnapshot;
private ColorSpace mColorSpace; private ColorSpace mColorSpace;
@@ -317,6 +333,11 @@ public class TaskSnapshot implements Parcelable {
return this; return this;
} }
public Builder setCaptureTime(long captureTime) {
mCaptureTime = captureTime;
return this;
}
public Builder setTopActivityComponent(ComponentName name) { public Builder setTopActivityComponent(ComponentName name) {
mTopActivity = name; mTopActivity = name;
return this; return this;
@@ -400,6 +421,7 @@ public class TaskSnapshot implements Parcelable {
public TaskSnapshot build() { public TaskSnapshot build() {
return new TaskSnapshot( return new TaskSnapshot(
mId, mId,
mCaptureTime,
mTopActivity, mTopActivity,
mSnapshot, mSnapshot,
mColorSpace, mColorSpace,

View File

@@ -88,6 +88,7 @@ public class SnapshotDrawerUtilsTest {
1, HardwareBuffer.USAGE_CPU_READ_RARELY); 1, HardwareBuffer.USAGE_CPU_READ_RARELY);
return new TaskSnapshot( return new TaskSnapshot(
System.currentTimeMillis(), System.currentTimeMillis(),
0 /* captureTime */,
new ComponentName("", ""), buffer, new ComponentName("", ""), buffer,
ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT, ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT,
Surface.ROTATION_0, taskSize, contentInsets, new Rect() /* letterboxInsets */, Surface.ROTATION_0, taskSize, contentInsets, new Rect() /* letterboxInsets */,

View File

@@ -1135,6 +1135,12 @@
"group": "WM_DEBUG_RECENTS_ANIMATIONS", "group": "WM_DEBUG_RECENTS_ANIMATIONS",
"at": "com\/android\/server\/wm\/RecentsAnimation.java" "at": "com\/android\/server\/wm\/RecentsAnimation.java"
}, },
"-1060529098": {
"message": " Skipping post-transition snapshot for task %d",
"level": "VERBOSE",
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
"at": "com\/android\/server\/wm\/Transition.java"
},
"-1060365734": { "-1060365734": {
"message": "Attempted to add QS dialog window with bad token %s. Aborting.", "message": "Attempted to add QS dialog window with bad token %s. Aborting.",
"level": "WARN", "level": "WARN",

View File

@@ -264,21 +264,18 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
void cancel(String reason) { void cancel(String reason) {
// restoring (to-home = false) involves submitting more WM changes, so by default, use // restoring (to-home = false) involves submitting more WM changes, so by default, use
// toHome = true when canceling. // toHome = true when canceling.
cancel(true /* toHome */, reason); cancel(true /* toHome */, false /* withScreenshots */, reason);
} }
void cancel(boolean toHome, String reason) { void cancel(boolean toHome, boolean withScreenshots, String reason) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
"[%d] RecentsController.cancel: toHome=%b reason=%s", "[%d] RecentsController.cancel: toHome=%b reason=%s",
mInstanceId, toHome, reason); mInstanceId, toHome, reason);
if (mListener != null) { if (mListener != null) {
try { if (withScreenshots) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, sendCancelWithSnapshots();
"[%d] RecentsController.cancel: calling onAnimationCanceled", } else {
mInstanceId); sendCancel(null, null);
mListener.onAnimationCanceled(null, null);
} catch (RemoteException e) {
Slog.e(TAG, "Error canceling recents animation", e);
} }
} }
if (mFinishCB != null) { if (mFinishCB != null) {
@@ -300,24 +297,34 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
snapshots = new TaskSnapshot[mPausingTasks.size()]; snapshots = new TaskSnapshot[mPausingTasks.size()];
try { try {
for (int i = 0; i < mPausingTasks.size(); ++i) { for (int i = 0; i < mPausingTasks.size(); ++i) {
TaskState state = mPausingTasks.get(0);
snapshots[i] = ActivityTaskManager.getService().takeTaskSnapshot( snapshots[i] = ActivityTaskManager.getService().takeTaskSnapshot(
mPausingTasks.get(0).mTaskInfo.taskId, false /* updateCache */); state.mTaskInfo.taskId, true /* updateCache */);
} }
} catch (RemoteException e) { } catch (RemoteException e) {
taskIds = null; taskIds = null;
snapshots = null; snapshots = null;
} }
} }
return sendCancel(taskIds, snapshots);
}
/**
* Sends a cancel message to the recents animation.
*/
private boolean sendCancel(@Nullable int[] taskIds,
@Nullable TaskSnapshot[] taskSnapshots) {
try { try {
final String cancelDetails = taskSnapshots != null ? " with snapshots" : "";
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
"[%d] RecentsController.cancel: calling onAnimationCanceled with snapshots", "[%d] RecentsController.cancel: calling onAnimationCanceled %s",
mInstanceId); mInstanceId, cancelDetails);
mListener.onAnimationCanceled(taskIds, snapshots); mListener.onAnimationCanceled(taskIds, taskSnapshots);
return true;
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Error canceling recents animation", e); Slog.e(TAG, "Error canceling recents animation", e);
return false; return false;
} }
return true;
} }
void cleanUp() { void cleanUp() {
@@ -519,7 +526,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
// Finish recents animation if the display is changed, so the default // Finish recents animation if the display is changed, so the default
// transition handler can play the animation such as rotation effect. // transition handler can play the animation such as rotation effect.
if (change.hasFlags(TransitionInfo.FLAG_IS_DISPLAY)) { if (change.hasFlags(TransitionInfo.FLAG_IS_DISPLAY)) {
cancel(mWillFinishToHome, "display change"); cancel(mWillFinishToHome, true /* withScreenshots */, "display change");
return; return;
} }
// Don't consider order-only changes as changing apps. // Don't consider order-only changes as changing apps.
@@ -633,7 +640,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
+ foundRecentsClosing); + foundRecentsClosing);
if (foundRecentsClosing) { if (foundRecentsClosing) {
mWillFinishToHome = false; mWillFinishToHome = false;
cancel(false /* toHome */, "didn't merge"); cancel(false /* toHome */, false /* withScreenshots */, "didn't merge");
} }
return; return;
} }

View File

@@ -364,6 +364,7 @@ public class StartingSurfaceDrawerTests extends ShellTestCase {
1, HardwareBuffer.USAGE_CPU_READ_RARELY); 1, HardwareBuffer.USAGE_CPU_READ_RARELY);
return new TaskSnapshot( return new TaskSnapshot(
System.currentTimeMillis(), System.currentTimeMillis(),
0 /* captureTime */,
new ComponentName("", ""), buffer, new ComponentName("", ""), buffer,
ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT, ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT,
Surface.ROTATION_0, taskSize, contentInsets, new Rect() /* letterboxInsets */, Surface.ROTATION_0, taskSize, contentInsets, new Rect() /* letterboxInsets */,

View File

@@ -30,6 +30,7 @@ import android.graphics.RecordingCanvas;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.RenderNode; import android.graphics.RenderNode;
import android.hardware.HardwareBuffer; import android.hardware.HardwareBuffer;
import android.os.SystemClock;
import android.os.Trace; import android.os.Trace;
import android.util.Pair; import android.util.Pair;
import android.util.Slog; import android.util.Slog;
@@ -213,6 +214,7 @@ abstract class AbsAppSnapshotController<TYPE extends WindowContainer,
// Failed to acquire image. Has been logged. // Failed to acquire image. Has been logged.
return null; return null;
} }
builder.setCaptureTime(SystemClock.elapsedRealtimeNanos());
builder.setSnapshot(screenshotBuffer.getHardwareBuffer()); builder.setSnapshot(screenshotBuffer.getHardwareBuffer());
builder.setColorSpace(screenshotBuffer.getColorSpace()); builder.setColorSpace(screenshotBuffer.getColorSpace());
return builder.build(); return builder.build();
@@ -432,6 +434,7 @@ abstract class AbsAppSnapshotController<TYPE extends WindowContainer,
// color above // color above
return new TaskSnapshot( return new TaskSnapshot(
System.currentTimeMillis() /* id */, System.currentTimeMillis() /* id */,
SystemClock.elapsedRealtimeNanos() /* captureTime */,
topActivity.mActivityComponent, hwBitmap.getHardwareBuffer(), topActivity.mActivityComponent, hwBitmap.getHardwareBuffer(),
hwBitmap.getColorSpace(), mainWindow.getConfiguration().orientation, hwBitmap.getColorSpace(), mainWindow.getConfiguration().orientation,
mainWindow.getWindowConfiguration().getRotation(), new Point(taskWidth, taskHeight), mainWindow.getWindowConfiguration().getRotation(), new Point(taskWidth, taskHeight),

View File

@@ -28,6 +28,7 @@ import android.graphics.BitmapFactory.Options;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.hardware.HardwareBuffer; import android.hardware.HardwareBuffer;
import android.os.SystemClock;
import android.util.Slog; import android.util.Slog;
import android.window.TaskSnapshot; import android.window.TaskSnapshot;
@@ -195,8 +196,9 @@ class AppSnapshotLoader {
taskSize = new Point(proto.taskWidth, proto.taskHeight); taskSize = new Point(proto.taskWidth, proto.taskHeight);
} }
return new TaskSnapshot(proto.id, topActivityComponent, buffer, return new TaskSnapshot(proto.id, SystemClock.elapsedRealtimeNanos(),
hwBitmap.getColorSpace(), proto.orientation, proto.rotation, taskSize, topActivityComponent, buffer, hwBitmap.getColorSpace(),
proto.orientation, proto.rotation, taskSize,
new Rect(proto.insetLeft, proto.insetTop, proto.insetRight, proto.insetBottom), new Rect(proto.insetLeft, proto.insetTop, proto.insetRight, proto.insetBottom),
new Rect(proto.letterboxInsetLeft, proto.letterboxInsetTop, new Rect(proto.letterboxInsetLeft, proto.letterboxInsetTop,
proto.letterboxInsetRight, proto.letterboxInsetBottom), proto.letterboxInsetRight, proto.letterboxInsetBottom),

View File

@@ -179,6 +179,18 @@ class TaskSnapshotController extends AbsAppSnapshotController<Task, TaskSnapshot
&& mPersistInfoProvider.enableLowResSnapshots()); && mPersistInfoProvider.enableLowResSnapshots());
} }
/**
* Returns the elapsed real time (in nanoseconds) at which a snapshot for the given task was
* last taken, or -1 if no such snapshot exists for that task.
*/
long getSnapshotCaptureTime(int taskId) {
final TaskSnapshot snapshot = mCache.getSnapshot(taskId);
if (snapshot != null) {
return snapshot.getCaptureTime();
}
return -1;
}
/** /**
* @see WindowManagerInternal#clearSnapshotCache * @see WindowManagerInternal#clearSnapshotCache
*/ */

View File

@@ -1086,12 +1086,23 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
if (commitVisibility) { if (commitVisibility) {
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
" Commit activity becoming invisible: %s", ar); " Commit activity becoming invisible: %s", ar);
final SnapshotController snapController = mController.mSnapshotController;
if (mTransientLaunches != null && !task.isVisibleRequested()) { if (mTransientLaunches != null && !task.isVisibleRequested()) {
final long startTimeNs = mLogger.mSendTimeNs;
final long lastSnapshotTimeNs = snapController.mTaskSnapshotController
.getSnapshotCaptureTime(task.mTaskId);
// If transition is transient, then snapshots are taken at end of // If transition is transient, then snapshots are taken at end of
// transition. // transition only if a snapshot was not already captured by request
mController.mSnapshotController.mTaskSnapshotController // during the transition
if (lastSnapshotTimeNs < startTimeNs) {
snapController.mTaskSnapshotController
.recordSnapshot(task, false /* allowSnapshotHome */); .recordSnapshot(task, false /* allowSnapshotHome */);
mController.mSnapshotController.mActivitySnapshotController } else {
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
" Skipping post-transition snapshot for task %d",
task.mTaskId);
}
snapController.mActivitySnapshotController
.notifyAppVisibilityChanged(ar, false /* visible */); .notifyAppVisibilityChanged(ar, false /* visible */);
} }
ar.commitVisibility(false /* visible */, false /* performLayout */, ar.commitVisibility(false /* visible */, false /* performLayout */,

View File

@@ -1286,7 +1286,7 @@ public class RecentTasksTest extends WindowTestsBase {
doReturn(bufferSize.x).when(buffer).getWidth(); doReturn(bufferSize.x).when(buffer).getWidth();
doReturn(bufferSize.y).when(buffer).getHeight(); doReturn(bufferSize.y).when(buffer).getHeight();
} }
return new TaskSnapshot(1, new ComponentName("", ""), buffer, return new TaskSnapshot(1, 0 /* captureTime */, new ComponentName("", ""), buffer,
ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT, ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT,
Surface.ROTATION_0, taskSize, new Rect() /* contentInsets */, Surface.ROTATION_0, taskSize, new Rect() /* contentInsets */,
new Rect() /* letterboxInsets*/, false /* isLowResolution */, new Rect() /* letterboxInsets*/, false /* isLowResolution */,

View File

@@ -218,7 +218,7 @@ class TaskSnapshotPersisterTestBase extends WindowTestsBase {
Canvas c = buffer.lockCanvas(); Canvas c = buffer.lockCanvas();
c.drawColor(Color.RED); c.drawColor(Color.RED);
buffer.unlockCanvasAndPost(c); buffer.unlockCanvasAndPost(c);
return new TaskSnapshot(MOCK_SNAPSHOT_ID, mTopActivityComponent, return new TaskSnapshot(MOCK_SNAPSHOT_ID, 0 /* captureTime */, mTopActivityComponent,
HardwareBuffer.createFromGraphicBuffer(buffer), HardwareBuffer.createFromGraphicBuffer(buffer),
ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT, ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT,
mRotation, taskSize, TEST_CONTENT_INSETS, TEST_LETTERBOX_INSETS, mRotation, taskSize, TEST_CONTENT_INSETS, TEST_LETTERBOX_INSETS,