diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 003268b33cdc0..602e4160a679c 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -1935,6 +1935,14 @@ class ActivityStarter { } else if (mSourceRecord != null) { return mSourceRecord.getTask(); } else if (mInTask != null) { + // The task is specified from AppTaskImpl, so it may not be attached yet. + if (!mInTask.isAttached()) { + // Clear reuse task so it can find a proper parent to add the task. + if (mReuseTask == mInTask) { + mReuseTask = null; + } + return getOrCreateRootTask(mStartActivity, mLaunchFlags, mInTask, mOptions); + } return mInTask; } else { final Task rootTask = getOrCreateRootTask(mStartActivity, mLaunchFlags, null /* task */, diff --git a/services/core/java/com/android/server/wm/AppTaskImpl.java b/services/core/java/com/android/server/wm/AppTaskImpl.java index 22a2c41ca5f32..6e46fa6b67d0d 100644 --- a/services/core/java/com/android/server/wm/AppTaskImpl.java +++ b/services/core/java/com/android/server/wm/AppTaskImpl.java @@ -26,6 +26,8 @@ import android.content.Intent; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; +import android.os.Parcel; +import android.os.RemoteException; import android.os.UserHandle; /** @@ -53,6 +55,16 @@ class AppTaskImpl extends IAppTask.Stub { } } + @Override + public boolean onTransact(int code, Parcel data, Parcel reply, int flags) + throws RemoteException { + try { + return super.onTransact(code, data, reply, flags); + } catch (RuntimeException e) { + throw ActivityTaskManagerService.logAndRethrowRuntimeExceptionOnTransact(TAG, e); + } + } + @Override public void finishAndRemoveTask() { checkCaller(); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java index 9902e83c3648d..908de34352c99 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -1139,18 +1139,8 @@ public class ActivityStarterTests extends WindowTestsBase { true /* createdByOrganizer */); sourceRecord.getTask().addChild(taskFragment, POSITION_TOP); - starter.startActivityInner( - /* r */targetRecord, - /* sourceRecord */ sourceRecord, - /* voiceSession */null, - /* voiceInteractor */ null, - /* startFlags */ 0, - /* doResume */true, - /* options */null, - /* inTask */null, - /* inTaskFragment */ taskFragment, - /* restrictedBgActivity */false, - /* intentGrants */null); + startActivityInner(starter, targetRecord, sourceRecord, null /* options */, + null /* inTask */, taskFragment); assertFalse(taskFragment.hasChild()); } @@ -1167,18 +1157,8 @@ public class ActivityStarterTests extends WindowTestsBase { taskFragment.setTaskFragmentOrganizer(mock(TaskFragmentOrganizerToken.class), SYSTEM_UID, "system_uid"); - starter.startActivityInner( - /* r */targetRecord, - /* sourceRecord */ sourceRecord, - /* voiceSession */null, - /* voiceInteractor */ null, - /* startFlags */ 0, - /* doResume */true, - /* options */null, - /* inTask */null, - /* inTaskFragment */ taskFragment, - /* restrictedBgActivity */false, - /* intentGrants */null); + startActivityInner(starter, targetRecord, sourceRecord, null /* options */, + null /* inTask */, taskFragment); assertTrue(taskFragment.hasChild()); } @@ -1195,18 +1175,8 @@ public class ActivityStarterTests extends WindowTestsBase { taskFragment.setTaskFragmentOrganizer(mock(TaskFragmentOrganizerToken.class), targetRecord.getUid(), "test_process_name"); - starter.startActivityInner( - /* r */targetRecord, - /* sourceRecord */ sourceRecord, - /* voiceSession */null, - /* voiceInteractor */ null, - /* startFlags */ 0, - /* doResume */true, - /* options */null, - /* inTask */null, - /* inTaskFragment */ taskFragment, - /* restrictedBgActivity */false, - /* intentGrants */null); + startActivityInner(starter, targetRecord, sourceRecord, null /* options */, + null /* inTask */, taskFragment); assertTrue(taskFragment.hasChild()); } @@ -1231,18 +1201,8 @@ public class ActivityStarterTests extends WindowTestsBase { doReturn(true).when(signingDetails).hasAncestorOrSelfWithDigest(any()); doReturn(signingDetails).when(androidPackage).getSigningDetails(); - starter.startActivityInner( - /* r */targetRecord, - /* sourceRecord */ sourceRecord, - /* voiceSession */null, - /* voiceInteractor */ null, - /* startFlags */ 0, - /* doResume */true, - /* options */null, - /* inTask */null, - /* inTaskFragment */ taskFragment, - /* restrictedBgActivity */false, - /* intentGrants */null); + startActivityInner(starter, targetRecord, sourceRecord, null /* options */, + null /* inTask */, taskFragment); assertTrue(taskFragment.hasChild()); } @@ -1258,22 +1218,29 @@ public class ActivityStarterTests extends WindowTestsBase { targetRecord.info.flags |= ActivityInfo.FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING; - starter.startActivityInner( - /* r */targetRecord, - /* sourceRecord */ sourceRecord, - /* voiceSession */null, - /* voiceInteractor */ null, - /* startFlags */ 0, - /* doResume */true, - /* options */null, - /* inTask */null, - /* inTaskFragment */ taskFragment, - /* restrictedBgActivity */false, - /* intentGrants */null); + startActivityInner(starter, targetRecord, sourceRecord, null /* options */, + null /* inTask */, taskFragment); assertTrue(taskFragment.hasChild()); } + @Test + public void testStartActivityInner_inTask() { + final ActivityStarter starter = prepareStarter(0, false); + // Simulate an app uses AppTask to create a non-attached task, and then it requests to + // start activity in the task. + final Task inTask = new TaskBuilder(mSupervisor).setTaskDisplayArea(null).setTaskId(123) + .build(); + inTask.inRecents = true; + assertFalse(inTask.isAttached()); + final ActivityRecord target = new ActivityBuilder(mAtm).build(); + startActivityInner(starter, target, null /* source */, null /* options */, inTask, + null /* inTaskFragment */); + + assertTrue(inTask.isAttached()); + assertEquals(inTask, target.getTask()); + } + @Test public void testLaunchCookie_newAndExistingTask() { final ActivityStarter starter = prepareStarter(0, false); @@ -1322,21 +1289,20 @@ public class ActivityStarterTests extends WindowTestsBase { // Start the target launch-into-pip activity from a source final ActivityRecord sourceRecord = new ActivityBuilder(mAtm).setCreateTask(true).build(); - starter.startActivityInner( - /* r */ targetRecord, - /* sourceRecord */ sourceRecord, - /* voiceSession */ null, - /* voiceInteractor */ null, - /* startFlags */ 0, - /* doResume */ true, - /* options */ opts, - /* inTask */ null, - /* inTaskFragment */ null, - /* restrictedBgActivity */ false, - /* intentGrants */ null); + startActivityInner(starter, targetRecord, sourceRecord, opts, + null /* inTask */, null /* inTaskFragment */); // Verify the ActivityRecord#getLaunchIntoPipHostActivity points to sourceRecord. assertThat(targetRecord.getLaunchIntoPipHostActivity()).isNotNull(); assertEquals(targetRecord.getLaunchIntoPipHostActivity(), sourceRecord); } + + private static void startActivityInner(ActivityStarter starter, ActivityRecord target, + ActivityRecord source, ActivityOptions options, Task inTask, + TaskFragment inTaskFragment) { + starter.startActivityInner(target, source, null /* voiceSession */, + null /* voiceInteractor */, 0 /* startFlags */, true /* doResume */, + options, inTask, inTaskFragment, false /* restrictedBgActivity */, + null /* intentGrants */); + } }