diff options
| author | 2016-02-12 12:22:19 -0800 | |
|---|---|---|
| committer | 2016-02-16 10:09:24 -0800 | |
| commit | 5658e4b94de91e938459e50d0f5e6ef837ffb4ac (patch) | |
| tree | f10a102661e55b6f861a3a11a4a10afbeb62b203 | |
| parent | 5393a6605f0ffd7f5e1e7e080c414096d6b0db2a (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
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 = |