diff options
| author | 2018-05-16 21:29:34 -0700 | |
|---|---|---|
| committer | 2018-05-29 22:31:08 -0700 | |
| commit | 09e1afa13f2f93ae0adadac1d45cd0d9900bc4a0 (patch) | |
| tree | c46fa8ef0f6706638e46ab0f13a8ccb46f17e4f0 | |
| parent | 478923bded903aa2e9e0357a61141053df20f590 (diff) | |
Don't pause non-top activities when making visible
Pausing non-top activities may break other lifecycle contracts, such
as onActivityResult() being delivered before onResume().
Bug: 79491318
Test: ActivityLifecycleTests
Change-Id: Idd287a5a85d39cbc849a9e60791b0111a6ab2fe8
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityRecord.java | 43 |
1 files changed, 34 insertions, 9 deletions
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index ef5a5a322aa8..1e2dc0c86520 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -1735,15 +1735,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo mStackSupervisor.mStoppingActivities.remove(this); mStackSupervisor.mGoingToSleepActivities.remove(this); - // If the activity is stopped or stopping, cycle to the paused state. We avoid doing - // this when there is an activity waiting to become translucent as the extra binder - // calls will lead to noticeable jank. A later call to - // ActivityStack#ensureActivitiesVisibleLocked will bring the activity to the proper - // paused state. We also avoid doing this for the activity the stack supervisor - // considers the resumed activity, as normal means will bring the activity from STOPPED - // to RESUMED. Adding PAUSING in this scenario will lead to double lifecycles. - if (isState(STOPPED, STOPPING) && stack.mTranslucentActivityWaiting == null - && mStackSupervisor.getResumedActivityLocked() != this) { + if (shouldPauseWhenBecomingVisible()) { // Capture reason before state change // An activity must be in the {@link PAUSING} state for the system to validate @@ -1760,6 +1752,39 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo handleAlreadyVisible(); } + /** Check if activity should be moved to PAUSED state when it becomes visible. */ + private boolean shouldPauseWhenBecomingVisible() { + // If the activity is stopped or stopping, cycle to the paused state. We avoid doing + // this when there is an activity waiting to become translucent as the extra binder + // calls will lead to noticeable jank. A later call to + // ActivityStack#ensureActivitiesVisibleLocked will bring the activity to the proper + // paused state. We also avoid doing this for the activity the stack supervisor + // considers the resumed activity, as normal means will bring the activity from STOPPED + // to RESUMED. Adding PAUSING in this scenario will lead to double lifecycles. + if (!isState(STOPPED, STOPPING) || getStack().mTranslucentActivityWaiting != null + || mStackSupervisor.getResumedActivityLocked() == this) { + return false; + } + + // Check if position in task allows to become paused + final int positionInTask = task.mActivities.indexOf(this); + if (positionInTask == -1) { + throw new IllegalStateException("Activity not found in its task"); + } + if (positionInTask == task.mActivities.size() - 1) { + // It's the topmost activity in the task - should become paused now + return true; + } + // Check if activity above is finishing now and this one becomes the topmost in task. + final ActivityRecord activityAbove = task.mActivities.get(positionInTask + 1); + if (activityAbove.finishing && results == null) { + // We will only allow pausing if activity above wasn't launched for result. Otherwise it + // will cause this activity to resume before getting result. + return true; + } + return false; + } + boolean handleAlreadyVisible() { stopFreezingScreenLocked(false); try { |