blob: b284cfaf69db2becfc7169216740d370f306e129 [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 Mautnerce5f3cb2013-04-22 08:58:54 -0700219 boolean isFocusedStack(ActivityStack stack) {
220 return getFocusedStack() == stack;
221 }
222
Craig Mautnerde4ef022013-04-07 19:01:33 -0700223 boolean isFrontStack(ActivityStack stack) {
Craig Mautner858d8a62013-04-23 17:08:34 -0700224 if (stack.mCurrentUser != mCurrentUser) {
225 return false;
226 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700227 return !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
Craig Mautner20e72272013-04-01 13:45:53 -0700228 }
229
Craig Mautnerde4ef022013-04-07 19:01:33 -0700230 void moveHomeStack(boolean toFront) {
231 final boolean homeInFront = isFrontStack(mHomeStack);
232 if (homeInFront ^ toFront) {
233 mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
234 }
235 }
236
Craig Mautner69ada552013-04-18 13:51:51 -0700237 boolean resumeHomeActivity(ActivityRecord prev) {
238 moveHomeStack(true);
239 if (prev != null) {
240 prev.mLaunchHomeTaskNext = false;
241 }
242 if (mHomeStack.topRunningActivityLocked(null) != null) {
Craig Mautner05d29032013-05-03 13:40:13 -0700243 return resumeTopActivitiesLocked(mHomeStack, prev, null);
Craig Mautner69ada552013-04-18 13:51:51 -0700244 }
245 return mService.startHomeActivityLocked(mCurrentUser);
246 }
247
Craig Mautnerde4ef022013-04-07 19:01:33 -0700248 final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r,
249 ActivityStack stack) {
250 if (stack == mHomeStack) {
251 return;
252 }
253 if ((sourceRecord == null && getLastStack() == mHomeStack) ||
254 (sourceRecord != null && sourceRecord.isHomeActivity)) {
255 if (r == null) {
256 r = stack.topRunningActivityLocked(null);
257 }
258 if (r != null && !r.isHomeActivity && r.isRootActivity()) {
259 r.mLaunchHomeTaskNext = true;
260 }
261 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700262 }
263
Craig Mautner27084302013-03-25 08:05:25 -0700264 void setDismissKeyguard(boolean dismiss) {
265 mDismissKeyguardOnNextActivity = dismiss;
266 }
267
Craig Mautner8d341ef2013-03-26 09:03:27 -0700268 TaskRecord anyTaskForIdLocked(int id) {
269 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
270 ActivityStack stack = mStacks.get(stackNdx);
271 TaskRecord task = stack.taskForIdLocked(id);
272 if (task != null) {
273 return task;
274 }
275 }
276 return null;
277 }
278
Craig Mautner6170f732013-04-02 13:05:23 -0700279 ActivityRecord isInAnyStackLocked(IBinder token) {
280 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
281 final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
282 if (r != null) {
283 return r;
284 }
285 }
286 return null;
287 }
288
Craig Mautner8d341ef2013-03-26 09:03:27 -0700289 int getNextTaskId() {
290 do {
291 mCurTaskId++;
292 if (mCurTaskId <= 0) {
293 mCurTaskId = 1;
294 }
295 } while (anyTaskForIdLocked(mCurTaskId) != null);
296 return mCurTaskId;
297 }
298
Craig Mautnerde4ef022013-04-07 19:01:33 -0700299 void removeTask(TaskRecord task) {
300 final ActivityStack stack = task.stack;
301 if (stack.removeTask(task) && !stack.isHomeStack()) {
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700302 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700303 mStacks.remove(stack);
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700304 final int stackId = stack.mStackId;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700305 final int nextStackId = mWindowManager.removeStack(stackId);
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700306 // TODO: Perhaps we need to let the ActivityManager determine the next focus...
Guang Zhubefa8b52013-05-12 23:10:39 -0700307 if (mFocusedStack.mStackId == stackId) {
Craig Mautner1602ec22013-05-12 10:24:27 -0700308 // If this is the last app stack, set mFocusedStack to null.
Craig Mautner29219d92013-04-16 20:19:12 -0700309 mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700310 }
311 }
312 }
313
314 ActivityRecord resumedAppLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700315 ActivityStack stack = getFocusedStack();
316 if (stack == null) {
317 return null;
318 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700319 ActivityRecord resumedActivity = stack.mResumedActivity;
320 if (resumedActivity == null || resumedActivity.app == null) {
321 resumedActivity = stack.mPausingActivity;
322 if (resumedActivity == null || resumedActivity.app == null) {
323 resumedActivity = stack.topRunningActivityLocked(null);
324 }
325 }
326 return resumedActivity;
327 }
328
Craig Mautner20e72272013-04-01 13:45:53 -0700329 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
330 boolean didSomething = false;
331 final String processName = app.processName;
332 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
333 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner858d8a62013-04-23 17:08:34 -0700334 if (!isFrontStack(stack)) {
335 continue;
336 }
Craig Mautner20e72272013-04-01 13:45:53 -0700337 ActivityRecord hr = stack.topRunningActivityLocked(null);
338 if (hr != null) {
339 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
340 && processName.equals(hr.processName)) {
341 try {
342 if (headless) {
343 Slog.e(TAG, "Starting activities not supported on headless device: "
344 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700345 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700346 didSomething = true;
347 }
348 } catch (Exception e) {
349 Slog.w(TAG, "Exception in new application when starting activity "
350 + hr.intent.getComponent().flattenToShortString(), e);
351 throw e;
352 }
Craig Mautner20e72272013-04-01 13:45:53 -0700353 }
354 }
355 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -0700356 if (!didSomething) {
357 ensureActivitiesVisibleLocked(null, 0);
358 }
Craig Mautner20e72272013-04-01 13:45:53 -0700359 return didSomething;
360 }
361
362 boolean allResumedActivitiesIdle() {
363 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700364 final ActivityRecord resumedActivity = mStacks.get(stackNdx).mResumedActivity;
365 if (resumedActivity == null || !resumedActivity.idle) {
Craig Mautner20e72272013-04-01 13:45:53 -0700366 return false;
367 }
368 }
369 return true;
370 }
371
Craig Mautnerde4ef022013-04-07 19:01:33 -0700372 boolean allResumedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700373 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
374 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner967212c2013-04-13 21:10:58 -0700375 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700376 final ActivityRecord r = stack.mResumedActivity;
377 if (r != null && r.state != ActivityState.RESUMED) {
378 return false;
379 }
380 }
381 }
382 // TODO: Not sure if this should check if all Paused are complete too.
383 switch (mStackState) {
384 case STACK_STATE_HOME_TO_BACK:
385 mStackState = STACK_STATE_HOME_IN_BACK;
386 break;
387 case STACK_STATE_HOME_TO_FRONT:
388 mStackState = STACK_STATE_HOME_IN_FRONT;
389 break;
390 }
391 return true;
392 }
393
394 boolean allResumedActivitiesVisible() {
395 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
396 final ActivityStack stack = mStacks.get(stackNdx);
397 final ActivityRecord r = stack.mResumedActivity;
398 if (r != null && (!r.nowVisible || r.waitingVisible)) {
399 return false;
400 }
401 }
402 return true;
403 }
404
Craig Mautnercf910b02013-04-23 11:23:27 -0700405 boolean pauseBackStacks(boolean userLeaving) {
406 boolean someActivityPaused = false;
407 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
408 final ActivityStack stack = mStacks.get(stackNdx);
409 if (!isFrontStack(stack) && stack.mResumedActivity != null) {
410 stack.startPausingLocked(userLeaving, false);
411 someActivityPaused = true;
412 }
413 }
414 return someActivityPaused;
415 }
416
Craig Mautnerde4ef022013-04-07 19:01:33 -0700417 boolean allPausedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700418 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
419 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner69ada552013-04-18 13:51:51 -0700420 final ActivityRecord r = stack.mPausingActivity;
421 if (r != null && r.state != ActivityState.PAUSED
422 && r.state != ActivityState.STOPPED
423 && r.state != ActivityState.STOPPING) {
424 return false;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700425 }
426 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700427 return true;
428 }
429
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700430 void reportActivityVisibleLocked(ActivityRecord r) {
Craig Mautner858d8a62013-04-23 17:08:34 -0700431 for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700432 WaitResult w = mWaitingActivityVisible.get(i);
433 w.timeout = false;
434 if (r != null) {
435 w.who = new ComponentName(r.info.packageName, r.info.name);
436 }
437 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
438 w.thisTime = w.totalTime;
439 }
440 mService.notifyAll();
441 dismissKeyguard();
442 }
443
444 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
445 long thisTime, long totalTime) {
446 for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
Craig Mautnerc64f73e2013-04-24 16:44:56 -0700447 WaitResult w = mWaitingActivityLaunched.remove(i);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700448 w.timeout = timeout;
449 if (r != null) {
450 w.who = new ComponentName(r.info.packageName, r.info.name);
451 }
452 w.thisTime = thisTime;
453 w.totalTime = totalTime;
454 }
455 mService.notifyAll();
456 }
457
Craig Mautner29219d92013-04-16 20:19:12 -0700458 ActivityRecord topRunningActivityLocked() {
Craig Mautner1602ec22013-05-12 10:24:27 -0700459 final ActivityStack focusedStack = getFocusedStack();
460 ActivityRecord r = focusedStack.topRunningActivityLocked(null);
461 if (r != null) {
462 return r;
Craig Mautner29219d92013-04-16 20:19:12 -0700463 }
Craig Mautner1602ec22013-05-12 10:24:27 -0700464
Craig Mautner29219d92013-04-16 20:19:12 -0700465 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
466 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner1602ec22013-05-12 10:24:27 -0700467 if (stack.mCurrentUser == mCurrentUser && stack != focusedStack &&
468 isFrontStack(stack)) {
Craig Mautner29219d92013-04-16 20:19:12 -0700469 r = stack.topRunningActivityLocked(null);
470 if (r != null) {
471 return r;
472 }
473 }
474 }
475 return null;
476 }
477
Craig Mautner20e72272013-04-01 13:45:53 -0700478 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
479 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
480 ActivityRecord r = null;
481 final int numStacks = mStacks.size();
482 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
483 final ActivityStack stack = mStacks.get(stackNdx);
484 final ActivityRecord ar =
485 stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700486 if (isFrontStack(stack)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700487 r = ar;
488 }
489 }
490 return r;
491 }
492
Craig Mautner23ac33b2013-04-01 16:26:35 -0700493 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
494 String profileFile, ParcelFileDescriptor profileFd, int userId) {
495 // Collect information about the target of the Intent.
496 ActivityInfo aInfo;
497 try {
498 ResolveInfo rInfo =
499 AppGlobals.getPackageManager().resolveIntent(
500 intent, resolvedType,
501 PackageManager.MATCH_DEFAULT_ONLY
502 | ActivityManagerService.STOCK_PM_FLAGS, userId);
503 aInfo = rInfo != null ? rInfo.activityInfo : null;
504 } catch (RemoteException e) {
505 aInfo = null;
506 }
507
508 if (aInfo != null) {
509 // Store the found target back into the intent, because now that
510 // we have it we never want to do this again. For example, if the
511 // user navigates back to this point in the history, we should
512 // always restart the exact same activity.
513 intent.setComponent(new ComponentName(
514 aInfo.applicationInfo.packageName, aInfo.name));
515
516 // Don't debug things in the system process
517 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
518 if (!aInfo.processName.equals("system")) {
519 mService.setDebugApp(aInfo.processName, true, false);
520 }
521 }
522
523 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
524 if (!aInfo.processName.equals("system")) {
525 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
526 }
527 }
528
529 if (profileFile != null) {
530 if (!aInfo.processName.equals("system")) {
531 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
532 profileFile, profileFd,
533 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
534 }
535 }
536 }
537 return aInfo;
538 }
539
Craig Mautner2219a1b2013-03-25 09:44:30 -0700540 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700541 moveHomeStack(true);
Craig Mautner6170f732013-04-02 13:05:23 -0700542 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
Craig Mautner2219a1b2013-03-25 09:44:30 -0700543 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700544 }
545
Craig Mautner23ac33b2013-04-01 16:26:35 -0700546 final int startActivityMayWait(IApplicationThread caller, int callingUid,
547 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
548 String resultWho, int requestCode, int startFlags, String profileFile,
549 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
550 Bundle options, int userId) {
551 // Refuse possible leaked file descriptors
552 if (intent != null && intent.hasFileDescriptors()) {
553 throw new IllegalArgumentException("File descriptors passed in Intent");
554 }
555 boolean componentSpecified = intent.getComponent() != null;
556
557 // Don't modify the client's object!
558 intent = new Intent(intent);
559
560 // Collect information about the target of the Intent.
561 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
562 profileFile, profileFd, userId);
563
564 synchronized (mService) {
565 int callingPid;
566 if (callingUid >= 0) {
567 callingPid = -1;
568 } else if (caller == null) {
569 callingPid = Binder.getCallingPid();
570 callingUid = Binder.getCallingUid();
571 } else {
572 callingPid = callingUid = -1;
573 }
574
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700575 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -0700576 stack.mConfigWillChange = config != null
Craig Mautner23ac33b2013-04-01 16:26:35 -0700577 && mService.mConfiguration.diff(config) != 0;
578 if (DEBUG_CONFIGURATION) Slog.v(TAG,
Craig Mautnerde4ef022013-04-07 19:01:33 -0700579 "Starting activity when config will change = " + stack.mConfigWillChange);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700580
581 final long origId = Binder.clearCallingIdentity();
582
583 if (aInfo != null &&
584 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
585 // This may be a heavy-weight process! Check to see if we already
586 // have another, different heavy-weight process running.
587 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
588 if (mService.mHeavyWeightProcess != null &&
589 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
590 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
591 int realCallingPid = callingPid;
592 int realCallingUid = callingUid;
593 if (caller != null) {
594 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
595 if (callerApp != null) {
596 realCallingPid = callerApp.pid;
597 realCallingUid = callerApp.info.uid;
598 } else {
599 Slog.w(TAG, "Unable to find app for caller " + caller
600 + " (pid=" + realCallingPid + ") when starting: "
601 + 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
719 ActivityRecord[] outActivity = new ActivityRecord[1];
720
721 int callingPid;
722 if (callingUid >= 0) {
723 callingPid = -1;
724 } else if (caller == null) {
725 callingPid = Binder.getCallingPid();
726 callingUid = Binder.getCallingUid();
727 } else {
728 callingPid = callingUid = -1;
729 }
730 final long origId = Binder.clearCallingIdentity();
731 try {
732 synchronized (mService) {
733
734 for (int i=0; i<intents.length; i++) {
735 Intent intent = intents[i];
736 if (intent == null) {
737 continue;
738 }
739
740 // Refuse possible leaked file descriptors
741 if (intent != null && intent.hasFileDescriptors()) {
742 throw new IllegalArgumentException("File descriptors passed in Intent");
743 }
744
745 boolean componentSpecified = intent.getComponent() != null;
746
747 // Don't modify the client's object!
748 intent = new Intent(intent);
749
750 // Collect information about the target of the Intent.
751 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
752 0, null, null, userId);
753 // TODO: New, check if this is correct
754 aInfo = mService.getActivityInfoForUser(aInfo, userId);
755
756 if (aInfo != null &&
757 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
758 != 0) {
759 throw new IllegalArgumentException(
760 "FLAG_CANT_SAVE_STATE not supported here");
761 }
762
763 Bundle theseOptions;
764 if (options != null && i == intents.length-1) {
765 theseOptions = options;
766 } else {
767 theseOptions = null;
768 }
Craig Mautner6170f732013-04-02 13:05:23 -0700769 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Craig Mautner23ac33b2013-04-01 16:26:35 -0700770 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
771 0, theseOptions, componentSpecified, outActivity);
772 if (res < 0) {
773 return res;
774 }
775
776 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
777 }
778 }
779 } finally {
780 Binder.restoreCallingIdentity(origId);
781 }
782
783 return ActivityManager.START_SUCCESS;
784 }
785
Craig Mautner2420ead2013-04-01 17:13:20 -0700786 final boolean realStartActivityLocked(ActivityRecord r,
787 ProcessRecord app, boolean andResume, boolean checkConfig)
788 throws RemoteException {
789
790 r.startFreezingScreenLocked(app, 0);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700791 mWindowManager.setAppVisibility(r.appToken, true);
Craig Mautner2420ead2013-04-01 17:13:20 -0700792
793 // schedule launch ticks to collect information about slow apps.
794 r.startLaunchTickingLocked();
795
796 // Have the window manager re-evaluate the orientation of
797 // the screen based on the new activity order. Note that
798 // as a result of this, it can call back into the activity
799 // manager with a new orientation. We don't care about that,
800 // because the activity is not currently running so we are
801 // just restarting it anyway.
802 if (checkConfig) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700803 Configuration config = mWindowManager.updateOrientationFromAppTokens(
Craig Mautner2420ead2013-04-01 17:13:20 -0700804 mService.mConfiguration,
805 r.mayFreezeScreenLocked(app) ? r.appToken : null);
806 mService.updateConfigurationLocked(config, r, false, false);
807 }
808
809 r.app = app;
810 app.waitingToKill = null;
811 r.launchCount++;
812 r.lastLaunchTime = SystemClock.uptimeMillis();
813
814 if (localLOGV) Slog.v(TAG, "Launching: " + r);
815
816 int idx = app.activities.indexOf(r);
817 if (idx < 0) {
818 app.activities.add(r);
819 }
820 mService.updateLruProcessLocked(app, true);
821
822 final ActivityStack stack = r.task.stack;
823 try {
824 if (app.thread == null) {
825 throw new RemoteException();
826 }
827 List<ResultInfo> results = null;
828 List<Intent> newIntents = null;
829 if (andResume) {
830 results = r.results;
831 newIntents = r.newIntents;
832 }
833 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
834 + " icicle=" + r.icicle
835 + " with results=" + results + " newIntents=" + newIntents
836 + " andResume=" + andResume);
837 if (andResume) {
838 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
839 r.userId, System.identityHashCode(r),
840 r.task.taskId, r.shortComponentName);
841 }
842 if (r.isHomeActivity) {
843 mService.mHomeProcess = app;
844 }
845 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
846 r.sleeping = false;
847 r.forceNewConfig = false;
848 mService.showAskCompatModeDialogLocked(r);
849 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
850 String profileFile = null;
851 ParcelFileDescriptor profileFd = null;
852 boolean profileAutoStop = false;
853 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
854 if (mService.mProfileProc == null || mService.mProfileProc == app) {
855 mService.mProfileProc = app;
856 profileFile = mService.mProfileFile;
857 profileFd = mService.mProfileFd;
858 profileAutoStop = mService.mAutoStopProfiler;
859 }
860 }
861 app.hasShownUi = true;
862 app.pendingUiClean = true;
863 if (profileFd != null) {
864 try {
865 profileFd = profileFd.dup();
866 } catch (IOException e) {
867 if (profileFd != null) {
868 try {
869 profileFd.close();
870 } catch (IOException o) {
871 }
872 profileFd = null;
873 }
874 }
875 }
876 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
877 System.identityHashCode(r), r.info,
878 new Configuration(mService.mConfiguration),
879 r.compat, r.icicle, results, newIntents, !andResume,
880 mService.isNextTransitionForward(), profileFile, profileFd,
881 profileAutoStop);
882
883 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
884 // This may be a heavy-weight process! Note that the package
885 // manager will ensure that only activity can run in the main
886 // process of the .apk, which is the only thing that will be
887 // considered heavy-weight.
888 if (app.processName.equals(app.info.packageName)) {
889 if (mService.mHeavyWeightProcess != null
890 && mService.mHeavyWeightProcess != app) {
891 Slog.w(TAG, "Starting new heavy weight process " + app
892 + " when already running "
893 + mService.mHeavyWeightProcess);
894 }
895 mService.mHeavyWeightProcess = app;
896 Message msg = mService.mHandler.obtainMessage(
897 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
898 msg.obj = r;
899 mService.mHandler.sendMessage(msg);
900 }
901 }
902
903 } catch (RemoteException e) {
904 if (r.launchFailed) {
905 // This is the second time we failed -- finish activity
906 // and give up.
907 Slog.e(TAG, "Second failure launching "
908 + r.intent.getComponent().flattenToShortString()
909 + ", giving up", e);
910 mService.appDiedLocked(app, app.pid, app.thread);
911 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
912 "2nd-crash", false);
913 return false;
914 }
915
916 // This is the first time we failed -- restart process and
917 // retry.
918 app.activities.remove(r);
919 throw e;
920 }
921
922 r.launchFailed = false;
923 if (stack.updateLRUListLocked(r)) {
924 Slog.w(TAG, "Activity " + r
925 + " being launched, but already in LRU list");
926 }
927
928 if (andResume) {
929 // As part of the process of launching, ActivityThread also performs
930 // a resume.
931 stack.minimalResumeActivityLocked(r);
932 } else {
933 // This activity is not starting in the resumed state... which
934 // should look like we asked it to pause+stop (but remain visible),
935 // and it has done so and reported back the current icicle and
936 // other state.
937 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
938 + " (starting in stopped state)");
939 r.state = ActivityState.STOPPED;
940 r.stopped = true;
941 }
942
943 // Launch the new version setup screen if needed. We do this -after-
944 // launching the initial activity (that is, home), so that it can have
945 // a chance to initialize itself while in the background, making the
946 // switch back to it faster and look better.
Craig Mautnerde4ef022013-04-07 19:01:33 -0700947 if (isFrontStack(stack)) {
Craig Mautner2420ead2013-04-01 17:13:20 -0700948 mService.startSetupActivityLocked();
949 }
950
951 return true;
952 }
953
Craig Mautnere79d42682013-04-01 19:01:53 -0700954 void startSpecificActivityLocked(ActivityRecord r,
955 boolean andResume, boolean checkConfig) {
956 // Is this activity's application already running?
957 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
958 r.info.applicationInfo.uid);
959
960 r.task.stack.setLaunchTime(r);
961
962 if (app != null && app.thread != null) {
963 try {
964 app.addPackage(r.info.packageName);
965 realStartActivityLocked(r, app, andResume, checkConfig);
966 return;
967 } catch (RemoteException e) {
968 Slog.w(TAG, "Exception when starting activity "
969 + r.intent.getComponent().flattenToShortString(), e);
970 }
971
972 // If a dead object exception was thrown -- fall through to
973 // restart the application.
974 }
975
976 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
977 "activity", r.intent.getComponent(), false, false);
978 }
979
Craig Mautner6170f732013-04-02 13:05:23 -0700980 final int startActivityLocked(IApplicationThread caller,
981 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
982 String resultWho, int requestCode,
983 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
984 boolean componentSpecified, ActivityRecord[] outActivity) {
985 int err = ActivityManager.START_SUCCESS;
986
987 ProcessRecord callerApp = null;
988 if (caller != null) {
989 callerApp = mService.getRecordForAppLocked(caller);
990 if (callerApp != null) {
991 callingPid = callerApp.pid;
992 callingUid = callerApp.info.uid;
993 } else {
994 Slog.w(TAG, "Unable to find app for caller " + caller
995 + " (pid=" + callingPid + ") when starting: "
996 + intent.toString());
997 err = ActivityManager.START_PERMISSION_DENIED;
998 }
999 }
1000
1001 if (err == ActivityManager.START_SUCCESS) {
1002 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
1003 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
1004 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
1005 }
1006
1007 ActivityRecord sourceRecord = null;
1008 ActivityRecord resultRecord = null;
1009 if (resultTo != null) {
1010 sourceRecord = isInAnyStackLocked(resultTo);
1011 if (DEBUG_RESULTS) Slog.v(
1012 TAG, "Will send result to " + resultTo + " " + sourceRecord);
1013 if (sourceRecord != null) {
1014 if (requestCode >= 0 && !sourceRecord.finishing) {
1015 resultRecord = sourceRecord;
1016 }
1017 }
1018 }
1019 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
1020
1021 int launchFlags = intent.getFlags();
1022
1023 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
1024 && sourceRecord != null) {
1025 // Transfer the result target from the source activity to the new
1026 // one being started, including any failures.
1027 if (requestCode >= 0) {
1028 ActivityOptions.abort(options);
1029 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
1030 }
1031 resultRecord = sourceRecord.resultTo;
1032 resultWho = sourceRecord.resultWho;
1033 requestCode = sourceRecord.requestCode;
1034 sourceRecord.resultTo = null;
1035 if (resultRecord != null) {
1036 resultRecord.removeResultsLocked(
1037 sourceRecord, resultWho, requestCode);
1038 }
1039 }
1040
1041 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
1042 // We couldn't find a class that can handle the given Intent.
1043 // That's the end of that!
1044 err = ActivityManager.START_INTENT_NOT_RESOLVED;
1045 }
1046
1047 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
1048 // We couldn't find the specific class specified in the Intent.
1049 // Also the end of the line.
1050 err = ActivityManager.START_CLASS_NOT_FOUND;
1051 }
1052
1053 if (err != ActivityManager.START_SUCCESS) {
1054 if (resultRecord != null) {
1055 resultStack.sendActivityResultLocked(-1,
1056 resultRecord, resultWho, requestCode,
1057 Activity.RESULT_CANCELED, null);
1058 }
1059 setDismissKeyguard(false);
1060 ActivityOptions.abort(options);
1061 return err;
1062 }
1063
1064 final int startAnyPerm = mService.checkPermission(
1065 START_ANY_ACTIVITY, callingPid, callingUid);
1066 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
1067 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
1068 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
1069 if (resultRecord != null) {
1070 resultStack.sendActivityResultLocked(-1,
1071 resultRecord, resultWho, requestCode,
1072 Activity.RESULT_CANCELED, null);
1073 }
1074 setDismissKeyguard(false);
1075 String msg;
1076 if (!aInfo.exported) {
1077 msg = "Permission Denial: starting " + intent.toString()
1078 + " from " + callerApp + " (pid=" + callingPid
1079 + ", uid=" + callingUid + ")"
1080 + " not exported from uid " + aInfo.applicationInfo.uid;
1081 } else {
1082 msg = "Permission Denial: starting " + intent.toString()
1083 + " from " + callerApp + " (pid=" + callingPid
1084 + ", uid=" + callingUid + ")"
1085 + " requires " + aInfo.permission;
1086 }
1087 Slog.w(TAG, msg);
1088 throw new SecurityException(msg);
1089 }
1090
Ben Gruver6617c3c2013-04-03 18:45:22 -07001091 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
Ben Gruver7b879f42013-04-08 14:56:55 -07001092 callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo);
Ben Gruver5e207332013-04-03 17:41:37 -07001093
Craig Mautner6170f732013-04-02 13:05:23 -07001094 if (mService.mController != null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001095 try {
1096 // The Intent we give to the watcher has the extra data
1097 // stripped off, since it can contain private information.
1098 Intent watchIntent = intent.cloneFilter();
Ben Gruver5e207332013-04-03 17:41:37 -07001099 abort |= !mService.mController.activityStarting(watchIntent,
Craig Mautner6170f732013-04-02 13:05:23 -07001100 aInfo.applicationInfo.packageName);
1101 } catch (RemoteException e) {
1102 mService.mController = null;
1103 }
Ben Gruver5e207332013-04-03 17:41:37 -07001104 }
Craig Mautner6170f732013-04-02 13:05:23 -07001105
Ben Gruver5e207332013-04-03 17:41:37 -07001106 if (abort) {
1107 if (resultRecord != null) {
1108 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Craig Mautner6170f732013-04-02 13:05:23 -07001109 Activity.RESULT_CANCELED, null);
Craig Mautner6170f732013-04-02 13:05:23 -07001110 }
Ben Gruver5e207332013-04-03 17:41:37 -07001111 // We pretend to the caller that it was really started, but
1112 // they will just get a cancel result.
1113 setDismissKeyguard(false);
1114 ActivityOptions.abort(options);
1115 return ActivityManager.START_SUCCESS;
Craig Mautner6170f732013-04-02 13:05:23 -07001116 }
1117
1118 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1119 intent, resolvedType, aInfo, mService.mConfiguration,
Craig Mautnerde4ef022013-04-07 19:01:33 -07001120 resultRecord, resultWho, requestCode, componentSpecified, this);
Craig Mautner6170f732013-04-02 13:05:23 -07001121 if (outActivity != null) {
1122 outActivity[0] = r;
1123 }
1124
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001125 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001126 if (stack.mResumedActivity == null
1127 || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
Craig Mautner6170f732013-04-02 13:05:23 -07001128 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1129 PendingActivityLaunch pal =
Craig Mautnerde4ef022013-04-07 19:01:33 -07001130 new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
Craig Mautner6170f732013-04-02 13:05:23 -07001131 mService.mPendingActivityLaunches.add(pal);
1132 setDismissKeyguard(false);
1133 ActivityOptions.abort(options);
1134 return ActivityManager.START_SWITCHES_CANCELED;
1135 }
1136 }
1137
1138 if (mService.mDidAppSwitch) {
1139 // This is the second allowed switch since we stopped switches,
1140 // so now just generally allow switches. Use case: user presses
1141 // home (switches disabled, switch to home, mDidAppSwitch now true);
1142 // user taps a home icon (coming from home so allowed, we hit here
1143 // and now allow anyone to switch again).
1144 mService.mAppSwitchesAllowedTime = 0;
1145 } else {
1146 mService.mDidAppSwitch = true;
1147 }
1148
1149 mService.doPendingActivityLaunchesLocked(false);
1150
Craig Mautner8849a5e2013-04-02 16:41:03 -07001151 err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001152 if (stack.mPausingActivity == null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001153 // Someone asked to have the keyguard dismissed on the next
1154 // activity start, but we are not actually doing an activity
1155 // switch... just dismiss the keyguard now, because we
1156 // probably want to see whatever is behind it.
1157 dismissKeyguard();
1158 }
1159 return err;
1160 }
1161
Craig Mautnerde4ef022013-04-07 19:01:33 -07001162 ActivityStack getCorrectStack(ActivityRecord r) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001163 if (!r.isHomeActivity || (r.task != null && !r.task.isHomeTask())) {
Craig Mautner858d8a62013-04-23 17:08:34 -07001164 int stackNdx;
1165 for (stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
1166 if (mStacks.get(stackNdx).mCurrentUser == mCurrentUser) {
1167 break;
1168 }
1169 }
1170 if (stackNdx == 0) {
1171 // Time to create the first app stack for this user.
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001172 int stackId = mService.createStack(-1, HOME_STACK_ID,
1173 StackBox.TASK_STACK_GOES_OVER, 1.0f);
Craig Mautner29219d92013-04-16 20:19:12 -07001174 mFocusedStack = getStack(stackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001175 }
Craig Mautner29219d92013-04-16 20:19:12 -07001176 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001177 }
1178 return mHomeStack;
1179 }
1180
Craig Mautner29219d92013-04-16 20:19:12 -07001181 void setFocusedStack(ActivityRecord r) {
1182 if (r == null) {
1183 return;
1184 }
Craig Mautner1602ec22013-05-12 10:24:27 -07001185 if (r.isHomeActivity || (r.task != null && r.task.isHomeTask())) {
Craig Mautner29219d92013-04-16 20:19:12 -07001186 if (mStackState != STACK_STATE_HOME_IN_FRONT) {
1187 mStackState = STACK_STATE_HOME_TO_FRONT;
1188 }
1189 } else {
1190 mFocusedStack = r.task.stack;
1191 if (mStackState != STACK_STATE_HOME_IN_BACK) {
1192 mStackState = STACK_STATE_HOME_TO_BACK;
1193 }
1194 }
1195 }
1196
Craig Mautner8849a5e2013-04-02 16:41:03 -07001197 final int startActivityUncheckedLocked(ActivityRecord r,
1198 ActivityRecord sourceRecord, int startFlags, boolean doResume,
1199 Bundle options) {
1200 final Intent intent = r.intent;
1201 final int callingUid = r.launchedFromUid;
1202
1203 int launchFlags = intent.getFlags();
1204
Craig Mautner8849a5e2013-04-02 16:41:03 -07001205 // We'll invoke onUserLeaving before onPause only if the launching
1206 // activity did not explicitly state that this is an automated launch.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001207 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1208 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001209
1210 // If the caller has asked not to resume at this point, we make note
1211 // of this in the record so that we can skip it when trying to find
1212 // the top running activity.
1213 if (!doResume) {
1214 r.delayedResume = true;
1215 }
1216
1217 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1218
1219 // If the onlyIfNeeded flag is set, then we can do this if the activity
1220 // being launched is the same as the one making the call... or, as
1221 // a special case, if we do not know the caller then we count the
1222 // current top activity as the caller.
1223 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1224 ActivityRecord checkedCaller = sourceRecord;
1225 if (checkedCaller == null) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001226 checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001227 }
1228 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1229 // Caller is not the same as launcher, so always needed.
1230 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1231 }
1232 }
1233
1234 if (sourceRecord == null) {
1235 // This activity is not being started from another... in this
1236 // case we -always- start a new task.
1237 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Craig Mautner29219d92013-04-16 20:19:12 -07001238 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1239 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001240 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1241 }
1242 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1243 // The original activity who is starting us is running as a single
1244 // instance... this new activity it is starting must go on its
1245 // own task.
1246 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1247 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1248 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1249 // The activity being started is a single instance... it always
1250 // gets launched into its own task.
1251 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1252 }
1253
Craig Mautnerde4ef022013-04-07 19:01:33 -07001254 final ActivityStack sourceStack;
Craig Mautner525f3d92013-05-07 14:01:50 -07001255 TaskRecord sourceTask;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001256 if (sourceRecord != null) {
1257 sourceTask = sourceRecord.task;
1258 sourceStack = sourceTask.stack;
1259 } else {
1260 sourceTask = null;
1261 sourceStack = null;
1262 }
1263
Craig Mautner8849a5e2013-04-02 16:41:03 -07001264 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1265 // For whatever reason this activity is being launched into a new
1266 // task... yet the caller has requested a result back. Well, that
1267 // is pretty messed up, so instead immediately send back a cancel
1268 // and let the new task continue launched as normal without a
1269 // dependency on its originator.
1270 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1271 r.resultTo.task.stack.sendActivityResultLocked(-1,
1272 r.resultTo, r.resultWho, r.requestCode,
1273 Activity.RESULT_CANCELED, null);
1274 r.resultTo = null;
1275 }
1276
1277 boolean addingToTask = false;
1278 boolean movedHome = false;
1279 TaskRecord reuseTask = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001280 ActivityStack targetStack;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001281 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1282 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1283 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1284 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1285 // If bring to front is requested, and no result is requested, and
1286 // we can find a task that was started with this same
1287 // component, then instead of launching bring that one to the front.
1288 if (r.resultTo == null) {
1289 // See if there is a task to bring to the front. If this is
1290 // a SINGLE_INSTANCE activity, there can be one and only one
1291 // instance of it in the history, and it is always in its own
1292 // unique task, so we do a special search.
1293 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
1294 ? findTaskLocked(intent, r.info)
1295 : findActivityLocked(intent, r.info);
1296 if (intentActivity != null) {
Craig Mautner29219d92013-04-16 20:19:12 -07001297 if (r.task == null) {
1298 r.task = intentActivity.task;
1299 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001300 targetStack = intentActivity.task.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001301 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001302 if (intentActivity.task.intent == null) {
1303 // This task was started because of movement of
1304 // the activity based on affinity... now that we
1305 // are actually launching it, we can assign the
1306 // base intent.
1307 intentActivity.task.setIntent(intent, r.info);
1308 }
1309 // If the target task is not in the front, then we need
1310 // to bring it to the front... except... well, with
1311 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
1312 // to have the same behavior as if a new instance was
1313 // being started, which means not bringing it to the front
1314 // if the caller is not itself in the front.
Craig Mautner165640b2013-04-20 10:34:33 -07001315 final ActivityStack lastStack = getLastStack();
1316 ActivityRecord curTop = lastStack == null?
1317 null : lastStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001318 if (curTop != null && curTop.task != intentActivity.task) {
1319 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001320 if (sourceRecord == null || sourceStack.topActivity() == sourceRecord) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001321 // We really do want to push this one into the
1322 // user's face, right now.
1323 movedHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001324 if ((launchFlags &
Craig Mautner29219d92013-04-16 20:19:12 -07001325 (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1326 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001327 // Caller wants to appear on home activity, so before starting
1328 // their own activity we will bring home to the front.
1329 r.mLaunchHomeTaskNext = true;
1330 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001331 targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1332 options = null;
1333 }
1334 }
1335 // If the caller has requested that the target task be
1336 // reset, then do so.
1337 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1338 intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1339 }
1340 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1341 // We don't need to start a new activity, and
1342 // the client said not to do anything if that
1343 // is the case, so this is it! And for paranoia, make
1344 // sure we have correctly resumed the top activity.
1345 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001346 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001347 resumeTopActivitiesLocked(targetStack, null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001348 } else {
1349 ActivityOptions.abort(options);
1350 }
Craig Mautner29219d92013-04-16 20:19:12 -07001351 if (r.task == null) Slog.v(TAG,
1352 "startActivityUncheckedLocked: task left null",
1353 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001354 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1355 }
1356 if ((launchFlags &
1357 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1358 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1359 // The caller has requested to completely replace any
1360 // existing task with its new activity. Well that should
1361 // not be too hard...
1362 reuseTask = intentActivity.task;
1363 reuseTask.performClearTaskLocked();
1364 reuseTask.setIntent(r.intent, r.info);
1365 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1366 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1367 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1368 // In this situation we want to remove all activities
1369 // from the task up to the one being started. In most
1370 // cases this means we are resetting the task to its
1371 // initial state.
1372 ActivityRecord top =
1373 intentActivity.task.performClearTaskLocked(r, launchFlags);
1374 if (top != null) {
1375 if (top.frontOfTask) {
1376 // Activity aliases may mean we use different
1377 // intents for the top activity, so make sure
1378 // the task now has the identity of the new
1379 // intent.
1380 top.task.setIntent(r.intent, r.info);
1381 }
1382 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1383 r, top.task);
1384 top.deliverNewIntentLocked(callingUid, r.intent);
1385 } else {
1386 // A special case: we need to
1387 // start the activity because it is not currently
1388 // running, and the caller has asked to clear the
1389 // current task to have this activity at the top.
1390 addingToTask = true;
1391 // Now pretend like this activity is being started
1392 // by the top of its task, so it is put in the
1393 // right place.
1394 sourceRecord = intentActivity;
1395 }
1396 } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1397 // In this case the top activity on the task is the
1398 // same as the one being launched, so we take that
1399 // as a request to bring the task to the foreground.
1400 // If the top activity in the task is the root
1401 // activity, deliver this new intent to it if it
1402 // desires.
1403 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1404 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1405 && intentActivity.realActivity.equals(r.realActivity)) {
1406 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1407 intentActivity.task);
1408 if (intentActivity.frontOfTask) {
1409 intentActivity.task.setIntent(r.intent, r.info);
1410 }
1411 intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1412 } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1413 // In this case we are launching the root activity
1414 // of the task, but with a different intent. We
1415 // should start a new instance on top.
1416 addingToTask = true;
1417 sourceRecord = intentActivity;
1418 }
1419 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1420 // In this case an activity is being launched in to an
1421 // existing task, without resetting that task. This
1422 // is typically the situation of launching an activity
1423 // from a notification or shortcut. We want to place
1424 // the new activity on top of the current task.
1425 addingToTask = true;
1426 sourceRecord = intentActivity;
1427 } else if (!intentActivity.task.rootWasReset) {
1428 // In this case we are launching in to an existing task
1429 // that has not yet been started from its front door.
1430 // The current task has been brought to the front.
1431 // Ideally, we'd probably like to place this new task
1432 // at the bottom of its stack, but that's a little hard
1433 // to do with the current organization of the code so
1434 // for now we'll just drop it.
1435 intentActivity.task.setIntent(r.intent, r.info);
1436 }
1437 if (!addingToTask && reuseTask == null) {
1438 // We didn't do anything... but it was needed (a.k.a., client
1439 // don't use that intent!) And for paranoia, make
1440 // sure we have correctly resumed the top activity.
1441 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001442 setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1443 targetStack.resumeTopActivityLocked(null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001444 } else {
1445 ActivityOptions.abort(options);
1446 }
Craig Mautner29219d92013-04-16 20:19:12 -07001447 if (r.task == null) Slog.v(TAG,
1448 "startActivityUncheckedLocked: task left null",
1449 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001450 return ActivityManager.START_TASK_TO_FRONT;
1451 }
1452 }
1453 }
1454 }
1455
1456 //String uri = r.intent.toURI();
1457 //Intent intent2 = new Intent(uri);
1458 //Slog.i(TAG, "Given intent: " + r.intent);
1459 //Slog.i(TAG, "URI is: " + uri);
1460 //Slog.i(TAG, "To intent: " + intent2);
1461
1462 if (r.packageName != null) {
1463 // If the activity being launched is the same as the one currently
1464 // at the top, then we need to check if it should only be launched
1465 // once.
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001466 ActivityStack topStack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001467 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001468 if (top != null && r.resultTo == null) {
1469 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1470 if (top.app != null && top.app.thread != null) {
1471 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1472 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1473 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1474 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1475 top.task);
1476 // For paranoia, make sure we have correctly
1477 // resumed the top activity.
1478 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001479 setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001480 resumeTopActivitiesLocked();
Craig Mautner8849a5e2013-04-02 16:41:03 -07001481 }
1482 ActivityOptions.abort(options);
1483 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1484 // We don't need to start a new activity, and
1485 // the client said not to do anything if that
1486 // is the case, so this is it!
Craig Mautner29219d92013-04-16 20:19:12 -07001487 if (r.task == null) Slog.v(TAG,
1488 "startActivityUncheckedLocked: task left null",
1489 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001490 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1491 }
1492 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner29219d92013-04-16 20:19:12 -07001493 if (r.task == null) Slog.v(TAG,
1494 "startActivityUncheckedLocked: task left null",
1495 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001496 return ActivityManager.START_DELIVERED_TO_TOP;
1497 }
1498 }
1499 }
1500 }
1501
1502 } else {
1503 if (r.resultTo != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001504 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1505 r.requestCode, Activity.RESULT_CANCELED, null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001506 }
1507 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001508 if (r.task == null) Slog.v(TAG,
1509 "startActivityUncheckedLocked: task left null",
1510 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001511 return ActivityManager.START_CLASS_NOT_FOUND;
1512 }
1513
1514 boolean newTask = false;
1515 boolean keepCurTransition = false;
1516
1517 // Should this be considered a new task?
1518 if (r.resultTo == null && !addingToTask
1519 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001520 targetStack = getCorrectStack(r);
1521 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001522 if (reuseTask == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001523 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1524 null, true);
1525 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1526 r.task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001527 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001528 r.setTask(reuseTask, reuseTask, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001529 }
1530 newTask = true;
1531 if (!movedHome) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001532 if ((launchFlags &
1533 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1534 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1535 // Caller wants to appear on home activity, so before starting
1536 // their own activity we will bring home to the front.
1537 r.mLaunchHomeTaskNext = true;
1538 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001539 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001540 } else if (sourceRecord != null) {
Craig Mautner525f3d92013-05-07 14:01:50 -07001541 sourceTask = sourceRecord.task;
1542 targetStack = sourceTask.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001543 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001544 if (!addingToTask &&
1545 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1546 // In this case, we are adding the activity to an existing
1547 // task, but the caller has asked to clear that task if the
1548 // activity is already running.
Craig Mautner525f3d92013-05-07 14:01:50 -07001549 ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001550 keepCurTransition = true;
1551 if (top != null) {
1552 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1553 top.deliverNewIntentLocked(callingUid, r.intent);
1554 // For paranoia, make sure we have correctly
1555 // resumed the top activity.
1556 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001557 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001558 targetStack.resumeTopActivityLocked(null);
1559 }
1560 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001561 if (r.task == null) Slog.v(TAG,
1562 "startActivityUncheckedLocked: task left null",
1563 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001564 return ActivityManager.START_DELIVERED_TO_TOP;
1565 }
1566 } else if (!addingToTask &&
1567 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1568 // In this case, we are launching an activity in our own task
1569 // that may already be running somewhere in the history, and
1570 // we want to shuffle it to the front of the stack if so.
Craig Mautner525f3d92013-05-07 14:01:50 -07001571 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001572 if (top != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001573 final TaskRecord task = top.task;
1574 task.moveActivityToFrontLocked(top);
1575 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001576 top.updateOptionsLocked(options);
1577 top.deliverNewIntentLocked(callingUid, r.intent);
1578 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001579 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001580 targetStack.resumeTopActivityLocked(null);
1581 }
Craig Mautner29219d92013-04-16 20:19:12 -07001582 if (r.task == null) Slog.v(TAG,
1583 "startActivityUncheckedLocked: task left null",
1584 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001585 return ActivityManager.START_DELIVERED_TO_TOP;
1586 }
1587 }
1588 // An existing activity is starting this new activity, so we want
1589 // to keep the new one in the same task as the one that is starting
1590 // it.
Craig Mautner525f3d92013-05-07 14:01:50 -07001591 r.setTask(sourceTask, sourceRecord.thumbHolder, false);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001592 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1593 + " in existing task " + r.task);
1594
1595 } else {
1596 // This not being started from an existing activity, and not part
1597 // of a new task... just put it in the top task, though these days
1598 // this case should never happen.
Craig Mautner1602ec22013-05-12 10:24:27 -07001599 targetStack = getCorrectStack(r);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001600 moveHomeStack(targetStack.isHomeStack());
Craig Mautner1602ec22013-05-12 10:24:27 -07001601 ActivityRecord prev = targetStack.topActivity();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001602 r.setTask(prev != null ? prev.task
1603 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1604 null, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001605 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1606 + " in new guessed " + r.task);
1607 }
1608
1609 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1610 intent, r.getUriPermissionsLocked());
1611
1612 if (newTask) {
1613 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1614 }
1615 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001616 setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001617 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
1618 return ActivityManager.START_SUCCESS;
1619 }
1620
Craig Mautnerf3333272013-04-22 10:55:53 -07001621 // Checked.
1622 final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
1623 Configuration config) {
1624 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
1625
1626 ActivityRecord res = null;
1627
1628 ArrayList<ActivityRecord> stops = null;
1629 ArrayList<ActivityRecord> finishes = null;
1630 ArrayList<UserStartedState> startingUsers = null;
1631 int NS = 0;
1632 int NF = 0;
1633 IApplicationThread sendThumbnail = null;
1634 boolean booting = false;
1635 boolean enableScreen = false;
1636 boolean activityRemoved = false;
1637
1638 ActivityRecord r = ActivityRecord.forToken(token);
1639 if (r != null) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07001640 if (DEBUG_IDLE) Slog.d(TAG, "activityIdleInternalLocked: Callers=" +
1641 Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07001642 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
1643 r.finishLaunchTickingLocked();
Craig Mautner525f3d92013-05-07 14:01:50 -07001644 res = r.task.stack.activityIdleInternalLocked(token);
Craig Mautnerf3333272013-04-22 10:55:53 -07001645 if (res != null) {
1646 if (fromTimeout) {
1647 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
1648 }
1649
1650 // This is a hack to semi-deal with a race condition
1651 // in the client where it can be constructed with a
1652 // newer configuration from when we asked it to launch.
1653 // We'll update with whatever configuration it now says
1654 // it used to launch.
1655 if (config != null) {
1656 r.configuration = config;
1657 }
1658
1659 // We are now idle. If someone is waiting for a thumbnail from
1660 // us, we can now deliver.
1661 r.idle = true;
1662 if (allResumedActivitiesIdle()) {
1663 mService.scheduleAppGcsLocked();
1664 }
1665 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
1666 sendThumbnail = r.app.thread;
1667 r.thumbnailNeeded = false;
1668 }
1669
1670 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
1671 if (!mService.mBooted && isFrontStack(r.task.stack)) {
1672 mService.mBooted = true;
1673 enableScreen = true;
1674 }
1675 } else if (fromTimeout) {
1676 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
1677 }
1678 }
1679
1680 // Atomically retrieve all of the other things to do.
1681 stops = processStoppingActivitiesLocked(true);
1682 NS = stops != null ? stops.size() : 0;
1683 if ((NF=mFinishingActivities.size()) > 0) {
1684 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
1685 mFinishingActivities.clear();
1686 }
1687
1688 final ArrayList<ActivityRecord> thumbnails;
1689 final int NT = mCancelledThumbnails.size();
1690 if (NT > 0) {
1691 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
1692 mCancelledThumbnails.clear();
1693 } else {
1694 thumbnails = null;
1695 }
1696
1697 if (isFrontStack(mHomeStack)) {
1698 booting = mService.mBooting;
1699 mService.mBooting = false;
1700 }
1701
1702 if (mStartingUsers.size() > 0) {
1703 startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
1704 mStartingUsers.clear();
1705 }
1706
1707 // Perform the following actions from unsynchronized state.
1708 final IApplicationThread thumbnailThread = sendThumbnail;
1709 mHandler.post(new Runnable() {
1710 @Override
1711 public void run() {
1712 if (thumbnailThread != null) {
1713 try {
1714 thumbnailThread.requestThumbnail(token);
1715 } catch (Exception e) {
1716 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
1717 mService.sendPendingThumbnail(null, token, null, null, true);
1718 }
1719 }
1720
1721 // Report back to any thumbnail receivers.
1722 for (int i = 0; i < NT; i++) {
1723 ActivityRecord r = thumbnails.get(i);
1724 mService.sendPendingThumbnail(r, null, null, null, true);
1725 }
1726 }
1727 });
1728
1729 // Stop any activities that are scheduled to do so but have been
1730 // waiting for the next one to start.
1731 for (int i = 0; i < NS; i++) {
1732 r = stops.get(i);
1733 final ActivityStack stack = r.task.stack;
1734 if (r.finishing) {
1735 stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
1736 } else {
1737 stack.stopActivityLocked(r);
1738 }
1739 }
1740
1741 // Finish any activities that are scheduled to do so but have been
1742 // waiting for the next one to start.
1743 for (int i = 0; i < NF; i++) {
1744 r = finishes.get(i);
1745 activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle");
1746 }
1747
1748 if (booting) {
1749 mService.finishBooting();
1750 } else if (startingUsers != null) {
1751 for (int i = 0; i < startingUsers.size(); i++) {
1752 mService.finishUserSwitch(startingUsers.get(i));
1753 }
1754 }
1755
1756 mService.trimApplications();
1757 //dump();
1758 //mWindowManager.dump();
1759
1760 if (enableScreen) {
1761 mService.enableScreenAfterBoot();
1762 }
1763
1764 if (activityRemoved) {
Craig Mautner05d29032013-05-03 13:40:13 -07001765 resumeTopActivitiesLocked();
Craig Mautnerf3333272013-04-22 10:55:53 -07001766 }
1767
1768 return res;
1769 }
1770
Craig Mautner8d341ef2013-03-26 09:03:27 -07001771 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
1772 // Just in case.
1773 final int numStacks = mStacks.size();
1774 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Craig Mautnere79d42682013-04-01 19:01:53 -07001775 mStacks.get(stackNdx).handleAppDiedLocked(app, restarting);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001776 }
1777 }
1778
1779 void closeSystemDialogsLocked() {
1780 final int numStacks = mStacks.size();
1781 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1782 final ActivityStack stack = mStacks.get(stackNdx);
1783 stack.closeSystemDialogsLocked();
1784 }
1785 }
1786
1787 /**
1788 * @return true if some activity was finished (or would have finished if doit were true).
1789 */
1790 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1791 boolean didSomething = false;
1792 final int numStacks = mStacks.size();
1793 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1794 final ActivityStack stack = mStacks.get(stackNdx);
1795 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1796 didSomething = true;
1797 }
1798 }
1799 return didSomething;
1800 }
1801
Craig Mautner05d29032013-05-03 13:40:13 -07001802 boolean resumeTopActivitiesLocked() {
1803 return resumeTopActivitiesLocked(null, null, null);
1804 }
1805
1806 boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
1807 Bundle targetOptions) {
1808 if (targetStack == null) {
1809 targetStack = getFocusedStack();
1810 }
1811 boolean result = false;
Craig Mautnerdbcb31f2013-04-02 12:32:53 -07001812 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001813 final ActivityStack stack = mStacks.get(stackNdx);
1814 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07001815 if (stack == targetStack) {
1816 result = stack.resumeTopActivityLocked(target, targetOptions);
1817 } else {
1818 stack.resumeTopActivityLocked(null);
1819 }
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001820 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001821 }
Craig Mautner05d29032013-05-03 13:40:13 -07001822 return result;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001823 }
1824
1825 void finishTopRunningActivityLocked(ProcessRecord app) {
1826 final int numStacks = mStacks.size();
1827 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1828 final ActivityStack stack = mStacks.get(stackNdx);
1829 stack.finishTopRunningActivityLocked(app);
1830 }
1831 }
1832
Craig Mautner8d341ef2013-03-26 09:03:27 -07001833 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
1834 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1835 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
1836 return;
1837 }
1838 }
1839 }
1840
Craig Mautner967212c2013-04-13 21:10:58 -07001841 ActivityStack getStack(int stackId) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001842 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1843 final ActivityStack stack = mStacks.get(stackNdx);
1844 if (stack.getStackId() == stackId) {
1845 return stack;
1846 }
1847 }
1848 return null;
1849 }
1850
Craig Mautner967212c2013-04-13 21:10:58 -07001851 ArrayList<ActivityStack> getStacks() {
1852 return new ArrayList<ActivityStack>(mStacks);
1853 }
1854
1855 int createStack() {
Craig Mautner858d8a62013-04-23 17:08:34 -07001856 while (true) {
1857 if (++mLastStackId <= HOME_STACK_ID) {
1858 mLastStackId = HOME_STACK_ID + 1;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001859 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001860 if (getStack(mLastStackId) == null) {
1861 break;
1862 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001863 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001864 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
1865 return mLastStackId;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001866 }
1867
1868 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
1869 final ActivityStack stack = getStack(stackId);
1870 if (stack == null) {
1871 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
1872 return;
1873 }
1874 stack.moveTask(taskId, toTop);
Craig Mautner05d29032013-05-03 13:40:13 -07001875 resumeTopActivitiesLocked();
Craig Mautner8d341ef2013-03-26 09:03:27 -07001876 }
1877
Craig Mautner8849a5e2013-04-02 16:41:03 -07001878 ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
1879 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1880 final ActivityRecord ar = mStacks.get(stackNdx).findTaskLocked(intent, info);
1881 if (ar != null) {
1882 return ar;
1883 }
1884 }
1885 return null;
1886 }
1887
1888 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
1889 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1890 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
1891 if (ar != null) {
1892 return ar;
1893 }
1894 }
1895 return null;
1896 }
1897
Craig Mautner8d341ef2013-03-26 09:03:27 -07001898 void goingToSleepLocked() {
1899 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1900 mStacks.get(stackNdx).stopIfSleepingLocked();
1901 }
1902 }
1903
1904 boolean shutdownLocked(int timeout) {
1905 boolean timedout = false;
1906 final int numStacks = mStacks.size();
1907 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1908 final ActivityStack stack = mStacks.get(stackNdx);
1909 if (stack.mResumedActivity != null) {
1910 stack.stopIfSleepingLocked();
1911 final long endTime = System.currentTimeMillis() + timeout;
1912 while (stack.mResumedActivity != null || stack.mPausingActivity != null) {
1913 long delay = endTime - System.currentTimeMillis();
1914 if (delay <= 0) {
1915 Slog.w(TAG, "Activity manager shutdown timed out");
1916 timedout = true;
1917 break;
1918 }
1919 try {
1920 mService.wait();
1921 } catch (InterruptedException e) {
1922 }
1923 }
1924 }
1925 }
1926 return timedout;
1927 }
1928
1929 void comeOutOfSleepIfNeededLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001930 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001931 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001932 stack.awakeFromSleepingLocked();
1933 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07001934 resumeTopActivitiesLocked();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001935 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001936 }
1937 }
1938
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001939 boolean reportResumedActivityLocked(ActivityRecord r) {
1940 final ActivityStack stack = r.task.stack;
1941 if (isFrontStack(stack)) {
Jeff Sharkey5782da72013-04-25 14:32:30 -07001942 mService.updateUsageStats(r, true);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001943 mService.setFocusedActivityLocked(r);
1944 }
1945 if (allResumedActivitiesComplete()) {
1946 ensureActivitiesVisibleLocked(null, 0);
1947 mWindowManager.executeAppTransition();
1948 return true;
1949 }
1950 return false;
1951 }
1952
Craig Mautner8d341ef2013-03-26 09:03:27 -07001953 void handleAppCrashLocked(ProcessRecord app) {
1954 final int numStacks = mStacks.size();
1955 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1956 final ActivityStack stack = mStacks.get(stackNdx);
1957 stack.handleAppCrashLocked(app);
1958 }
1959 }
1960
Craig Mautnerde4ef022013-04-07 19:01:33 -07001961 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
Craig Mautner580ea812013-04-25 12:58:38 -07001962 // First the front stacks. In case any are not fullscreen and are in front of home.
1963 boolean showHomeBehindStack = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001964 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner580ea812013-04-25 12:58:38 -07001965 final ActivityStack stack = mStacks.get(stackNdx);
1966 if (isFrontStack(stack)) {
1967 showHomeBehindStack =
1968 stack.ensureActivitiesVisibleLocked(starting, configChanges);
1969 }
1970 }
1971 // Now do back stacks.
1972 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1973 final ActivityStack stack = mStacks.get(stackNdx);
1974 if (!isFrontStack(stack)) {
1975 stack.ensureActivitiesVisibleLocked(starting, configChanges, showHomeBehindStack);
1976 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001977 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001978 }
1979
1980 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
1981 final int numStacks = mStacks.size();
1982 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1983 final ActivityStack stack = mStacks.get(stackNdx);
1984 stack.scheduleDestroyActivities(app, false, reason);
1985 }
1986 }
1987
1988 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner858d8a62013-04-23 17:08:34 -07001989 mUserStates.put(mCurrentUser, new UserState());
Craig Mautner2420ead2013-04-01 17:13:20 -07001990 mCurrentUser = userId;
Craig Mautner858d8a62013-04-23 17:08:34 -07001991 UserState userState = mUserStates.get(userId);
1992 if (userState != null) {
1993 userState.restore();
1994 mUserStates.delete(userId);
1995 } else {
1996 mFocusedStack = null;
1997 mStackState = STACK_STATE_HOME_IN_FRONT;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001998 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001999
2000 mStartingUsers.add(uss);
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002001 boolean haveActivities = mHomeStack.switchUserLocked(userId);
Craig Mautner858d8a62013-04-23 17:08:34 -07002002
2003 resumeTopActivitiesLocked();
2004
Craig Mautner8d341ef2013-03-26 09:03:27 -07002005 return haveActivities;
Craig Mautner2219a1b2013-03-25 09:44:30 -07002006 }
2007
Craig Mautnerde4ef022013-04-07 19:01:33 -07002008 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
2009 int N = mStoppingActivities.size();
2010 if (N <= 0) return null;
2011
2012 ArrayList<ActivityRecord> stops = null;
2013
2014 final boolean nowVisible = allResumedActivitiesVisible();
2015 for (int i=0; i<N; i++) {
2016 ActivityRecord s = mStoppingActivities.get(i);
2017 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
2018 + nowVisible + " waitingVisible=" + s.waitingVisible
2019 + " finishing=" + s.finishing);
2020 if (s.waitingVisible && nowVisible) {
2021 mWaitingVisibleActivities.remove(s);
2022 s.waitingVisible = false;
2023 if (s.finishing) {
2024 // If this activity is finishing, it is sitting on top of
2025 // everyone else but we now know it is no longer needed...
2026 // so get rid of it. Otherwise, we need to go through the
2027 // normal flow and hide it once we determine that it is
2028 // hidden by the activities in front of it.
2029 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002030 mWindowManager.setAppVisibility(s.appToken, false);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002031 }
2032 }
2033 if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
2034 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
2035 if (stops == null) {
2036 stops = new ArrayList<ActivityRecord>();
2037 }
2038 stops.add(s);
2039 mStoppingActivities.remove(i);
2040 N--;
2041 i--;
2042 }
2043 }
2044
2045 return stops;
2046 }
2047
Craig Mautnercf910b02013-04-23 11:23:27 -07002048 void validateTopActivitiesLocked() {
2049 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2050 final ActivityStack stack = mStacks.get(stackNdx);
2051 final ActivityRecord r = stack.topRunningActivityLocked(null);
2052 if (isFrontStack(stack)) {
2053 if (r == null) {
2054 Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
2055 } else {
2056 if (stack.mPausingActivity != null) {
2057 Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
2058 " state=" + r.state);
2059 }
2060 if (r.state != ActivityState.INITIALIZING &&
2061 r.state != ActivityState.RESUMED) {
2062 Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
2063 " state=" + r.state);
2064 }
2065 }
2066 } else {
2067 if (stack.mResumedActivity != null) {
2068 Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
2069 " state=" + r.state);
2070 }
2071 if (r != null && (r.state == ActivityState.INITIALIZING
2072 || r.state == ActivityState.RESUMED)) {
2073 Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
2074 " state=" + r.state);
2075 }
2076 }
2077 }
2078 }
2079
Craig Mautner27084302013-03-25 08:05:25 -07002080 public void dump(PrintWriter pw, String prefix) {
2081 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
2082 pw.println(mDismissKeyguardOnNextActivity);
2083 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002084
Craig Mautner20e72272013-04-01 13:45:53 -07002085 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002086 return getFocusedStack().getDumpActivitiesLocked(name);
Craig Mautner20e72272013-04-01 13:45:53 -07002087 }
2088
Craig Mautner8d341ef2013-03-26 09:03:27 -07002089 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
2090 boolean dumpClient, String dumpPackage) {
2091 final int numStacks = mStacks.size();
2092 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2093 final ActivityStack stack = mStacks.get(stackNdx);
2094 pw.print(" Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
2095 stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
2096 pw.println(" ");
2097 pw.println(" Running activities (most recent first):");
2098 dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false,
2099 dumpPackage);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002100 if (stack.mGoingToSleepActivities.size() > 0) {
2101 pw.println(" ");
2102 pw.println(" Activities waiting to sleep:");
2103 dumpHistoryList(fd, pw, stack.mGoingToSleepActivities, " ", "Sleep", false,
2104 !dumpAll, false, dumpPackage);
2105 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002106
Craig Mautner8d341ef2013-03-26 09:03:27 -07002107 pw.print(" Stack #"); pw.println(mStacks.indexOf(stack));
2108 if (stack.mPausingActivity != null) {
2109 pw.println(" mPausingActivity: " + stack.mPausingActivity);
2110 }
2111 pw.println(" mResumedActivity: " + stack.mResumedActivity);
2112 if (dumpAll) {
2113 pw.println(" mLastPausedActivity: " + stack.mLastPausedActivity);
2114 pw.println(" mSleepTimeout: " + stack.mSleepTimeout);
2115 }
2116 }
2117
Craig Mautnerf3333272013-04-22 10:55:53 -07002118 if (mFinishingActivities.size() > 0) {
2119 pw.println(" ");
2120 pw.println(" Activities waiting to finish:");
2121 dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll, false,
2122 dumpPackage);
2123 }
2124
Craig Mautnerde4ef022013-04-07 19:01:33 -07002125 if (mStoppingActivities.size() > 0) {
2126 pw.println(" ");
2127 pw.println(" Activities waiting to stop:");
2128 dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, false,
2129 dumpPackage);
2130 }
2131
2132 if (mWaitingVisibleActivities.size() > 0) {
2133 pw.println(" ");
2134 pw.println(" Activities waiting for another to become visible:");
2135 dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
2136 false, dumpPackage);
2137 }
2138
Craig Mautner8d341ef2013-03-26 09:03:27 -07002139 if (dumpAll) {
2140 pw.println(" ");
2141 pw.println(" mCurTaskId: " + mCurTaskId);
2142 }
2143 return true;
2144 }
2145
2146 static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
2147 String prefix, String label, boolean complete, boolean brief, boolean client,
2148 String dumpPackage) {
2149 TaskRecord lastTask = null;
2150 boolean needNL = false;
2151 final String innerPrefix = prefix + " ";
2152 final String[] args = new String[0];
2153 for (int i=list.size()-1; i>=0; i--) {
2154 final ActivityRecord r = list.get(i);
2155 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
2156 continue;
2157 }
2158 final boolean full = !brief && (complete || !r.isInHistory());
2159 if (needNL) {
2160 pw.println(" ");
2161 needNL = false;
2162 }
2163 if (lastTask != r.task) {
2164 lastTask = r.task;
2165 pw.print(prefix);
2166 pw.print(full ? "* " : " ");
2167 pw.println(lastTask);
2168 if (full) {
2169 lastTask.dump(pw, prefix + " ");
2170 } else if (complete) {
2171 // Complete + brief == give a summary. Isn't that obvious?!?
2172 if (lastTask.intent != null) {
2173 pw.print(prefix); pw.print(" ");
2174 pw.println(lastTask.intent.toInsecureStringWithClip());
2175 }
2176 }
2177 }
2178 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
2179 pw.print(" #"); pw.print(i); pw.print(": ");
2180 pw.println(r);
2181 if (full) {
2182 r.dump(pw, innerPrefix);
2183 } else if (complete) {
2184 // Complete + brief == give a summary. Isn't that obvious?!?
2185 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
2186 if (r.app != null) {
2187 pw.print(innerPrefix); pw.println(r.app);
2188 }
2189 }
2190 if (client && r.app != null && r.app.thread != null) {
2191 // flush anything that is already in the PrintWriter since the thread is going
2192 // to write to the file descriptor directly
2193 pw.flush();
2194 try {
2195 TransferPipe tp = new TransferPipe();
2196 try {
2197 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
2198 r.appToken, innerPrefix, args);
2199 // Short timeout, since blocking here can
2200 // deadlock with the application.
2201 tp.go(fd, 2000);
2202 } finally {
2203 tp.kill();
2204 }
2205 } catch (IOException e) {
2206 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
2207 } catch (RemoteException e) {
2208 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
2209 }
2210 needNL = true;
2211 }
2212 }
2213 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002214
Craig Mautnerf3333272013-04-22 10:55:53 -07002215 void scheduleIdleTimeoutLocked(ActivityRecord next) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002216 if (DEBUG_IDLE) Slog.d(TAG, "scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4));
Craig Mautnerc64f73e2013-04-24 16:44:56 -07002217 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
2218 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
Craig Mautnerf3333272013-04-22 10:55:53 -07002219 }
2220
2221 final void scheduleIdleLocked() {
Craig Mautner05d29032013-05-03 13:40:13 -07002222 mHandler.sendEmptyMessage(IDLE_NOW_MSG);
Craig Mautnerf3333272013-04-22 10:55:53 -07002223 }
2224
2225 void removeTimeoutsForActivityLocked(ActivityRecord r) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002226 if (DEBUG_IDLE) Slog.d(TAG, "removeTimeoutsForActivity: Callers=" + Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07002227 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
2228 }
2229
Craig Mautner05d29032013-05-03 13:40:13 -07002230 final void scheduleResumeTopActivities() {
2231 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2232 }
2233
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002234 private final class ActivityStackSupervisorHandler extends Handler {
Craig Mautnerf3333272013-04-22 10:55:53 -07002235
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002236 public ActivityStackSupervisorHandler(Looper looper) {
2237 super(looper);
2238 }
2239
Craig Mautnerf3333272013-04-22 10:55:53 -07002240 void activityIdleInternal(ActivityRecord r) {
2241 synchronized (mService) {
2242 activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
2243 }
2244 }
2245
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002246 @Override
2247 public void handleMessage(Message msg) {
2248 switch (msg.what) {
Craig Mautnerf3333272013-04-22 10:55:53 -07002249 case IDLE_TIMEOUT_MSG: {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002250 if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_TIMEOUT_MSG: Callers=" +
2251 Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07002252 if (mService.mDidDexOpt) {
2253 mService.mDidDexOpt = false;
2254 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2255 nmsg.obj = msg.obj;
2256 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
2257 return;
2258 }
2259 // We don't at this point know if the activity is fullscreen,
2260 // so we need to be conservative and assume it isn't.
2261 activityIdleInternal((ActivityRecord)msg.obj);
2262 } break;
2263 case IDLE_NOW_MSG: {
2264 activityIdleInternal((ActivityRecord)msg.obj);
2265 } break;
Craig Mautner05d29032013-05-03 13:40:13 -07002266 case RESUME_TOP_ACTIVITY_MSG: {
2267 synchronized (mService) {
2268 resumeTopActivitiesLocked();
2269 }
2270 } break;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002271 }
2272 }
2273 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002274
2275 private final class UserState {
2276 final ActivityStack mSavedFocusedStack;
2277 final int mSavedStackState;
2278
2279 public UserState() {
2280 ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2281 mSavedFocusedStack = supervisor.mFocusedStack;
2282 mSavedStackState = supervisor.mStackState;
2283 }
2284
2285 void restore() {
2286 ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2287 supervisor.mFocusedStack = mSavedFocusedStack;
2288 supervisor.mStackState = mSavedStackState;
2289 }
2290 }
Craig Mautner27084302013-03-25 08:05:25 -07002291}