Loading core/java/android/window/TransitionInfo.java +27 −2 Original line number Diff line number Diff line Loading @@ -397,6 +397,8 @@ public final class TransitionInfo implements Parcelable { private @Surface.Rotation int mEndFixedRotation = ROTATION_UNDEFINED; private int mRotationAnimation = ROTATION_ANIMATION_UNSPECIFIED; private @ColorInt int mBackgroundColor; private SurfaceControl mSnapshot = null; private float mSnapshotLuma; public Change(@Nullable WindowContainerToken container, @NonNull SurfaceControl leash) { mContainer = container; Loading @@ -420,6 +422,8 @@ public final class TransitionInfo implements Parcelable { mEndFixedRotation = in.readInt(); mRotationAnimation = in.readInt(); mBackgroundColor = in.readInt(); mSnapshot = in.readTypedObject(SurfaceControl.CREATOR); mSnapshotLuma = in.readFloat(); } /** Sets the parent of this change's container. The parent must be a participant or null. */ Loading Loading @@ -489,6 +493,12 @@ public final class TransitionInfo implements Parcelable { mBackgroundColor = backgroundColor; } /** Sets a snapshot surface for the "start" state of the container. */ public void setSnapshot(@Nullable SurfaceControl snapshot, float luma) { mSnapshot = snapshot; mSnapshotLuma = luma; } /** @return the container that is changing. May be null if non-remotable (eg. activity) */ @Nullable public WindowContainerToken getContainer() { Loading Loading @@ -587,6 +597,17 @@ public final class TransitionInfo implements Parcelable { return mBackgroundColor; } /** @return a snapshot surface (if applicable). */ @Nullable public SurfaceControl getSnapshot() { return mSnapshot; } /** @return the luma calculated for the snapshot surface (if applicable). */ public float getSnapshotLuma() { return mSnapshotLuma; } /** @hide */ @Override public void writeToParcel(@NonNull Parcel dest, int flags) { Loading @@ -605,6 +626,8 @@ public final class TransitionInfo implements Parcelable { dest.writeInt(mEndFixedRotation); dest.writeInt(mRotationAnimation); dest.writeInt(mBackgroundColor); dest.writeTypedObject(mSnapshot, flags); dest.writeFloat(mSnapshotLuma); } @NonNull Loading @@ -629,11 +652,13 @@ public final class TransitionInfo implements Parcelable { @Override public String toString() { return "{" + mContainer + "(" + mParent + ") leash=" + mLeash String out = "{" + mContainer + "(" + mParent + ") leash=" + mLeash + " m=" + modeToString(mMode) + " f=" + flagsToString(mFlags) + " sb=" + mStartAbsBounds + " eb=" + mEndAbsBounds + " eo=" + mEndRelOffset + " r=" + mStartRotation + "->" + mEndRotation + ":" + mRotationAnimation + " endFixedRotation=" + mEndFixedRotation + "}"; + " endFixedRotation=" + mEndFixedRotation; if (mSnapshot != null) out += " snapshot=" + mSnapshot; return out + "}"; } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java +35 −28 Original line number Diff line number Diff line Loading @@ -139,6 +139,11 @@ class ScreenRotationAnimation { .build(); try { if (change.getSnapshot() != null) { mScreenshotLayer = change.getSnapshot(); t.reparent(mScreenshotLayer, mAnimLeash); mStartLuma = change.getSnapshotLuma(); } else { SurfaceControl.LayerCaptureArgs args = new SurfaceControl.LayerCaptureArgs.Builder(mSurfaceControl) .setCaptureSecureLayers(true) Loading @@ -161,16 +166,20 @@ class ScreenRotationAnimation { .setName("RotationLayer") .build(); t.setLayer(mAnimLeash, SCREEN_FREEZE_LAYER_BASE); t.show(mAnimLeash); // Crop the real content in case it contains a larger child layer, e.g. wallpaper. t.setCrop(mSurfaceControl, new Rect(0, 0, mEndWidth, mEndHeight)); final ColorSpace colorSpace = screenshotBuffer.getColorSpace(); final HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer(); t.setDataSpace(mScreenshotLayer, colorSpace.getDataSpace()); t.setBuffer(mScreenshotLayer, hardwareBuffer); t.show(mScreenshotLayer); if (!isCustomRotate()) { mStartLuma = getMedianBorderLuma(hardwareBuffer, colorSpace); } } t.setLayer(mAnimLeash, SCREEN_FREEZE_LAYER_BASE); t.show(mAnimLeash); // Crop the real content in case it contains a larger child layer, e.g. wallpaper. t.setCrop(mSurfaceControl, new Rect(0, 0, mEndWidth, mEndHeight)); if (!isCustomRotate()) { mBackColorSurface = new SurfaceControl.Builder(session) Loading @@ -181,8 +190,6 @@ class ScreenRotationAnimation { .setName("BackColorSurface") .build(); mStartLuma = getMedianBorderLuma(hardwareBuffer, colorSpace); t.setLayer(mBackColorSurface, -1); t.setColor(mBackColorSurface, new float[]{mStartLuma, mStartLuma, mStartLuma}); t.show(mBackColorSurface); Loading services/core/java/com/android/server/wm/Transition.java +27 −9 Original line number Diff line number Diff line Loading @@ -93,11 +93,13 @@ import com.android.internal.protolog.ProtoLogGroup; import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.inputmethod.InputMethodManagerInternal; import com.android.server.wm.utils.RotationAnimationUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.function.Predicate; /** Loading Loading @@ -289,9 +291,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe if (mContainerFreezer == null) { mContainerFreezer = new ScreenshotFreezer(); } mIsSeamlessRotation = true; final WindowState top = dc.getDisplayPolicy().getTopFullscreenOpaqueWindow(); if (top != null) { mIsSeamlessRotation = true; top.mSyncMethodOverride = BLASTSyncEngine.METHOD_BLAST; ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Override sync-method for %s " + "because seamless rotating", top.getName()); Loading Loading @@ -1635,6 +1637,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe change.setEndAbsBounds(bounds); } change.setRotation(info.mRotation, endRotation); if (info.mSnapshot != null) { change.setSnapshot(info.mSnapshot, info.mSnapshotLuma); } out.addChange(change); } Loading Loading @@ -1790,6 +1795,10 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe /** These are just extra info. They aren't used for change-detection. */ @Flag int mFlags = FLAG_NONE; /** Snapshot surface and luma, if relevant. */ SurfaceControl mSnapshot; float mSnapshotLuma; ChangeInfo(@NonNull WindowContainer origState) { mVisible = origState.isVisibleRequested(); mWindowingMode = origState.getWindowingMode(); Loading Loading @@ -2098,8 +2107,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe */ @VisibleForTesting private class ScreenshotFreezer implements IContainerFreezer { /** Values are the screenshot "surfaces" or null if it was frozen via BLAST override. */ private final ArrayMap<WindowContainer, SurfaceControl> mSnapshots = new ArrayMap<>(); /** Keeps track of which windows are frozen. Not all frozen windows have snapshots. */ private final ArraySet<WindowContainer> mFrozen = new ArraySet<>(); /** Takes a screenshot and puts it at the top of the container's surface. */ @Override Loading @@ -2109,7 +2118,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe // Check if any parents have already been "frozen". If so, `wc` is already part of that // snapshot, so just skip it. for (WindowContainer p = wc; p != null; p = p.getParent()) { if (mSnapshots.containsKey(p)) return false; if (mFrozen.contains(p)) return false; } if (mIsSeamlessRotation) { Loading @@ -2118,7 +2127,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe if (top != null && (top == wc || top.isDescendantOf(wc))) { // Don't use screenshots for seamless windows: these will use BLAST even if not // BLAST mode. mSnapshots.put(wc, null); mFrozen.add(wc); return true; } } Loading Loading @@ -2151,7 +2160,15 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe .setCallsite("Transition.ScreenshotSync") .setBLASTLayer() .build(); mSnapshots.put(wc, snapshotSurface); mFrozen.add(wc); final ChangeInfo changeInfo = Objects.requireNonNull(mChanges.get(wc)); changeInfo.mSnapshot = snapshotSurface; if (wc.asDisplayContent() != null) { // This isn't cheap, so only do it for rotations: assume display-level is rotate // since most of the time it is. changeInfo.mSnapshotLuma = RotationAnimationUtils.getMedianBorderLuma( screenshotBuffer.getHardwareBuffer(), screenshotBuffer.getColorSpace()); } SurfaceControl.Transaction t = wc.mWmService.mTransactionFactory.get(); t.setBuffer(snapshotSurface, buffer); Loading @@ -2172,11 +2189,12 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe @Override public void cleanUp(SurfaceControl.Transaction t) { for (int i = 0; i < mSnapshots.size(); ++i) { SurfaceControl snap = mSnapshots.valueAt(i); for (int i = 0; i < mFrozen.size(); ++i) { SurfaceControl snap = Objects.requireNonNull(mChanges.get(mFrozen.valueAt(i))).mSnapshot; // May be null if it was frozen via BLAST override. if (snap == null) continue; t.remove(snap); t.reparent(snap, null /* newParent */); } } } Loading services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +38 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_TO_BACK; Loading Loading @@ -82,6 +83,7 @@ import org.mockito.ArgumentCaptor; import java.util.ArrayList; import java.util.Arrays; import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.function.Function; Loading Loading @@ -1167,6 +1169,42 @@ public class TransitionTests extends WindowTestsBase { assertTrue(mSyncEngine.isReady(transition.getSyncId())); } @Test public void testVisibleChange_snapshot() { registerTestTransitionPlayer(); final ActivityRecord app = createActivityRecord(mDisplayContent); final Transition transition = new Transition(TRANSIT_CHANGE, 0 /* flags */, app.mTransitionController, mWm.mSyncEngine); app.mTransitionController.moveToCollecting(transition, BLASTSyncEngine.METHOD_NONE); final SurfaceControl mockSnapshot = mock(SurfaceControl.class); transition.setContainerFreezer(new Transition.IContainerFreezer() { @Override public boolean freeze(@NonNull WindowContainer wc, @NonNull Rect bounds) { Objects.requireNonNull(transition.mChanges.get(wc)).mSnapshot = mockSnapshot; return true; } @Override public void cleanUp(SurfaceControl.Transaction t) { } }); final Task task = app.getTask(); transition.collect(task); final Rect bounds = new Rect(task.getBounds()); Configuration c = new Configuration(task.getRequestedOverrideConfiguration()); bounds.inset(10, 10); c.windowConfiguration.setBounds(bounds); task.onRequestedOverrideConfigurationChanged(c); ArrayList<WindowContainer> targets = Transition.calculateTargets( transition.mParticipants, transition.mChanges); TransitionInfo info = Transition.calculateTransitionInfo( TRANSIT_CHANGE, 0, targets, transition.mChanges, mMockT); assertEquals(mockSnapshot, info.getChange(task.mRemoteToken.toWindowContainerToken()).getSnapshot()); transition.abort(); } private static void makeTaskOrganized(Task... tasks) { final ITaskOrganizer organizer = mock(ITaskOrganizer.class); for (Task t : tasks) { Loading Loading
core/java/android/window/TransitionInfo.java +27 −2 Original line number Diff line number Diff line Loading @@ -397,6 +397,8 @@ public final class TransitionInfo implements Parcelable { private @Surface.Rotation int mEndFixedRotation = ROTATION_UNDEFINED; private int mRotationAnimation = ROTATION_ANIMATION_UNSPECIFIED; private @ColorInt int mBackgroundColor; private SurfaceControl mSnapshot = null; private float mSnapshotLuma; public Change(@Nullable WindowContainerToken container, @NonNull SurfaceControl leash) { mContainer = container; Loading @@ -420,6 +422,8 @@ public final class TransitionInfo implements Parcelable { mEndFixedRotation = in.readInt(); mRotationAnimation = in.readInt(); mBackgroundColor = in.readInt(); mSnapshot = in.readTypedObject(SurfaceControl.CREATOR); mSnapshotLuma = in.readFloat(); } /** Sets the parent of this change's container. The parent must be a participant or null. */ Loading Loading @@ -489,6 +493,12 @@ public final class TransitionInfo implements Parcelable { mBackgroundColor = backgroundColor; } /** Sets a snapshot surface for the "start" state of the container. */ public void setSnapshot(@Nullable SurfaceControl snapshot, float luma) { mSnapshot = snapshot; mSnapshotLuma = luma; } /** @return the container that is changing. May be null if non-remotable (eg. activity) */ @Nullable public WindowContainerToken getContainer() { Loading Loading @@ -587,6 +597,17 @@ public final class TransitionInfo implements Parcelable { return mBackgroundColor; } /** @return a snapshot surface (if applicable). */ @Nullable public SurfaceControl getSnapshot() { return mSnapshot; } /** @return the luma calculated for the snapshot surface (if applicable). */ public float getSnapshotLuma() { return mSnapshotLuma; } /** @hide */ @Override public void writeToParcel(@NonNull Parcel dest, int flags) { Loading @@ -605,6 +626,8 @@ public final class TransitionInfo implements Parcelable { dest.writeInt(mEndFixedRotation); dest.writeInt(mRotationAnimation); dest.writeInt(mBackgroundColor); dest.writeTypedObject(mSnapshot, flags); dest.writeFloat(mSnapshotLuma); } @NonNull Loading @@ -629,11 +652,13 @@ public final class TransitionInfo implements Parcelable { @Override public String toString() { return "{" + mContainer + "(" + mParent + ") leash=" + mLeash String out = "{" + mContainer + "(" + mParent + ") leash=" + mLeash + " m=" + modeToString(mMode) + " f=" + flagsToString(mFlags) + " sb=" + mStartAbsBounds + " eb=" + mEndAbsBounds + " eo=" + mEndRelOffset + " r=" + mStartRotation + "->" + mEndRotation + ":" + mRotationAnimation + " endFixedRotation=" + mEndFixedRotation + "}"; + " endFixedRotation=" + mEndFixedRotation; if (mSnapshot != null) out += " snapshot=" + mSnapshot; return out + "}"; } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java +35 −28 Original line number Diff line number Diff line Loading @@ -139,6 +139,11 @@ class ScreenRotationAnimation { .build(); try { if (change.getSnapshot() != null) { mScreenshotLayer = change.getSnapshot(); t.reparent(mScreenshotLayer, mAnimLeash); mStartLuma = change.getSnapshotLuma(); } else { SurfaceControl.LayerCaptureArgs args = new SurfaceControl.LayerCaptureArgs.Builder(mSurfaceControl) .setCaptureSecureLayers(true) Loading @@ -161,16 +166,20 @@ class ScreenRotationAnimation { .setName("RotationLayer") .build(); t.setLayer(mAnimLeash, SCREEN_FREEZE_LAYER_BASE); t.show(mAnimLeash); // Crop the real content in case it contains a larger child layer, e.g. wallpaper. t.setCrop(mSurfaceControl, new Rect(0, 0, mEndWidth, mEndHeight)); final ColorSpace colorSpace = screenshotBuffer.getColorSpace(); final HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer(); t.setDataSpace(mScreenshotLayer, colorSpace.getDataSpace()); t.setBuffer(mScreenshotLayer, hardwareBuffer); t.show(mScreenshotLayer); if (!isCustomRotate()) { mStartLuma = getMedianBorderLuma(hardwareBuffer, colorSpace); } } t.setLayer(mAnimLeash, SCREEN_FREEZE_LAYER_BASE); t.show(mAnimLeash); // Crop the real content in case it contains a larger child layer, e.g. wallpaper. t.setCrop(mSurfaceControl, new Rect(0, 0, mEndWidth, mEndHeight)); if (!isCustomRotate()) { mBackColorSurface = new SurfaceControl.Builder(session) Loading @@ -181,8 +190,6 @@ class ScreenRotationAnimation { .setName("BackColorSurface") .build(); mStartLuma = getMedianBorderLuma(hardwareBuffer, colorSpace); t.setLayer(mBackColorSurface, -1); t.setColor(mBackColorSurface, new float[]{mStartLuma, mStartLuma, mStartLuma}); t.show(mBackColorSurface); Loading
services/core/java/com/android/server/wm/Transition.java +27 −9 Original line number Diff line number Diff line Loading @@ -93,11 +93,13 @@ import com.android.internal.protolog.ProtoLogGroup; import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.inputmethod.InputMethodManagerInternal; import com.android.server.wm.utils.RotationAnimationUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.function.Predicate; /** Loading Loading @@ -289,9 +291,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe if (mContainerFreezer == null) { mContainerFreezer = new ScreenshotFreezer(); } mIsSeamlessRotation = true; final WindowState top = dc.getDisplayPolicy().getTopFullscreenOpaqueWindow(); if (top != null) { mIsSeamlessRotation = true; top.mSyncMethodOverride = BLASTSyncEngine.METHOD_BLAST; ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Override sync-method for %s " + "because seamless rotating", top.getName()); Loading Loading @@ -1635,6 +1637,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe change.setEndAbsBounds(bounds); } change.setRotation(info.mRotation, endRotation); if (info.mSnapshot != null) { change.setSnapshot(info.mSnapshot, info.mSnapshotLuma); } out.addChange(change); } Loading Loading @@ -1790,6 +1795,10 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe /** These are just extra info. They aren't used for change-detection. */ @Flag int mFlags = FLAG_NONE; /** Snapshot surface and luma, if relevant. */ SurfaceControl mSnapshot; float mSnapshotLuma; ChangeInfo(@NonNull WindowContainer origState) { mVisible = origState.isVisibleRequested(); mWindowingMode = origState.getWindowingMode(); Loading Loading @@ -2098,8 +2107,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe */ @VisibleForTesting private class ScreenshotFreezer implements IContainerFreezer { /** Values are the screenshot "surfaces" or null if it was frozen via BLAST override. */ private final ArrayMap<WindowContainer, SurfaceControl> mSnapshots = new ArrayMap<>(); /** Keeps track of which windows are frozen. Not all frozen windows have snapshots. */ private final ArraySet<WindowContainer> mFrozen = new ArraySet<>(); /** Takes a screenshot and puts it at the top of the container's surface. */ @Override Loading @@ -2109,7 +2118,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe // Check if any parents have already been "frozen". If so, `wc` is already part of that // snapshot, so just skip it. for (WindowContainer p = wc; p != null; p = p.getParent()) { if (mSnapshots.containsKey(p)) return false; if (mFrozen.contains(p)) return false; } if (mIsSeamlessRotation) { Loading @@ -2118,7 +2127,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe if (top != null && (top == wc || top.isDescendantOf(wc))) { // Don't use screenshots for seamless windows: these will use BLAST even if not // BLAST mode. mSnapshots.put(wc, null); mFrozen.add(wc); return true; } } Loading Loading @@ -2151,7 +2160,15 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe .setCallsite("Transition.ScreenshotSync") .setBLASTLayer() .build(); mSnapshots.put(wc, snapshotSurface); mFrozen.add(wc); final ChangeInfo changeInfo = Objects.requireNonNull(mChanges.get(wc)); changeInfo.mSnapshot = snapshotSurface; if (wc.asDisplayContent() != null) { // This isn't cheap, so only do it for rotations: assume display-level is rotate // since most of the time it is. changeInfo.mSnapshotLuma = RotationAnimationUtils.getMedianBorderLuma( screenshotBuffer.getHardwareBuffer(), screenshotBuffer.getColorSpace()); } SurfaceControl.Transaction t = wc.mWmService.mTransactionFactory.get(); t.setBuffer(snapshotSurface, buffer); Loading @@ -2172,11 +2189,12 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe @Override public void cleanUp(SurfaceControl.Transaction t) { for (int i = 0; i < mSnapshots.size(); ++i) { SurfaceControl snap = mSnapshots.valueAt(i); for (int i = 0; i < mFrozen.size(); ++i) { SurfaceControl snap = Objects.requireNonNull(mChanges.get(mFrozen.valueAt(i))).mSnapshot; // May be null if it was frozen via BLAST override. if (snap == null) continue; t.remove(snap); t.reparent(snap, null /* newParent */); } } } Loading
services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +38 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_TO_BACK; Loading Loading @@ -82,6 +83,7 @@ import org.mockito.ArgumentCaptor; import java.util.ArrayList; import java.util.Arrays; import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.function.Function; Loading Loading @@ -1167,6 +1169,42 @@ public class TransitionTests extends WindowTestsBase { assertTrue(mSyncEngine.isReady(transition.getSyncId())); } @Test public void testVisibleChange_snapshot() { registerTestTransitionPlayer(); final ActivityRecord app = createActivityRecord(mDisplayContent); final Transition transition = new Transition(TRANSIT_CHANGE, 0 /* flags */, app.mTransitionController, mWm.mSyncEngine); app.mTransitionController.moveToCollecting(transition, BLASTSyncEngine.METHOD_NONE); final SurfaceControl mockSnapshot = mock(SurfaceControl.class); transition.setContainerFreezer(new Transition.IContainerFreezer() { @Override public boolean freeze(@NonNull WindowContainer wc, @NonNull Rect bounds) { Objects.requireNonNull(transition.mChanges.get(wc)).mSnapshot = mockSnapshot; return true; } @Override public void cleanUp(SurfaceControl.Transaction t) { } }); final Task task = app.getTask(); transition.collect(task); final Rect bounds = new Rect(task.getBounds()); Configuration c = new Configuration(task.getRequestedOverrideConfiguration()); bounds.inset(10, 10); c.windowConfiguration.setBounds(bounds); task.onRequestedOverrideConfigurationChanged(c); ArrayList<WindowContainer> targets = Transition.calculateTargets( transition.mParticipants, transition.mChanges); TransitionInfo info = Transition.calculateTransitionInfo( TRANSIT_CHANGE, 0, targets, transition.mChanges, mMockT); assertEquals(mockSnapshot, info.getChange(task.mRemoteToken.toWindowContainerToken()).getSnapshot()); transition.abort(); } private static void makeTaskOrganized(Task... tasks) { final ITaskOrganizer organizer = mock(ITaskOrganizer.class); for (Task t : tasks) { Loading