Loading services/core/java/com/android/server/wm/ActivityStartController.java +9 −2 Original line number Diff line number Diff line Loading @@ -490,9 +490,16 @@ public class ActivityStartController { return START_SUCCESS; } void startActivityInTaskFragment(@NonNull TaskFragment taskFragment, /** * Starts an activity in the TaskFragment. * @param taskFragment TaskFragment {@link TaskFragment} to start the activity in. * @param activityIntent intent to start the activity. * @param activityOptions ActivityOptions to start the activity with. * @return the start result. */ int startActivityInTaskFragment(@NonNull TaskFragment taskFragment, @NonNull Intent activityIntent, @Nullable Bundle activityOptions) { obtainStarter(activityIntent, "startActivityInTaskFragment") return obtainStarter(activityIntent, "startActivityInTaskFragment") .setActivityOptions(activityOptions) .setInTaskFragment(taskFragment) .setCallingUid(Binder.getCallingUid()) Loading services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java +50 −5 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.wm; import static android.window.TaskFragmentOrganizer.putExceptionInBundle; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER; import static com.android.server.wm.WindowOrganizerController.configurationsAreEqualForOrganizer; Loading @@ -23,6 +25,7 @@ import android.annotation.IntDef; import android.annotation.Nullable; import android.content.res.Configuration; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.util.ArrayMap; Loading Loading @@ -190,6 +193,16 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr Slog.e(TAG, "Exception sending onTaskFragmentParentInfoChanged callback", e); } } void onTaskFragmentError(ITaskFragmentOrganizer organizer, IBinder errorCallbackToken, Throwable exception) { final Bundle exceptionBundle = putExceptionInBundle(exception); try { organizer.onTaskFragmentError(errorCallbackToken, exceptionBundle); } catch (RemoteException e) { Slog.e(TAG, "Exception sending onTaskFragmentError callback", e); } } } @Override Loading Loading @@ -289,6 +302,14 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr state.removeTaskFragment(taskFragment); } void onTaskFragmentError(ITaskFragmentOrganizer organizer, IBinder errorCallbackToken, Throwable exception) { validateAndGetState(organizer); PendingTaskFragmentEvent pendingEvent = new PendingTaskFragmentEvent(organizer, errorCallbackToken, exception, PendingTaskFragmentEvent.EVENT_ERROR); mPendingTaskFragmentEvents.add(pendingEvent); } private void removeOrganizer(ITaskFragmentOrganizer organizer) { final TaskFragmentOrganizerState state = validateAndGetState(organizer); // remove all of the children of the organized TaskFragment Loading Loading @@ -321,25 +342,45 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr static final int EVENT_VANISHED = 1; static final int EVENT_INFO_CHANGED = 2; static final int EVENT_PARENT_INFO_CHANGED = 3; static final int EVENT_ERROR = 4; @IntDef(prefix = "EVENT_", value = { EVENT_APPEARED, EVENT_VANISHED, EVENT_INFO_CHANGED, EVENT_PARENT_INFO_CHANGED EVENT_PARENT_INFO_CHANGED, EVENT_ERROR }) @Retention(RetentionPolicy.SOURCE) public @interface EventType {} @EventType final int mEventType; final TaskFragment mTaskFragment; final ITaskFragmentOrganizer mTaskFragmentOrg; private final int mEventType; private final ITaskFragmentOrganizer mTaskFragmentOrg; private final TaskFragment mTaskFragment; private final IBinder mErrorCallback; private final Throwable mException; private PendingTaskFragmentEvent(TaskFragment taskFragment, ITaskFragmentOrganizer taskFragmentOrg, @EventType int eventType) { this(taskFragment, taskFragmentOrg, null /* errorCallback */, null /* exception */, eventType); } private PendingTaskFragmentEvent(ITaskFragmentOrganizer taskFragmentOrg, IBinder errorCallback, Throwable exception, @EventType int eventType) { this(null /* taskFragment */, taskFragmentOrg, errorCallback, exception, eventType); } PendingTaskFragmentEvent(TaskFragment taskFragment, ITaskFragmentOrganizer taskFragmentOrg, private PendingTaskFragmentEvent(TaskFragment taskFragment, ITaskFragmentOrganizer taskFragmentOrg, IBinder errorCallback, Throwable exception, @EventType int eventType) { mTaskFragment = taskFragment; mTaskFragmentOrg = taskFragmentOrg; mErrorCallback = errorCallback; mException = exception; mEventType = eventType; } Loading Loading @@ -407,6 +448,10 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr break; case PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED: state.onTaskFragmentParentInfoChanged(taskFragmentOrg, taskFragment); break; case PendingTaskFragmentEvent.EVENT_ERROR: state.onTaskFragmentError(taskFragmentOrg, event.mErrorCallback, event.mException); } } mPendingTaskFragmentEvents.clear(); Loading services/core/java/com/android/server/wm/WindowOrganizerController.java +57 −20 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.wm; import static android.Manifest.permission.START_TASKS_FROM_RECENTS; import static android.app.ActivityManager.isStartResultSuccessful; import static android.view.Display.DEFAULT_DISPLAY; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT; Loading Loading @@ -44,6 +45,7 @@ import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.WindowConfiguration; import android.content.ActivityNotFoundException; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.res.Configuration; Loading Loading @@ -369,7 +371,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub final boolean isInLockTaskMode = mService.isInLockTaskMode(); for (int i = 0; i < hopSize; ++i) { effects |= applyHierarchyOp(hops.get(i), effects, syncId, transition, isInLockTaskMode, caller); isInLockTaskMode, caller, t.getErrorCallbackToken(), t.getTaskFragmentOrganizer()); } } // Queue-up bounds-change transactions for tasks which are now organized. Do Loading Loading @@ -525,7 +528,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub private int applyHierarchyOp(WindowContainerTransaction.HierarchyOp hop, int effects, int syncId, @Nullable Transition transition, boolean isInLockTaskMode, @Nullable CallerInfo caller) { @Nullable CallerInfo caller, @Nullable IBinder errorCallbackToken, @Nullable ITaskFragmentOrganizer organizer) { final int type = hop.getType(); switch (type) { case HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT: { Loading Loading @@ -652,7 +656,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub case HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT: final TaskFragmentCreationParams taskFragmentCreationOptions = hop.getTaskFragmentCreationOptions(); createTaskFragment(taskFragmentCreationOptions); createTaskFragment(taskFragmentCreationOptions, errorCallbackToken); break; case HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT: wc = WindowContainer.fromBinder(hop.getContainer()); Loading @@ -665,28 +669,36 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub throw new IllegalArgumentException( "Can only delete organized TaskFragment, but not Task."); } deleteTaskFragment(taskFragment); deleteTaskFragment(taskFragment, errorCallbackToken); break; case HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT: fragmentToken = hop.getContainer(); if (!mLaunchTaskFragments.containsKey(fragmentToken)) { throw new IllegalArgumentException( 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(); mService.getActivityStartController() .startActivityInTaskFragment(mLaunchTaskFragments.get(fragmentToken), activityIntent, activityOptions); // TODO(b/189385246) : report the failure back to the organizer if the activity // start failed final TaskFragment tf = mLaunchTaskFragments.get(fragmentToken); final int result = mService.getActivityStartController() .startActivityInTaskFragment(tf, activityIntent, activityOptions); if (!isStartResultSuccessful(result)) { final Throwable exception = new ActivityNotFoundException("start activity in taskFragment failed"); sendTaskFragmentOperationFailure(tf.getTaskFragmentOrganizer(), errorCallbackToken, exception); } 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) { throw new IllegalArgumentException( 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); break; Loading @@ -700,7 +712,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub + oldParent); break; } reparentTaskFragment(oldParent, newParent); reparentTaskFragment(oldParent, newParent, errorCallbackToken); break; } return effects; Loading Loading @@ -1076,17 +1088,25 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } } void createTaskFragment(@NonNull TaskFragmentCreationParams creationParams) { void createTaskFragment(@NonNull TaskFragmentCreationParams creationParams, @Nullable IBinder errorCallbackToken) { final ActivityRecord ownerActivity = ActivityRecord.forTokenLocked(creationParams.getOwnerToken()); if (ownerActivity == null || ownerActivity.getTask() == null) { // TODO(b/189385246) : report the failure back to the organizer final Throwable exception = new IllegalArgumentException("Not allowed to operate with invalid ownerToken"); sendTaskFragmentOperationFailure(creationParams.getOrganizer(), errorCallbackToken, exception); return; } // The ownerActivity has to belong to the same app as the root Activity of the target Task. final ActivityRecord rootActivity = ownerActivity.getTask().getRootActivity(); if (rootActivity.getUid() != ownerActivity.getUid()) { // TODO(b/189385246) : report the failure back to the organizer final Throwable exception = new IllegalArgumentException("Not allowed to operate with the ownerToken while " + "the root activity of the target task belong to the different app"); sendTaskFragmentOperationFailure(creationParams.getOrganizer(), errorCallbackToken, exception); return; } final TaskFragment taskFragment = new TaskFragment(mService, Loading @@ -1102,13 +1122,16 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } void reparentTaskFragment(@NonNull WindowContainer oldParent, @Nullable WindowContainer newParent) { @Nullable WindowContainer newParent, @Nullable IBinder errorCallbackToken) { WindowContainer parent = newParent; if (parent == null && oldParent.asTaskFragment() != null) { parent = oldParent.asTaskFragment().getTask(); } if (parent == null) { // TODO(b/189385246) : report the failure back to the organizer final Throwable exception = new IllegalArgumentException("Not allowed to operate with invalid container"); sendTaskFragmentOperationFailure(oldParent.asTaskFragment().getTaskFragmentOrganizer(), errorCallbackToken, exception); return; } while (oldParent.hasChild()) { Loading @@ -1116,11 +1139,16 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } } void deleteTaskFragment(@NonNull TaskFragment taskFragment) { void deleteTaskFragment(@NonNull TaskFragment taskFragment, @Nullable IBinder errorCallbackToken) { final int index = mLaunchTaskFragments.indexOfValue(taskFragment); if (index < 0) { throw new IllegalArgumentException( "Not allowed to operate with invalid taskFragment"); final Throwable exception = new IllegalArgumentException("Not allowed to operate with invalid " + "taskFragment"); sendTaskFragmentOperationFailure(taskFragment.getTaskFragmentOrganizer(), errorCallbackToken, exception); return; } mLaunchTaskFragments.removeAt(index); taskFragment.removeImmediately(); Loading @@ -1135,4 +1163,13 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub mUid = Binder.getCallingUid(); } } void sendTaskFragmentOperationFailure(@NonNull ITaskFragmentOrganizer organizer, @Nullable IBinder errorCallbackToken, @NonNull Throwable exception) { if (organizer == null) { throw new IllegalArgumentException("Not allowed to operate with invalid organizer"); } mService.mTaskFragmentOrganizerController .onTaskFragmentError(organizer, errorCallbackToken, exception); } } services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java +4 −5 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.server.wm; import static android.window.TaskFragmentOrganizer.putExceptionInBundle; 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.testing.Assert.assertThrows; Loading @@ -35,7 +33,6 @@ import android.content.Intent; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; Loading Loading @@ -198,9 +195,11 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { public void testOnTaskFragmentError() throws RemoteException { final IBinder errorCallbackToken = new Binder(); final Throwable exception = new IllegalArgumentException("Test exception"); final Bundle exceptionBundle = putExceptionInBundle(exception); mIOrganizer.onTaskFragmentError(errorCallbackToken, exceptionBundle); mController.registerOrganizer(mIOrganizer); mController.onTaskFragmentError(mTaskFragment.getTaskFragmentOrganizer(), errorCallbackToken, exception); mController.dispatchPendingEvents(); verify(mOrganizer).onTaskFragmentError(eq(errorCallbackToken), eq(exception)); } Loading Loading
services/core/java/com/android/server/wm/ActivityStartController.java +9 −2 Original line number Diff line number Diff line Loading @@ -490,9 +490,16 @@ public class ActivityStartController { return START_SUCCESS; } void startActivityInTaskFragment(@NonNull TaskFragment taskFragment, /** * Starts an activity in the TaskFragment. * @param taskFragment TaskFragment {@link TaskFragment} to start the activity in. * @param activityIntent intent to start the activity. * @param activityOptions ActivityOptions to start the activity with. * @return the start result. */ int startActivityInTaskFragment(@NonNull TaskFragment taskFragment, @NonNull Intent activityIntent, @Nullable Bundle activityOptions) { obtainStarter(activityIntent, "startActivityInTaskFragment") return obtainStarter(activityIntent, "startActivityInTaskFragment") .setActivityOptions(activityOptions) .setInTaskFragment(taskFragment) .setCallingUid(Binder.getCallingUid()) Loading
services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java +50 −5 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.wm; import static android.window.TaskFragmentOrganizer.putExceptionInBundle; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER; import static com.android.server.wm.WindowOrganizerController.configurationsAreEqualForOrganizer; Loading @@ -23,6 +25,7 @@ import android.annotation.IntDef; import android.annotation.Nullable; import android.content.res.Configuration; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.util.ArrayMap; Loading Loading @@ -190,6 +193,16 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr Slog.e(TAG, "Exception sending onTaskFragmentParentInfoChanged callback", e); } } void onTaskFragmentError(ITaskFragmentOrganizer organizer, IBinder errorCallbackToken, Throwable exception) { final Bundle exceptionBundle = putExceptionInBundle(exception); try { organizer.onTaskFragmentError(errorCallbackToken, exceptionBundle); } catch (RemoteException e) { Slog.e(TAG, "Exception sending onTaskFragmentError callback", e); } } } @Override Loading Loading @@ -289,6 +302,14 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr state.removeTaskFragment(taskFragment); } void onTaskFragmentError(ITaskFragmentOrganizer organizer, IBinder errorCallbackToken, Throwable exception) { validateAndGetState(organizer); PendingTaskFragmentEvent pendingEvent = new PendingTaskFragmentEvent(organizer, errorCallbackToken, exception, PendingTaskFragmentEvent.EVENT_ERROR); mPendingTaskFragmentEvents.add(pendingEvent); } private void removeOrganizer(ITaskFragmentOrganizer organizer) { final TaskFragmentOrganizerState state = validateAndGetState(organizer); // remove all of the children of the organized TaskFragment Loading Loading @@ -321,25 +342,45 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr static final int EVENT_VANISHED = 1; static final int EVENT_INFO_CHANGED = 2; static final int EVENT_PARENT_INFO_CHANGED = 3; static final int EVENT_ERROR = 4; @IntDef(prefix = "EVENT_", value = { EVENT_APPEARED, EVENT_VANISHED, EVENT_INFO_CHANGED, EVENT_PARENT_INFO_CHANGED EVENT_PARENT_INFO_CHANGED, EVENT_ERROR }) @Retention(RetentionPolicy.SOURCE) public @interface EventType {} @EventType final int mEventType; final TaskFragment mTaskFragment; final ITaskFragmentOrganizer mTaskFragmentOrg; private final int mEventType; private final ITaskFragmentOrganizer mTaskFragmentOrg; private final TaskFragment mTaskFragment; private final IBinder mErrorCallback; private final Throwable mException; private PendingTaskFragmentEvent(TaskFragment taskFragment, ITaskFragmentOrganizer taskFragmentOrg, @EventType int eventType) { this(taskFragment, taskFragmentOrg, null /* errorCallback */, null /* exception */, eventType); } private PendingTaskFragmentEvent(ITaskFragmentOrganizer taskFragmentOrg, IBinder errorCallback, Throwable exception, @EventType int eventType) { this(null /* taskFragment */, taskFragmentOrg, errorCallback, exception, eventType); } PendingTaskFragmentEvent(TaskFragment taskFragment, ITaskFragmentOrganizer taskFragmentOrg, private PendingTaskFragmentEvent(TaskFragment taskFragment, ITaskFragmentOrganizer taskFragmentOrg, IBinder errorCallback, Throwable exception, @EventType int eventType) { mTaskFragment = taskFragment; mTaskFragmentOrg = taskFragmentOrg; mErrorCallback = errorCallback; mException = exception; mEventType = eventType; } Loading Loading @@ -407,6 +448,10 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr break; case PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED: state.onTaskFragmentParentInfoChanged(taskFragmentOrg, taskFragment); break; case PendingTaskFragmentEvent.EVENT_ERROR: state.onTaskFragmentError(taskFragmentOrg, event.mErrorCallback, event.mException); } } mPendingTaskFragmentEvents.clear(); Loading
services/core/java/com/android/server/wm/WindowOrganizerController.java +57 −20 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.wm; import static android.Manifest.permission.START_TASKS_FROM_RECENTS; import static android.app.ActivityManager.isStartResultSuccessful; import static android.view.Display.DEFAULT_DISPLAY; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT; Loading Loading @@ -44,6 +45,7 @@ import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.WindowConfiguration; import android.content.ActivityNotFoundException; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.res.Configuration; Loading Loading @@ -369,7 +371,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub final boolean isInLockTaskMode = mService.isInLockTaskMode(); for (int i = 0; i < hopSize; ++i) { effects |= applyHierarchyOp(hops.get(i), effects, syncId, transition, isInLockTaskMode, caller); isInLockTaskMode, caller, t.getErrorCallbackToken(), t.getTaskFragmentOrganizer()); } } // Queue-up bounds-change transactions for tasks which are now organized. Do Loading Loading @@ -525,7 +528,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub private int applyHierarchyOp(WindowContainerTransaction.HierarchyOp hop, int effects, int syncId, @Nullable Transition transition, boolean isInLockTaskMode, @Nullable CallerInfo caller) { @Nullable CallerInfo caller, @Nullable IBinder errorCallbackToken, @Nullable ITaskFragmentOrganizer organizer) { final int type = hop.getType(); switch (type) { case HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT: { Loading Loading @@ -652,7 +656,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub case HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT: final TaskFragmentCreationParams taskFragmentCreationOptions = hop.getTaskFragmentCreationOptions(); createTaskFragment(taskFragmentCreationOptions); createTaskFragment(taskFragmentCreationOptions, errorCallbackToken); break; case HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT: wc = WindowContainer.fromBinder(hop.getContainer()); Loading @@ -665,28 +669,36 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub throw new IllegalArgumentException( "Can only delete organized TaskFragment, but not Task."); } deleteTaskFragment(taskFragment); deleteTaskFragment(taskFragment, errorCallbackToken); break; case HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT: fragmentToken = hop.getContainer(); if (!mLaunchTaskFragments.containsKey(fragmentToken)) { throw new IllegalArgumentException( 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(); mService.getActivityStartController() .startActivityInTaskFragment(mLaunchTaskFragments.get(fragmentToken), activityIntent, activityOptions); // TODO(b/189385246) : report the failure back to the organizer if the activity // start failed final TaskFragment tf = mLaunchTaskFragments.get(fragmentToken); final int result = mService.getActivityStartController() .startActivityInTaskFragment(tf, activityIntent, activityOptions); if (!isStartResultSuccessful(result)) { final Throwable exception = new ActivityNotFoundException("start activity in taskFragment failed"); sendTaskFragmentOperationFailure(tf.getTaskFragmentOrganizer(), errorCallbackToken, exception); } 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) { throw new IllegalArgumentException( 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); break; Loading @@ -700,7 +712,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub + oldParent); break; } reparentTaskFragment(oldParent, newParent); reparentTaskFragment(oldParent, newParent, errorCallbackToken); break; } return effects; Loading Loading @@ -1076,17 +1088,25 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } } void createTaskFragment(@NonNull TaskFragmentCreationParams creationParams) { void createTaskFragment(@NonNull TaskFragmentCreationParams creationParams, @Nullable IBinder errorCallbackToken) { final ActivityRecord ownerActivity = ActivityRecord.forTokenLocked(creationParams.getOwnerToken()); if (ownerActivity == null || ownerActivity.getTask() == null) { // TODO(b/189385246) : report the failure back to the organizer final Throwable exception = new IllegalArgumentException("Not allowed to operate with invalid ownerToken"); sendTaskFragmentOperationFailure(creationParams.getOrganizer(), errorCallbackToken, exception); return; } // The ownerActivity has to belong to the same app as the root Activity of the target Task. final ActivityRecord rootActivity = ownerActivity.getTask().getRootActivity(); if (rootActivity.getUid() != ownerActivity.getUid()) { // TODO(b/189385246) : report the failure back to the organizer final Throwable exception = new IllegalArgumentException("Not allowed to operate with the ownerToken while " + "the root activity of the target task belong to the different app"); sendTaskFragmentOperationFailure(creationParams.getOrganizer(), errorCallbackToken, exception); return; } final TaskFragment taskFragment = new TaskFragment(mService, Loading @@ -1102,13 +1122,16 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } void reparentTaskFragment(@NonNull WindowContainer oldParent, @Nullable WindowContainer newParent) { @Nullable WindowContainer newParent, @Nullable IBinder errorCallbackToken) { WindowContainer parent = newParent; if (parent == null && oldParent.asTaskFragment() != null) { parent = oldParent.asTaskFragment().getTask(); } if (parent == null) { // TODO(b/189385246) : report the failure back to the organizer final Throwable exception = new IllegalArgumentException("Not allowed to operate with invalid container"); sendTaskFragmentOperationFailure(oldParent.asTaskFragment().getTaskFragmentOrganizer(), errorCallbackToken, exception); return; } while (oldParent.hasChild()) { Loading @@ -1116,11 +1139,16 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } } void deleteTaskFragment(@NonNull TaskFragment taskFragment) { void deleteTaskFragment(@NonNull TaskFragment taskFragment, @Nullable IBinder errorCallbackToken) { final int index = mLaunchTaskFragments.indexOfValue(taskFragment); if (index < 0) { throw new IllegalArgumentException( "Not allowed to operate with invalid taskFragment"); final Throwable exception = new IllegalArgumentException("Not allowed to operate with invalid " + "taskFragment"); sendTaskFragmentOperationFailure(taskFragment.getTaskFragmentOrganizer(), errorCallbackToken, exception); return; } mLaunchTaskFragments.removeAt(index); taskFragment.removeImmediately(); Loading @@ -1135,4 +1163,13 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub mUid = Binder.getCallingUid(); } } void sendTaskFragmentOperationFailure(@NonNull ITaskFragmentOrganizer organizer, @Nullable IBinder errorCallbackToken, @NonNull Throwable exception) { if (organizer == null) { throw new IllegalArgumentException("Not allowed to operate with invalid organizer"); } mService.mTaskFragmentOrganizerController .onTaskFragmentError(organizer, errorCallbackToken, exception); } }
services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java +4 −5 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.server.wm; import static android.window.TaskFragmentOrganizer.putExceptionInBundle; 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.testing.Assert.assertThrows; Loading @@ -35,7 +33,6 @@ import android.content.Intent; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; Loading Loading @@ -198,9 +195,11 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { public void testOnTaskFragmentError() throws RemoteException { final IBinder errorCallbackToken = new Binder(); final Throwable exception = new IllegalArgumentException("Test exception"); final Bundle exceptionBundle = putExceptionInBundle(exception); mIOrganizer.onTaskFragmentError(errorCallbackToken, exceptionBundle); mController.registerOrganizer(mIOrganizer); mController.onTaskFragmentError(mTaskFragment.getTaskFragmentOrganizer(), errorCallbackToken, exception); mController.dispatchPendingEvents(); verify(mOrganizer).onTaskFragmentError(eq(errorCallbackToken), eq(exception)); } Loading