Merge "Do not depend on task activities decrementing with finish." into pi-dev

This commit is contained in:
Bryce Lee
2018-03-08 01:40:13 +00:00
committed by Android (Google) Code Review
5 changed files with 87 additions and 25 deletions

View File

@@ -347,6 +347,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
private final Rect mTmpRect2 = new Rect();
private final ActivityOptions mTmpOptions = ActivityOptions.makeBasic();
/** List for processing through a set of activities */
private final ArrayList<ActivityRecord> mTmpActivities = new ArrayList<>();
/** Run all ActivityStacks through this */
protected final ActivityStackSupervisor mStackSupervisor;
@@ -4405,11 +4408,15 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
"Removing app " + app + " from history with " + i + " entries");
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = activities.get(activityNdx);
--i;
mTmpActivities.clear();
mTmpActivities.addAll(activities);
while (!mTmpActivities.isEmpty()) {
final int targetIndex = mTmpActivities.size() - 1;
final ActivityRecord r = mTmpActivities.remove(targetIndex);
if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
"Record #" + i + " " + r + ": app=" + r.app);
"Record #" + targetIndex + " " + r + ": app=" + r.app);
if (r.app == app) {
if (r.visible) {
hasVisibleActivities = true;
@@ -4827,9 +4834,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
ComponentName homeActivity = null;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
int numActivities = activities.size();
for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
ActivityRecord r = activities.get(activityNdx);
mTmpActivities.clear();
mTmpActivities.addAll(activities);
while (!mTmpActivities.isEmpty()) {
ActivityRecord r = mTmpActivities.remove(0);
final boolean sameComponent =
(r.packageName.equals(packageName) && (filterByClasses == null
|| filterByClasses.contains(r.realActivity.getClassName())))
@@ -4862,12 +4871,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
r.app = null;
}
lastTask = r.getTask();
if (finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop",
true)) {
// r has been deleted from mActivities, accommodate.
--numActivities;
--activityNdx;
}
finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop",
true);
}
}
}

View File

@@ -2002,7 +2002,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
} else if (intent != null) {
sb.append(" I=");
sb.append(intent.getComponent().flattenToShortString());
} else if (affinityIntent != null) {
} else if (affinityIntent != null && affinityIntent.getComponent() != null) {
sb.append(" aI=");
sb.append(affinityIntent.getComponent().flattenToShortString());
} else {

View File

@@ -486,4 +486,45 @@ public class ActivityStackTests extends ActivityTestsBase {
verify(lifecycleManager, times(1)).scheduleTransaction(eq(app.thread),
eq(r.appToken), any(DestroyActivityItem.class));
}
@Test
public void testFinishDisabledPackageActivities() throws Exception {
final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build();
final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask).build();
// Making the second activity a task overlay without an app means it will be removed from
// the task's activities as well once first activity is removed.
secondActivity.mTaskOverlay = true;
secondActivity.app = null;
assertEquals(mTask.mActivities.size(), 2);
mStack.finishDisabledPackageActivitiesLocked(firstActivity.packageName, null,
true /* doit */, true /* evenPersistent */, UserHandle.USER_ALL);
assertTrue(mTask.mActivities.isEmpty());
assertTrue(mStack.getAllTasks().isEmpty());
}
@Test
public void testHandleAppDied() throws Exception {
final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build();
final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask).build();
// Making the first activity a task overlay means it will be removed from the task's
// activities as well once second activity is removed as handleAppDied processes the
// activity list in reverse.
firstActivity.mTaskOverlay = true;
firstActivity.app = null;
// second activity will be immediately removed as it has no state.
secondActivity.haveState = false;
assertEquals(mTask.mActivities.size(), 2);
mStack.handleAppDiedLocked(secondActivity.app);
assertTrue(mTask.mActivities.isEmpty());
assertTrue(mStack.getAllTasks().isEmpty());
}
}

View File

@@ -197,11 +197,6 @@ public class ActivityStarterTests extends ActivityTestsBase {
final ActivityInfo aInfo = containsConditions(preconditions, PRECONDITION_NO_ACTIVITY_INFO)
? null : new ActivityInfo();
if (aInfo != null) {
aInfo.applicationInfo = new ApplicationInfo();
aInfo.applicationInfo.packageName = ActivityBuilder.DEFAULT_PACKAGE;
}
IVoiceInteractionSession voiceSession =
containsConditions(preconditions, PRECONDITION_SOURCE_VOICE_SESSION)
? mock(IVoiceInteractionSession.class) : null;
@@ -210,6 +205,11 @@ public class ActivityStarterTests extends ActivityTestsBase {
final ActivityBuilder builder = new ActivityBuilder(service).setTask(
new TaskBuilder(service.mStackSupervisor).setVoiceSession(voiceSession).build());
if (aInfo != null) {
aInfo.applicationInfo = new ApplicationInfo();
aInfo.applicationInfo.packageName = builder.getDefaultComponentPackageName();
}
// Offset uid by one from {@link ActivityInfo} to simulate different uids.
if (containsConditions(preconditions, PRECONDITION_DIFFERENT_UID)) {
builder.setUid(aInfo.applicationInfo.uid + 1);

View File

@@ -67,6 +67,12 @@ public class ActivityTestsBase {
private final Context mContext = InstrumentationRegistry.getContext();
private HandlerThread mHandlerThread;
// Default package name
static final String DEFAULT_COMPONENT_PACKAGE_NAME = "com.foo";
// Default base activity name
private static final String DEFAULT_COMPONENT_CLASS_NAME = ".BarActivity";
@Before
public void setUp() throws Exception {
if (!sOneTimeSetupDone) {
@@ -106,11 +112,7 @@ public class ActivityTestsBase {
// An id appended to the end of the component name to make it unique
private static int sCurrentActivityId = 0;
// Default package name
static final String DEFAULT_PACKAGE = "com.foo";
// Default base activity name
private static final String DEFAULT_BASE_ACTIVITY_NAME = ".BarActivity";
private final ActivityManagerService mService;
@@ -149,11 +151,15 @@ public class ActivityTestsBase {
return this;
}
String getDefaultComponentPackageName() {
return DEFAULT_COMPONENT_PACKAGE_NAME;
}
ActivityRecord build() {
if (mComponent == null) {
final int id = sCurrentActivityId++;
mComponent = ComponentName.createRelative(DEFAULT_PACKAGE,
DEFAULT_BASE_ACTIVITY_NAME + id);
mComponent = ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME,
DEFAULT_COMPONENT_CLASS_NAME + id);
}
if (mCreateTask) {
@@ -191,6 +197,9 @@ public class ActivityTestsBase {
* Builder for creating new tasks.
*/
protected static class TaskBuilder {
// Default package name
static final String DEFAULT_PACKAGE = "com.bar";
private final ActivityStackSupervisor mSupervisor;
private ComponentName mComponent;
@@ -252,6 +261,11 @@ public class ActivityTestsBase {
aInfo.applicationInfo.packageName = mPackage;
Intent intent = new Intent();
if (mComponent == null) {
mComponent = ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME,
DEFAULT_COMPONENT_CLASS_NAME);
}
intent.setComponent(mComponent);
intent.setFlags(mFlags);
@@ -312,6 +326,8 @@ public class ActivityTestsBase {
doNothing().when(supervisor).ensureActivitiesVisibleLocked(any(), anyInt(), anyBoolean());
// Do not schedule idle timeouts
doNothing().when(supervisor).scheduleIdleTimeoutLocked(any());
// unit test version does not handle launch wake lock
doNothing().when(supervisor).acquireLaunchWakelock();
supervisor.initialize();