Fix issue #6319312: Consecutive call to Activity's onCreate()/onResume()...
...without onPause() in between
There was a bug in the handling of "always finish activities" where we
would go through destroying activities while in the middle of updating
the activity stack. This would result in the activity behind the
non-full-screen activity being created and then immediately destroyed,
which things were not expecting.
Change-Id: Idaa89089f7b1af7eb747d7b8f9f394beeb2d23fa
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 25fae83..1e14f5b 100755
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -45,7 +45,6 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
-import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -289,7 +288,19 @@
static final int RESUME_TOP_ACTIVITY_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6;
static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 7;
static final int STOP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 8;
-
+ static final int DESTROY_ACTIVITIES_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 9;
+
+ static class ScheduleDestroyArgs {
+ final ProcessRecord mOwner;
+ final boolean mOomAdj;
+ final String mReason;
+ ScheduleDestroyArgs(ProcessRecord owner, boolean oomAdj, String reason) {
+ mOwner = owner;
+ mOomAdj = oomAdj;
+ mReason = reason;
+ }
+ }
+
final Handler mHandler = new Handler() {
//public Handler() {
// if (localLOGV) Slog.v(TAG, "Handler started!");
@@ -384,6 +395,12 @@
}
}
} break;
+ case DESTROY_ACTIVITIES_MSG: {
+ ScheduleDestroyArgs args = (ScheduleDestroyArgs)msg.obj;
+ synchronized (mService) {
+ destroyActivitiesLocked(args.mOwner, args.mOomAdj, args.mReason);
+ }
+ }
}
}
};
@@ -3821,19 +3838,39 @@
r.connections = null;
}
}
-
+
+ final void scheduleDestroyActivities(ProcessRecord owner, boolean oomAdj, String reason) {
+ Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG);
+ msg.obj = new ScheduleDestroyArgs(owner, oomAdj, reason);
+ mHandler.sendMessage(msg);
+ }
+
final void destroyActivitiesLocked(ProcessRecord owner, boolean oomAdj, String reason) {
+ boolean lastIsOpaque = false;
for (int i=mHistory.size()-1; i>=0; i--) {
ActivityRecord r = mHistory.get(i);
+ if (r.finishing) {
+ continue;
+ }
+ if (r.fullscreen) {
+ lastIsOpaque = true;
+ }
if (owner != null && r.app != owner) {
continue;
}
+ if (!lastIsOpaque) {
+ continue;
+ }
// We can destroy this one if we have its icicle saved and
// it is not in the process of pausing/stopping/finishing.
- if (r.app != null && r.haveState && !r.visible && r.stopped && !r.finishing
+ if (r.app != null && r != mResumedActivity && r != mPausingActivity
+ && r.haveState && !r.visible && r.stopped
&& r.state != ActivityState.DESTROYING
&& r.state != ActivityState.DESTROYED) {
- destroyActivityLocked(r, true, oomAdj, "trim");
+ if (DEBUG_SWITCH) Slog.v(TAG, "Destroying " + r + " in state " + r.state
+ + " resumed=" + mResumedActivity
+ + " pausing=" + mPausingActivity);
+ destroyActivityLocked(r, true, oomAdj, reason);
}
}
}
@@ -3847,7 +3884,7 @@
final boolean destroyActivityLocked(ActivityRecord r,
boolean removeFromApp, boolean oomAdj, String reason) {
if (DEBUG_SWITCH) Slog.v(
- TAG, "Removing activity: token=" + r
+ TAG, "Removing activity from " + reason + ": token=" + r
+ ", app=" + (r.app != null ? r.app.processName : "(null)"));
EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
System.identityHashCode(r),