[ActivityManager] Fix activity always visible.
Sample code, symptom video and detail:
http://code.google.com/p/android/issues/detail?id=87909
If device is sleeping, activity will be paused immediately
after resume, it is unnecessary to force complete it.
Otherwise the state may get worse because mPausingActivity
is cleared, the real pausing from activityPausedLocked won't
be able to complete pause flow (PAUSING to PAUSED).
If the fail-to-pause activity called finish, it will also
cannot complete finish flow because only !PAUSING can do it.
This results in an activity that has visible=true, finishing=true,
state=PAUSING and always show on wallpaper.
Issue flow:
Case 1
1.At home stack and screen off.
2.A task T contains one activity Z and its process was died.
3.Launch new activity X on T.
4.Before activity Z complete resume, any process
bound and died trigger update visibility and resume top.
5.X calls finish.
6.Turn on screen, X will be always visible.
Case 2
1.Launch Settings (or any), press home key.
2.Launch an activity X in Task T, press home key.
3.Kill process of activity X, turn off screen.
4.Launch activity X with NEW_TASK | CLEAR_TASK.
5.Activity X calls finish.
6.Turn on screen, X will be always visible.
Change-Id: I8ca1845fd100e13ec58382c8c0105bf0a9f8137d
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 399566a..cd3d4fd 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -807,8 +807,14 @@
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
boolean dontWait) {
if (mPausingActivity != null) {
- Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity);
- completePauseLocked(false);
+ Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
+ + " state=" + mPausingActivity.state);
+ if (!mService.isSleeping()) {
+ // Avoid recursion among check for sleep and complete pause during sleeping.
+ // Because activity will be paused immediately after resume, just let pause
+ // be completed by the order of activity paused from clients.
+ completePauseLocked(false);
+ }
}
ActivityRecord prev = mResumedActivity;
if (prev == null) {