Loading services/core/java/com/android/server/wm/WindowOrganizerController.java +125 −99 Original line number Diff line number Diff line Loading @@ -581,27 +581,130 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub task.getDisplayArea().setLaunchAdjacentFlagRootTask(clearRoot ? null : task); break; } case HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS: case HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS: { effects |= setAdjacentRootsHierarchyOp(hop); break; } // The following operations may change task order so they are skipped while in lock task // mode. The above operations are still allowed because they don't move tasks. And it may // be necessary such as clearing launch root after entering lock task mode. case HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT: { final TaskFragmentCreationParams taskFragmentCreationOptions = hop.getTaskFragmentCreationOptions(); createTaskFragment(taskFragmentCreationOptions, errorCallbackToken); break; } case HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT: { final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer()); if (wc == null || !wc.isAttached()) { Slog.e(TAG, "Attempt to operate on unknown or detached container: " + wc); break; } final TaskFragment taskFragment = wc.asTaskFragment(); if (taskFragment == null || taskFragment.asTask() != null) { throw new IllegalArgumentException( "Can only delete organized TaskFragment, but not Task."); } if (isInLockTaskMode) { final ActivityRecord bottomActivity = taskFragment.getActivity( a -> !a.finishing, false /* traverseTopToBottom */); if (bottomActivity != null && mService.getLockTaskController().activityBlockedFromFinish( bottomActivity)) { Slog.w(TAG, "Skip removing TaskFragment due in lock task mode."); sendTaskFragmentOperationFailure(organizer, errorCallbackToken, new IllegalStateException( "Not allow to delete task fragment in lock task mode.")); break; } } effects |= deleteTaskFragment(taskFragment, errorCallbackToken); break; } case HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT: { final IBinder fragmentToken = hop.getContainer(); if (!mLaunchTaskFragments.containsKey(fragmentToken)) { final Throwable exception = new IllegalArgumentException( "Not allowed to operate with invalid fragment token"); sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); break; } final Intent activityIntent = hop.getActivityIntent(); final Bundle activityOptions = hop.getLaunchOptions(); final TaskFragment tf = mLaunchTaskFragments.get(fragmentToken); final int result = mService.getActivityStartController() .startActivityInTaskFragment(tf, activityIntent, activityOptions, hop.getCallingActivity()); if (!isStartResultSuccessful(result)) { sendTaskFragmentOperationFailure(tf.getTaskFragmentOrganizer(), errorCallbackToken, convertStartFailureToThrowable(result, activityIntent)); } break; } case HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT: { final IBinder fragmentToken = hop.getNewParent(); final ActivityRecord activity = ActivityRecord.forTokenLocked(hop.getContainer()); if (!mLaunchTaskFragments.containsKey(fragmentToken) || activity == null) { final Throwable exception = new IllegalArgumentException( "Not allowed to operate with invalid fragment token or activity."); sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); break; } activity.reparent(mLaunchTaskFragments.get(fragmentToken), POSITION_TOP); effects |= TRANSACT_EFFECTS_LIFECYCLE; break; } case HIERARCHY_OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS: { final IBinder fragmentToken = hop.getContainer(); final IBinder adjacentFragmentToken = hop.getAdjacentRoot(); final TaskFragment tf1 = mLaunchTaskFragments.get(fragmentToken); final TaskFragment tf2 = adjacentFragmentToken != null ? mLaunchTaskFragments.get(adjacentFragmentToken) : null; if (tf1 == null || (adjacentFragmentToken != null && tf2 == null)) { final Throwable exception = new IllegalArgumentException( "Not allowed to set adjacent on invalid fragment tokens"); sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); break; } tf1.setAdjacentTaskFragment(tf2); effects |= TRANSACT_EFFECTS_LIFECYCLE; final Bundle bundle = hop.getLaunchOptions(); final WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams = bundle != null ? new WindowContainerTransaction.TaskFragmentAdjacentParams( bundle) : null; if (adjacentParams == null) { break; } tf1.setDelayLastActivityRemoval( adjacentParams.shouldDelayPrimaryLastActivityRemoval()); if (tf2 != null) { tf2.setDelayLastActivityRemoval( adjacentParams.shouldDelaySecondaryLastActivityRemoval()); } break; } default: { // The other operations may change task order so they are skipped while in lock // task mode. The above operations are still allowed because they don't move // tasks. And it may be necessary such as clearing launch root after entering // lock task mode. if (isInLockTaskMode) { Slog.w(TAG, "Skip applying hierarchy operation " + hop + " while in lock task mode"); Slog.w(TAG, "Skip applying hierarchy operation " + hop + " while in lock task mode"); return effects; } } } final WindowContainer wc; final IBinder fragmentToken; switch (type) { case HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT: case HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT: { effects |= reparentChildrenTasksHierarchyOp(hop, transition, syncId); break; } case HIERARCHY_OP_TYPE_REORDER: case HIERARCHY_OP_TYPE_REPARENT: wc = WindowContainer.fromBinder(hop.getContainer()); case HIERARCHY_OP_TYPE_REPARENT: { final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer()); if (wc == null || !wc.isAttached()) { Slog.e(TAG, "Attempt to operate on detached container: " + wc); break; Loading Loading @@ -630,7 +733,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } effects |= sanitizeAndApplyHierarchyOp(wc, hop); break; case HIERARCHY_OP_TYPE_LAUNCH_TASK: } case HIERARCHY_OP_TYPE_LAUNCH_TASK: { mService.mAmInternal.enforceCallingPermission(START_TASKS_FROM_RECENTS, "launchTask HierarchyOp"); final Bundle launchOpts = hop.getLaunchOptions(); Loading Loading @@ -660,7 +764,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } } break; case HIERARCHY_OP_TYPE_PENDING_INTENT: } case HIERARCHY_OP_TYPE_PENDING_INTENT: { String resolvedType = hop.getActivityIntent() != null ? hop.getActivityIntent().resolveTypeIfNeeded( mService.mContext.getContentResolver()) Loading @@ -683,57 +788,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub hop.getActivityIntent(), resolvedType, null /* finishReceiver */, null /* requiredPermission */, options); break; case HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT: final TaskFragmentCreationParams taskFragmentCreationOptions = hop.getTaskFragmentCreationOptions(); createTaskFragment(taskFragmentCreationOptions, errorCallbackToken); break; case HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT: wc = WindowContainer.fromBinder(hop.getContainer()); if (wc == null || !wc.isAttached()) { Slog.e(TAG, "Attempt to operate on unknown or detached container: " + wc); break; } final TaskFragment taskFragment = wc.asTaskFragment(); if (taskFragment == null || taskFragment.asTask() != null) { throw new IllegalArgumentException( "Can only delete organized TaskFragment, but not Task."); } effects |= deleteTaskFragment(taskFragment, errorCallbackToken); break; case HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT: fragmentToken = hop.getContainer(); if (!mLaunchTaskFragments.containsKey(fragmentToken)) { final Throwable exception = new IllegalArgumentException( "Not allowed to operate with invalid fragment token"); sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); break; } final Intent activityIntent = hop.getActivityIntent(); final Bundle activityOptions = hop.getLaunchOptions(); final TaskFragment tf = mLaunchTaskFragments.get(fragmentToken); final int result = mService.getActivityStartController() .startActivityInTaskFragment(tf, activityIntent, activityOptions, hop.getCallingActivity()); if (!isStartResultSuccessful(result)) { sendTaskFragmentOperationFailure(tf.getTaskFragmentOrganizer(), errorCallbackToken, convertStartFailureToThrowable(result, activityIntent)); } break; case HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT: fragmentToken = hop.getNewParent(); final ActivityRecord activity = ActivityRecord.forTokenLocked(hop.getContainer()); if (!mLaunchTaskFragments.containsKey(fragmentToken) || activity == null) { final Throwable exception = new IllegalArgumentException( "Not allowed to operate with invalid fragment token or activity."); sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); break; } activity.reparent(mLaunchTaskFragments.get(fragmentToken), POSITION_TOP); effects |= TRANSACT_EFFECTS_LIFECYCLE; break; case HIERARCHY_OP_TYPE_REPARENT_CHILDREN: case HIERARCHY_OP_TYPE_REPARENT_CHILDREN: { final WindowContainer oldParent = WindowContainer.fromBinder(hop.getContainer()); final WindowContainer newParent = hop.getNewParent() != null ? WindowContainer.fromBinder(hop.getNewParent()) Loading @@ -746,37 +802,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub reparentTaskFragment(oldParent, newParent, errorCallbackToken); effects |= TRANSACT_EFFECTS_LIFECYCLE; break; case HIERARCHY_OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS: fragmentToken = hop.getContainer(); final IBinder adjacentFragmentToken = hop.getAdjacentRoot(); final TaskFragment tf1 = mLaunchTaskFragments.get(fragmentToken); final TaskFragment tf2 = adjacentFragmentToken != null ? mLaunchTaskFragments.get(adjacentFragmentToken) : null; if (tf1 == null || (adjacentFragmentToken != null && tf2 == null)) { final Throwable exception = new IllegalArgumentException( "Not allowed to set adjacent on invalid fragment tokens"); sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); break; } tf1.setAdjacentTaskFragment(tf2); effects |= TRANSACT_EFFECTS_LIFECYCLE; final Bundle bundle = hop.getLaunchOptions(); final WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams = bundle != null ? new WindowContainerTransaction.TaskFragmentAdjacentParams( bundle) : null; if (adjacentParams == null) { break; } tf1.setDelayLastActivityRemoval( adjacentParams.shouldDelayPrimaryLastActivityRemoval()); if (tf2 != null) { tf2.setDelayLastActivityRemoval( adjacentParams.shouldDelaySecondaryLastActivityRemoval()); } break; } return effects; } Loading Loading
services/core/java/com/android/server/wm/WindowOrganizerController.java +125 −99 Original line number Diff line number Diff line Loading @@ -581,27 +581,130 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub task.getDisplayArea().setLaunchAdjacentFlagRootTask(clearRoot ? null : task); break; } case HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS: case HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS: { effects |= setAdjacentRootsHierarchyOp(hop); break; } // The following operations may change task order so they are skipped while in lock task // mode. The above operations are still allowed because they don't move tasks. And it may // be necessary such as clearing launch root after entering lock task mode. case HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT: { final TaskFragmentCreationParams taskFragmentCreationOptions = hop.getTaskFragmentCreationOptions(); createTaskFragment(taskFragmentCreationOptions, errorCallbackToken); break; } case HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT: { final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer()); if (wc == null || !wc.isAttached()) { Slog.e(TAG, "Attempt to operate on unknown or detached container: " + wc); break; } final TaskFragment taskFragment = wc.asTaskFragment(); if (taskFragment == null || taskFragment.asTask() != null) { throw new IllegalArgumentException( "Can only delete organized TaskFragment, but not Task."); } if (isInLockTaskMode) { final ActivityRecord bottomActivity = taskFragment.getActivity( a -> !a.finishing, false /* traverseTopToBottom */); if (bottomActivity != null && mService.getLockTaskController().activityBlockedFromFinish( bottomActivity)) { Slog.w(TAG, "Skip removing TaskFragment due in lock task mode."); sendTaskFragmentOperationFailure(organizer, errorCallbackToken, new IllegalStateException( "Not allow to delete task fragment in lock task mode.")); break; } } effects |= deleteTaskFragment(taskFragment, errorCallbackToken); break; } case HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT: { final IBinder fragmentToken = hop.getContainer(); if (!mLaunchTaskFragments.containsKey(fragmentToken)) { final Throwable exception = new IllegalArgumentException( "Not allowed to operate with invalid fragment token"); sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); break; } final Intent activityIntent = hop.getActivityIntent(); final Bundle activityOptions = hop.getLaunchOptions(); final TaskFragment tf = mLaunchTaskFragments.get(fragmentToken); final int result = mService.getActivityStartController() .startActivityInTaskFragment(tf, activityIntent, activityOptions, hop.getCallingActivity()); if (!isStartResultSuccessful(result)) { sendTaskFragmentOperationFailure(tf.getTaskFragmentOrganizer(), errorCallbackToken, convertStartFailureToThrowable(result, activityIntent)); } break; } case HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT: { final IBinder fragmentToken = hop.getNewParent(); final ActivityRecord activity = ActivityRecord.forTokenLocked(hop.getContainer()); if (!mLaunchTaskFragments.containsKey(fragmentToken) || activity == null) { final Throwable exception = new IllegalArgumentException( "Not allowed to operate with invalid fragment token or activity."); sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); break; } activity.reparent(mLaunchTaskFragments.get(fragmentToken), POSITION_TOP); effects |= TRANSACT_EFFECTS_LIFECYCLE; break; } case HIERARCHY_OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS: { final IBinder fragmentToken = hop.getContainer(); final IBinder adjacentFragmentToken = hop.getAdjacentRoot(); final TaskFragment tf1 = mLaunchTaskFragments.get(fragmentToken); final TaskFragment tf2 = adjacentFragmentToken != null ? mLaunchTaskFragments.get(adjacentFragmentToken) : null; if (tf1 == null || (adjacentFragmentToken != null && tf2 == null)) { final Throwable exception = new IllegalArgumentException( "Not allowed to set adjacent on invalid fragment tokens"); sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); break; } tf1.setAdjacentTaskFragment(tf2); effects |= TRANSACT_EFFECTS_LIFECYCLE; final Bundle bundle = hop.getLaunchOptions(); final WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams = bundle != null ? new WindowContainerTransaction.TaskFragmentAdjacentParams( bundle) : null; if (adjacentParams == null) { break; } tf1.setDelayLastActivityRemoval( adjacentParams.shouldDelayPrimaryLastActivityRemoval()); if (tf2 != null) { tf2.setDelayLastActivityRemoval( adjacentParams.shouldDelaySecondaryLastActivityRemoval()); } break; } default: { // The other operations may change task order so they are skipped while in lock // task mode. The above operations are still allowed because they don't move // tasks. And it may be necessary such as clearing launch root after entering // lock task mode. if (isInLockTaskMode) { Slog.w(TAG, "Skip applying hierarchy operation " + hop + " while in lock task mode"); Slog.w(TAG, "Skip applying hierarchy operation " + hop + " while in lock task mode"); return effects; } } } final WindowContainer wc; final IBinder fragmentToken; switch (type) { case HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT: case HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT: { effects |= reparentChildrenTasksHierarchyOp(hop, transition, syncId); break; } case HIERARCHY_OP_TYPE_REORDER: case HIERARCHY_OP_TYPE_REPARENT: wc = WindowContainer.fromBinder(hop.getContainer()); case HIERARCHY_OP_TYPE_REPARENT: { final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer()); if (wc == null || !wc.isAttached()) { Slog.e(TAG, "Attempt to operate on detached container: " + wc); break; Loading Loading @@ -630,7 +733,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } effects |= sanitizeAndApplyHierarchyOp(wc, hop); break; case HIERARCHY_OP_TYPE_LAUNCH_TASK: } case HIERARCHY_OP_TYPE_LAUNCH_TASK: { mService.mAmInternal.enforceCallingPermission(START_TASKS_FROM_RECENTS, "launchTask HierarchyOp"); final Bundle launchOpts = hop.getLaunchOptions(); Loading Loading @@ -660,7 +764,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } } break; case HIERARCHY_OP_TYPE_PENDING_INTENT: } case HIERARCHY_OP_TYPE_PENDING_INTENT: { String resolvedType = hop.getActivityIntent() != null ? hop.getActivityIntent().resolveTypeIfNeeded( mService.mContext.getContentResolver()) Loading @@ -683,57 +788,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub hop.getActivityIntent(), resolvedType, null /* finishReceiver */, null /* requiredPermission */, options); break; case HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT: final TaskFragmentCreationParams taskFragmentCreationOptions = hop.getTaskFragmentCreationOptions(); createTaskFragment(taskFragmentCreationOptions, errorCallbackToken); break; case HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT: wc = WindowContainer.fromBinder(hop.getContainer()); if (wc == null || !wc.isAttached()) { Slog.e(TAG, "Attempt to operate on unknown or detached container: " + wc); break; } final TaskFragment taskFragment = wc.asTaskFragment(); if (taskFragment == null || taskFragment.asTask() != null) { throw new IllegalArgumentException( "Can only delete organized TaskFragment, but not Task."); } effects |= deleteTaskFragment(taskFragment, errorCallbackToken); break; case HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT: fragmentToken = hop.getContainer(); if (!mLaunchTaskFragments.containsKey(fragmentToken)) { final Throwable exception = new IllegalArgumentException( "Not allowed to operate with invalid fragment token"); sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); break; } final Intent activityIntent = hop.getActivityIntent(); final Bundle activityOptions = hop.getLaunchOptions(); final TaskFragment tf = mLaunchTaskFragments.get(fragmentToken); final int result = mService.getActivityStartController() .startActivityInTaskFragment(tf, activityIntent, activityOptions, hop.getCallingActivity()); if (!isStartResultSuccessful(result)) { sendTaskFragmentOperationFailure(tf.getTaskFragmentOrganizer(), errorCallbackToken, convertStartFailureToThrowable(result, activityIntent)); } break; case HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT: fragmentToken = hop.getNewParent(); final ActivityRecord activity = ActivityRecord.forTokenLocked(hop.getContainer()); if (!mLaunchTaskFragments.containsKey(fragmentToken) || activity == null) { final Throwable exception = new IllegalArgumentException( "Not allowed to operate with invalid fragment token or activity."); sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); break; } activity.reparent(mLaunchTaskFragments.get(fragmentToken), POSITION_TOP); effects |= TRANSACT_EFFECTS_LIFECYCLE; break; case HIERARCHY_OP_TYPE_REPARENT_CHILDREN: case HIERARCHY_OP_TYPE_REPARENT_CHILDREN: { final WindowContainer oldParent = WindowContainer.fromBinder(hop.getContainer()); final WindowContainer newParent = hop.getNewParent() != null ? WindowContainer.fromBinder(hop.getNewParent()) Loading @@ -746,37 +802,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub reparentTaskFragment(oldParent, newParent, errorCallbackToken); effects |= TRANSACT_EFFECTS_LIFECYCLE; break; case HIERARCHY_OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS: fragmentToken = hop.getContainer(); final IBinder adjacentFragmentToken = hop.getAdjacentRoot(); final TaskFragment tf1 = mLaunchTaskFragments.get(fragmentToken); final TaskFragment tf2 = adjacentFragmentToken != null ? mLaunchTaskFragments.get(adjacentFragmentToken) : null; if (tf1 == null || (adjacentFragmentToken != null && tf2 == null)) { final Throwable exception = new IllegalArgumentException( "Not allowed to set adjacent on invalid fragment tokens"); sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); break; } tf1.setAdjacentTaskFragment(tf2); effects |= TRANSACT_EFFECTS_LIFECYCLE; final Bundle bundle = hop.getLaunchOptions(); final WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams = bundle != null ? new WindowContainerTransaction.TaskFragmentAdjacentParams( bundle) : null; if (adjacentParams == null) { break; } tf1.setDelayLastActivityRemoval( adjacentParams.shouldDelayPrimaryLastActivityRemoval()); if (tf2 != null) { tf2.setDelayLastActivityRemoval( adjacentParams.shouldDelaySecondaryLastActivityRemoval()); } break; } return effects; } Loading