Ensure task will be attached when starting activity from AppTask
ActivityManager#addAppTask can add a non-attached task into recents. And then the caller can use ActivityManager.AppTask#startActivity to launch activity in the task. The specified task will be mInTask, but before putting activity in it, the task must attach to hierarchy, otherwise it may cause NPE on random places by the incomplete launch. Bug: 227634021 Test: atest ActivityStarterTests#testStartActivityInner_inTask Change-Id: I66242e2ffa94be19bad49354b5d9cccded17b25c
This commit is contained in:
@@ -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 */,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 */);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user