summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCraig Mautner <cmautner@google.com>2013-07-05 15:27:08 -0700
committerCraig Mautner <cmautner@google.com>2013-07-05 15:27:08 -0700
commit7ea5bd497f842c8181f6455da6c8013e06578d45 (patch)
tree776409310107cbf194610a5d0d2d9f4b73ae1b8a
parentd9fb14a38aaa795948e5827d33e3d6fdc108f624 (diff)
downloadframeworks_base-7ea5bd497f842c8181f6455da6c8013e06578d45.zip
frameworks_base-7ea5bd497f842c8181f6455da6c8013e06578d45.tar.gz
frameworks_base-7ea5bd497f842c8181f6455da6c8013e06578d45.tar.bz2
Move mLaunchingActivity from stack to supervisor.
There did not need to be one launching wakelock for each stack. Moving it to the stack supervisor makes the logic much simpler and fixes bug 9693439. Change-Id: I5c9ae856540170a4d66fedb74becb6959c44dd8f
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java2
-rw-r--r--services/java/com/android/server/am/ActivityStack.java84
-rw-r--r--services/java/com/android/server/am/ActivityStackSupervisor.java147
3 files changed, 108 insertions, 125 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 6425693..21febda 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -10187,7 +10187,7 @@ public final class ActivityManagerService extends ActivityManagerNative
TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
pw.println("");
pw.println(" mGoingToSleep=" + mStackSupervisor.mGoingToSleep);
- pw.println(" mLaunchingActivity=" + getFocusedStack().mLaunchingActivity);
+ pw.println(" mLaunchingActivity=" + mStackSupervisor.mLaunchingActivity);
pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
pw.println(" mNumNonCachedProcs=" + mNumNonCachedProcs
+ " (" + mLruProcesses.size() + " total)"
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 9013b4a..7ecb35d 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -69,7 +69,6 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
-import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -102,9 +101,6 @@ final class ActivityStack {
// from the application in order to get its saved state.
static final int STOP_TIMEOUT = 10*1000;
- // How long we can hold the launch wake lock before giving up.
- static final int LAUNCH_TIMEOUT = 10*1000;
-
// How long we wait until giving up on an activity telling us it has
// finished destroying itself.
static final int DESTROY_TIMEOUT = 10*1000;
@@ -121,10 +117,6 @@ final class ActivityStack {
// is being started.
static final boolean SHOW_APP_STARTING_PREVIEW = true;
- // For debugging to make sure the caller when acquiring/releasing our
- // wake lock is the system process.
- static final boolean VALIDATE_WAKE_LOCK_CALLER = true;
-
enum ActivityState {
INITIALIZING,
RESUMED,
@@ -167,14 +159,6 @@ final class ActivityStack {
final ArrayList<ActivityRecord> mNoAnimActivities = new ArrayList<ActivityRecord>();
/**
- * We don't want to allow the device to go to sleep while in the process
- * of launching an activity. This is primarily to allow alarm intent
- * receivers to launch an activity and get that to run before the device
- * goes back to sleep.
- */
- final PowerManager.WakeLock mLaunchingActivity;
-
- /**
* When we are in the process of pausing an activity, before starting the
* next one, this variable holds the activity that is currently being paused.
*/
@@ -225,8 +209,7 @@ final class ActivityStack {
/** Run all ActivityStacks through this */
final ActivityStackSupervisor mStackSupervisor;
- static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG;
- static final int LAUNCH_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
+ static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
static final int STOP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 4;
@@ -285,23 +268,6 @@ final class ActivityStack {
activityDestroyedLocked(r != null ? r.appToken : null);
}
} break;
- case LAUNCH_TIMEOUT_MSG: {
- if (mService.mDidDexOpt) {
- mService.mDidDexOpt = false;
- mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
- return;
- }
- synchronized (mService) {
- if (mLaunchingActivity.isHeld()) {
- Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
- if (VALIDATE_WAKE_LOCK_CALLER
- && Binder.getCallingUid() != Process.myUid()) {
- throw new IllegalStateException("Calling must be system uid");
- }
- mLaunchingActivity.release();
- }
- }
- } break;
case STOP_TIMEOUT_MSG: {
ActivityRecord r = (ActivityRecord)msg.obj;
// We don't at this point know if the activity is fullscreen,
@@ -338,12 +304,6 @@ final class ActivityStack {
mStackSupervisor = service.mStackSupervisor;
mContext = context;
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
- if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
- throw new IllegalStateException("Calling must be system uid");
- }
- mLaunchingActivity =
- pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
- mLaunchingActivity.setReferenceCounted(false);
mStackId = stackId;
mCurrentUser = service.mCurrentUserId;
}
@@ -610,16 +570,6 @@ final class ActivityStack {
r.displayStartTime = r.fullyDrawnStartTime = 0;
}
- void stopIfSleepingLocked() {
- if (mLaunchingActivity.isHeld()) {
- if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
- throw new IllegalStateException("Calling must be system uid");
- }
- mLaunchingActivity.release();
- mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
- }
- }
-
void awakeFromSleepingLocked() {
// Ensure activities are no longer sleeping.
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
@@ -743,14 +693,7 @@ final class ActivityStack {
// If we are not going to sleep, we want to ensure the device is
// awake until the next activity is started.
if (!mService.isSleepingOrShuttingDown()) {
- if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
- throw new IllegalStateException("Calling must be system uid");
- }
- mLaunchingActivity.acquire();
- if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
- // To be safe, don't allow the wake lock to be held for too long.
- mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
- }
+ mStackSupervisor.acquireLaunchWakelock();
}
if (mPausingActivity != null) {
@@ -2121,29 +2064,6 @@ final class ActivityStack {
}
}
- final ActivityRecord activityIdleInternalLocked(final IBinder token) {
- if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
-
- // Get the activity record.
- ActivityRecord res = isInStackLocked(token);
- if (res != null) {
- // No longer need to keep the device awake.
- if (mResumedActivity == res && mLaunchingActivity.isHeld()) {
- mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
- if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
- throw new IllegalStateException("Calling must be system uid");
- }
- mLaunchingActivity.release();
- }
-
- // If this activity is fullscreen, set up to hide those under it.
- if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + res);
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
- }
-
- return res;
- }
-
/**
* @return Returns true if the activity is being finished, false if for
* some reason it is being left as-is.
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index 9afac2c..63f91ac 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -62,6 +62,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -98,10 +99,18 @@ public final class ActivityStackSupervisor {
/** How long we can hold the sleep wake lock before giving up. */
static final int SLEEP_TIMEOUT = 5*1000;
+ // How long we can hold the launch wake lock before giving up.
+ static final int LAUNCH_TIMEOUT = 10*1000;
+
static final int IDLE_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG;
static final int IDLE_NOW_MSG = FIRST_SUPERVISOR_STACK_MSG + 1;
static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2;
static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3;
+ static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 4;
+
+ // For debugging to make sure the caller when acquiring/releasing our
+ // wake lock is the system process.
+ static final boolean VALIDATE_WAKE_LOCK_CALLER = false;
final ActivityManagerService mService;
final Context mContext;
@@ -183,6 +192,14 @@ public final class ActivityStackSupervisor {
boolean mSleepTimeout = false;
/**
+ * We don't want to allow the device to go to sleep while in the process
+ * of launching an activity. This is primarily to allow alarm intent
+ * receivers to launch an activity and get that to run before the device
+ * goes back to sleep.
+ */
+ final PowerManager.WakeLock mLaunchingActivity;
+
+ /**
* Set when the system is going to sleep, until we have
* successfully paused the current activity and released our wake lock.
* At that point the system is allowed to actually sleep.
@@ -197,6 +214,12 @@ public final class ActivityStackSupervisor {
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
mHandler = new ActivityStackSupervisorHandler(looper);
+ if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
+ throw new IllegalStateException("Calling must be system uid");
+ }
+ mLaunchingActivity =
+ pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
+ mLaunchingActivity.setReferenceCounted(false);
}
void setWindowManager(WindowManagerService wm) {
@@ -388,7 +411,11 @@ public final class ActivityStackSupervisor {
boolean allResumedActivitiesIdle() {
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityRecord resumedActivity = mStacks.get(stackNdx).mResumedActivity;
+ final ActivityStack stack = mStacks.get(stackNdx);
+ if (!isFrontStack(stack)) {
+ continue;
+ }
+ final ActivityRecord resumedActivity = stack.mResumedActivity;
if (resumedActivity == null || !resumedActivity.idle) {
return false;
}
@@ -1666,13 +1693,22 @@ public final class ActivityStackSupervisor {
return ActivityManager.START_SUCCESS;
}
+ void acquireLaunchWakelock() {
+ if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
+ throw new IllegalStateException("Calling must be system uid");
+ }
+ mLaunchingActivity.acquire();
+ if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
+ // To be safe, don't allow the wake lock to be held for too long.
+ mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
+ }
+ }
+
// Checked.
final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
Configuration config) {
if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
- ActivityRecord res = null;
-
ArrayList<ActivityRecord> stops = null;
ArrayList<ActivityRecord> finishes = null;
ArrayList<UserStartedState> startingUsers = null;
@@ -1689,41 +1725,50 @@ public final class ActivityStackSupervisor {
Debug.getCallers(4));
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
r.finishLaunchTickingLocked();
- res = r.task.stack.activityIdleInternalLocked(token);
- if (res != null) {
- if (fromTimeout) {
- reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
- }
+ if (fromTimeout) {
+ reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
+ }
- // This is a hack to semi-deal with a race condition
- // in the client where it can be constructed with a
- // newer configuration from when we asked it to launch.
- // We'll update with whatever configuration it now says
- // it used to launch.
- if (config != null) {
- r.configuration = config;
- }
+ // This is a hack to semi-deal with a race condition
+ // in the client where it can be constructed with a
+ // newer configuration from when we asked it to launch.
+ // We'll update with whatever configuration it now says
+ // it used to launch.
+ if (config != null) {
+ r.configuration = config;
+ }
- // We are now idle. If someone is waiting for a thumbnail from
- // us, we can now deliver.
- r.idle = true;
- if (allResumedActivitiesIdle()) {
- mService.scheduleAppGcsLocked();
- mService.requestPssLocked(r.app, SystemClock.uptimeMillis(), false);
- }
- if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
- sendThumbnail = r.app.thread;
- r.thumbnailNeeded = false;
- }
-
- //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
- if (!mService.mBooted && isFrontStack(r.task.stack)) {
- mService.mBooted = true;
- enableScreen = true;
+ // We are now idle. If someone is waiting for a thumbnail from
+ // us, we can now deliver.
+ r.idle = true;
+
+ if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
+ sendThumbnail = r.app.thread;
+ r.thumbnailNeeded = false;
+ }
+
+ //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
+ if (!mService.mBooted && isFrontStack(r.task.stack)) {
+ mService.mBooted = true;
+ enableScreen = true;
+ }
+ }
+
+ if (allResumedActivitiesIdle()) {
+ if (r != null) {
+ mService.scheduleAppGcsLocked();
+ mService.requestPssLocked(r.app, SystemClock.uptimeMillis(), false);
+ }
+
+ if (mLaunchingActivity.isHeld()) {
+ mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
+ if (VALIDATE_WAKE_LOCK_CALLER &&
+ Binder.getCallingUid() != Process.myUid()) {
+ throw new IllegalStateException("Calling must be system uid");
}
- } else if (fromTimeout) {
- reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
+ mLaunchingActivity.release();
}
+ ensureActivitiesVisibleLocked(null, 0);
}
// Atomically retrieve all of the other things to do.
@@ -1814,7 +1859,7 @@ public final class ActivityStackSupervisor {
resumeTopActivitiesLocked();
}
- return res;
+ return r;
}
void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
@@ -1882,7 +1927,7 @@ public final class ActivityStackSupervisor {
void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
- if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack=" +
+ if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack=" +
mStacks.get(stackNdx));
return;
}
@@ -1956,11 +2001,12 @@ public final class ActivityStackSupervisor {
scheduleSleepTimeout();
if (!mGoingToSleep.isHeld()) {
mGoingToSleep.acquire();
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (stack.mResumedActivity != null) {
- stack.stopIfSleepingLocked();
+ if (mLaunchingActivity.isHeld()) {
+ if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
+ throw new IllegalStateException("Calling must be system uid");
}
+ mLaunchingActivity.release();
+ mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
}
}
}
@@ -2423,8 +2469,8 @@ public final class ActivityStackSupervisor {
synchronized (mService) {
activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
}
- }
-
+ }
+
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
@@ -2459,6 +2505,23 @@ public final class ActivityStackSupervisor {
}
}
} break;
+ case LAUNCH_TIMEOUT_MSG: {
+ if (mService.mDidDexOpt) {
+ mService.mDidDexOpt = false;
+ mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
+ return;
+ }
+ synchronized (mService) {
+ if (mLaunchingActivity.isHeld()) {
+ Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
+ if (VALIDATE_WAKE_LOCK_CALLER
+ && Binder.getCallingUid() != Process.myUid()) {
+ throw new IllegalStateException("Calling must be system uid");
+ }
+ mLaunchingActivity.release();
+ }
+ }
+ } break;
}
}
}