From 3b21bdc2d50a232a8731df9361c3958651af5933 Mon Sep 17 00:00:00 2001 From: Louis Chang Date: Mon, 25 Mar 2019 15:49:14 +0800 Subject: [PATCH] Fix Launcher crash while handling top resumed state The process of current top resumed activity was killed. Before getting the callbacks from binder death recipient, the process was being restarted while bringing up other non-UI components - such as sending broadcast. Since the top resumed activity was not being updated, ATM had to schedule to the client for dropping the top resumed state after process bound. So, exceptions thrown because it was illegal to drop the top resumed state for a fresh client. Check if necessary to update top resumed activity whenever the stack resumed activity changes. Bug: 128837461 Test: run emulator for 10 times Test: atest ActivityLifecycleTopResumedStateTests Test: atest ActivityLifecycleKeyguardTests Test: atest ActivityLifecycleTests Change-Id: Iefde9bbe5ae50f3a241235faa505a2e58ed681ee --- .../core/java/com/android/server/wm/ActivityRecord.java | 7 ++++--- .../core/java/com/android/server/wm/ActivityStack.java | 3 +-- .../com/android/server/wm/ActivityStackSupervisor.java | 5 ++--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index e08e1ff013484..e2253e7f83ceb 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -693,13 +693,13 @@ final class ActivityRecord extends ConfigurationContainer { } } - void scheduleTopResumedActivityChanged(boolean onTop) { + boolean scheduleTopResumedActivityChanged(boolean onTop) { if (!attachedToProcess()) { if (DEBUG_STATES) { Slog.w(TAG, "Can't report activity position update - client not running" + ", activityRecord=" + this); } - return; + return false; } try { if (DEBUG_STATES) { @@ -710,7 +710,9 @@ final class ActivityRecord extends ConfigurationContainer { TopResumedActivityChangeItem.obtain(onTop)); } catch (RemoteException e) { // If process died, whatever. + return false; } + return true; } void updateMultiWindowMode() { @@ -3408,7 +3410,6 @@ final class ActivityRecord extends ConfigurationContainer { transaction.addCallback(callbackItem); transaction.setLifecycleStateRequest(lifecycleItem); mAtmService.getLifecycleManager().scheduleTransaction(transaction); - mStackSupervisor.updateTopResumedActivityIfNeeded(); // Note: don't need to call pauseIfSleepingLocked() here, because the caller will only // request resume if this activity is currently resumed, which implies we aren't // sleeping. diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index fad4dbd5613b2..419f5be5bbc80 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -1500,7 +1500,6 @@ class ActivityStack extends ConfigurationContainer { + " callers=" + Debug.getCallers(5)); r.setState(RESUMED, "minimalResumeActivityLocked"); r.completeResumeLocked(); - mStackSupervisor.updateTopResumedActivityIfNeeded(); if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "Launch completed; removing icicle of " + r.icicle); } @@ -2571,7 +2570,6 @@ class ActivityStack extends ConfigurationContainer { // Protect against recursion. mInResumeTopActivity = true; result = resumeTopActivityInnerLocked(prev, options); - mStackSupervisor.updateTopResumedActivityIfNeeded(); // When resuming the top activity, it may be necessary to pause the top activity (for // example, returning to the lock screen. We suppress the normal pause logic in @@ -2606,6 +2604,7 @@ class ActivityStack extends ConfigurationContainer { if (DEBUG_STACK) Slog.d(TAG_STACK, "setResumedActivity stack:" + this + " + from: " + mResumedActivity + " to:" + r + " reason:" + reason); mResumedActivity = r; + mStackSupervisor.updateTopResumedActivityIfNeeded(); } @GuardedBy("mService") diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index 53dc1df5a46aa..afdbd73d520da 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -853,7 +853,6 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { // Schedule transaction. mService.getLifecycleManager().scheduleTransaction(clientTransaction); - updateTopResumedActivityIfNeeded(); if ((proc.mInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0 && mService.mHasHeavyWeightFeature) { @@ -2321,8 +2320,8 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { // mTopResumedActivityWaitingForPrev == true at this point would mean that an activity // before the prevTopActivity one hasn't reported back yet. So server never sent the top // resumed state change message to prevTopActivity. - if (prevActivityReceivedTopState) { - prevTopActivity.scheduleTopResumedActivityChanged(false /* onTop */); + if (prevActivityReceivedTopState + && prevTopActivity.scheduleTopResumedActivityChanged(false /* onTop */)) { scheduleTopResumedStateLossTimeout(prevTopActivity); mTopResumedActivityWaitingForPrev = true; }