summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Andrii Kulian <akulian@google.com> 2018-05-16 21:29:34 -0700
committer Andrii Kulian <akulian@google.com> 2018-05-29 22:31:08 -0700
commit09e1afa13f2f93ae0adadac1d45cd0d9900bc4a0 (patch)
treec46fa8ef0f6706638e46ab0f13a8ccb46f17e4f0
parent478923bded903aa2e9e0357a61141053df20f590 (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.java43
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 {