From 3345c4ea9687bb35a8c419ec21ec90b49616b2c9 Mon Sep 17 00:00:00 2001 From: Bryce Lee Date: Tue, 25 Apr 2017 07:40:41 -0700 Subject: [PATCH] Don't call adjustFocusedActivityStackLocked on finished activity. When an activity is finished, adjustFocusedActivityStackLocked is already called on the associated record and the task association is lost. Calling it again is redundant and leads to a crash as we assume the task is still associated with the activity. Change-Id: Ie7cc9ad8b1542d7415b7409e539c88d3b4ec8dcd Fixes: 37329424 Test: bit FrameworksServicesTests:com.android.server.am.ActivityStackTests#testStopActivityWhenActivityDestroyed --- .../java/com/android/server/am/ActivityStack.java | 12 ++++++++++-- .../com/android/server/am/ActivityStackTests.java | 13 +++++++++++++ .../com/android/server/am/ActivityTestsBase.java | 5 +++++ 3 files changed, 28 insertions(+), 2 deletions(-) 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() {