blob: a6ab6f4897cdd4a0245421524b0fe00fd2e920c0 [file] [log] [blame]
Craig Mautner27084302013-03-25 08:05:25 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Craig Mautner6170f732013-04-02 13:05:23 -070019import static android.Manifest.permission.START_ANY_ACTIVITY;
Craig Mautner29219d92013-04-16 20:19:12 -070020import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
21import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Craig Mautner6170f732013-04-02 13:05:23 -070022import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Craig Mautner2420ead2013-04-01 17:13:20 -070023import static com.android.server.am.ActivityManagerService.localLOGV;
Craig Mautner23ac33b2013-04-01 16:26:35 -070024import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION;
Craig Mautner6170f732013-04-02 13:05:23 -070025import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
Craig Mautner2420ead2013-04-01 17:13:20 -070026import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
Craig Mautner8849a5e2013-04-02 16:41:03 -070027import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
28import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
Craig Mautner05d29032013-05-03 13:40:13 -070029import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
Craig Mautner8d341ef2013-03-26 09:03:27 -070030import static com.android.server.am.ActivityManagerService.TAG;
31
Craig Mautner2420ead2013-04-01 17:13:20 -070032import android.app.Activity;
Craig Mautner23ac33b2013-04-01 16:26:35 -070033import android.app.ActivityManager;
34import android.app.ActivityOptions;
35import android.app.AppGlobals;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070036import android.app.IActivityManager;
Craig Mautner23ac33b2013-04-01 16:26:35 -070037import android.app.IApplicationThread;
Craig Mautner20e72272013-04-01 13:45:53 -070038import android.app.IThumbnailReceiver;
Craig Mautner23ac33b2013-04-01 16:26:35 -070039import android.app.PendingIntent;
Craig Mautner20e72272013-04-01 13:45:53 -070040import android.app.ActivityManager.RunningTaskInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070041import android.app.IActivityManager.WaitResult;
Craig Mautner2420ead2013-04-01 17:13:20 -070042import android.app.ResultInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070043import android.content.ComponentName;
Craig Mautner2219a1b2013-03-25 09:44:30 -070044import android.content.Context;
Craig Mautner23ac33b2013-04-01 16:26:35 -070045import android.content.IIntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070046import android.content.Intent;
Craig Mautner23ac33b2013-04-01 16:26:35 -070047import android.content.IntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070048import android.content.pm.ActivityInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070049import android.content.pm.ApplicationInfo;
50import android.content.pm.PackageManager;
51import android.content.pm.ResolveInfo;
52import android.content.res.Configuration;
53import android.os.Binder;
Craig Mautner8d341ef2013-03-26 09:03:27 -070054import android.os.Bundle;
Craig Mautnerb59dcfd2013-05-06 13:12:58 -070055import android.os.Debug;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070056import android.os.Handler;
Craig Mautner23ac33b2013-04-01 16:26:35 -070057import android.os.IBinder;
Craig Mautner2219a1b2013-03-25 09:44:30 -070058import android.os.Looper;
Craig Mautner2420ead2013-04-01 17:13:20 -070059import android.os.Message;
Craig Mautner23ac33b2013-04-01 16:26:35 -070060import android.os.ParcelFileDescriptor;
Craig Mautner8d341ef2013-03-26 09:03:27 -070061import android.os.RemoteException;
Craig Mautner23ac33b2013-04-01 16:26:35 -070062import android.os.SystemClock;
Craig Mautner6170f732013-04-02 13:05:23 -070063import android.os.UserHandle;
Craig Mautner2420ead2013-04-01 17:13:20 -070064import android.util.EventLog;
Craig Mautner8d341ef2013-03-26 09:03:27 -070065import android.util.Slog;
Craig Mautner858d8a62013-04-23 17:08:34 -070066import android.util.SparseArray;
Craig Mautner2219a1b2013-03-25 09:44:30 -070067
Craig Mautner23ac33b2013-04-01 16:26:35 -070068import com.android.internal.app.HeavyWeightSwitcherActivity;
Craig Mautner6170f732013-04-02 13:05:23 -070069import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
Craig Mautner2420ead2013-04-01 17:13:20 -070070import com.android.server.am.ActivityStack.ActivityState;
Craig Mautnerde4ef022013-04-07 19:01:33 -070071import com.android.server.wm.StackBox;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070072import com.android.server.wm.WindowManagerService;
Craig Mautner23ac33b2013-04-01 16:26:35 -070073
Craig Mautner8d341ef2013-03-26 09:03:27 -070074import java.io.FileDescriptor;
75import java.io.IOException;
Craig Mautner27084302013-03-25 08:05:25 -070076import java.io.PrintWriter;
Craig Mautner2219a1b2013-03-25 09:44:30 -070077import java.util.ArrayList;
Craig Mautner8d341ef2013-03-26 09:03:27 -070078import java.util.List;
Craig Mautner27084302013-03-25 08:05:25 -070079
80public class ActivityStackSupervisor {
Craig Mautnera9a3fb12013-04-18 10:01:00 -070081 static final boolean DEBUG_STACK = ActivityManagerService.DEBUG_STACK;
82
Craig Mautnerde4ef022013-04-07 19:01:33 -070083 static final boolean DEBUG = ActivityManagerService.DEBUG || false;
84 static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
85 static final boolean DEBUG_APP = DEBUG || false;
86 static final boolean DEBUG_SAVED_STATE = DEBUG || false;
87 static final boolean DEBUG_STATES = DEBUG || false;
Craig Mautnerb59dcfd2013-05-06 13:12:58 -070088 static final boolean DEBUG_IDLE = DEBUG || false;
Craig Mautner2420ead2013-04-01 17:13:20 -070089
Craig Mautner2219a1b2013-03-25 09:44:30 -070090 public static final int HOME_STACK_ID = 0;
Craig Mautner27084302013-03-25 08:05:25 -070091
Craig Mautnerf3333272013-04-22 10:55:53 -070092 /** How long we wait until giving up on the last activity telling us it is idle. */
93 static final int IDLE_TIMEOUT = 10*1000;
94
Craig Mautner05d29032013-05-03 13:40:13 -070095 static final int IDLE_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG;
96 static final int IDLE_NOW_MSG = FIRST_SUPERVISOR_STACK_MSG + 1;
97 static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2;
Craig Mautnerf3333272013-04-22 10:55:53 -070098
Craig Mautner27084302013-03-25 08:05:25 -070099 final ActivityManagerService mService;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700100 final Context mContext;
101 final Looper mLooper;
Craig Mautner27084302013-03-25 08:05:25 -0700102
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700103 final ActivityStackSupervisorHandler mHandler;
104
105 /** Short cut */
106 WindowManagerService mWindowManager;
107
Craig Mautner27084302013-03-25 08:05:25 -0700108 /** Dismiss the keyguard after the next activity is displayed? */
109 private boolean mDismissKeyguardOnNextActivity = false;
110
Craig Mautner8d341ef2013-03-26 09:03:27 -0700111 /** Identifier counter for all ActivityStacks */
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700112 private int mLastStackId = HOME_STACK_ID;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700113
114 /** Task identifier that activities are currently being started in. Incremented each time a
115 * new task is created. */
116 private int mCurTaskId = 0;
117
Craig Mautner2420ead2013-04-01 17:13:20 -0700118 /** The current user */
119 private int mCurrentUser;
120
Craig Mautner8d341ef2013-03-26 09:03:27 -0700121 /** The stack containing the launcher app */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700122 private ActivityStack mHomeStack;
Craig Mautner20e72272013-04-01 13:45:53 -0700123
Craig Mautnerde4ef022013-04-07 19:01:33 -0700124 /** The non-home stack currently receiving input or launching the next activity. If home is
Craig Mautner29219d92013-04-16 20:19:12 -0700125 * in front then mHomeStack overrides mFocusedStack. */
126 private ActivityStack mFocusedStack;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700127
128 /** All the non-launcher stacks */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700129 private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
130
Craig Mautnerde4ef022013-04-07 19:01:33 -0700131 private static final int STACK_STATE_HOME_IN_FRONT = 0;
132 private static final int STACK_STATE_HOME_TO_BACK = 1;
133 private static final int STACK_STATE_HOME_IN_BACK = 2;
134 private static final int STACK_STATE_HOME_TO_FRONT = 3;
135 private int mStackState = STACK_STATE_HOME_IN_FRONT;
136
137 /** List of activities that are waiting for a new activity to become visible before completing
138 * whatever operation they are supposed to do. */
139 final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();
140
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700141 /** List of processes waiting to find out about the next visible activity. */
142 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible =
143 new ArrayList<IActivityManager.WaitResult>();
144
145 /** List of processes waiting to find out about the next launched activity. */
146 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched =
147 new ArrayList<IActivityManager.WaitResult>();
148
Craig Mautnerde4ef022013-04-07 19:01:33 -0700149 /** List of activities that are ready to be stopped, but waiting for the next activity to
150 * settle down before doing so. */
151 final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();
152
Craig Mautnerf3333272013-04-22 10:55:53 -0700153 /** List of activities that are ready to be finished, but waiting for the previous activity to
154 * settle down before doing so. It contains ActivityRecord objects. */
155 final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<ActivityRecord>();
156
157 /** List of ActivityRecord objects that have been finished and must still report back to a
158 * pending thumbnail receiver. */
159 final ArrayList<ActivityRecord> mCancelledThumbnails = new ArrayList<ActivityRecord>();
160
161 /** Used on user changes */
162 final ArrayList<UserStartedState> mStartingUsers = new ArrayList<UserStartedState>();
163
Craig Mautnerde4ef022013-04-07 19:01:33 -0700164 /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity
165 * is being brought in front of us. */
166 boolean mUserLeaving = false;
167
Craig Mautner858d8a62013-04-23 17:08:34 -0700168 /** Stacks belonging to users other than mCurrentUser. Indexed by userId. */
169 final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
170
Craig Mautner2219a1b2013-03-25 09:44:30 -0700171 public ActivityStackSupervisor(ActivityManagerService service, Context context,
172 Looper looper) {
Craig Mautner27084302013-03-25 08:05:25 -0700173 mService = service;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700174 mContext = context;
175 mLooper = looper;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700176 mHandler = new ActivityStackSupervisorHandler(looper);
Craig Mautner2219a1b2013-03-25 09:44:30 -0700177 }
178
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700179 void setWindowManager(WindowManagerService wm) {
180 mWindowManager = wm;
181 mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700182 mStacks.add(mHomeStack);
Craig Mautner27084302013-03-25 08:05:25 -0700183 }
184
185 void dismissKeyguard() {
186 if (mDismissKeyguardOnNextActivity) {
187 mDismissKeyguardOnNextActivity = false;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700188 mWindowManager.dismissKeyguard();
Craig Mautner27084302013-03-25 08:05:25 -0700189 }
190 }
191
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700192 ActivityStack getFocusedStack() {
Craig Mautnerf88c50f2013-04-18 19:25:12 -0700193 if (mFocusedStack == null) {
194 return mHomeStack;
195 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700196 switch (mStackState) {
197 case STACK_STATE_HOME_IN_FRONT:
198 case STACK_STATE_HOME_TO_FRONT:
199 return mHomeStack;
200 case STACK_STATE_HOME_IN_BACK:
201 case STACK_STATE_HOME_TO_BACK:
202 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700203 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700204 }
Craig Mautner20e72272013-04-01 13:45:53 -0700205 }
206
Craig Mautnerde4ef022013-04-07 19:01:33 -0700207 ActivityStack getLastStack() {
208 switch (mStackState) {
209 case STACK_STATE_HOME_IN_FRONT:
210 case STACK_STATE_HOME_TO_BACK:
211 return mHomeStack;
212 case STACK_STATE_HOME_TO_FRONT:
213 case STACK_STATE_HOME_IN_BACK:
214 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700215 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700216 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700217 }
218
Craig Mautnerde4ef022013-04-07 19:01:33 -0700219 boolean isFrontStack(ActivityStack stack) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700220 return (stack.mCurrentUser == mCurrentUser) &&
221 !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
Craig Mautner20e72272013-04-01 13:45:53 -0700222 }
223
Craig Mautnerde4ef022013-04-07 19:01:33 -0700224 void moveHomeStack(boolean toFront) {
225 final boolean homeInFront = isFrontStack(mHomeStack);
226 if (homeInFront ^ toFront) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700227 if (DEBUG_STACK) Slog.d(TAG, "moveHomeTask: mStackState old=" +
228 stackStateToString(mStackState) + " new=" + stackStateToString(homeInFront ?
229 STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700230 mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
231 }
232 }
233
Craig Mautner69ada552013-04-18 13:51:51 -0700234 boolean resumeHomeActivity(ActivityRecord prev) {
235 moveHomeStack(true);
236 if (prev != null) {
237 prev.mLaunchHomeTaskNext = false;
238 }
239 if (mHomeStack.topRunningActivityLocked(null) != null) {
Craig Mautner05d29032013-05-03 13:40:13 -0700240 return resumeTopActivitiesLocked(mHomeStack, prev, null);
Craig Mautner69ada552013-04-18 13:51:51 -0700241 }
242 return mService.startHomeActivityLocked(mCurrentUser);
243 }
244
Craig Mautnerde4ef022013-04-07 19:01:33 -0700245 final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r,
246 ActivityStack stack) {
247 if (stack == mHomeStack) {
248 return;
249 }
250 if ((sourceRecord == null && getLastStack() == mHomeStack) ||
Craig Mautner86d67a42013-05-14 10:34:38 -0700251 (sourceRecord != null && sourceRecord.isHomeActivity())) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700252 if (r == null) {
253 r = stack.topRunningActivityLocked(null);
254 }
Craig Mautner86d67a42013-05-14 10:34:38 -0700255 if (r != null && !r.isHomeActivity() && r.isRootActivity()) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700256 r.mLaunchHomeTaskNext = true;
257 }
258 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700259 }
260
Craig Mautner27084302013-03-25 08:05:25 -0700261 void setDismissKeyguard(boolean dismiss) {
262 mDismissKeyguardOnNextActivity = dismiss;
263 }
264
Craig Mautner8d341ef2013-03-26 09:03:27 -0700265 TaskRecord anyTaskForIdLocked(int id) {
266 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
267 ActivityStack stack = mStacks.get(stackNdx);
268 TaskRecord task = stack.taskForIdLocked(id);
269 if (task != null) {
270 return task;
271 }
272 }
273 return null;
274 }
275
Craig Mautner6170f732013-04-02 13:05:23 -0700276 ActivityRecord isInAnyStackLocked(IBinder token) {
277 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
278 final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
279 if (r != null) {
280 return r;
281 }
282 }
283 return null;
284 }
285
Craig Mautner8d341ef2013-03-26 09:03:27 -0700286 int getNextTaskId() {
287 do {
288 mCurTaskId++;
289 if (mCurTaskId <= 0) {
290 mCurTaskId = 1;
291 }
292 } while (anyTaskForIdLocked(mCurTaskId) != null);
293 return mCurTaskId;
294 }
295
Craig Mautnerde4ef022013-04-07 19:01:33 -0700296 void removeTask(TaskRecord task) {
297 final ActivityStack stack = task.stack;
298 if (stack.removeTask(task) && !stack.isHomeStack()) {
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700299 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700300 mStacks.remove(stack);
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700301 final int stackId = stack.mStackId;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700302 final int nextStackId = mWindowManager.removeStack(stackId);
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700303 // TODO: Perhaps we need to let the ActivityManager determine the next focus...
Guang Zhubefa8b52013-05-12 23:10:39 -0700304 if (mFocusedStack.mStackId == stackId) {
Craig Mautner1602ec22013-05-12 10:24:27 -0700305 // If this is the last app stack, set mFocusedStack to null.
Craig Mautner29219d92013-04-16 20:19:12 -0700306 mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700307 }
308 }
309 }
310
311 ActivityRecord resumedAppLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700312 ActivityStack stack = getFocusedStack();
313 if (stack == null) {
314 return null;
315 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700316 ActivityRecord resumedActivity = stack.mResumedActivity;
317 if (resumedActivity == null || resumedActivity.app == null) {
318 resumedActivity = stack.mPausingActivity;
319 if (resumedActivity == null || resumedActivity.app == null) {
320 resumedActivity = stack.topRunningActivityLocked(null);
321 }
322 }
323 return resumedActivity;
324 }
325
Craig Mautner20e72272013-04-01 13:45:53 -0700326 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
327 boolean didSomething = false;
328 final String processName = app.processName;
329 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
330 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner858d8a62013-04-23 17:08:34 -0700331 if (!isFrontStack(stack)) {
332 continue;
333 }
Craig Mautner20e72272013-04-01 13:45:53 -0700334 ActivityRecord hr = stack.topRunningActivityLocked(null);
335 if (hr != null) {
336 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
337 && processName.equals(hr.processName)) {
338 try {
339 if (headless) {
340 Slog.e(TAG, "Starting activities not supported on headless device: "
341 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700342 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700343 didSomething = true;
344 }
345 } catch (Exception e) {
346 Slog.w(TAG, "Exception in new application when starting activity "
347 + hr.intent.getComponent().flattenToShortString(), e);
348 throw e;
349 }
Craig Mautner20e72272013-04-01 13:45:53 -0700350 }
351 }
352 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -0700353 if (!didSomething) {
354 ensureActivitiesVisibleLocked(null, 0);
355 }
Craig Mautner20e72272013-04-01 13:45:53 -0700356 return didSomething;
357 }
358
359 boolean allResumedActivitiesIdle() {
360 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700361 final ActivityRecord resumedActivity = mStacks.get(stackNdx).mResumedActivity;
362 if (resumedActivity == null || !resumedActivity.idle) {
Craig Mautner20e72272013-04-01 13:45:53 -0700363 return false;
364 }
365 }
366 return true;
367 }
368
Craig Mautnerde4ef022013-04-07 19:01:33 -0700369 boolean allResumedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700370 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
371 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner967212c2013-04-13 21:10:58 -0700372 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700373 final ActivityRecord r = stack.mResumedActivity;
374 if (r != null && r.state != ActivityState.RESUMED) {
375 return false;
376 }
377 }
378 }
379 // TODO: Not sure if this should check if all Paused are complete too.
380 switch (mStackState) {
381 case STACK_STATE_HOME_TO_BACK:
Craig Mautner76ea2242013-05-15 11:40:05 -0700382 if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
383 stackStateToString(STACK_STATE_HOME_TO_BACK) + " new=" +
384 stackStateToString(STACK_STATE_HOME_IN_BACK));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700385 mStackState = STACK_STATE_HOME_IN_BACK;
386 break;
387 case STACK_STATE_HOME_TO_FRONT:
Craig Mautner76ea2242013-05-15 11:40:05 -0700388 if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
389 stackStateToString(STACK_STATE_HOME_TO_FRONT) + " new=" +
390 stackStateToString(STACK_STATE_HOME_IN_FRONT));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700391 mStackState = STACK_STATE_HOME_IN_FRONT;
392 break;
393 }
394 return true;
395 }
396
397 boolean allResumedActivitiesVisible() {
398 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
399 final ActivityStack stack = mStacks.get(stackNdx);
400 final ActivityRecord r = stack.mResumedActivity;
401 if (r != null && (!r.nowVisible || r.waitingVisible)) {
402 return false;
403 }
404 }
405 return true;
406 }
407
Craig Mautnercf910b02013-04-23 11:23:27 -0700408 boolean pauseBackStacks(boolean userLeaving) {
409 boolean someActivityPaused = false;
410 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
411 final ActivityStack stack = mStacks.get(stackNdx);
412 if (!isFrontStack(stack) && stack.mResumedActivity != null) {
413 stack.startPausingLocked(userLeaving, false);
414 someActivityPaused = true;
415 }
416 }
417 return someActivityPaused;
418 }
419
Craig Mautnerde4ef022013-04-07 19:01:33 -0700420 boolean allPausedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700421 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
422 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner69ada552013-04-18 13:51:51 -0700423 final ActivityRecord r = stack.mPausingActivity;
424 if (r != null && r.state != ActivityState.PAUSED
425 && r.state != ActivityState.STOPPED
426 && r.state != ActivityState.STOPPING) {
427 return false;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700428 }
429 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700430 return true;
431 }
432
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700433 void reportActivityVisibleLocked(ActivityRecord r) {
Craig Mautner858d8a62013-04-23 17:08:34 -0700434 for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700435 WaitResult w = mWaitingActivityVisible.get(i);
436 w.timeout = false;
437 if (r != null) {
438 w.who = new ComponentName(r.info.packageName, r.info.name);
439 }
440 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
441 w.thisTime = w.totalTime;
442 }
443 mService.notifyAll();
444 dismissKeyguard();
445 }
446
447 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
448 long thisTime, long totalTime) {
449 for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
Craig Mautnerc64f73e2013-04-24 16:44:56 -0700450 WaitResult w = mWaitingActivityLaunched.remove(i);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700451 w.timeout = timeout;
452 if (r != null) {
453 w.who = new ComponentName(r.info.packageName, r.info.name);
454 }
455 w.thisTime = thisTime;
456 w.totalTime = totalTime;
457 }
458 mService.notifyAll();
459 }
460
Craig Mautner29219d92013-04-16 20:19:12 -0700461 ActivityRecord topRunningActivityLocked() {
Craig Mautner1602ec22013-05-12 10:24:27 -0700462 final ActivityStack focusedStack = getFocusedStack();
463 ActivityRecord r = focusedStack.topRunningActivityLocked(null);
464 if (r != null) {
465 return r;
Craig Mautner29219d92013-04-16 20:19:12 -0700466 }
Craig Mautner1602ec22013-05-12 10:24:27 -0700467
Craig Mautner29219d92013-04-16 20:19:12 -0700468 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
469 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner1602ec22013-05-12 10:24:27 -0700470 if (stack.mCurrentUser == mCurrentUser && stack != focusedStack &&
471 isFrontStack(stack)) {
Craig Mautner29219d92013-04-16 20:19:12 -0700472 r = stack.topRunningActivityLocked(null);
473 if (r != null) {
474 return r;
475 }
476 }
477 }
478 return null;
479 }
480
Craig Mautner20e72272013-04-01 13:45:53 -0700481 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
482 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
483 ActivityRecord r = null;
Craig Mautner20e72272013-04-01 13:45:53 -0700484 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
485 final ActivityStack stack = mStacks.get(stackNdx);
486 final ActivityRecord ar =
487 stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700488 if (isFrontStack(stack)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700489 r = ar;
490 }
491 }
492 return r;
493 }
494
Craig Mautner23ac33b2013-04-01 16:26:35 -0700495 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
496 String profileFile, ParcelFileDescriptor profileFd, int userId) {
497 // Collect information about the target of the Intent.
498 ActivityInfo aInfo;
499 try {
500 ResolveInfo rInfo =
501 AppGlobals.getPackageManager().resolveIntent(
502 intent, resolvedType,
503 PackageManager.MATCH_DEFAULT_ONLY
504 | ActivityManagerService.STOCK_PM_FLAGS, userId);
505 aInfo = rInfo != null ? rInfo.activityInfo : null;
506 } catch (RemoteException e) {
507 aInfo = null;
508 }
509
510 if (aInfo != null) {
511 // Store the found target back into the intent, because now that
512 // we have it we never want to do this again. For example, if the
513 // user navigates back to this point in the history, we should
514 // always restart the exact same activity.
515 intent.setComponent(new ComponentName(
516 aInfo.applicationInfo.packageName, aInfo.name));
517
518 // Don't debug things in the system process
519 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
520 if (!aInfo.processName.equals("system")) {
521 mService.setDebugApp(aInfo.processName, true, false);
522 }
523 }
524
525 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
526 if (!aInfo.processName.equals("system")) {
527 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
528 }
529 }
530
531 if (profileFile != null) {
532 if (!aInfo.processName.equals("system")) {
533 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
534 profileFile, profileFd,
535 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
536 }
537 }
538 }
539 return aInfo;
540 }
541
Craig Mautner2219a1b2013-03-25 09:44:30 -0700542 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700543 moveHomeStack(true);
Craig Mautner6170f732013-04-02 13:05:23 -0700544 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
Craig Mautner2219a1b2013-03-25 09:44:30 -0700545 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700546 }
547
Craig Mautner23ac33b2013-04-01 16:26:35 -0700548 final int startActivityMayWait(IApplicationThread caller, int callingUid,
549 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
550 String resultWho, int requestCode, int startFlags, String profileFile,
551 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
552 Bundle options, int userId) {
553 // Refuse possible leaked file descriptors
554 if (intent != null && intent.hasFileDescriptors()) {
555 throw new IllegalArgumentException("File descriptors passed in Intent");
556 }
557 boolean componentSpecified = intent.getComponent() != null;
558
559 // Don't modify the client's object!
560 intent = new Intent(intent);
561
562 // Collect information about the target of the Intent.
563 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
564 profileFile, profileFd, userId);
565
566 synchronized (mService) {
567 int callingPid;
568 if (callingUid >= 0) {
569 callingPid = -1;
570 } else if (caller == null) {
571 callingPid = Binder.getCallingPid();
572 callingUid = Binder.getCallingUid();
573 } else {
574 callingPid = callingUid = -1;
575 }
576
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700577 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -0700578 stack.mConfigWillChange = config != null
Craig Mautner23ac33b2013-04-01 16:26:35 -0700579 && mService.mConfiguration.diff(config) != 0;
580 if (DEBUG_CONFIGURATION) Slog.v(TAG,
Craig Mautnerde4ef022013-04-07 19:01:33 -0700581 "Starting activity when config will change = " + stack.mConfigWillChange);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700582
583 final long origId = Binder.clearCallingIdentity();
584
585 if (aInfo != null &&
586 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
587 // This may be a heavy-weight process! Check to see if we already
588 // have another, different heavy-weight process running.
589 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
590 if (mService.mHeavyWeightProcess != null &&
591 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
592 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700593 int realCallingUid = callingUid;
594 if (caller != null) {
595 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
596 if (callerApp != null) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700597 realCallingUid = callerApp.info.uid;
598 } else {
599 Slog.w(TAG, "Unable to find app for caller " + caller
Craig Mautner76ea2242013-05-15 11:40:05 -0700600 + " (pid=" + callingPid + ") when starting: "
Craig Mautner23ac33b2013-04-01 16:26:35 -0700601 + intent.toString());
602 ActivityOptions.abort(options);
603 return ActivityManager.START_PERMISSION_DENIED;
604 }
605 }
606
607 IIntentSender target = mService.getIntentSenderLocked(
608 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
609 realCallingUid, userId, null, null, 0, new Intent[] { intent },
610 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
611 | PendingIntent.FLAG_ONE_SHOT, null);
612
613 Intent newIntent = new Intent();
614 if (requestCode >= 0) {
615 // Caller is requesting a result.
616 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
617 }
618 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
619 new IntentSender(target));
620 if (mService.mHeavyWeightProcess.activities.size() > 0) {
621 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
622 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
623 hist.packageName);
624 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
625 hist.task.taskId);
626 }
627 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
628 aInfo.packageName);
629 newIntent.setFlags(intent.getFlags());
630 newIntent.setClassName("android",
631 HeavyWeightSwitcherActivity.class.getName());
632 intent = newIntent;
633 resolvedType = null;
634 caller = null;
635 callingUid = Binder.getCallingUid();
636 callingPid = Binder.getCallingPid();
637 componentSpecified = true;
638 try {
639 ResolveInfo rInfo =
640 AppGlobals.getPackageManager().resolveIntent(
641 intent, null,
642 PackageManager.MATCH_DEFAULT_ONLY
643 | ActivityManagerService.STOCK_PM_FLAGS, userId);
644 aInfo = rInfo != null ? rInfo.activityInfo : null;
645 aInfo = mService.getActivityInfoForUser(aInfo, userId);
646 } catch (RemoteException e) {
647 aInfo = null;
648 }
649 }
650 }
651 }
652
Craig Mautner6170f732013-04-02 13:05:23 -0700653 int res = startActivityLocked(caller, intent, resolvedType,
Craig Mautner23ac33b2013-04-01 16:26:35 -0700654 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
655 callingPackage, startFlags, options, componentSpecified, null);
656
Craig Mautnerde4ef022013-04-07 19:01:33 -0700657 if (stack.mConfigWillChange) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700658 // If the caller also wants to switch to a new configuration,
659 // do so now. This allows a clean switch, as we are waiting
660 // for the current activity to pause (so we will not destroy
661 // it), and have not yet started the next activity.
662 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
663 "updateConfiguration()");
Craig Mautnerde4ef022013-04-07 19:01:33 -0700664 stack.mConfigWillChange = false;
Craig Mautner23ac33b2013-04-01 16:26:35 -0700665 if (DEBUG_CONFIGURATION) Slog.v(TAG,
666 "Updating to new configuration after starting activity.");
667 mService.updateConfigurationLocked(config, null, false, false);
668 }
669
670 Binder.restoreCallingIdentity(origId);
671
672 if (outResult != null) {
673 outResult.result = res;
674 if (res == ActivityManager.START_SUCCESS) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700675 mWaitingActivityLaunched.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700676 do {
677 try {
678 mService.wait();
679 } catch (InterruptedException e) {
680 }
681 } while (!outResult.timeout && outResult.who == null);
682 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700683 ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700684 if (r.nowVisible) {
685 outResult.timeout = false;
686 outResult.who = new ComponentName(r.info.packageName, r.info.name);
687 outResult.totalTime = 0;
688 outResult.thisTime = 0;
689 } else {
690 outResult.thisTime = SystemClock.uptimeMillis();
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700691 mWaitingActivityVisible.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700692 do {
693 try {
694 mService.wait();
695 } catch (InterruptedException e) {
696 }
697 } while (!outResult.timeout && outResult.who == null);
698 }
699 }
700 }
701
702 return res;
703 }
704 }
705
706 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
707 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
708 Bundle options, int userId) {
709 if (intents == null) {
710 throw new NullPointerException("intents is null");
711 }
712 if (resolvedTypes == null) {
713 throw new NullPointerException("resolvedTypes is null");
714 }
715 if (intents.length != resolvedTypes.length) {
716 throw new IllegalArgumentException("intents are length different than resolvedTypes");
717 }
718
Craig Mautner23ac33b2013-04-01 16:26:35 -0700719
720 int callingPid;
721 if (callingUid >= 0) {
722 callingPid = -1;
723 } else if (caller == null) {
724 callingPid = Binder.getCallingPid();
725 callingUid = Binder.getCallingUid();
726 } else {
727 callingPid = callingUid = -1;
728 }
729 final long origId = Binder.clearCallingIdentity();
730 try {
731 synchronized (mService) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700732 ActivityRecord[] outActivity = new ActivityRecord[1];
Craig Mautner23ac33b2013-04-01 16:26:35 -0700733 for (int i=0; i<intents.length; i++) {
734 Intent intent = intents[i];
735 if (intent == null) {
736 continue;
737 }
738
739 // Refuse possible leaked file descriptors
740 if (intent != null && intent.hasFileDescriptors()) {
741 throw new IllegalArgumentException("File descriptors passed in Intent");
742 }
743
744 boolean componentSpecified = intent.getComponent() != null;
745
746 // Don't modify the client's object!
747 intent = new Intent(intent);
748
749 // Collect information about the target of the Intent.
750 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
751 0, null, null, userId);
752 // TODO: New, check if this is correct
753 aInfo = mService.getActivityInfoForUser(aInfo, userId);
754
755 if (aInfo != null &&
756 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
757 != 0) {
758 throw new IllegalArgumentException(
759 "FLAG_CANT_SAVE_STATE not supported here");
760 }
761
762 Bundle theseOptions;
763 if (options != null && i == intents.length-1) {
764 theseOptions = options;
765 } else {
766 theseOptions = null;
767 }
Craig Mautner6170f732013-04-02 13:05:23 -0700768 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Craig Mautner23ac33b2013-04-01 16:26:35 -0700769 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
770 0, theseOptions, componentSpecified, outActivity);
771 if (res < 0) {
772 return res;
773 }
774
775 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
776 }
777 }
778 } finally {
779 Binder.restoreCallingIdentity(origId);
780 }
781
782 return ActivityManager.START_SUCCESS;
783 }
784
Craig Mautner2420ead2013-04-01 17:13:20 -0700785 final boolean realStartActivityLocked(ActivityRecord r,
786 ProcessRecord app, boolean andResume, boolean checkConfig)
787 throws RemoteException {
788
789 r.startFreezingScreenLocked(app, 0);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700790 mWindowManager.setAppVisibility(r.appToken, true);
Craig Mautner2420ead2013-04-01 17:13:20 -0700791
792 // schedule launch ticks to collect information about slow apps.
793 r.startLaunchTickingLocked();
794
795 // Have the window manager re-evaluate the orientation of
796 // the screen based on the new activity order. Note that
797 // as a result of this, it can call back into the activity
798 // manager with a new orientation. We don't care about that,
799 // because the activity is not currently running so we are
800 // just restarting it anyway.
801 if (checkConfig) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700802 Configuration config = mWindowManager.updateOrientationFromAppTokens(
Craig Mautner2420ead2013-04-01 17:13:20 -0700803 mService.mConfiguration,
804 r.mayFreezeScreenLocked(app) ? r.appToken : null);
805 mService.updateConfigurationLocked(config, r, false, false);
806 }
807
808 r.app = app;
809 app.waitingToKill = null;
810 r.launchCount++;
811 r.lastLaunchTime = SystemClock.uptimeMillis();
812
813 if (localLOGV) Slog.v(TAG, "Launching: " + r);
814
815 int idx = app.activities.indexOf(r);
816 if (idx < 0) {
817 app.activities.add(r);
818 }
819 mService.updateLruProcessLocked(app, true);
820
821 final ActivityStack stack = r.task.stack;
822 try {
823 if (app.thread == null) {
824 throw new RemoteException();
825 }
826 List<ResultInfo> results = null;
827 List<Intent> newIntents = null;
828 if (andResume) {
829 results = r.results;
830 newIntents = r.newIntents;
831 }
832 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
833 + " icicle=" + r.icicle
834 + " with results=" + results + " newIntents=" + newIntents
835 + " andResume=" + andResume);
836 if (andResume) {
837 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
838 r.userId, System.identityHashCode(r),
839 r.task.taskId, r.shortComponentName);
840 }
Craig Mautner86d67a42013-05-14 10:34:38 -0700841 if (r.isHomeActivity()) {
Craig Mautner2420ead2013-04-01 17:13:20 -0700842 mService.mHomeProcess = app;
843 }
844 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
845 r.sleeping = false;
846 r.forceNewConfig = false;
847 mService.showAskCompatModeDialogLocked(r);
848 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
849 String profileFile = null;
850 ParcelFileDescriptor profileFd = null;
851 boolean profileAutoStop = false;
852 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
853 if (mService.mProfileProc == null || mService.mProfileProc == app) {
854 mService.mProfileProc = app;
855 profileFile = mService.mProfileFile;
856 profileFd = mService.mProfileFd;
857 profileAutoStop = mService.mAutoStopProfiler;
858 }
859 }
860 app.hasShownUi = true;
861 app.pendingUiClean = true;
862 if (profileFd != null) {
863 try {
864 profileFd = profileFd.dup();
865 } catch (IOException e) {
866 if (profileFd != null) {
867 try {
868 profileFd.close();
869 } catch (IOException o) {
870 }
871 profileFd = null;
872 }
873 }
874 }
875 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
876 System.identityHashCode(r), r.info,
877 new Configuration(mService.mConfiguration),
878 r.compat, r.icicle, results, newIntents, !andResume,
879 mService.isNextTransitionForward(), profileFile, profileFd,
880 profileAutoStop);
881
882 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
883 // This may be a heavy-weight process! Note that the package
884 // manager will ensure that only activity can run in the main
885 // process of the .apk, which is the only thing that will be
886 // considered heavy-weight.
887 if (app.processName.equals(app.info.packageName)) {
888 if (mService.mHeavyWeightProcess != null
889 && mService.mHeavyWeightProcess != app) {
890 Slog.w(TAG, "Starting new heavy weight process " + app
891 + " when already running "
892 + mService.mHeavyWeightProcess);
893 }
894 mService.mHeavyWeightProcess = app;
895 Message msg = mService.mHandler.obtainMessage(
896 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
897 msg.obj = r;
898 mService.mHandler.sendMessage(msg);
899 }
900 }
901
902 } catch (RemoteException e) {
903 if (r.launchFailed) {
904 // This is the second time we failed -- finish activity
905 // and give up.
906 Slog.e(TAG, "Second failure launching "
907 + r.intent.getComponent().flattenToShortString()
908 + ", giving up", e);
909 mService.appDiedLocked(app, app.pid, app.thread);
910 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
911 "2nd-crash", false);
912 return false;
913 }
914
915 // This is the first time we failed -- restart process and
916 // retry.
917 app.activities.remove(r);
918 throw e;
919 }
920
921 r.launchFailed = false;
922 if (stack.updateLRUListLocked(r)) {
923 Slog.w(TAG, "Activity " + r
924 + " being launched, but already in LRU list");
925 }
926
927 if (andResume) {
928 // As part of the process of launching, ActivityThread also performs
929 // a resume.
930 stack.minimalResumeActivityLocked(r);
931 } else {
932 // This activity is not starting in the resumed state... which
933 // should look like we asked it to pause+stop (but remain visible),
934 // and it has done so and reported back the current icicle and
935 // other state.
936 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
937 + " (starting in stopped state)");
938 r.state = ActivityState.STOPPED;
939 r.stopped = true;
940 }
941
942 // Launch the new version setup screen if needed. We do this -after-
943 // launching the initial activity (that is, home), so that it can have
944 // a chance to initialize itself while in the background, making the
945 // switch back to it faster and look better.
Craig Mautnerde4ef022013-04-07 19:01:33 -0700946 if (isFrontStack(stack)) {
Craig Mautner2420ead2013-04-01 17:13:20 -0700947 mService.startSetupActivityLocked();
948 }
949
950 return true;
951 }
952
Craig Mautnere79d42682013-04-01 19:01:53 -0700953 void startSpecificActivityLocked(ActivityRecord r,
954 boolean andResume, boolean checkConfig) {
955 // Is this activity's application already running?
956 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
957 r.info.applicationInfo.uid);
958
959 r.task.stack.setLaunchTime(r);
960
961 if (app != null && app.thread != null) {
962 try {
963 app.addPackage(r.info.packageName);
964 realStartActivityLocked(r, app, andResume, checkConfig);
965 return;
966 } catch (RemoteException e) {
967 Slog.w(TAG, "Exception when starting activity "
968 + r.intent.getComponent().flattenToShortString(), e);
969 }
970
971 // If a dead object exception was thrown -- fall through to
972 // restart the application.
973 }
974
975 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
976 "activity", r.intent.getComponent(), false, false);
977 }
978
Craig Mautner6170f732013-04-02 13:05:23 -0700979 final int startActivityLocked(IApplicationThread caller,
980 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
981 String resultWho, int requestCode,
982 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
983 boolean componentSpecified, ActivityRecord[] outActivity) {
984 int err = ActivityManager.START_SUCCESS;
985
986 ProcessRecord callerApp = null;
987 if (caller != null) {
988 callerApp = mService.getRecordForAppLocked(caller);
989 if (callerApp != null) {
990 callingPid = callerApp.pid;
991 callingUid = callerApp.info.uid;
992 } else {
993 Slog.w(TAG, "Unable to find app for caller " + caller
994 + " (pid=" + callingPid + ") when starting: "
995 + intent.toString());
996 err = ActivityManager.START_PERMISSION_DENIED;
997 }
998 }
999
1000 if (err == ActivityManager.START_SUCCESS) {
1001 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
1002 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
1003 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
1004 }
1005
1006 ActivityRecord sourceRecord = null;
1007 ActivityRecord resultRecord = null;
1008 if (resultTo != null) {
1009 sourceRecord = isInAnyStackLocked(resultTo);
1010 if (DEBUG_RESULTS) Slog.v(
1011 TAG, "Will send result to " + resultTo + " " + sourceRecord);
1012 if (sourceRecord != null) {
1013 if (requestCode >= 0 && !sourceRecord.finishing) {
1014 resultRecord = sourceRecord;
1015 }
1016 }
1017 }
1018 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
1019
1020 int launchFlags = intent.getFlags();
1021
1022 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
1023 && sourceRecord != null) {
1024 // Transfer the result target from the source activity to the new
1025 // one being started, including any failures.
1026 if (requestCode >= 0) {
1027 ActivityOptions.abort(options);
1028 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
1029 }
1030 resultRecord = sourceRecord.resultTo;
1031 resultWho = sourceRecord.resultWho;
1032 requestCode = sourceRecord.requestCode;
1033 sourceRecord.resultTo = null;
1034 if (resultRecord != null) {
1035 resultRecord.removeResultsLocked(
1036 sourceRecord, resultWho, requestCode);
1037 }
1038 }
1039
1040 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
1041 // We couldn't find a class that can handle the given Intent.
1042 // That's the end of that!
1043 err = ActivityManager.START_INTENT_NOT_RESOLVED;
1044 }
1045
1046 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
1047 // We couldn't find the specific class specified in the Intent.
1048 // Also the end of the line.
1049 err = ActivityManager.START_CLASS_NOT_FOUND;
1050 }
1051
1052 if (err != ActivityManager.START_SUCCESS) {
1053 if (resultRecord != null) {
1054 resultStack.sendActivityResultLocked(-1,
1055 resultRecord, resultWho, requestCode,
1056 Activity.RESULT_CANCELED, null);
1057 }
1058 setDismissKeyguard(false);
1059 ActivityOptions.abort(options);
1060 return err;
1061 }
1062
1063 final int startAnyPerm = mService.checkPermission(
1064 START_ANY_ACTIVITY, callingPid, callingUid);
1065 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
1066 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
1067 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
1068 if (resultRecord != null) {
1069 resultStack.sendActivityResultLocked(-1,
1070 resultRecord, resultWho, requestCode,
1071 Activity.RESULT_CANCELED, null);
1072 }
1073 setDismissKeyguard(false);
1074 String msg;
1075 if (!aInfo.exported) {
1076 msg = "Permission Denial: starting " + intent.toString()
1077 + " from " + callerApp + " (pid=" + callingPid
1078 + ", uid=" + callingUid + ")"
1079 + " not exported from uid " + aInfo.applicationInfo.uid;
1080 } else {
1081 msg = "Permission Denial: starting " + intent.toString()
1082 + " from " + callerApp + " (pid=" + callingPid
1083 + ", uid=" + callingUid + ")"
1084 + " requires " + aInfo.permission;
1085 }
1086 Slog.w(TAG, msg);
1087 throw new SecurityException(msg);
1088 }
1089
Ben Gruver6617c3c2013-04-03 18:45:22 -07001090 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
Ben Gruver7b879f42013-04-08 14:56:55 -07001091 callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo);
Ben Gruver5e207332013-04-03 17:41:37 -07001092
Craig Mautner6170f732013-04-02 13:05:23 -07001093 if (mService.mController != null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001094 try {
1095 // The Intent we give to the watcher has the extra data
1096 // stripped off, since it can contain private information.
1097 Intent watchIntent = intent.cloneFilter();
Ben Gruver5e207332013-04-03 17:41:37 -07001098 abort |= !mService.mController.activityStarting(watchIntent,
Craig Mautner6170f732013-04-02 13:05:23 -07001099 aInfo.applicationInfo.packageName);
1100 } catch (RemoteException e) {
1101 mService.mController = null;
1102 }
Ben Gruver5e207332013-04-03 17:41:37 -07001103 }
Craig Mautner6170f732013-04-02 13:05:23 -07001104
Ben Gruver5e207332013-04-03 17:41:37 -07001105 if (abort) {
1106 if (resultRecord != null) {
1107 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Craig Mautner6170f732013-04-02 13:05:23 -07001108 Activity.RESULT_CANCELED, null);
Craig Mautner6170f732013-04-02 13:05:23 -07001109 }
Ben Gruver5e207332013-04-03 17:41:37 -07001110 // We pretend to the caller that it was really started, but
1111 // they will just get a cancel result.
1112 setDismissKeyguard(false);
1113 ActivityOptions.abort(options);
1114 return ActivityManager.START_SUCCESS;
Craig Mautner6170f732013-04-02 13:05:23 -07001115 }
1116
1117 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1118 intent, resolvedType, aInfo, mService.mConfiguration,
Craig Mautnerde4ef022013-04-07 19:01:33 -07001119 resultRecord, resultWho, requestCode, componentSpecified, this);
Craig Mautner6170f732013-04-02 13:05:23 -07001120 if (outActivity != null) {
1121 outActivity[0] = r;
1122 }
1123
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001124 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001125 if (stack.mResumedActivity == null
1126 || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
Craig Mautner6170f732013-04-02 13:05:23 -07001127 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1128 PendingActivityLaunch pal =
Craig Mautnerde4ef022013-04-07 19:01:33 -07001129 new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
Craig Mautner6170f732013-04-02 13:05:23 -07001130 mService.mPendingActivityLaunches.add(pal);
1131 setDismissKeyguard(false);
1132 ActivityOptions.abort(options);
1133 return ActivityManager.START_SWITCHES_CANCELED;
1134 }
1135 }
1136
1137 if (mService.mDidAppSwitch) {
1138 // This is the second allowed switch since we stopped switches,
1139 // so now just generally allow switches. Use case: user presses
1140 // home (switches disabled, switch to home, mDidAppSwitch now true);
1141 // user taps a home icon (coming from home so allowed, we hit here
1142 // and now allow anyone to switch again).
1143 mService.mAppSwitchesAllowedTime = 0;
1144 } else {
1145 mService.mDidAppSwitch = true;
1146 }
1147
1148 mService.doPendingActivityLaunchesLocked(false);
1149
Craig Mautner8849a5e2013-04-02 16:41:03 -07001150 err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001151 if (stack.mPausingActivity == null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001152 // Someone asked to have the keyguard dismissed on the next
1153 // activity start, but we are not actually doing an activity
1154 // switch... just dismiss the keyguard now, because we
1155 // probably want to see whatever is behind it.
1156 dismissKeyguard();
1157 }
1158 return err;
1159 }
1160
Craig Mautnerde4ef022013-04-07 19:01:33 -07001161 ActivityStack getCorrectStack(ActivityRecord r) {
Craig Mautner86d67a42013-05-14 10:34:38 -07001162 if (r.isApplicationActivity() || (r.task != null && r.task.isApplicationTask())) {
Craig Mautner858d8a62013-04-23 17:08:34 -07001163 int stackNdx;
1164 for (stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
1165 if (mStacks.get(stackNdx).mCurrentUser == mCurrentUser) {
1166 break;
1167 }
1168 }
1169 if (stackNdx == 0) {
1170 // Time to create the first app stack for this user.
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001171 int stackId = mService.createStack(-1, HOME_STACK_ID,
1172 StackBox.TASK_STACK_GOES_OVER, 1.0f);
Craig Mautner29219d92013-04-16 20:19:12 -07001173 mFocusedStack = getStack(stackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001174 }
Craig Mautner29219d92013-04-16 20:19:12 -07001175 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001176 }
1177 return mHomeStack;
1178 }
1179
Craig Mautner29219d92013-04-16 20:19:12 -07001180 void setFocusedStack(ActivityRecord r) {
1181 if (r == null) {
1182 return;
1183 }
Craig Mautner86d67a42013-05-14 10:34:38 -07001184 if (!r.isApplicationActivity() || (r.task != null && !r.task.isApplicationTask())) {
Craig Mautner29219d92013-04-16 20:19:12 -07001185 if (mStackState != STACK_STATE_HOME_IN_FRONT) {
Craig Mautner76ea2242013-05-15 11:40:05 -07001186 if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
1187 stackStateToString(mStackState) + " new=" +
1188 stackStateToString(STACK_STATE_HOME_TO_FRONT) +
1189 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001190 mStackState = STACK_STATE_HOME_TO_FRONT;
1191 }
1192 } else {
1193 mFocusedStack = r.task.stack;
1194 if (mStackState != STACK_STATE_HOME_IN_BACK) {
Craig Mautner76ea2242013-05-15 11:40:05 -07001195 if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
1196 stackStateToString(mStackState) + " new=" +
1197 stackStateToString(STACK_STATE_HOME_TO_BACK) +
1198 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001199 mStackState = STACK_STATE_HOME_TO_BACK;
1200 }
1201 }
1202 }
1203
Craig Mautner8849a5e2013-04-02 16:41:03 -07001204 final int startActivityUncheckedLocked(ActivityRecord r,
1205 ActivityRecord sourceRecord, int startFlags, boolean doResume,
1206 Bundle options) {
1207 final Intent intent = r.intent;
1208 final int callingUid = r.launchedFromUid;
1209
1210 int launchFlags = intent.getFlags();
1211
Craig Mautner8849a5e2013-04-02 16:41:03 -07001212 // We'll invoke onUserLeaving before onPause only if the launching
1213 // activity did not explicitly state that this is an automated launch.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001214 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1215 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001216
1217 // If the caller has asked not to resume at this point, we make note
1218 // of this in the record so that we can skip it when trying to find
1219 // the top running activity.
1220 if (!doResume) {
1221 r.delayedResume = true;
1222 }
1223
1224 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1225
1226 // If the onlyIfNeeded flag is set, then we can do this if the activity
1227 // being launched is the same as the one making the call... or, as
1228 // a special case, if we do not know the caller then we count the
1229 // current top activity as the caller.
1230 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1231 ActivityRecord checkedCaller = sourceRecord;
1232 if (checkedCaller == null) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001233 checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001234 }
1235 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1236 // Caller is not the same as launcher, so always needed.
1237 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1238 }
1239 }
1240
1241 if (sourceRecord == null) {
1242 // This activity is not being started from another... in this
1243 // case we -always- start a new task.
1244 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Craig Mautner29219d92013-04-16 20:19:12 -07001245 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1246 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001247 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1248 }
1249 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1250 // The original activity who is starting us is running as a single
1251 // instance... this new activity it is starting must go on its
1252 // own task.
1253 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1254 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1255 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1256 // The activity being started is a single instance... it always
1257 // gets launched into its own task.
1258 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1259 }
1260
Craig Mautnerde4ef022013-04-07 19:01:33 -07001261 final ActivityStack sourceStack;
Craig Mautner525f3d92013-05-07 14:01:50 -07001262 TaskRecord sourceTask;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001263 if (sourceRecord != null) {
1264 sourceTask = sourceRecord.task;
1265 sourceStack = sourceTask.stack;
1266 } else {
1267 sourceTask = null;
1268 sourceStack = null;
1269 }
1270
Craig Mautner8849a5e2013-04-02 16:41:03 -07001271 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1272 // For whatever reason this activity is being launched into a new
1273 // task... yet the caller has requested a result back. Well, that
1274 // is pretty messed up, so instead immediately send back a cancel
1275 // and let the new task continue launched as normal without a
1276 // dependency on its originator.
1277 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1278 r.resultTo.task.stack.sendActivityResultLocked(-1,
1279 r.resultTo, r.resultWho, r.requestCode,
1280 Activity.RESULT_CANCELED, null);
1281 r.resultTo = null;
1282 }
1283
1284 boolean addingToTask = false;
1285 boolean movedHome = false;
1286 TaskRecord reuseTask = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001287 ActivityStack targetStack;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001288 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1289 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1290 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1291 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1292 // If bring to front is requested, and no result is requested, and
1293 // we can find a task that was started with this same
1294 // component, then instead of launching bring that one to the front.
1295 if (r.resultTo == null) {
1296 // See if there is a task to bring to the front. If this is
1297 // a SINGLE_INSTANCE activity, there can be one and only one
1298 // instance of it in the history, and it is always in its own
1299 // unique task, so we do a special search.
1300 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
1301 ? findTaskLocked(intent, r.info)
1302 : findActivityLocked(intent, r.info);
1303 if (intentActivity != null) {
Craig Mautner29219d92013-04-16 20:19:12 -07001304 if (r.task == null) {
1305 r.task = intentActivity.task;
1306 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001307 targetStack = intentActivity.task.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001308 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001309 if (intentActivity.task.intent == null) {
1310 // This task was started because of movement of
1311 // the activity based on affinity... now that we
1312 // are actually launching it, we can assign the
1313 // base intent.
1314 intentActivity.task.setIntent(intent, r.info);
1315 }
1316 // If the target task is not in the front, then we need
1317 // to bring it to the front... except... well, with
1318 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
1319 // to have the same behavior as if a new instance was
1320 // being started, which means not bringing it to the front
1321 // if the caller is not itself in the front.
Craig Mautner165640b2013-04-20 10:34:33 -07001322 final ActivityStack lastStack = getLastStack();
1323 ActivityRecord curTop = lastStack == null?
1324 null : lastStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001325 if (curTop != null && curTop.task != intentActivity.task) {
1326 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001327 if (sourceRecord == null || sourceStack.topActivity() == sourceRecord) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001328 // We really do want to push this one into the
1329 // user's face, right now.
1330 movedHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001331 if ((launchFlags &
Craig Mautner29219d92013-04-16 20:19:12 -07001332 (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1333 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001334 // Caller wants to appear on home activity, so before starting
1335 // their own activity we will bring home to the front.
1336 r.mLaunchHomeTaskNext = true;
1337 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001338 targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1339 options = null;
1340 }
1341 }
1342 // If the caller has requested that the target task be
1343 // reset, then do so.
1344 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1345 intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1346 }
1347 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1348 // We don't need to start a new activity, and
1349 // the client said not to do anything if that
1350 // is the case, so this is it! And for paranoia, make
1351 // sure we have correctly resumed the top activity.
1352 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001353 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001354 resumeTopActivitiesLocked(targetStack, null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001355 } else {
1356 ActivityOptions.abort(options);
1357 }
Craig Mautner29219d92013-04-16 20:19:12 -07001358 if (r.task == null) Slog.v(TAG,
1359 "startActivityUncheckedLocked: task left null",
1360 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001361 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1362 }
1363 if ((launchFlags &
1364 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1365 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1366 // The caller has requested to completely replace any
1367 // existing task with its new activity. Well that should
1368 // not be too hard...
1369 reuseTask = intentActivity.task;
1370 reuseTask.performClearTaskLocked();
1371 reuseTask.setIntent(r.intent, r.info);
1372 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1373 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1374 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1375 // In this situation we want to remove all activities
1376 // from the task up to the one being started. In most
1377 // cases this means we are resetting the task to its
1378 // initial state.
1379 ActivityRecord top =
1380 intentActivity.task.performClearTaskLocked(r, launchFlags);
1381 if (top != null) {
1382 if (top.frontOfTask) {
1383 // Activity aliases may mean we use different
1384 // intents for the top activity, so make sure
1385 // the task now has the identity of the new
1386 // intent.
1387 top.task.setIntent(r.intent, r.info);
1388 }
1389 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1390 r, top.task);
1391 top.deliverNewIntentLocked(callingUid, r.intent);
1392 } else {
1393 // A special case: we need to
1394 // start the activity because it is not currently
1395 // running, and the caller has asked to clear the
1396 // current task to have this activity at the top.
1397 addingToTask = true;
1398 // Now pretend like this activity is being started
1399 // by the top of its task, so it is put in the
1400 // right place.
1401 sourceRecord = intentActivity;
1402 }
1403 } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1404 // In this case the top activity on the task is the
1405 // same as the one being launched, so we take that
1406 // as a request to bring the task to the foreground.
1407 // If the top activity in the task is the root
1408 // activity, deliver this new intent to it if it
1409 // desires.
1410 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1411 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1412 && intentActivity.realActivity.equals(r.realActivity)) {
1413 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1414 intentActivity.task);
1415 if (intentActivity.frontOfTask) {
1416 intentActivity.task.setIntent(r.intent, r.info);
1417 }
1418 intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1419 } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1420 // In this case we are launching the root activity
1421 // of the task, but with a different intent. We
1422 // should start a new instance on top.
1423 addingToTask = true;
1424 sourceRecord = intentActivity;
1425 }
1426 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1427 // In this case an activity is being launched in to an
1428 // existing task, without resetting that task. This
1429 // is typically the situation of launching an activity
1430 // from a notification or shortcut. We want to place
1431 // the new activity on top of the current task.
1432 addingToTask = true;
1433 sourceRecord = intentActivity;
1434 } else if (!intentActivity.task.rootWasReset) {
1435 // In this case we are launching in to an existing task
1436 // that has not yet been started from its front door.
1437 // The current task has been brought to the front.
1438 // Ideally, we'd probably like to place this new task
1439 // at the bottom of its stack, but that's a little hard
1440 // to do with the current organization of the code so
1441 // for now we'll just drop it.
1442 intentActivity.task.setIntent(r.intent, r.info);
1443 }
1444 if (!addingToTask && reuseTask == null) {
1445 // We didn't do anything... but it was needed (a.k.a., client
1446 // don't use that intent!) And for paranoia, make
1447 // sure we have correctly resumed the top activity.
1448 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001449 setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1450 targetStack.resumeTopActivityLocked(null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001451 } else {
1452 ActivityOptions.abort(options);
1453 }
Craig Mautner29219d92013-04-16 20:19:12 -07001454 if (r.task == null) Slog.v(TAG,
1455 "startActivityUncheckedLocked: task left null",
1456 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001457 return ActivityManager.START_TASK_TO_FRONT;
1458 }
1459 }
1460 }
1461 }
1462
1463 //String uri = r.intent.toURI();
1464 //Intent intent2 = new Intent(uri);
1465 //Slog.i(TAG, "Given intent: " + r.intent);
1466 //Slog.i(TAG, "URI is: " + uri);
1467 //Slog.i(TAG, "To intent: " + intent2);
1468
1469 if (r.packageName != null) {
1470 // If the activity being launched is the same as the one currently
1471 // at the top, then we need to check if it should only be launched
1472 // once.
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001473 ActivityStack topStack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001474 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001475 if (top != null && r.resultTo == null) {
1476 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1477 if (top.app != null && top.app.thread != null) {
1478 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1479 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1480 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1481 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1482 top.task);
1483 // For paranoia, make sure we have correctly
1484 // resumed the top activity.
1485 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001486 setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001487 resumeTopActivitiesLocked();
Craig Mautner8849a5e2013-04-02 16:41:03 -07001488 }
1489 ActivityOptions.abort(options);
1490 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1491 // We don't need to start a new activity, and
1492 // the client said not to do anything if that
1493 // is the case, so this is it!
Craig Mautner29219d92013-04-16 20:19:12 -07001494 if (r.task == null) Slog.v(TAG,
1495 "startActivityUncheckedLocked: task left null",
1496 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001497 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1498 }
1499 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner29219d92013-04-16 20:19:12 -07001500 if (r.task == null) Slog.v(TAG,
1501 "startActivityUncheckedLocked: task left null",
1502 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001503 return ActivityManager.START_DELIVERED_TO_TOP;
1504 }
1505 }
1506 }
1507 }
1508
1509 } else {
1510 if (r.resultTo != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001511 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1512 r.requestCode, Activity.RESULT_CANCELED, null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001513 }
1514 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001515 if (r.task == null) Slog.v(TAG,
1516 "startActivityUncheckedLocked: task left null",
1517 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001518 return ActivityManager.START_CLASS_NOT_FOUND;
1519 }
1520
1521 boolean newTask = false;
1522 boolean keepCurTransition = false;
1523
1524 // Should this be considered a new task?
1525 if (r.resultTo == null && !addingToTask
1526 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001527 targetStack = getCorrectStack(r);
1528 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001529 if (reuseTask == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001530 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1531 null, true);
1532 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1533 r.task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001534 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001535 r.setTask(reuseTask, reuseTask, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001536 }
1537 newTask = true;
1538 if (!movedHome) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001539 if ((launchFlags &
1540 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1541 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1542 // Caller wants to appear on home activity, so before starting
1543 // their own activity we will bring home to the front.
1544 r.mLaunchHomeTaskNext = true;
1545 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001546 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001547 } else if (sourceRecord != null) {
Craig Mautner525f3d92013-05-07 14:01:50 -07001548 sourceTask = sourceRecord.task;
1549 targetStack = sourceTask.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001550 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001551 if (!addingToTask &&
1552 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1553 // In this case, we are adding the activity to an existing
1554 // task, but the caller has asked to clear that task if the
1555 // activity is already running.
Craig Mautner525f3d92013-05-07 14:01:50 -07001556 ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001557 keepCurTransition = true;
1558 if (top != null) {
1559 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1560 top.deliverNewIntentLocked(callingUid, r.intent);
1561 // For paranoia, make sure we have correctly
1562 // resumed the top activity.
1563 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001564 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001565 targetStack.resumeTopActivityLocked(null);
1566 }
1567 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001568 if (r.task == null) Slog.v(TAG,
1569 "startActivityUncheckedLocked: task left null",
1570 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001571 return ActivityManager.START_DELIVERED_TO_TOP;
1572 }
1573 } else if (!addingToTask &&
1574 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1575 // In this case, we are launching an activity in our own task
1576 // that may already be running somewhere in the history, and
1577 // we want to shuffle it to the front of the stack if so.
Craig Mautner525f3d92013-05-07 14:01:50 -07001578 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001579 if (top != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001580 final TaskRecord task = top.task;
1581 task.moveActivityToFrontLocked(top);
1582 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001583 top.updateOptionsLocked(options);
1584 top.deliverNewIntentLocked(callingUid, r.intent);
1585 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001586 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001587 targetStack.resumeTopActivityLocked(null);
1588 }
Craig Mautner29219d92013-04-16 20:19:12 -07001589 if (r.task == null) Slog.v(TAG,
1590 "startActivityUncheckedLocked: task left null",
1591 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001592 return ActivityManager.START_DELIVERED_TO_TOP;
1593 }
1594 }
1595 // An existing activity is starting this new activity, so we want
1596 // to keep the new one in the same task as the one that is starting
1597 // it.
Craig Mautner525f3d92013-05-07 14:01:50 -07001598 r.setTask(sourceTask, sourceRecord.thumbHolder, false);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001599 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1600 + " in existing task " + r.task);
1601
1602 } else {
1603 // This not being started from an existing activity, and not part
1604 // of a new task... just put it in the top task, though these days
1605 // this case should never happen.
Craig Mautner1602ec22013-05-12 10:24:27 -07001606 targetStack = getCorrectStack(r);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001607 moveHomeStack(targetStack.isHomeStack());
Craig Mautner1602ec22013-05-12 10:24:27 -07001608 ActivityRecord prev = targetStack.topActivity();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001609 r.setTask(prev != null ? prev.task
1610 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1611 null, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001612 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1613 + " in new guessed " + r.task);
1614 }
1615
1616 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1617 intent, r.getUriPermissionsLocked());
1618
1619 if (newTask) {
1620 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1621 }
1622 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001623 setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001624 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
1625 return ActivityManager.START_SUCCESS;
1626 }
1627
Craig Mautnerf3333272013-04-22 10:55:53 -07001628 // Checked.
1629 final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
1630 Configuration config) {
1631 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
1632
1633 ActivityRecord res = null;
1634
1635 ArrayList<ActivityRecord> stops = null;
1636 ArrayList<ActivityRecord> finishes = null;
1637 ArrayList<UserStartedState> startingUsers = null;
1638 int NS = 0;
1639 int NF = 0;
1640 IApplicationThread sendThumbnail = null;
1641 boolean booting = false;
1642 boolean enableScreen = false;
1643 boolean activityRemoved = false;
1644
1645 ActivityRecord r = ActivityRecord.forToken(token);
1646 if (r != null) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07001647 if (DEBUG_IDLE) Slog.d(TAG, "activityIdleInternalLocked: Callers=" +
1648 Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07001649 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
1650 r.finishLaunchTickingLocked();
Craig Mautner525f3d92013-05-07 14:01:50 -07001651 res = r.task.stack.activityIdleInternalLocked(token);
Craig Mautnerf3333272013-04-22 10:55:53 -07001652 if (res != null) {
1653 if (fromTimeout) {
1654 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
1655 }
1656
1657 // This is a hack to semi-deal with a race condition
1658 // in the client where it can be constructed with a
1659 // newer configuration from when we asked it to launch.
1660 // We'll update with whatever configuration it now says
1661 // it used to launch.
1662 if (config != null) {
1663 r.configuration = config;
1664 }
1665
1666 // We are now idle. If someone is waiting for a thumbnail from
1667 // us, we can now deliver.
1668 r.idle = true;
1669 if (allResumedActivitiesIdle()) {
1670 mService.scheduleAppGcsLocked();
1671 }
1672 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
1673 sendThumbnail = r.app.thread;
1674 r.thumbnailNeeded = false;
1675 }
1676
1677 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
1678 if (!mService.mBooted && isFrontStack(r.task.stack)) {
1679 mService.mBooted = true;
1680 enableScreen = true;
1681 }
1682 } else if (fromTimeout) {
1683 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
1684 }
1685 }
1686
1687 // Atomically retrieve all of the other things to do.
1688 stops = processStoppingActivitiesLocked(true);
1689 NS = stops != null ? stops.size() : 0;
1690 if ((NF=mFinishingActivities.size()) > 0) {
1691 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
1692 mFinishingActivities.clear();
1693 }
1694
1695 final ArrayList<ActivityRecord> thumbnails;
1696 final int NT = mCancelledThumbnails.size();
1697 if (NT > 0) {
1698 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
1699 mCancelledThumbnails.clear();
1700 } else {
1701 thumbnails = null;
1702 }
1703
1704 if (isFrontStack(mHomeStack)) {
1705 booting = mService.mBooting;
1706 mService.mBooting = false;
1707 }
1708
1709 if (mStartingUsers.size() > 0) {
1710 startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
1711 mStartingUsers.clear();
1712 }
1713
1714 // Perform the following actions from unsynchronized state.
1715 final IApplicationThread thumbnailThread = sendThumbnail;
1716 mHandler.post(new Runnable() {
1717 @Override
1718 public void run() {
1719 if (thumbnailThread != null) {
1720 try {
1721 thumbnailThread.requestThumbnail(token);
1722 } catch (Exception e) {
1723 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
1724 mService.sendPendingThumbnail(null, token, null, null, true);
1725 }
1726 }
1727
1728 // Report back to any thumbnail receivers.
1729 for (int i = 0; i < NT; i++) {
1730 ActivityRecord r = thumbnails.get(i);
1731 mService.sendPendingThumbnail(r, null, null, null, true);
1732 }
1733 }
1734 });
1735
1736 // Stop any activities that are scheduled to do so but have been
1737 // waiting for the next one to start.
1738 for (int i = 0; i < NS; i++) {
1739 r = stops.get(i);
1740 final ActivityStack stack = r.task.stack;
1741 if (r.finishing) {
1742 stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
1743 } else {
1744 stack.stopActivityLocked(r);
1745 }
1746 }
1747
1748 // Finish any activities that are scheduled to do so but have been
1749 // waiting for the next one to start.
1750 for (int i = 0; i < NF; i++) {
1751 r = finishes.get(i);
1752 activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle");
1753 }
1754
1755 if (booting) {
1756 mService.finishBooting();
1757 } else if (startingUsers != null) {
1758 for (int i = 0; i < startingUsers.size(); i++) {
1759 mService.finishUserSwitch(startingUsers.get(i));
1760 }
1761 }
1762
1763 mService.trimApplications();
1764 //dump();
1765 //mWindowManager.dump();
1766
1767 if (enableScreen) {
1768 mService.enableScreenAfterBoot();
1769 }
1770
1771 if (activityRemoved) {
Craig Mautner05d29032013-05-03 13:40:13 -07001772 resumeTopActivitiesLocked();
Craig Mautnerf3333272013-04-22 10:55:53 -07001773 }
1774
1775 return res;
1776 }
1777
Craig Mautner8d341ef2013-03-26 09:03:27 -07001778 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
1779 // Just in case.
1780 final int numStacks = mStacks.size();
1781 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Craig Mautnere79d42682013-04-01 19:01:53 -07001782 mStacks.get(stackNdx).handleAppDiedLocked(app, restarting);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001783 }
1784 }
1785
1786 void closeSystemDialogsLocked() {
1787 final int numStacks = mStacks.size();
1788 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1789 final ActivityStack stack = mStacks.get(stackNdx);
1790 stack.closeSystemDialogsLocked();
1791 }
1792 }
1793
1794 /**
1795 * @return true if some activity was finished (or would have finished if doit were true).
1796 */
1797 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1798 boolean didSomething = false;
1799 final int numStacks = mStacks.size();
1800 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1801 final ActivityStack stack = mStacks.get(stackNdx);
1802 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1803 didSomething = true;
1804 }
1805 }
1806 return didSomething;
1807 }
1808
Craig Mautner05d29032013-05-03 13:40:13 -07001809 boolean resumeTopActivitiesLocked() {
1810 return resumeTopActivitiesLocked(null, null, null);
1811 }
1812
1813 boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
1814 Bundle targetOptions) {
1815 if (targetStack == null) {
1816 targetStack = getFocusedStack();
1817 }
1818 boolean result = false;
Craig Mautnerdbcb31f2013-04-02 12:32:53 -07001819 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001820 final ActivityStack stack = mStacks.get(stackNdx);
1821 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07001822 if (stack == targetStack) {
1823 result = stack.resumeTopActivityLocked(target, targetOptions);
1824 } else {
1825 stack.resumeTopActivityLocked(null);
1826 }
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001827 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001828 }
Craig Mautner05d29032013-05-03 13:40:13 -07001829 return result;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001830 }
1831
1832 void finishTopRunningActivityLocked(ProcessRecord app) {
1833 final int numStacks = mStacks.size();
1834 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1835 final ActivityStack stack = mStacks.get(stackNdx);
1836 stack.finishTopRunningActivityLocked(app);
1837 }
1838 }
1839
Craig Mautner8d341ef2013-03-26 09:03:27 -07001840 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
1841 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1842 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
1843 return;
1844 }
1845 }
1846 }
1847
Craig Mautner967212c2013-04-13 21:10:58 -07001848 ActivityStack getStack(int stackId) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001849 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1850 final ActivityStack stack = mStacks.get(stackNdx);
1851 if (stack.getStackId() == stackId) {
1852 return stack;
1853 }
1854 }
1855 return null;
1856 }
1857
Craig Mautner967212c2013-04-13 21:10:58 -07001858 ArrayList<ActivityStack> getStacks() {
1859 return new ArrayList<ActivityStack>(mStacks);
1860 }
1861
1862 int createStack() {
Craig Mautner858d8a62013-04-23 17:08:34 -07001863 while (true) {
1864 if (++mLastStackId <= HOME_STACK_ID) {
1865 mLastStackId = HOME_STACK_ID + 1;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001866 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001867 if (getStack(mLastStackId) == null) {
1868 break;
1869 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001870 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001871 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
1872 return mLastStackId;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001873 }
1874
1875 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
1876 final ActivityStack stack = getStack(stackId);
1877 if (stack == null) {
1878 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
1879 return;
1880 }
1881 stack.moveTask(taskId, toTop);
Craig Mautner05d29032013-05-03 13:40:13 -07001882 resumeTopActivitiesLocked();
Craig Mautner8d341ef2013-03-26 09:03:27 -07001883 }
1884
Craig Mautner8849a5e2013-04-02 16:41:03 -07001885 ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
1886 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1887 final ActivityRecord ar = mStacks.get(stackNdx).findTaskLocked(intent, info);
1888 if (ar != null) {
1889 return ar;
1890 }
1891 }
1892 return null;
1893 }
1894
1895 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
1896 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1897 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
1898 if (ar != null) {
1899 return ar;
1900 }
1901 }
1902 return null;
1903 }
1904
Craig Mautner8d341ef2013-03-26 09:03:27 -07001905 void goingToSleepLocked() {
1906 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1907 mStacks.get(stackNdx).stopIfSleepingLocked();
1908 }
1909 }
1910
1911 boolean shutdownLocked(int timeout) {
1912 boolean timedout = false;
1913 final int numStacks = mStacks.size();
1914 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1915 final ActivityStack stack = mStacks.get(stackNdx);
1916 if (stack.mResumedActivity != null) {
1917 stack.stopIfSleepingLocked();
1918 final long endTime = System.currentTimeMillis() + timeout;
1919 while (stack.mResumedActivity != null || stack.mPausingActivity != null) {
1920 long delay = endTime - System.currentTimeMillis();
1921 if (delay <= 0) {
1922 Slog.w(TAG, "Activity manager shutdown timed out");
1923 timedout = true;
1924 break;
1925 }
1926 try {
1927 mService.wait();
1928 } catch (InterruptedException e) {
1929 }
1930 }
1931 }
1932 }
1933 return timedout;
1934 }
1935
1936 void comeOutOfSleepIfNeededLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001937 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001938 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001939 stack.awakeFromSleepingLocked();
1940 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07001941 resumeTopActivitiesLocked();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001942 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001943 }
1944 }
1945
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001946 boolean reportResumedActivityLocked(ActivityRecord r) {
1947 final ActivityStack stack = r.task.stack;
1948 if (isFrontStack(stack)) {
Jeff Sharkey5782da72013-04-25 14:32:30 -07001949 mService.updateUsageStats(r, true);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001950 mService.setFocusedActivityLocked(r);
1951 }
1952 if (allResumedActivitiesComplete()) {
1953 ensureActivitiesVisibleLocked(null, 0);
1954 mWindowManager.executeAppTransition();
1955 return true;
1956 }
1957 return false;
1958 }
1959
Craig Mautner8d341ef2013-03-26 09:03:27 -07001960 void handleAppCrashLocked(ProcessRecord app) {
1961 final int numStacks = mStacks.size();
1962 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1963 final ActivityStack stack = mStacks.get(stackNdx);
1964 stack.handleAppCrashLocked(app);
1965 }
1966 }
1967
Craig Mautnerde4ef022013-04-07 19:01:33 -07001968 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
Craig Mautner580ea812013-04-25 12:58:38 -07001969 // First the front stacks. In case any are not fullscreen and are in front of home.
1970 boolean showHomeBehindStack = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001971 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner580ea812013-04-25 12:58:38 -07001972 final ActivityStack stack = mStacks.get(stackNdx);
1973 if (isFrontStack(stack)) {
1974 showHomeBehindStack =
1975 stack.ensureActivitiesVisibleLocked(starting, configChanges);
1976 }
1977 }
1978 // Now do back stacks.
1979 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1980 final ActivityStack stack = mStacks.get(stackNdx);
1981 if (!isFrontStack(stack)) {
1982 stack.ensureActivitiesVisibleLocked(starting, configChanges, showHomeBehindStack);
1983 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001984 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001985 }
1986
1987 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
1988 final int numStacks = mStacks.size();
1989 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1990 final ActivityStack stack = mStacks.get(stackNdx);
1991 stack.scheduleDestroyActivities(app, false, reason);
1992 }
1993 }
1994
1995 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner858d8a62013-04-23 17:08:34 -07001996 mUserStates.put(mCurrentUser, new UserState());
Craig Mautner2420ead2013-04-01 17:13:20 -07001997 mCurrentUser = userId;
Craig Mautner858d8a62013-04-23 17:08:34 -07001998 UserState userState = mUserStates.get(userId);
1999 if (userState != null) {
2000 userState.restore();
2001 mUserStates.delete(userId);
2002 } else {
2003 mFocusedStack = null;
Craig Mautner76ea2242013-05-15 11:40:05 -07002004 if (DEBUG_STACK) Slog.d(TAG, "switchUserLocked: mStackState=" +
2005 stackStateToString(STACK_STATE_HOME_IN_FRONT));
Craig Mautner858d8a62013-04-23 17:08:34 -07002006 mStackState = STACK_STATE_HOME_IN_FRONT;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002007 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002008
2009 mStartingUsers.add(uss);
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002010 boolean haveActivities = mHomeStack.switchUserLocked(userId);
Craig Mautner858d8a62013-04-23 17:08:34 -07002011
2012 resumeTopActivitiesLocked();
2013
Craig Mautner8d341ef2013-03-26 09:03:27 -07002014 return haveActivities;
Craig Mautner2219a1b2013-03-25 09:44:30 -07002015 }
2016
Craig Mautnerde4ef022013-04-07 19:01:33 -07002017 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
2018 int N = mStoppingActivities.size();
2019 if (N <= 0) return null;
2020
2021 ArrayList<ActivityRecord> stops = null;
2022
2023 final boolean nowVisible = allResumedActivitiesVisible();
2024 for (int i=0; i<N; i++) {
2025 ActivityRecord s = mStoppingActivities.get(i);
2026 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
2027 + nowVisible + " waitingVisible=" + s.waitingVisible
2028 + " finishing=" + s.finishing);
2029 if (s.waitingVisible && nowVisible) {
2030 mWaitingVisibleActivities.remove(s);
2031 s.waitingVisible = false;
2032 if (s.finishing) {
2033 // If this activity is finishing, it is sitting on top of
2034 // everyone else but we now know it is no longer needed...
2035 // so get rid of it. Otherwise, we need to go through the
2036 // normal flow and hide it once we determine that it is
2037 // hidden by the activities in front of it.
2038 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002039 mWindowManager.setAppVisibility(s.appToken, false);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002040 }
2041 }
2042 if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
2043 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
2044 if (stops == null) {
2045 stops = new ArrayList<ActivityRecord>();
2046 }
2047 stops.add(s);
2048 mStoppingActivities.remove(i);
2049 N--;
2050 i--;
2051 }
2052 }
2053
2054 return stops;
2055 }
2056
Craig Mautnercf910b02013-04-23 11:23:27 -07002057 void validateTopActivitiesLocked() {
2058 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2059 final ActivityStack stack = mStacks.get(stackNdx);
2060 final ActivityRecord r = stack.topRunningActivityLocked(null);
2061 if (isFrontStack(stack)) {
2062 if (r == null) {
2063 Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
2064 } else {
2065 if (stack.mPausingActivity != null) {
2066 Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
2067 " state=" + r.state);
2068 }
2069 if (r.state != ActivityState.INITIALIZING &&
2070 r.state != ActivityState.RESUMED) {
2071 Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
2072 " state=" + r.state);
2073 }
2074 }
2075 } else {
2076 if (stack.mResumedActivity != null) {
2077 Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
2078 " state=" + r.state);
2079 }
2080 if (r != null && (r.state == ActivityState.INITIALIZING
2081 || r.state == ActivityState.RESUMED)) {
2082 Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
2083 " state=" + r.state);
2084 }
2085 }
2086 }
2087 }
2088
Craig Mautner76ea2242013-05-15 11:40:05 -07002089 private static String stackStateToString(int stackState) {
2090 switch (stackState) {
2091 case STACK_STATE_HOME_IN_FRONT: return "STACK_STATE_HOME_IN_FRONT";
2092 case STACK_STATE_HOME_TO_BACK: return "STACK_STATE_HOME_TO_BACK";
2093 case STACK_STATE_HOME_IN_BACK: return "STACK_STATE_HOME_IN_BACK";
2094 case STACK_STATE_HOME_TO_FRONT: return "STACK_STATE_HOME_TO_FRONT";
2095 default: return "Unknown stackState=" + stackState;
2096 }
2097 }
2098
Craig Mautner27084302013-03-25 08:05:25 -07002099 public void dump(PrintWriter pw, String prefix) {
2100 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
2101 pw.println(mDismissKeyguardOnNextActivity);
Craig Mautner76ea2242013-05-15 11:40:05 -07002102 pw.print(prefix); pw.print("mStackState="); pw.println(stackStateToString(mStackState));
Craig Mautner27084302013-03-25 08:05:25 -07002103 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002104
Craig Mautner20e72272013-04-01 13:45:53 -07002105 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002106 return getFocusedStack().getDumpActivitiesLocked(name);
Craig Mautner20e72272013-04-01 13:45:53 -07002107 }
2108
Craig Mautner8d341ef2013-03-26 09:03:27 -07002109 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
2110 boolean dumpClient, String dumpPackage) {
Craig Mautner76ea2242013-05-15 11:40:05 -07002111 pw.print(" mStackState="); pw.println(stackStateToString(mStackState));
Craig Mautner8d341ef2013-03-26 09:03:27 -07002112 final int numStacks = mStacks.size();
2113 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2114 final ActivityStack stack = mStacks.get(stackNdx);
2115 pw.print(" Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
2116 stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
2117 pw.println(" ");
2118 pw.println(" Running activities (most recent first):");
2119 dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false,
2120 dumpPackage);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002121 if (stack.mGoingToSleepActivities.size() > 0) {
2122 pw.println(" ");
2123 pw.println(" Activities waiting to sleep:");
2124 dumpHistoryList(fd, pw, stack.mGoingToSleepActivities, " ", "Sleep", false,
2125 !dumpAll, false, dumpPackage);
2126 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002127
Craig Mautner8d341ef2013-03-26 09:03:27 -07002128 pw.print(" Stack #"); pw.println(mStacks.indexOf(stack));
2129 if (stack.mPausingActivity != null) {
2130 pw.println(" mPausingActivity: " + stack.mPausingActivity);
2131 }
2132 pw.println(" mResumedActivity: " + stack.mResumedActivity);
2133 if (dumpAll) {
2134 pw.println(" mLastPausedActivity: " + stack.mLastPausedActivity);
2135 pw.println(" mSleepTimeout: " + stack.mSleepTimeout);
2136 }
2137 }
2138
Craig Mautnerf3333272013-04-22 10:55:53 -07002139 if (mFinishingActivities.size() > 0) {
2140 pw.println(" ");
2141 pw.println(" Activities waiting to finish:");
2142 dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll, false,
2143 dumpPackage);
2144 }
2145
Craig Mautnerde4ef022013-04-07 19:01:33 -07002146 if (mStoppingActivities.size() > 0) {
2147 pw.println(" ");
2148 pw.println(" Activities waiting to stop:");
2149 dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, false,
2150 dumpPackage);
2151 }
2152
2153 if (mWaitingVisibleActivities.size() > 0) {
2154 pw.println(" ");
2155 pw.println(" Activities waiting for another to become visible:");
2156 dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
2157 false, dumpPackage);
2158 }
2159
Craig Mautner8d341ef2013-03-26 09:03:27 -07002160 if (dumpAll) {
2161 pw.println(" ");
2162 pw.println(" mCurTaskId: " + mCurTaskId);
2163 }
2164 return true;
2165 }
2166
Craig Mautner76ea2242013-05-15 11:40:05 -07002167 static void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
Craig Mautner8d341ef2013-03-26 09:03:27 -07002168 String prefix, String label, boolean complete, boolean brief, boolean client,
2169 String dumpPackage) {
2170 TaskRecord lastTask = null;
2171 boolean needNL = false;
2172 final String innerPrefix = prefix + " ";
2173 final String[] args = new String[0];
2174 for (int i=list.size()-1; i>=0; i--) {
2175 final ActivityRecord r = list.get(i);
2176 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
2177 continue;
2178 }
2179 final boolean full = !brief && (complete || !r.isInHistory());
2180 if (needNL) {
2181 pw.println(" ");
2182 needNL = false;
2183 }
2184 if (lastTask != r.task) {
2185 lastTask = r.task;
2186 pw.print(prefix);
2187 pw.print(full ? "* " : " ");
2188 pw.println(lastTask);
2189 if (full) {
2190 lastTask.dump(pw, prefix + " ");
2191 } else if (complete) {
2192 // Complete + brief == give a summary. Isn't that obvious?!?
2193 if (lastTask.intent != null) {
2194 pw.print(prefix); pw.print(" ");
2195 pw.println(lastTask.intent.toInsecureStringWithClip());
2196 }
2197 }
2198 }
2199 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
2200 pw.print(" #"); pw.print(i); pw.print(": ");
2201 pw.println(r);
2202 if (full) {
2203 r.dump(pw, innerPrefix);
2204 } else if (complete) {
2205 // Complete + brief == give a summary. Isn't that obvious?!?
2206 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
2207 if (r.app != null) {
2208 pw.print(innerPrefix); pw.println(r.app);
2209 }
2210 }
2211 if (client && r.app != null && r.app.thread != null) {
2212 // flush anything that is already in the PrintWriter since the thread is going
2213 // to write to the file descriptor directly
2214 pw.flush();
2215 try {
2216 TransferPipe tp = new TransferPipe();
2217 try {
2218 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
2219 r.appToken, innerPrefix, args);
2220 // Short timeout, since blocking here can
2221 // deadlock with the application.
2222 tp.go(fd, 2000);
2223 } finally {
2224 tp.kill();
2225 }
2226 } catch (IOException e) {
2227 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
2228 } catch (RemoteException e) {
2229 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
2230 }
2231 needNL = true;
2232 }
2233 }
2234 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002235
Craig Mautnerf3333272013-04-22 10:55:53 -07002236 void scheduleIdleTimeoutLocked(ActivityRecord next) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002237 if (DEBUG_IDLE) Slog.d(TAG, "scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4));
Craig Mautnerc64f73e2013-04-24 16:44:56 -07002238 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
2239 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
Craig Mautnerf3333272013-04-22 10:55:53 -07002240 }
2241
2242 final void scheduleIdleLocked() {
Craig Mautner05d29032013-05-03 13:40:13 -07002243 mHandler.sendEmptyMessage(IDLE_NOW_MSG);
Craig Mautnerf3333272013-04-22 10:55:53 -07002244 }
2245
2246 void removeTimeoutsForActivityLocked(ActivityRecord r) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002247 if (DEBUG_IDLE) Slog.d(TAG, "removeTimeoutsForActivity: Callers=" + Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07002248 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
2249 }
2250
Craig Mautner05d29032013-05-03 13:40:13 -07002251 final void scheduleResumeTopActivities() {
2252 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2253 }
2254
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002255 private final class ActivityStackSupervisorHandler extends Handler {
Craig Mautnerf3333272013-04-22 10:55:53 -07002256
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002257 public ActivityStackSupervisorHandler(Looper looper) {
2258 super(looper);
2259 }
2260
Craig Mautnerf3333272013-04-22 10:55:53 -07002261 void activityIdleInternal(ActivityRecord r) {
2262 synchronized (mService) {
2263 activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
2264 }
2265 }
2266
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002267 @Override
2268 public void handleMessage(Message msg) {
2269 switch (msg.what) {
Craig Mautnerf3333272013-04-22 10:55:53 -07002270 case IDLE_TIMEOUT_MSG: {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002271 if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_TIMEOUT_MSG: Callers=" +
2272 Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07002273 if (mService.mDidDexOpt) {
2274 mService.mDidDexOpt = false;
2275 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2276 nmsg.obj = msg.obj;
2277 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
2278 return;
2279 }
2280 // We don't at this point know if the activity is fullscreen,
2281 // so we need to be conservative and assume it isn't.
2282 activityIdleInternal((ActivityRecord)msg.obj);
2283 } break;
2284 case IDLE_NOW_MSG: {
2285 activityIdleInternal((ActivityRecord)msg.obj);
2286 } break;
Craig Mautner05d29032013-05-03 13:40:13 -07002287 case RESUME_TOP_ACTIVITY_MSG: {
2288 synchronized (mService) {
2289 resumeTopActivitiesLocked();
2290 }
2291 } break;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002292 }
2293 }
2294 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002295
2296 private final class UserState {
2297 final ActivityStack mSavedFocusedStack;
2298 final int mSavedStackState;
2299
2300 public UserState() {
2301 ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2302 mSavedFocusedStack = supervisor.mFocusedStack;
2303 mSavedStackState = supervisor.mStackState;
2304 }
2305
2306 void restore() {
2307 ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2308 supervisor.mFocusedStack = mSavedFocusedStack;
Craig Mautner76ea2242013-05-15 11:40:05 -07002309 if (DEBUG_STACK) Slog.d(TAG, "UserState.restore: mStackState old=" +
2310 stackStateToString(mSavedStackState));
Craig Mautner858d8a62013-04-23 17:08:34 -07002311 supervisor.mStackState = mSavedStackState;
2312 }
2313 }
Craig Mautner27084302013-03-25 08:05:25 -07002314}