diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 728a3b98e638e..82e2a3deadf1e 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -3301,13 +3301,21 @@ class ActivityStack extends ConfigurationContai final ActivityRecord next = topRunningActivityLocked(); final String myReason = reason + " adjustFocus"; + if (next != r) { if (next != null && StackId.keepFocusInStackIfPossible(mStackId) && isFocusable()) { // For freeform, docked, and pinned stacks we always keep the focus within the // stack as long as there is a running activity. return; } else { + // Task is not guaranteed to be non-null. For example, destroying the + // {@link ActivityRecord} will disassociate the task from the activity. final TaskRecord task = r.getTask(); + + if (task == null) { + throw new IllegalStateException("activity no longer associated with task:" + r); + } + final boolean isAssistantOrOverAssistant = task.getStack().isAssistantStack() || task.isOverAssistantStack(); if (r.frontOfTask && isATopFinishingTask(task) @@ -3373,8 +3381,8 @@ class ActivityStack extends ConfigurationContai if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + r); if (requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, "stop-no-history", false)) { - // Activity was finished, no need to continue trying to schedule stop. - adjustFocusedActivityStackLocked(r, "stopActivityFinished"); + // If {@link requestFinishActivityLocked} returns {@code true}, + // {@link adjustFocusedActivityStackLocked} would have been already called. r.resumeKeyDispatchingLocked(); return; } diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java index 58166b6c1ac5b..c87eaed5c9542 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import android.content.ComponentName; +import android.content.pm.ActivityInfo; import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -84,4 +85,16 @@ public class ActivityStackTests extends ActivityTestsBase { // Make sure the resumed activity is untouched. assertEquals(testStack.mResumedActivity, activityRecord); } + + @Test + public void testStopActivityWhenActivityDestroyed() throws Exception { + final ActivityManagerService service = createActivityManagerService(); + final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID); + final ActivityRecord activityRecord = createActivity(service, testActivityComponent, task); + activityRecord.info.flags |= ActivityInfo.FLAG_NO_HISTORY; + final ActivityStack testStack = service.mStackSupervisor.getStack(TEST_STACK_ID); + service.mStackSupervisor.setFocusStackUnchecked("testStopActivityWithDestroy", testStack); + + testStack.stopActivityLocked(activityRecord); + } } diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java index 0827084420329..3fc2c1246c596 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java @@ -161,6 +161,11 @@ public class ActivityTestsBase { void moveHomeStackToFront(String reason) { } + @Override + boolean moveHomeStackTaskToTop(String reason) { + return true; + } + // Invoked during {@link ActivityStack} creation. @Override void updateUIDsPresentOnDisplay() {