Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3ca99e2a authored by Winson Chung's avatar Winson Chung
Browse files

Fix issue with task snapshots being taken too late

- Currently, a display change while recents transition is playing will
  result in the display change being applied prior to the recents
  animation playing, which means that the transition-end snapshots are
  taken in the wrong display configuration
- Instead, When a display change is requested mid-recents transition,
  cancel the current transition and record the snapshots in place
  (this matchs legacy recents animation behavior)
- Separately, if the snapshot is requested & recorded mid transition,
  then we can ignore the post-transition screenshot (which would be
  wrong in the display change case, or just extraneous even in the normal
  case where launcher has requested a screenshot itself already).
  We do this by comparing the time that the last snapshot was taken
  with the start of the transition.

Fixes: 278189494
Test: Go into Overview and rotate the device and observe the task views
Change-Id: I985cd9c852a326027ae3ab4f7ffe837431d1c654
parent 57d6975c
Loading
Loading
Loading
Loading
+23 −1
Original line number Original line Diff line number Diff line
@@ -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,
+1 −0
Original line number Original line Diff line number Diff line
@@ -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 */,
+6 −0
Original line number Original line Diff line number Diff line
@@ -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",
+23 −16
Original line number Original line Diff line number Diff line
@@ -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;
            }
            }
+1 −0
Original line number Original line Diff line number Diff line
@@ -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 */,
Loading