Loading services/core/java/com/android/server/wm/Transition.java +19 −9 Original line number Diff line number Diff line Loading @@ -1205,7 +1205,14 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe return false; } final @TransitionInfo.TransitionMode int mode = changes.get(target).getTransitMode(target); final ChangeInfo change = changes.get(target); if (change.mStartParent != null && target.getParent() != change.mStartParent) { // When a window is reparented, the state change won't fit into any of the parents. // Don't promote such change so that we can animate the reparent if needed. return false; } final @TransitionInfo.TransitionMode int mode = change.getTransitMode(target); for (int i = parent.getChildCount() - 1; i >= 0; --i) { final WindowContainer<?> sibling = parent.getChildAt(i); if (target == sibling) continue; Loading Loading @@ -1345,14 +1352,14 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe // Intermediate parents must be those that has window to be managed by Shell. continue; } if (parentChange.mParent != null && !skipIntermediateReports) { changes.get(wc).mParent = p; if (parentChange.mEndParent != null && !skipIntermediateReports) { changes.get(wc).mEndParent = p; // The chain above the parent was processed. break; } if (targetList.contains(p)) { if (skipIntermediateReports) { changes.get(wc).mParent = p; changes.get(wc).mEndParent = p; } else { intermediates.add(p); } Loading @@ -1364,10 +1371,10 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe } if (!foundParentInTargets || intermediates.isEmpty()) continue; // Add any always-report parents along the way. changes.get(wc).mParent = intermediates.get(0); changes.get(wc).mEndParent = intermediates.get(0); for (int j = 0; j < intermediates.size() - 1; j++) { final WindowContainer<?> intermediate = intermediates.get(j); changes.get(intermediate).mParent = intermediates.get(j + 1); changes.get(intermediate).mEndParent = intermediates.get(j + 1); targets.add(intermediate); } } Loading Loading @@ -1480,8 +1487,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe target.mRemoteToken != null ? target.mRemoteToken.toWindowContainerToken() : null, getLeashSurface(target, startT)); // TODO(shell-transitions): Use leash for non-organized windows. if (info.mParent != null) { change.setParent(info.mParent.mRemoteToken.toWindowContainerToken()); if (info.mEndParent != null) { change.setParent(info.mEndParent.mRemoteToken.toWindowContainerToken()); } change.setMode(info.getTransitMode(target)); change.setStartAbsBounds(info.mAbsoluteBounds); Loading Loading @@ -1664,7 +1671,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe @interface Flag {} // Usually "post" change state. WindowContainer mParent; WindowContainer mEndParent; // Parent before change state. WindowContainer mStartParent; // State tracking boolean mExistenceChanged = false; Loading @@ -1685,6 +1694,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe mAbsoluteBounds.set(origState.getBounds()); mShowWallpaper = origState.showWallpaper(); mRotation = origState.getWindowConfiguration().getRotation(); mStartParent = origState.getParent(); } @VisibleForTesting Loading services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +35 −0 Original line number Diff line number Diff line Loading @@ -36,8 +36,10 @@ import static android.window.TransitionInfo.FLAG_SHOW_WALLPAPER; import static android.window.TransitionInfo.FLAG_TRANSLUCENT; import static android.window.TransitionInfo.isIndependent; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.WindowContainer.POSITION_TOP; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; Loading Loading @@ -1079,6 +1081,39 @@ public class TransitionTests extends WindowTestsBase { assertTrue((info.getChanges().get(1).getFlags() & FLAG_IS_EMBEDDED) != 0); } @Test public void testIncludeEmbeddedActivityReparent() { final Transition transition = createTestTransition(TRANSIT_OPEN); final Task task = createTask(mDisplayContent); task.setBounds(new Rect(0, 0, 2000, 1000)); final ActivityRecord activity = createActivityRecord(task); activity.mVisibleRequested = true; // Skip manipulate the SurfaceControl. doNothing().when(activity).setDropInputMode(anyInt()); final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); mAtm.mTaskFragmentOrganizerController.registerOrganizer( ITaskFragmentOrganizer.Stub.asInterface(organizer.getOrganizerToken().asBinder())); final TaskFragment embeddedTf = new TaskFragmentBuilder(mAtm) .setParentTask(task) .setOrganizer(organizer) .build(); // TaskFragment with different bounds from Task. embeddedTf.setBounds(new Rect(0, 0, 1000, 1000)); // Start states. transition.collect(activity); transition.collectExistenceChange(embeddedTf); // End states. activity.reparent(embeddedTf, POSITION_TOP); // Verify that both activity and TaskFragment are included. final ArrayList<WindowContainer> targets = Transition.calculateTargets( transition.mParticipants, transition.mChanges); assertTrue(targets.contains(embeddedTf)); assertTrue(targets.contains(activity)); } private static void makeTaskOrganized(Task... tasks) { final ITaskOrganizer organizer = mock(ITaskOrganizer.class); for (Task t : tasks) { Loading Loading
services/core/java/com/android/server/wm/Transition.java +19 −9 Original line number Diff line number Diff line Loading @@ -1205,7 +1205,14 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe return false; } final @TransitionInfo.TransitionMode int mode = changes.get(target).getTransitMode(target); final ChangeInfo change = changes.get(target); if (change.mStartParent != null && target.getParent() != change.mStartParent) { // When a window is reparented, the state change won't fit into any of the parents. // Don't promote such change so that we can animate the reparent if needed. return false; } final @TransitionInfo.TransitionMode int mode = change.getTransitMode(target); for (int i = parent.getChildCount() - 1; i >= 0; --i) { final WindowContainer<?> sibling = parent.getChildAt(i); if (target == sibling) continue; Loading Loading @@ -1345,14 +1352,14 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe // Intermediate parents must be those that has window to be managed by Shell. continue; } if (parentChange.mParent != null && !skipIntermediateReports) { changes.get(wc).mParent = p; if (parentChange.mEndParent != null && !skipIntermediateReports) { changes.get(wc).mEndParent = p; // The chain above the parent was processed. break; } if (targetList.contains(p)) { if (skipIntermediateReports) { changes.get(wc).mParent = p; changes.get(wc).mEndParent = p; } else { intermediates.add(p); } Loading @@ -1364,10 +1371,10 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe } if (!foundParentInTargets || intermediates.isEmpty()) continue; // Add any always-report parents along the way. changes.get(wc).mParent = intermediates.get(0); changes.get(wc).mEndParent = intermediates.get(0); for (int j = 0; j < intermediates.size() - 1; j++) { final WindowContainer<?> intermediate = intermediates.get(j); changes.get(intermediate).mParent = intermediates.get(j + 1); changes.get(intermediate).mEndParent = intermediates.get(j + 1); targets.add(intermediate); } } Loading Loading @@ -1480,8 +1487,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe target.mRemoteToken != null ? target.mRemoteToken.toWindowContainerToken() : null, getLeashSurface(target, startT)); // TODO(shell-transitions): Use leash for non-organized windows. if (info.mParent != null) { change.setParent(info.mParent.mRemoteToken.toWindowContainerToken()); if (info.mEndParent != null) { change.setParent(info.mEndParent.mRemoteToken.toWindowContainerToken()); } change.setMode(info.getTransitMode(target)); change.setStartAbsBounds(info.mAbsoluteBounds); Loading Loading @@ -1664,7 +1671,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe @interface Flag {} // Usually "post" change state. WindowContainer mParent; WindowContainer mEndParent; // Parent before change state. WindowContainer mStartParent; // State tracking boolean mExistenceChanged = false; Loading @@ -1685,6 +1694,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe mAbsoluteBounds.set(origState.getBounds()); mShowWallpaper = origState.showWallpaper(); mRotation = origState.getWindowConfiguration().getRotation(); mStartParent = origState.getParent(); } @VisibleForTesting Loading
services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +35 −0 Original line number Diff line number Diff line Loading @@ -36,8 +36,10 @@ import static android.window.TransitionInfo.FLAG_SHOW_WALLPAPER; import static android.window.TransitionInfo.FLAG_TRANSLUCENT; import static android.window.TransitionInfo.isIndependent; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.WindowContainer.POSITION_TOP; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; Loading Loading @@ -1079,6 +1081,39 @@ public class TransitionTests extends WindowTestsBase { assertTrue((info.getChanges().get(1).getFlags() & FLAG_IS_EMBEDDED) != 0); } @Test public void testIncludeEmbeddedActivityReparent() { final Transition transition = createTestTransition(TRANSIT_OPEN); final Task task = createTask(mDisplayContent); task.setBounds(new Rect(0, 0, 2000, 1000)); final ActivityRecord activity = createActivityRecord(task); activity.mVisibleRequested = true; // Skip manipulate the SurfaceControl. doNothing().when(activity).setDropInputMode(anyInt()); final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); mAtm.mTaskFragmentOrganizerController.registerOrganizer( ITaskFragmentOrganizer.Stub.asInterface(organizer.getOrganizerToken().asBinder())); final TaskFragment embeddedTf = new TaskFragmentBuilder(mAtm) .setParentTask(task) .setOrganizer(organizer) .build(); // TaskFragment with different bounds from Task. embeddedTf.setBounds(new Rect(0, 0, 1000, 1000)); // Start states. transition.collect(activity); transition.collectExistenceChange(embeddedTf); // End states. activity.reparent(embeddedTf, POSITION_TOP); // Verify that both activity and TaskFragment are included. final ArrayList<WindowContainer> targets = Transition.calculateTargets( transition.mParticipants, transition.mChanges); assertTrue(targets.contains(embeddedTf)); assertTrue(targets.contains(activity)); } private static void makeTaskOrganized(Task... tasks) { final ITaskOrganizer organizer = mock(ITaskOrganizer.class); for (Task t : tasks) { Loading