Loading services/core/java/com/android/server/wm/WindowOrganizerController.java +9 −4 Original line number Original line Diff line number Diff line Loading @@ -122,7 +122,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub * A Map which manages the relationship between * A Map which manages the relationship between * {@link TaskFragmentCreationParams#getFragmentToken()} and {@link TaskFragment} * {@link TaskFragmentCreationParams#getFragmentToken()} and {@link TaskFragment} */ */ private final ArrayMap<IBinder, TaskFragment> mLaunchTaskFragments = new ArrayMap<>(); @VisibleForTesting final ArrayMap<IBinder, TaskFragment> mLaunchTaskFragments = new ArrayMap<>(); WindowOrganizerController(ActivityTaskManagerService atm) { WindowOrganizerController(ActivityTaskManagerService atm) { mService = atm; mService = atm; Loading Loading @@ -672,7 +673,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub throw new IllegalArgumentException( throw new IllegalArgumentException( "Can only delete organized TaskFragment, but not Task."); "Can only delete organized TaskFragment, but not Task."); } } deleteTaskFragment(taskFragment, errorCallbackToken); effects |= deleteTaskFragment(taskFragment, errorCallbackToken); break; break; case HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT: case HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT: fragmentToken = hop.getContainer(); fragmentToken = hop.getContainer(); Loading Loading @@ -704,6 +705,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub break; break; } } activity.reparent(mLaunchTaskFragments.get(fragmentToken), POSITION_TOP); activity.reparent(mLaunchTaskFragments.get(fragmentToken), POSITION_TOP); effects |= TRANSACT_EFFECTS_LIFECYCLE; break; break; case HIERARCHY_OP_TYPE_REPARENT_CHILDREN: case HIERARCHY_OP_TYPE_REPARENT_CHILDREN: final WindowContainer oldParent = WindowContainer.fromBinder(hop.getContainer()); final WindowContainer oldParent = WindowContainer.fromBinder(hop.getContainer()); Loading @@ -716,6 +718,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub break; break; } } reparentTaskFragment(oldParent, newParent, errorCallbackToken); reparentTaskFragment(oldParent, newParent, errorCallbackToken); effects |= TRANSACT_EFFECTS_LIFECYCLE; break; break; case HIERARCHY_OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS: case HIERARCHY_OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS: fragmentToken = hop.getContainer(); fragmentToken = hop.getContainer(); Loading @@ -731,6 +734,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub break; break; } } tf1.setAdjacentTaskFragment(tf2); tf1.setAdjacentTaskFragment(tf2); effects |= TRANSACT_EFFECTS_LIFECYCLE; final Bundle bundle = hop.getLaunchOptions(); final Bundle bundle = hop.getLaunchOptions(); final WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams = final WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams = Loading Loading @@ -1175,7 +1179,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } } } } void deleteTaskFragment(@NonNull TaskFragment taskFragment, private int deleteTaskFragment(@NonNull TaskFragment taskFragment, @Nullable IBinder errorCallbackToken) { @Nullable IBinder errorCallbackToken) { final int index = mLaunchTaskFragments.indexOfValue(taskFragment); final int index = mLaunchTaskFragments.indexOfValue(taskFragment); if (index < 0) { if (index < 0) { Loading @@ -1184,10 +1188,11 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub + "taskFragment"); + "taskFragment"); sendTaskFragmentOperationFailure(taskFragment.getTaskFragmentOrganizer(), sendTaskFragmentOperationFailure(taskFragment.getTaskFragmentOrganizer(), errorCallbackToken, exception); errorCallbackToken, exception); return; return 0; } } mLaunchTaskFragments.removeAt(index); mLaunchTaskFragments.removeAt(index); taskFragment.remove(true /* withTransition */, "deleteTaskFragment"); taskFragment.remove(true /* withTransition */, "deleteTaskFragment"); return TRANSACT_EFFECTS_LIFECYCLE; } } @Nullable @Nullable Loading services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java +41 −1 Original line number Original line Diff line number Diff line Loading @@ -76,7 +76,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { @Before @Before public void setup() { public void setup() { mController = mWm.mAtmService.mWindowOrganizerController.mTaskFragmentOrganizerController; mController = mAtm.mWindowOrganizerController.mTaskFragmentOrganizerController; mOrganizer = new TaskFragmentOrganizer(Runnable::run); mOrganizer = new TaskFragmentOrganizer(Runnable::run); mOrganizerToken = mOrganizer.getOrganizerToken(); mOrganizerToken = mOrganizer.getOrganizerToken(); mIOrganizer = ITaskFragmentOrganizer.Stub.asInterface(mOrganizerToken.asBinder()); mIOrganizer = ITaskFragmentOrganizer.Stub.asInterface(mOrganizerToken.asBinder()); Loading Loading @@ -284,7 +284,9 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { @Test @Test public void testApplyTransaction_enforceHierarchyChange_deleteTaskFragment() public void testApplyTransaction_enforceHierarchyChange_deleteTaskFragment() throws RemoteException { throws RemoteException { mController.registerOrganizer(mIOrganizer); mOrganizer.applyTransaction(mTransaction); mOrganizer.applyTransaction(mTransaction); doReturn(true).when(mTaskFragment).isAttached(); // Throw exception if the transaction is trying to change a window that is not organized by // Throw exception if the transaction is trying to change a window that is not organized by // the organizer. // the organizer. Loading @@ -300,8 +302,18 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { // Allow transaction to change a TaskFragment created by the organizer. // Allow transaction to change a TaskFragment created by the organizer. mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */); mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */); clearInvocations(mAtm.mRootWindowContainer); mAtm.getWindowOrganizerController().applyTransaction(mTransaction); mAtm.getWindowOrganizerController().applyTransaction(mTransaction); // No lifecycle update when the TaskFragment is not recorded. verify(mAtm.mRootWindowContainer, never()).resumeFocusedTasksTopActivities(); mAtm.mWindowOrganizerController.mLaunchTaskFragments .put(mFragmentToken, mTaskFragment); mAtm.getWindowOrganizerController().applyTransaction(mTransaction); verify(mAtm.mRootWindowContainer).resumeFocusedTasksTopActivities(); } } @Test @Test Loading @@ -327,8 +339,11 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { // Allow transaction to change a TaskFragment created by the organizer. // Allow transaction to change a TaskFragment created by the organizer. mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */); mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */); taskFragment2.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */); taskFragment2.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */); clearInvocations(mAtm.mRootWindowContainer); mAtm.getWindowOrganizerController().applyTransaction(mTransaction); mAtm.getWindowOrganizerController().applyTransaction(mTransaction); verify(mAtm.mRootWindowContainer).resumeFocusedTasksTopActivities(); } } @Test @Test Loading Loading @@ -360,6 +375,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { public void testApplyTransaction_enforceHierarchyChange_reparentChildren() public void testApplyTransaction_enforceHierarchyChange_reparentChildren() throws RemoteException { throws RemoteException { mOrganizer.applyTransaction(mTransaction); mOrganizer.applyTransaction(mTransaction); mController.registerOrganizer(mIOrganizer); doReturn(true).when(mTaskFragment).isAttached(); // Throw exception if the transaction is trying to change a window that is not organized by // Throw exception if the transaction is trying to change a window that is not organized by // the organizer. // the organizer. Loading @@ -375,7 +392,30 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { // Allow transaction to change a TaskFragment created by the organizer. // Allow transaction to change a TaskFragment created by the organizer. mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */); mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */); clearInvocations(mAtm.mRootWindowContainer); mAtm.getWindowOrganizerController().applyTransaction(mTransaction); mAtm.getWindowOrganizerController().applyTransaction(mTransaction); verify(mAtm.mRootWindowContainer).resumeFocusedTasksTopActivities(); } @Test public void testApplyTransaction_reparentActivityToTaskFragment_triggerLifecycleUpdate() throws RemoteException { final ActivityRecord activity = createActivityRecord(mDefaultDisplay); mOrganizer.applyTransaction(mTransaction); mController.registerOrganizer(mIOrganizer); mTaskFragment = new TaskFragmentBuilder(mAtm) .setCreateParentTask() .setFragmentToken(mFragmentToken) .build(); mAtm.mWindowOrganizerController.mLaunchTaskFragments .put(mFragmentToken, mTaskFragment); mTransaction.reparentActivityToTaskFragment(mFragmentToken, activity.appToken); clearInvocations(mAtm.mRootWindowContainer); mAtm.getWindowOrganizerController().applyTransaction(mTransaction); verify(mAtm.mRootWindowContainer).resumeFocusedTasksTopActivities(); } } } } services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +7 −1 Original line number Original line Diff line number Diff line Loading @@ -1140,6 +1140,7 @@ class WindowTestsBase extends SystemServiceTestsBase { private int mCreateActivityCount = 0; private int mCreateActivityCount = 0; @Nullable @Nullable private TaskFragmentOrganizer mOrganizer; private TaskFragmentOrganizer mOrganizer; private IBinder mFragmentToken; TaskFragmentBuilder(ActivityTaskManagerService service) { TaskFragmentBuilder(ActivityTaskManagerService service) { mAtm = service; mAtm = service; Loading Loading @@ -1171,10 +1172,15 @@ class WindowTestsBase extends SystemServiceTestsBase { return this; return this; } } TaskFragmentBuilder setFragmentToken(@Nullable IBinder fragmentToken) { mFragmentToken = fragmentToken; return this; } TaskFragment build() { TaskFragment build() { SystemServicesTestRule.checkHoldsLock(mAtm.mGlobalLock); SystemServicesTestRule.checkHoldsLock(mAtm.mGlobalLock); final TaskFragment taskFragment = new TaskFragment(mAtm, null /* fragmentToken */, final TaskFragment taskFragment = new TaskFragment(mAtm, mFragmentToken, mOrganizer != null); mOrganizer != null); if (mParentTask == null && mCreateParentTask) { if (mParentTask == null && mCreateParentTask) { mParentTask = new TaskBuilder(mAtm.mTaskSupervisor).build(); mParentTask = new TaskBuilder(mAtm.mTaskSupervisor).build(); Loading Loading
services/core/java/com/android/server/wm/WindowOrganizerController.java +9 −4 Original line number Original line Diff line number Diff line Loading @@ -122,7 +122,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub * A Map which manages the relationship between * A Map which manages the relationship between * {@link TaskFragmentCreationParams#getFragmentToken()} and {@link TaskFragment} * {@link TaskFragmentCreationParams#getFragmentToken()} and {@link TaskFragment} */ */ private final ArrayMap<IBinder, TaskFragment> mLaunchTaskFragments = new ArrayMap<>(); @VisibleForTesting final ArrayMap<IBinder, TaskFragment> mLaunchTaskFragments = new ArrayMap<>(); WindowOrganizerController(ActivityTaskManagerService atm) { WindowOrganizerController(ActivityTaskManagerService atm) { mService = atm; mService = atm; Loading Loading @@ -672,7 +673,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub throw new IllegalArgumentException( throw new IllegalArgumentException( "Can only delete organized TaskFragment, but not Task."); "Can only delete organized TaskFragment, but not Task."); } } deleteTaskFragment(taskFragment, errorCallbackToken); effects |= deleteTaskFragment(taskFragment, errorCallbackToken); break; break; case HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT: case HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT: fragmentToken = hop.getContainer(); fragmentToken = hop.getContainer(); Loading Loading @@ -704,6 +705,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub break; break; } } activity.reparent(mLaunchTaskFragments.get(fragmentToken), POSITION_TOP); activity.reparent(mLaunchTaskFragments.get(fragmentToken), POSITION_TOP); effects |= TRANSACT_EFFECTS_LIFECYCLE; break; break; case HIERARCHY_OP_TYPE_REPARENT_CHILDREN: case HIERARCHY_OP_TYPE_REPARENT_CHILDREN: final WindowContainer oldParent = WindowContainer.fromBinder(hop.getContainer()); final WindowContainer oldParent = WindowContainer.fromBinder(hop.getContainer()); Loading @@ -716,6 +718,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub break; break; } } reparentTaskFragment(oldParent, newParent, errorCallbackToken); reparentTaskFragment(oldParent, newParent, errorCallbackToken); effects |= TRANSACT_EFFECTS_LIFECYCLE; break; break; case HIERARCHY_OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS: case HIERARCHY_OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS: fragmentToken = hop.getContainer(); fragmentToken = hop.getContainer(); Loading @@ -731,6 +734,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub break; break; } } tf1.setAdjacentTaskFragment(tf2); tf1.setAdjacentTaskFragment(tf2); effects |= TRANSACT_EFFECTS_LIFECYCLE; final Bundle bundle = hop.getLaunchOptions(); final Bundle bundle = hop.getLaunchOptions(); final WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams = final WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams = Loading Loading @@ -1175,7 +1179,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } } } } void deleteTaskFragment(@NonNull TaskFragment taskFragment, private int deleteTaskFragment(@NonNull TaskFragment taskFragment, @Nullable IBinder errorCallbackToken) { @Nullable IBinder errorCallbackToken) { final int index = mLaunchTaskFragments.indexOfValue(taskFragment); final int index = mLaunchTaskFragments.indexOfValue(taskFragment); if (index < 0) { if (index < 0) { Loading @@ -1184,10 +1188,11 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub + "taskFragment"); + "taskFragment"); sendTaskFragmentOperationFailure(taskFragment.getTaskFragmentOrganizer(), sendTaskFragmentOperationFailure(taskFragment.getTaskFragmentOrganizer(), errorCallbackToken, exception); errorCallbackToken, exception); return; return 0; } } mLaunchTaskFragments.removeAt(index); mLaunchTaskFragments.removeAt(index); taskFragment.remove(true /* withTransition */, "deleteTaskFragment"); taskFragment.remove(true /* withTransition */, "deleteTaskFragment"); return TRANSACT_EFFECTS_LIFECYCLE; } } @Nullable @Nullable Loading
services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java +41 −1 Original line number Original line Diff line number Diff line Loading @@ -76,7 +76,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { @Before @Before public void setup() { public void setup() { mController = mWm.mAtmService.mWindowOrganizerController.mTaskFragmentOrganizerController; mController = mAtm.mWindowOrganizerController.mTaskFragmentOrganizerController; mOrganizer = new TaskFragmentOrganizer(Runnable::run); mOrganizer = new TaskFragmentOrganizer(Runnable::run); mOrganizerToken = mOrganizer.getOrganizerToken(); mOrganizerToken = mOrganizer.getOrganizerToken(); mIOrganizer = ITaskFragmentOrganizer.Stub.asInterface(mOrganizerToken.asBinder()); mIOrganizer = ITaskFragmentOrganizer.Stub.asInterface(mOrganizerToken.asBinder()); Loading Loading @@ -284,7 +284,9 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { @Test @Test public void testApplyTransaction_enforceHierarchyChange_deleteTaskFragment() public void testApplyTransaction_enforceHierarchyChange_deleteTaskFragment() throws RemoteException { throws RemoteException { mController.registerOrganizer(mIOrganizer); mOrganizer.applyTransaction(mTransaction); mOrganizer.applyTransaction(mTransaction); doReturn(true).when(mTaskFragment).isAttached(); // Throw exception if the transaction is trying to change a window that is not organized by // Throw exception if the transaction is trying to change a window that is not organized by // the organizer. // the organizer. Loading @@ -300,8 +302,18 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { // Allow transaction to change a TaskFragment created by the organizer. // Allow transaction to change a TaskFragment created by the organizer. mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */); mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */); clearInvocations(mAtm.mRootWindowContainer); mAtm.getWindowOrganizerController().applyTransaction(mTransaction); mAtm.getWindowOrganizerController().applyTransaction(mTransaction); // No lifecycle update when the TaskFragment is not recorded. verify(mAtm.mRootWindowContainer, never()).resumeFocusedTasksTopActivities(); mAtm.mWindowOrganizerController.mLaunchTaskFragments .put(mFragmentToken, mTaskFragment); mAtm.getWindowOrganizerController().applyTransaction(mTransaction); verify(mAtm.mRootWindowContainer).resumeFocusedTasksTopActivities(); } } @Test @Test Loading @@ -327,8 +339,11 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { // Allow transaction to change a TaskFragment created by the organizer. // Allow transaction to change a TaskFragment created by the organizer. mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */); mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */); taskFragment2.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */); taskFragment2.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */); clearInvocations(mAtm.mRootWindowContainer); mAtm.getWindowOrganizerController().applyTransaction(mTransaction); mAtm.getWindowOrganizerController().applyTransaction(mTransaction); verify(mAtm.mRootWindowContainer).resumeFocusedTasksTopActivities(); } } @Test @Test Loading Loading @@ -360,6 +375,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { public void testApplyTransaction_enforceHierarchyChange_reparentChildren() public void testApplyTransaction_enforceHierarchyChange_reparentChildren() throws RemoteException { throws RemoteException { mOrganizer.applyTransaction(mTransaction); mOrganizer.applyTransaction(mTransaction); mController.registerOrganizer(mIOrganizer); doReturn(true).when(mTaskFragment).isAttached(); // Throw exception if the transaction is trying to change a window that is not organized by // Throw exception if the transaction is trying to change a window that is not organized by // the organizer. // the organizer. Loading @@ -375,7 +392,30 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { // Allow transaction to change a TaskFragment created by the organizer. // Allow transaction to change a TaskFragment created by the organizer. mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */); mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* pid */); clearInvocations(mAtm.mRootWindowContainer); mAtm.getWindowOrganizerController().applyTransaction(mTransaction); mAtm.getWindowOrganizerController().applyTransaction(mTransaction); verify(mAtm.mRootWindowContainer).resumeFocusedTasksTopActivities(); } @Test public void testApplyTransaction_reparentActivityToTaskFragment_triggerLifecycleUpdate() throws RemoteException { final ActivityRecord activity = createActivityRecord(mDefaultDisplay); mOrganizer.applyTransaction(mTransaction); mController.registerOrganizer(mIOrganizer); mTaskFragment = new TaskFragmentBuilder(mAtm) .setCreateParentTask() .setFragmentToken(mFragmentToken) .build(); mAtm.mWindowOrganizerController.mLaunchTaskFragments .put(mFragmentToken, mTaskFragment); mTransaction.reparentActivityToTaskFragment(mFragmentToken, activity.appToken); clearInvocations(mAtm.mRootWindowContainer); mAtm.getWindowOrganizerController().applyTransaction(mTransaction); verify(mAtm.mRootWindowContainer).resumeFocusedTasksTopActivities(); } } } }
services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +7 −1 Original line number Original line Diff line number Diff line Loading @@ -1140,6 +1140,7 @@ class WindowTestsBase extends SystemServiceTestsBase { private int mCreateActivityCount = 0; private int mCreateActivityCount = 0; @Nullable @Nullable private TaskFragmentOrganizer mOrganizer; private TaskFragmentOrganizer mOrganizer; private IBinder mFragmentToken; TaskFragmentBuilder(ActivityTaskManagerService service) { TaskFragmentBuilder(ActivityTaskManagerService service) { mAtm = service; mAtm = service; Loading Loading @@ -1171,10 +1172,15 @@ class WindowTestsBase extends SystemServiceTestsBase { return this; return this; } } TaskFragmentBuilder setFragmentToken(@Nullable IBinder fragmentToken) { mFragmentToken = fragmentToken; return this; } TaskFragment build() { TaskFragment build() { SystemServicesTestRule.checkHoldsLock(mAtm.mGlobalLock); SystemServicesTestRule.checkHoldsLock(mAtm.mGlobalLock); final TaskFragment taskFragment = new TaskFragment(mAtm, null /* fragmentToken */, final TaskFragment taskFragment = new TaskFragment(mAtm, mFragmentToken, mOrganizer != null); mOrganizer != null); if (mParentTask == null && mCreateParentTask) { if (mParentTask == null && mCreateParentTask) { mParentTask = new TaskBuilder(mAtm.mTaskSupervisor).build(); mParentTask = new TaskBuilder(mAtm.mTaskSupervisor).build(); Loading