summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Wale Ogunwale <ogunwale@google.com> 2016-02-12 12:22:19 -0800
committer Wale Ogunwale <ogunwale@google.com> 2016-02-16 10:09:24 -0800
commit5658e4b94de91e938459e50d0f5e6ef837ffb4ac (patch)
treef10a102661e55b6f861a3a11a4a10afbeb62b203
parent5393a6605f0ffd7f5e1e7e080c414096d6b0db2a (diff)
Don't resume activity on start if there are activities pausing.
The path to start an activity if it isn't running was unconditionally resuming the starting activity which we don't do if there are activities pausing. It now starts the activity in a paused state if other activities are pausing. It is then resumed when pause completes. Also, improved logging in BoundsAnimationController and removed some disabled code that has been in the codebase for 6yrs... Bug: 26982752 Change-Id: Ie042fc938331127f1270fca1b5905b067b9dae7c
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java52
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java17
-rw-r--r--services/core/java/com/android/server/wm/BoundsAnimationController.java35
3 files changed, 57 insertions, 47 deletions
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 1103ea4874d2..e36160aa2674 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -25,6 +25,7 @@ import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
+import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
import static android.content.res.Configuration.SCREENLAYOUT_UNDEFINED;
@@ -766,8 +767,8 @@ final class ActivityStack {
void minimalResumeActivityLocked(ActivityRecord r) {
r.state = ActivityState.RESUMED;
- if (DEBUG_STATES) Slog.v(TAG_STATES,
- "Moving to RESUMED: " + r + " (starting new instance)");
+ if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + r + " (starting new instance)"
+ + " callers=" + Debug.getCallers(5));
mResumedActivity = r;
r.task.touchActiveTime();
mRecentTasks.addLocked(r.task);
@@ -1054,6 +1055,7 @@ final class ActivityStack {
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r
+ (timeout ? " (due to timeout)" : " (pause complete)"));
completePauseLocked(true);
+ return;
} else {
EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
r.userId, System.identityHashCode(r), r.shortComponentName,
@@ -1069,6 +1071,7 @@ final class ActivityStack {
}
}
}
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
final void activityStoppedLocked(ActivityRecord r, Bundle icicle,
@@ -1198,12 +1201,13 @@ final class ActivityStack {
prev.cpuTimeAtResume = 0; // reset it
}
- // Notify when the task stack has changed, but only if visibilities changed (not just
- // focus).
+ // Notify when the task stack has changed, but only if visibilities changed (not just focus)
if (mStackSupervisor.mAppVisibilitiesChangedSinceLastPause) {
mService.notifyTaskStackChangedLocked();
mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
}
+
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
private void addToStopping(ActivityRecord r) {
@@ -2005,8 +2009,7 @@ final class ActivityStack {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
- // If we are currently pausing an activity, then don't do anything
- // until that is done.
+ // If we are currently pausing an activity, then don't do anything until that is done.
if (!mStackSupervisor.allPausedActivitiesComplete()) {
if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
"resumeTopActivityLocked: Skip resume: some activity pausing.");
@@ -2014,40 +2017,10 @@ final class ActivityStack {
return false;
}
- // Okay we are now going to start a switch, to 'next'. We may first
- // have to pause the current activity, but this is an important point
- // where we have decided to go to 'next' so keep track of that.
- // XXX "App Redirected" dialog is getting too many false positives
- // at this point, so turn off for now.
- if (false) {
- if (mLastStartedActivity != null && !mLastStartedActivity.finishing) {
- long now = SystemClock.uptimeMillis();
- final boolean inTime = mLastStartedActivity.startTime != 0
- && (mLastStartedActivity.startTime + START_WARN_TIME) >= now;
- final int lastUid = mLastStartedActivity.info.applicationInfo.uid;
- final int nextUid = next.info.applicationInfo.uid;
- if (inTime && lastUid != nextUid
- && lastUid != next.launchedFromUid
- && mService.checkPermission(
- android.Manifest.permission.STOP_APP_SWITCHES,
- -1, next.launchedFromUid)
- != PackageManager.PERMISSION_GRANTED) {
- mService.showLaunchWarningLocked(mLastStartedActivity, next);
- } else {
- next.startTime = now;
- mLastStartedActivity = next;
- }
- } else {
- next.startTime = SystemClock.uptimeMillis();
- mLastStartedActivity = next;
- }
- }
-
mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
- // We need to start pausing the current activity so the top one
- // can be resumed...
- boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
+ // We need to start pausing the current activity so the top one can be resumed...
+ final boolean dontWaitForPause = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
@@ -4425,7 +4398,8 @@ final class ActivityStack {
try {
if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH,
- "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + r);
+ "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + r
+ + " callers=" + Debug.getCallers(6));
r.forceNewConfig = false;
r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents, changes,
!andResume, new Configuration(mService.mConfiguration),
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 93a36eb1d3d8..662c51e659c1 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1065,9 +1065,18 @@ public final class ActivityStackSupervisor implements DisplayListener {
return resolveActivity(intent, rInfo, startFlags, profilerInfo);
}
- final boolean realStartActivityLocked(ActivityRecord r,
- ProcessRecord app, boolean andResume, boolean checkConfig)
- throws RemoteException {
+ final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
+ boolean andResume, boolean checkConfig) throws RemoteException {
+
+ if (!allPausedActivitiesComplete()) {
+ // While there are activities pausing we skipping starting any new activities until
+ // pauses are complete. NOTE: that we also do this for activities that are starting in
+ // the paused state because they will first be resumed then paused on the client side.
+ if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
+ "realStartActivityLocked: Skipping start of r=" + r
+ + " some activities pausing...");
+ return false;
+ }
if (andResume) {
r.startFreezingScreenLocked(app, 0);
@@ -2263,7 +2272,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
boolean kept = true;
try {
final ActivityStack stack = moveTaskToStackUncheckedLocked(
- task, stackId, toTop, forceFocus, "moveTaskToStack:" + reason);
+ task, stackId, toTop, forceFocus, reason + " moveTaskToStack");
stackId = stack.mStackId;
if (!animate) {
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index 0678ca2de365..f0efebed0747 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -24,6 +24,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.graphics.Rect;
+import android.os.Debug;
import android.util.ArrayMap;
import android.util.Slog;
import android.view.animation.LinearInterpolator;
@@ -39,7 +40,10 @@ import android.view.animation.LinearInterpolator;
* The object that is resized needs to implement {@link AnimateBoundsUser} interface.
*/
public class BoundsAnimationController {
- private static final String TAG = TAG_WITH_CLASS_NAME ? "BoundsAnimationController" : TAG_WM;
+ private static final boolean DEBUG_LOCAL = false;
+ private static final boolean DEBUG = DEBUG_LOCAL || DEBUG_ANIM;
+ private static final String TAG = TAG_WITH_CLASS_NAME || DEBUG_LOCAL
+ ? "BoundsAnimationController" : TAG_WM;
private static final int DEBUG_ANIMATION_SLOW_DOWN_FACTOR = 1;
// Only accessed on UI thread.
@@ -80,9 +84,9 @@ public class BoundsAnimationController {
mTmpRect.top = (int) (mFrom.top * remains + mTo.top * value + 0.5f);
mTmpRect.right = (int) (mFrom.right * remains + mTo.right * value + 0.5f);
mTmpRect.bottom = (int) (mFrom.bottom * remains + mTo.bottom * value + 0.5f);
- if (DEBUG_ANIM) Slog.d(TAG, "animateUpdate: mTarget=" + mTarget + ", mBounds="
- + mTmpRect + ", from=" + mFrom + ", mTo=" + mTo + ", value=" + value
- + ", remains=" + remains);
+ if (DEBUG) Slog.d(TAG, "animateUpdate: mTarget=" + mTarget + " mBounds="
+ + mTmpRect + " from=" + mFrom + " mTo=" + mTo + " value=" + value
+ + " remains=" + remains);
if (!mTarget.setSize(mTmpRect)) {
// Whoops, the target doesn't feel like animating anymore. Let's immediately finish
// any further animation.
@@ -93,6 +97,8 @@ public class BoundsAnimationController {
@Override
public void onAnimationStart(Animator animation) {
+ if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
+ + " mReplacement=" + mReplacement);
if (!mReplacement) {
mTarget.onAnimationStart();
}
@@ -100,6 +106,8 @@ public class BoundsAnimationController {
@Override
public void onAnimationEnd(Animator animation) {
+ if (DEBUG) Slog.d(TAG, "onAnimationEnd: mTarget=" + mTarget
+ + " mMoveToFullScreen=" + mMoveToFullScreen + " mWillReplace=" + mWillReplace);
finishAnimation();
if (mMoveToFullScreen && !mWillReplace) {
mTarget.moveToFullscreen();
@@ -114,10 +122,18 @@ public class BoundsAnimationController {
@Override
public void cancel() {
mWillReplace = true;
+ if (DEBUG) Slog.d(TAG, "cancel: willReplace mTarget=" + mTarget);
super.cancel();
}
+ /** Returns true if the animation target is the same as the input bounds. */
+ public boolean isAnimatingTo(Rect bounds) {
+ return mTo.equals(bounds);
+ }
+
private void finishAnimation() {
+ if (DEBUG) Slog.d(TAG, "finishAnimation: mTarget=" + mTarget
+ + " callers" + Debug.getCallers(2));
if (!mWillReplace) {
mTarget.onAnimationEnd();
}
@@ -167,7 +183,18 @@ public class BoundsAnimationController {
final BoundsAnimator existing = mRunningAnimations.get(target);
final boolean replacing = existing != null;
+
+ if (DEBUG) Slog.d(TAG, "animateBounds: target=" + target + " from=" + from + " to=" + to
+ + " moveToFullscreen=" + moveToFullscreen + " replacing=" + replacing);
+
if (replacing) {
+ if (existing.isAnimatingTo(to)) {
+ // Just les the current animation complete if it has the same destination as the
+ // one we are trying to start.
+ if (DEBUG) Slog.d(TAG, "animateBounds: same destination as existing=" + existing
+ + " ignoring...");
+ return;
+ }
existing.cancel();
}
final BoundsAnimator animator =