blob: 69e9f762387556eb4a7845189ef67bc44a87097d [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...
Craig Mautner29219d92013-04-16 20:19:12 -0700307 if (mFocusedStack.mStackId == stackId) {
308 mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700309 }
310 }
311 }
312
313 ActivityRecord resumedAppLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700314 ActivityStack stack = getFocusedStack();
315 if (stack == null) {
316 return null;
317 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700318 ActivityRecord resumedActivity = stack.mResumedActivity;
319 if (resumedActivity == null || resumedActivity.app == null) {
320 resumedActivity = stack.mPausingActivity;
321 if (resumedActivity == null || resumedActivity.app == null) {
322 resumedActivity = stack.topRunningActivityLocked(null);
323 }
324 }
325 return resumedActivity;
326 }
327
Craig Mautner20e72272013-04-01 13:45:53 -0700328 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
329 boolean didSomething = false;
330 final String processName = app.processName;
331 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
332 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner858d8a62013-04-23 17:08:34 -0700333 if (!isFrontStack(stack)) {
334 continue;
335 }
Craig Mautner20e72272013-04-01 13:45:53 -0700336 ActivityRecord hr = stack.topRunningActivityLocked(null);
337 if (hr != null) {
338 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
339 && processName.equals(hr.processName)) {
340 try {
341 if (headless) {
342 Slog.e(TAG, "Starting activities not supported on headless device: "
343 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700344 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700345 didSomething = true;
346 }
347 } catch (Exception e) {
348 Slog.w(TAG, "Exception in new application when starting activity "
349 + hr.intent.getComponent().flattenToShortString(), e);
350 throw e;
351 }
Craig Mautner20e72272013-04-01 13:45:53 -0700352 }
353 }
354 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -0700355 if (!didSomething) {
356 ensureActivitiesVisibleLocked(null, 0);
357 }
Craig Mautner20e72272013-04-01 13:45:53 -0700358 return didSomething;
359 }
360
361 boolean allResumedActivitiesIdle() {
362 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700363 final ActivityRecord resumedActivity = mStacks.get(stackNdx).mResumedActivity;
364 if (resumedActivity == null || !resumedActivity.idle) {
Craig Mautner20e72272013-04-01 13:45:53 -0700365 return false;
366 }
367 }
368 return true;
369 }
370
Craig Mautnerde4ef022013-04-07 19:01:33 -0700371 boolean allResumedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700372 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
373 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner967212c2013-04-13 21:10:58 -0700374 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700375 final ActivityRecord r = stack.mResumedActivity;
376 if (r != null && r.state != ActivityState.RESUMED) {
377 return false;
378 }
379 }
380 }
381 // TODO: Not sure if this should check if all Paused are complete too.
382 switch (mStackState) {
383 case STACK_STATE_HOME_TO_BACK:
384 mStackState = STACK_STATE_HOME_IN_BACK;
385 break;
386 case STACK_STATE_HOME_TO_FRONT:
387 mStackState = STACK_STATE_HOME_IN_FRONT;
388 break;
389 }
390 return true;
391 }
392
393 boolean allResumedActivitiesVisible() {
394 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
395 final ActivityStack stack = mStacks.get(stackNdx);
396 final ActivityRecord r = stack.mResumedActivity;
397 if (r != null && (!r.nowVisible || r.waitingVisible)) {
398 return false;
399 }
400 }
401 return true;
402 }
403
Craig Mautnercf910b02013-04-23 11:23:27 -0700404 boolean pauseBackStacks(boolean userLeaving) {
405 boolean someActivityPaused = false;
406 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
407 final ActivityStack stack = mStacks.get(stackNdx);
408 if (!isFrontStack(stack) && stack.mResumedActivity != null) {
409 stack.startPausingLocked(userLeaving, false);
410 someActivityPaused = true;
411 }
412 }
413 return someActivityPaused;
414 }
415
Craig Mautnerde4ef022013-04-07 19:01:33 -0700416 boolean allPausedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700417 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
418 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner69ada552013-04-18 13:51:51 -0700419 final ActivityRecord r = stack.mPausingActivity;
420 if (r != null && r.state != ActivityState.PAUSED
421 && r.state != ActivityState.STOPPED
422 && r.state != ActivityState.STOPPING) {
423 return false;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700424 }
425 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700426 return true;
427 }
428
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700429 void reportActivityVisibleLocked(ActivityRecord r) {
Craig Mautner858d8a62013-04-23 17:08:34 -0700430 for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700431 WaitResult w = mWaitingActivityVisible.get(i);
432 w.timeout = false;
433 if (r != null) {
434 w.who = new ComponentName(r.info.packageName, r.info.name);
435 }
436 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
437 w.thisTime = w.totalTime;
438 }
439 mService.notifyAll();
440 dismissKeyguard();
441 }
442
443 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
444 long thisTime, long totalTime) {
445 for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
Craig Mautnerc64f73e2013-04-24 16:44:56 -0700446 WaitResult w = mWaitingActivityLaunched.remove(i);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700447 w.timeout = timeout;
448 if (r != null) {
449 w.who = new ComponentName(r.info.packageName, r.info.name);
450 }
451 w.thisTime = thisTime;
452 w.totalTime = totalTime;
453 }
454 mService.notifyAll();
455 }
456
Craig Mautner29219d92013-04-16 20:19:12 -0700457 ActivityRecord topRunningActivityLocked() {
458 ActivityRecord r = null;
459 if (mFocusedStack != null) {
460 r = mFocusedStack.topRunningActivityLocked(null);
461 if (r != null) {
462 return r;
463 }
464 }
465 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
466 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner858d8a62013-04-23 17:08:34 -0700467 if (stack.mCurrentUser != mCurrentUser) {
468 continue;
469 }
Craig Mautner29219d92013-04-16 20:19:12 -0700470 if (stack != mFocusedStack && isFrontStack(stack)) {
471 r = stack.topRunningActivityLocked(null);
472 if (r != null) {
473 return r;
474 }
475 }
476 }
477 return null;
478 }
479
Craig Mautner20e72272013-04-01 13:45:53 -0700480 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
481 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
482 ActivityRecord r = null;
483 final int numStacks = mStacks.size();
484 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
485 final ActivityStack stack = mStacks.get(stackNdx);
486 final ActivityRecord ar =
487 stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700488 if (isFrontStack(stack)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700489 r = ar;
490 }
491 }
492 return r;
493 }
494
Craig Mautner23ac33b2013-04-01 16:26:35 -0700495 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
496 String profileFile, ParcelFileDescriptor profileFd, int userId) {
497 // Collect information about the target of the Intent.
498 ActivityInfo aInfo;
499 try {
500 ResolveInfo rInfo =
501 AppGlobals.getPackageManager().resolveIntent(
502 intent, resolvedType,
503 PackageManager.MATCH_DEFAULT_ONLY
504 | ActivityManagerService.STOCK_PM_FLAGS, userId);
505 aInfo = rInfo != null ? rInfo.activityInfo : null;
506 } catch (RemoteException e) {
507 aInfo = null;
508 }
509
510 if (aInfo != null) {
511 // Store the found target back into the intent, because now that
512 // we have it we never want to do this again. For example, if the
513 // user navigates back to this point in the history, we should
514 // always restart the exact same activity.
515 intent.setComponent(new ComponentName(
516 aInfo.applicationInfo.packageName, aInfo.name));
517
518 // Don't debug things in the system process
519 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
520 if (!aInfo.processName.equals("system")) {
521 mService.setDebugApp(aInfo.processName, true, false);
522 }
523 }
524
525 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
526 if (!aInfo.processName.equals("system")) {
527 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
528 }
529 }
530
531 if (profileFile != null) {
532 if (!aInfo.processName.equals("system")) {
533 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
534 profileFile, profileFd,
535 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
536 }
537 }
538 }
539 return aInfo;
540 }
541
Craig Mautner2219a1b2013-03-25 09:44:30 -0700542 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700543 moveHomeStack(true);
Craig Mautner6170f732013-04-02 13:05:23 -0700544 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
Craig Mautner2219a1b2013-03-25 09:44:30 -0700545 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700546 }
547
Craig Mautner23ac33b2013-04-01 16:26:35 -0700548 final int startActivityMayWait(IApplicationThread caller, int callingUid,
549 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
550 String resultWho, int requestCode, int startFlags, String profileFile,
551 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
552 Bundle options, int userId) {
553 // Refuse possible leaked file descriptors
554 if (intent != null && intent.hasFileDescriptors()) {
555 throw new IllegalArgumentException("File descriptors passed in Intent");
556 }
557 boolean componentSpecified = intent.getComponent() != null;
558
559 // Don't modify the client's object!
560 intent = new Intent(intent);
561
562 // Collect information about the target of the Intent.
563 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
564 profileFile, profileFd, userId);
565
566 synchronized (mService) {
567 int callingPid;
568 if (callingUid >= 0) {
569 callingPid = -1;
570 } else if (caller == null) {
571 callingPid = Binder.getCallingPid();
572 callingUid = Binder.getCallingUid();
573 } else {
574 callingPid = callingUid = -1;
575 }
576
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700577 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -0700578 stack.mConfigWillChange = config != null
Craig Mautner23ac33b2013-04-01 16:26:35 -0700579 && mService.mConfiguration.diff(config) != 0;
580 if (DEBUG_CONFIGURATION) Slog.v(TAG,
Craig Mautnerde4ef022013-04-07 19:01:33 -0700581 "Starting activity when config will change = " + stack.mConfigWillChange);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700582
583 final long origId = Binder.clearCallingIdentity();
584
585 if (aInfo != null &&
586 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
587 // This may be a heavy-weight process! Check to see if we already
588 // have another, different heavy-weight process running.
589 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
590 if (mService.mHeavyWeightProcess != null &&
591 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
592 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
593 int realCallingPid = callingPid;
594 int realCallingUid = callingUid;
595 if (caller != null) {
596 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
597 if (callerApp != null) {
598 realCallingPid = callerApp.pid;
599 realCallingUid = callerApp.info.uid;
600 } else {
601 Slog.w(TAG, "Unable to find app for caller " + caller
602 + " (pid=" + realCallingPid + ") when starting: "
603 + intent.toString());
604 ActivityOptions.abort(options);
605 return ActivityManager.START_PERMISSION_DENIED;
606 }
607 }
608
609 IIntentSender target = mService.getIntentSenderLocked(
610 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
611 realCallingUid, userId, null, null, 0, new Intent[] { intent },
612 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
613 | PendingIntent.FLAG_ONE_SHOT, null);
614
615 Intent newIntent = new Intent();
616 if (requestCode >= 0) {
617 // Caller is requesting a result.
618 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
619 }
620 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
621 new IntentSender(target));
622 if (mService.mHeavyWeightProcess.activities.size() > 0) {
623 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
624 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
625 hist.packageName);
626 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
627 hist.task.taskId);
628 }
629 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
630 aInfo.packageName);
631 newIntent.setFlags(intent.getFlags());
632 newIntent.setClassName("android",
633 HeavyWeightSwitcherActivity.class.getName());
634 intent = newIntent;
635 resolvedType = null;
636 caller = null;
637 callingUid = Binder.getCallingUid();
638 callingPid = Binder.getCallingPid();
639 componentSpecified = true;
640 try {
641 ResolveInfo rInfo =
642 AppGlobals.getPackageManager().resolveIntent(
643 intent, null,
644 PackageManager.MATCH_DEFAULT_ONLY
645 | ActivityManagerService.STOCK_PM_FLAGS, userId);
646 aInfo = rInfo != null ? rInfo.activityInfo : null;
647 aInfo = mService.getActivityInfoForUser(aInfo, userId);
648 } catch (RemoteException e) {
649 aInfo = null;
650 }
651 }
652 }
653 }
654
Craig Mautner6170f732013-04-02 13:05:23 -0700655 int res = startActivityLocked(caller, intent, resolvedType,
Craig Mautner23ac33b2013-04-01 16:26:35 -0700656 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
657 callingPackage, startFlags, options, componentSpecified, null);
658
Craig Mautnerde4ef022013-04-07 19:01:33 -0700659 if (stack.mConfigWillChange) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700660 // If the caller also wants to switch to a new configuration,
661 // do so now. This allows a clean switch, as we are waiting
662 // for the current activity to pause (so we will not destroy
663 // it), and have not yet started the next activity.
664 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
665 "updateConfiguration()");
Craig Mautnerde4ef022013-04-07 19:01:33 -0700666 stack.mConfigWillChange = false;
Craig Mautner23ac33b2013-04-01 16:26:35 -0700667 if (DEBUG_CONFIGURATION) Slog.v(TAG,
668 "Updating to new configuration after starting activity.");
669 mService.updateConfigurationLocked(config, null, false, false);
670 }
671
672 Binder.restoreCallingIdentity(origId);
673
674 if (outResult != null) {
675 outResult.result = res;
676 if (res == ActivityManager.START_SUCCESS) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700677 mWaitingActivityLaunched.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700678 do {
679 try {
680 mService.wait();
681 } catch (InterruptedException e) {
682 }
683 } while (!outResult.timeout && outResult.who == null);
684 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700685 ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700686 if (r.nowVisible) {
687 outResult.timeout = false;
688 outResult.who = new ComponentName(r.info.packageName, r.info.name);
689 outResult.totalTime = 0;
690 outResult.thisTime = 0;
691 } else {
692 outResult.thisTime = SystemClock.uptimeMillis();
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700693 mWaitingActivityVisible.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700694 do {
695 try {
696 mService.wait();
697 } catch (InterruptedException e) {
698 }
699 } while (!outResult.timeout && outResult.who == null);
700 }
701 }
702 }
703
704 return res;
705 }
706 }
707
708 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
709 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
710 Bundle options, int userId) {
711 if (intents == null) {
712 throw new NullPointerException("intents is null");
713 }
714 if (resolvedTypes == null) {
715 throw new NullPointerException("resolvedTypes is null");
716 }
717 if (intents.length != resolvedTypes.length) {
718 throw new IllegalArgumentException("intents are length different than resolvedTypes");
719 }
720
721 ActivityRecord[] outActivity = new ActivityRecord[1];
722
723 int callingPid;
724 if (callingUid >= 0) {
725 callingPid = -1;
726 } else if (caller == null) {
727 callingPid = Binder.getCallingPid();
728 callingUid = Binder.getCallingUid();
729 } else {
730 callingPid = callingUid = -1;
731 }
732 final long origId = Binder.clearCallingIdentity();
733 try {
734 synchronized (mService) {
735
736 for (int i=0; i<intents.length; i++) {
737 Intent intent = intents[i];
738 if (intent == null) {
739 continue;
740 }
741
742 // Refuse possible leaked file descriptors
743 if (intent != null && intent.hasFileDescriptors()) {
744 throw new IllegalArgumentException("File descriptors passed in Intent");
745 }
746
747 boolean componentSpecified = intent.getComponent() != null;
748
749 // Don't modify the client's object!
750 intent = new Intent(intent);
751
752 // Collect information about the target of the Intent.
753 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
754 0, null, null, userId);
755 // TODO: New, check if this is correct
756 aInfo = mService.getActivityInfoForUser(aInfo, userId);
757
758 if (aInfo != null &&
759 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
760 != 0) {
761 throw new IllegalArgumentException(
762 "FLAG_CANT_SAVE_STATE not supported here");
763 }
764
765 Bundle theseOptions;
766 if (options != null && i == intents.length-1) {
767 theseOptions = options;
768 } else {
769 theseOptions = null;
770 }
Craig Mautner6170f732013-04-02 13:05:23 -0700771 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Craig Mautner23ac33b2013-04-01 16:26:35 -0700772 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
773 0, theseOptions, componentSpecified, outActivity);
774 if (res < 0) {
775 return res;
776 }
777
778 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
779 }
780 }
781 } finally {
782 Binder.restoreCallingIdentity(origId);
783 }
784
785 return ActivityManager.START_SUCCESS;
786 }
787
Craig Mautner2420ead2013-04-01 17:13:20 -0700788 final boolean realStartActivityLocked(ActivityRecord r,
789 ProcessRecord app, boolean andResume, boolean checkConfig)
790 throws RemoteException {
791
792 r.startFreezingScreenLocked(app, 0);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700793 mWindowManager.setAppVisibility(r.appToken, true);
Craig Mautner2420ead2013-04-01 17:13:20 -0700794
795 // schedule launch ticks to collect information about slow apps.
796 r.startLaunchTickingLocked();
797
798 // Have the window manager re-evaluate the orientation of
799 // the screen based on the new activity order. Note that
800 // as a result of this, it can call back into the activity
801 // manager with a new orientation. We don't care about that,
802 // because the activity is not currently running so we are
803 // just restarting it anyway.
804 if (checkConfig) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700805 Configuration config = mWindowManager.updateOrientationFromAppTokens(
Craig Mautner2420ead2013-04-01 17:13:20 -0700806 mService.mConfiguration,
807 r.mayFreezeScreenLocked(app) ? r.appToken : null);
808 mService.updateConfigurationLocked(config, r, false, false);
809 }
810
811 r.app = app;
812 app.waitingToKill = null;
813 r.launchCount++;
814 r.lastLaunchTime = SystemClock.uptimeMillis();
815
816 if (localLOGV) Slog.v(TAG, "Launching: " + r);
817
818 int idx = app.activities.indexOf(r);
819 if (idx < 0) {
820 app.activities.add(r);
821 }
822 mService.updateLruProcessLocked(app, true);
823
824 final ActivityStack stack = r.task.stack;
825 try {
826 if (app.thread == null) {
827 throw new RemoteException();
828 }
829 List<ResultInfo> results = null;
830 List<Intent> newIntents = null;
831 if (andResume) {
832 results = r.results;
833 newIntents = r.newIntents;
834 }
835 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
836 + " icicle=" + r.icicle
837 + " with results=" + results + " newIntents=" + newIntents
838 + " andResume=" + andResume);
839 if (andResume) {
840 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
841 r.userId, System.identityHashCode(r),
842 r.task.taskId, r.shortComponentName);
843 }
844 if (r.isHomeActivity) {
845 mService.mHomeProcess = app;
846 }
847 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
848 r.sleeping = false;
849 r.forceNewConfig = false;
850 mService.showAskCompatModeDialogLocked(r);
851 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
852 String profileFile = null;
853 ParcelFileDescriptor profileFd = null;
854 boolean profileAutoStop = false;
855 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
856 if (mService.mProfileProc == null || mService.mProfileProc == app) {
857 mService.mProfileProc = app;
858 profileFile = mService.mProfileFile;
859 profileFd = mService.mProfileFd;
860 profileAutoStop = mService.mAutoStopProfiler;
861 }
862 }
863 app.hasShownUi = true;
864 app.pendingUiClean = true;
865 if (profileFd != null) {
866 try {
867 profileFd = profileFd.dup();
868 } catch (IOException e) {
869 if (profileFd != null) {
870 try {
871 profileFd.close();
872 } catch (IOException o) {
873 }
874 profileFd = null;
875 }
876 }
877 }
878 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
879 System.identityHashCode(r), r.info,
880 new Configuration(mService.mConfiguration),
881 r.compat, r.icicle, results, newIntents, !andResume,
882 mService.isNextTransitionForward(), profileFile, profileFd,
883 profileAutoStop);
884
885 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
886 // This may be a heavy-weight process! Note that the package
887 // manager will ensure that only activity can run in the main
888 // process of the .apk, which is the only thing that will be
889 // considered heavy-weight.
890 if (app.processName.equals(app.info.packageName)) {
891 if (mService.mHeavyWeightProcess != null
892 && mService.mHeavyWeightProcess != app) {
893 Slog.w(TAG, "Starting new heavy weight process " + app
894 + " when already running "
895 + mService.mHeavyWeightProcess);
896 }
897 mService.mHeavyWeightProcess = app;
898 Message msg = mService.mHandler.obtainMessage(
899 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
900 msg.obj = r;
901 mService.mHandler.sendMessage(msg);
902 }
903 }
904
905 } catch (RemoteException e) {
906 if (r.launchFailed) {
907 // This is the second time we failed -- finish activity
908 // and give up.
909 Slog.e(TAG, "Second failure launching "
910 + r.intent.getComponent().flattenToShortString()
911 + ", giving up", e);
912 mService.appDiedLocked(app, app.pid, app.thread);
913 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
914 "2nd-crash", false);
915 return false;
916 }
917
918 // This is the first time we failed -- restart process and
919 // retry.
920 app.activities.remove(r);
921 throw e;
922 }
923
924 r.launchFailed = false;
925 if (stack.updateLRUListLocked(r)) {
926 Slog.w(TAG, "Activity " + r
927 + " being launched, but already in LRU list");
928 }
929
930 if (andResume) {
931 // As part of the process of launching, ActivityThread also performs
932 // a resume.
933 stack.minimalResumeActivityLocked(r);
934 } else {
935 // This activity is not starting in the resumed state... which
936 // should look like we asked it to pause+stop (but remain visible),
937 // and it has done so and reported back the current icicle and
938 // other state.
939 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
940 + " (starting in stopped state)");
941 r.state = ActivityState.STOPPED;
942 r.stopped = true;
943 }
944
945 // Launch the new version setup screen if needed. We do this -after-
946 // launching the initial activity (that is, home), so that it can have
947 // a chance to initialize itself while in the background, making the
948 // switch back to it faster and look better.
Craig Mautnerde4ef022013-04-07 19:01:33 -0700949 if (isFrontStack(stack)) {
Craig Mautner2420ead2013-04-01 17:13:20 -0700950 mService.startSetupActivityLocked();
951 }
952
953 return true;
954 }
955
Craig Mautnere79d42682013-04-01 19:01:53 -0700956 void startSpecificActivityLocked(ActivityRecord r,
957 boolean andResume, boolean checkConfig) {
958 // Is this activity's application already running?
959 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
960 r.info.applicationInfo.uid);
961
962 r.task.stack.setLaunchTime(r);
963
964 if (app != null && app.thread != null) {
965 try {
966 app.addPackage(r.info.packageName);
967 realStartActivityLocked(r, app, andResume, checkConfig);
968 return;
969 } catch (RemoteException e) {
970 Slog.w(TAG, "Exception when starting activity "
971 + r.intent.getComponent().flattenToShortString(), e);
972 }
973
974 // If a dead object exception was thrown -- fall through to
975 // restart the application.
976 }
977
978 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
979 "activity", r.intent.getComponent(), false, false);
980 }
981
Craig Mautner6170f732013-04-02 13:05:23 -0700982 final int startActivityLocked(IApplicationThread caller,
983 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
984 String resultWho, int requestCode,
985 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
986 boolean componentSpecified, ActivityRecord[] outActivity) {
987 int err = ActivityManager.START_SUCCESS;
988
989 ProcessRecord callerApp = null;
990 if (caller != null) {
991 callerApp = mService.getRecordForAppLocked(caller);
992 if (callerApp != null) {
993 callingPid = callerApp.pid;
994 callingUid = callerApp.info.uid;
995 } else {
996 Slog.w(TAG, "Unable to find app for caller " + caller
997 + " (pid=" + callingPid + ") when starting: "
998 + intent.toString());
999 err = ActivityManager.START_PERMISSION_DENIED;
1000 }
1001 }
1002
1003 if (err == ActivityManager.START_SUCCESS) {
1004 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
1005 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
1006 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
1007 }
1008
1009 ActivityRecord sourceRecord = null;
1010 ActivityRecord resultRecord = null;
1011 if (resultTo != null) {
1012 sourceRecord = isInAnyStackLocked(resultTo);
1013 if (DEBUG_RESULTS) Slog.v(
1014 TAG, "Will send result to " + resultTo + " " + sourceRecord);
1015 if (sourceRecord != null) {
1016 if (requestCode >= 0 && !sourceRecord.finishing) {
1017 resultRecord = sourceRecord;
1018 }
1019 }
1020 }
1021 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
1022
1023 int launchFlags = intent.getFlags();
1024
1025 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
1026 && sourceRecord != null) {
1027 // Transfer the result target from the source activity to the new
1028 // one being started, including any failures.
1029 if (requestCode >= 0) {
1030 ActivityOptions.abort(options);
1031 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
1032 }
1033 resultRecord = sourceRecord.resultTo;
1034 resultWho = sourceRecord.resultWho;
1035 requestCode = sourceRecord.requestCode;
1036 sourceRecord.resultTo = null;
1037 if (resultRecord != null) {
1038 resultRecord.removeResultsLocked(
1039 sourceRecord, resultWho, requestCode);
1040 }
1041 }
1042
1043 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
1044 // We couldn't find a class that can handle the given Intent.
1045 // That's the end of that!
1046 err = ActivityManager.START_INTENT_NOT_RESOLVED;
1047 }
1048
1049 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
1050 // We couldn't find the specific class specified in the Intent.
1051 // Also the end of the line.
1052 err = ActivityManager.START_CLASS_NOT_FOUND;
1053 }
1054
1055 if (err != ActivityManager.START_SUCCESS) {
1056 if (resultRecord != null) {
1057 resultStack.sendActivityResultLocked(-1,
1058 resultRecord, resultWho, requestCode,
1059 Activity.RESULT_CANCELED, null);
1060 }
1061 setDismissKeyguard(false);
1062 ActivityOptions.abort(options);
1063 return err;
1064 }
1065
1066 final int startAnyPerm = mService.checkPermission(
1067 START_ANY_ACTIVITY, callingPid, callingUid);
1068 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
1069 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
1070 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
1071 if (resultRecord != null) {
1072 resultStack.sendActivityResultLocked(-1,
1073 resultRecord, resultWho, requestCode,
1074 Activity.RESULT_CANCELED, null);
1075 }
1076 setDismissKeyguard(false);
1077 String msg;
1078 if (!aInfo.exported) {
1079 msg = "Permission Denial: starting " + intent.toString()
1080 + " from " + callerApp + " (pid=" + callingPid
1081 + ", uid=" + callingUid + ")"
1082 + " not exported from uid " + aInfo.applicationInfo.uid;
1083 } else {
1084 msg = "Permission Denial: starting " + intent.toString()
1085 + " from " + callerApp + " (pid=" + callingPid
1086 + ", uid=" + callingUid + ")"
1087 + " requires " + aInfo.permission;
1088 }
1089 Slog.w(TAG, msg);
1090 throw new SecurityException(msg);
1091 }
1092
Ben Gruver6617c3c2013-04-03 18:45:22 -07001093 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
Ben Gruver7b879f42013-04-08 14:56:55 -07001094 callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo);
Ben Gruver5e207332013-04-03 17:41:37 -07001095
Craig Mautner6170f732013-04-02 13:05:23 -07001096 if (mService.mController != null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001097 try {
1098 // The Intent we give to the watcher has the extra data
1099 // stripped off, since it can contain private information.
1100 Intent watchIntent = intent.cloneFilter();
Ben Gruver5e207332013-04-03 17:41:37 -07001101 abort |= !mService.mController.activityStarting(watchIntent,
Craig Mautner6170f732013-04-02 13:05:23 -07001102 aInfo.applicationInfo.packageName);
1103 } catch (RemoteException e) {
1104 mService.mController = null;
1105 }
Ben Gruver5e207332013-04-03 17:41:37 -07001106 }
Craig Mautner6170f732013-04-02 13:05:23 -07001107
Ben Gruver5e207332013-04-03 17:41:37 -07001108 if (abort) {
1109 if (resultRecord != null) {
1110 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Craig Mautner6170f732013-04-02 13:05:23 -07001111 Activity.RESULT_CANCELED, null);
Craig Mautner6170f732013-04-02 13:05:23 -07001112 }
Ben Gruver5e207332013-04-03 17:41:37 -07001113 // We pretend to the caller that it was really started, but
1114 // they will just get a cancel result.
1115 setDismissKeyguard(false);
1116 ActivityOptions.abort(options);
1117 return ActivityManager.START_SUCCESS;
Craig Mautner6170f732013-04-02 13:05:23 -07001118 }
1119
1120 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1121 intent, resolvedType, aInfo, mService.mConfiguration,
Craig Mautnerde4ef022013-04-07 19:01:33 -07001122 resultRecord, resultWho, requestCode, componentSpecified, this);
Craig Mautner6170f732013-04-02 13:05:23 -07001123 if (outActivity != null) {
1124 outActivity[0] = r;
1125 }
1126
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001127 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001128 if (stack.mResumedActivity == null
1129 || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
Craig Mautner6170f732013-04-02 13:05:23 -07001130 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1131 PendingActivityLaunch pal =
Craig Mautnerde4ef022013-04-07 19:01:33 -07001132 new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
Craig Mautner6170f732013-04-02 13:05:23 -07001133 mService.mPendingActivityLaunches.add(pal);
1134 setDismissKeyguard(false);
1135 ActivityOptions.abort(options);
1136 return ActivityManager.START_SWITCHES_CANCELED;
1137 }
1138 }
1139
1140 if (mService.mDidAppSwitch) {
1141 // This is the second allowed switch since we stopped switches,
1142 // so now just generally allow switches. Use case: user presses
1143 // home (switches disabled, switch to home, mDidAppSwitch now true);
1144 // user taps a home icon (coming from home so allowed, we hit here
1145 // and now allow anyone to switch again).
1146 mService.mAppSwitchesAllowedTime = 0;
1147 } else {
1148 mService.mDidAppSwitch = true;
1149 }
1150
1151 mService.doPendingActivityLaunchesLocked(false);
1152
Craig Mautner8849a5e2013-04-02 16:41:03 -07001153 err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001154 if (stack.mPausingActivity == null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001155 // Someone asked to have the keyguard dismissed on the next
1156 // activity start, but we are not actually doing an activity
1157 // switch... just dismiss the keyguard now, because we
1158 // probably want to see whatever is behind it.
1159 dismissKeyguard();
1160 }
1161 return err;
1162 }
1163
Craig Mautnerde4ef022013-04-07 19:01:33 -07001164 ActivityStack getCorrectStack(ActivityRecord r) {
1165 if (!r.isHomeActivity) {
Craig Mautner858d8a62013-04-23 17:08:34 -07001166 int stackNdx;
1167 for (stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
1168 if (mStacks.get(stackNdx).mCurrentUser == mCurrentUser) {
1169 break;
1170 }
1171 }
1172 if (stackNdx == 0) {
1173 // Time to create the first app stack for this user.
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001174 int stackId = mService.createStack(-1, HOME_STACK_ID,
1175 StackBox.TASK_STACK_GOES_OVER, 1.0f);
Craig Mautner29219d92013-04-16 20:19:12 -07001176 mFocusedStack = getStack(stackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001177 }
Craig Mautner29219d92013-04-16 20:19:12 -07001178 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001179 }
1180 return mHomeStack;
1181 }
1182
Craig Mautner29219d92013-04-16 20:19:12 -07001183 void setFocusedStack(ActivityRecord r) {
1184 if (r == null) {
1185 return;
1186 }
1187 if (r.isHomeActivity) {
1188 if (mStackState != STACK_STATE_HOME_IN_FRONT) {
1189 mStackState = STACK_STATE_HOME_TO_FRONT;
1190 }
1191 } else {
1192 mFocusedStack = r.task.stack;
1193 if (mStackState != STACK_STATE_HOME_IN_BACK) {
1194 mStackState = STACK_STATE_HOME_TO_BACK;
1195 }
1196 }
1197 }
1198
Craig Mautner8849a5e2013-04-02 16:41:03 -07001199 final int startActivityUncheckedLocked(ActivityRecord r,
1200 ActivityRecord sourceRecord, int startFlags, boolean doResume,
1201 Bundle options) {
1202 final Intent intent = r.intent;
1203 final int callingUid = r.launchedFromUid;
1204
1205 int launchFlags = intent.getFlags();
1206
Craig Mautner8849a5e2013-04-02 16:41:03 -07001207 // We'll invoke onUserLeaving before onPause only if the launching
1208 // activity did not explicitly state that this is an automated launch.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001209 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1210 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001211
1212 // If the caller has asked not to resume at this point, we make note
1213 // of this in the record so that we can skip it when trying to find
1214 // the top running activity.
1215 if (!doResume) {
1216 r.delayedResume = true;
1217 }
1218
1219 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1220
1221 // If the onlyIfNeeded flag is set, then we can do this if the activity
1222 // being launched is the same as the one making the call... or, as
1223 // a special case, if we do not know the caller then we count the
1224 // current top activity as the caller.
1225 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1226 ActivityRecord checkedCaller = sourceRecord;
1227 if (checkedCaller == null) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001228 checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001229 }
1230 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1231 // Caller is not the same as launcher, so always needed.
1232 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1233 }
1234 }
1235
1236 if (sourceRecord == null) {
1237 // This activity is not being started from another... in this
1238 // case we -always- start a new task.
1239 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Craig Mautner29219d92013-04-16 20:19:12 -07001240 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1241 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001242 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1243 }
1244 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1245 // The original activity who is starting us is running as a single
1246 // instance... this new activity it is starting must go on its
1247 // own task.
1248 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1249 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1250 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1251 // The activity being started is a single instance... it always
1252 // gets launched into its own task.
1253 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1254 }
1255
Craig Mautnerde4ef022013-04-07 19:01:33 -07001256 final ActivityStack sourceStack;
1257 final TaskRecord sourceTask;
1258 if (sourceRecord != null) {
1259 sourceTask = sourceRecord.task;
1260 sourceStack = sourceTask.stack;
1261 } else {
1262 sourceTask = null;
1263 sourceStack = null;
1264 }
1265
Craig Mautner8849a5e2013-04-02 16:41:03 -07001266 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1267 // For whatever reason this activity is being launched into a new
1268 // task... yet the caller has requested a result back. Well, that
1269 // is pretty messed up, so instead immediately send back a cancel
1270 // and let the new task continue launched as normal without a
1271 // dependency on its originator.
1272 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1273 r.resultTo.task.stack.sendActivityResultLocked(-1,
1274 r.resultTo, r.resultWho, r.requestCode,
1275 Activity.RESULT_CANCELED, null);
1276 r.resultTo = null;
1277 }
1278
1279 boolean addingToTask = false;
1280 boolean movedHome = false;
1281 TaskRecord reuseTask = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001282 ActivityStack targetStack;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001283 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1284 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1285 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1286 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1287 // If bring to front is requested, and no result is requested, and
1288 // we can find a task that was started with this same
1289 // component, then instead of launching bring that one to the front.
1290 if (r.resultTo == null) {
1291 // See if there is a task to bring to the front. If this is
1292 // a SINGLE_INSTANCE activity, there can be one and only one
1293 // instance of it in the history, and it is always in its own
1294 // unique task, so we do a special search.
1295 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
1296 ? findTaskLocked(intent, r.info)
1297 : findActivityLocked(intent, r.info);
1298 if (intentActivity != null) {
Craig Mautner29219d92013-04-16 20:19:12 -07001299 if (r.task == null) {
1300 r.task = intentActivity.task;
1301 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001302 targetStack = intentActivity.task.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001303 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001304 if (intentActivity.task.intent == null) {
1305 // This task was started because of movement of
1306 // the activity based on affinity... now that we
1307 // are actually launching it, we can assign the
1308 // base intent.
1309 intentActivity.task.setIntent(intent, r.info);
1310 }
1311 // If the target task is not in the front, then we need
1312 // to bring it to the front... except... well, with
1313 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
1314 // to have the same behavior as if a new instance was
1315 // being started, which means not bringing it to the front
1316 // if the caller is not itself in the front.
Craig Mautner165640b2013-04-20 10:34:33 -07001317 final ActivityStack lastStack = getLastStack();
1318 ActivityRecord curTop = lastStack == null?
1319 null : lastStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001320 if (curTop != null && curTop.task != intentActivity.task) {
1321 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001322 if (sourceRecord == null || sourceStack.topActivity() == sourceRecord) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001323 // We really do want to push this one into the
1324 // user's face, right now.
1325 movedHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001326 if ((launchFlags &
Craig Mautner29219d92013-04-16 20:19:12 -07001327 (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1328 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001329 // Caller wants to appear on home activity, so before starting
1330 // their own activity we will bring home to the front.
1331 r.mLaunchHomeTaskNext = true;
1332 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001333 targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1334 options = null;
1335 }
1336 }
1337 // If the caller has requested that the target task be
1338 // reset, then do so.
1339 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1340 intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1341 }
1342 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1343 // We don't need to start a new activity, and
1344 // the client said not to do anything if that
1345 // is the case, so this is it! And for paranoia, make
1346 // sure we have correctly resumed the top activity.
1347 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001348 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001349 resumeTopActivitiesLocked(targetStack, null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001350 } else {
1351 ActivityOptions.abort(options);
1352 }
Craig Mautner29219d92013-04-16 20:19:12 -07001353 if (r.task == null) Slog.v(TAG,
1354 "startActivityUncheckedLocked: task left null",
1355 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001356 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1357 }
1358 if ((launchFlags &
1359 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1360 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1361 // The caller has requested to completely replace any
1362 // existing task with its new activity. Well that should
1363 // not be too hard...
1364 reuseTask = intentActivity.task;
1365 reuseTask.performClearTaskLocked();
1366 reuseTask.setIntent(r.intent, r.info);
1367 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1368 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1369 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1370 // In this situation we want to remove all activities
1371 // from the task up to the one being started. In most
1372 // cases this means we are resetting the task to its
1373 // initial state.
1374 ActivityRecord top =
1375 intentActivity.task.performClearTaskLocked(r, launchFlags);
1376 if (top != null) {
1377 if (top.frontOfTask) {
1378 // Activity aliases may mean we use different
1379 // intents for the top activity, so make sure
1380 // the task now has the identity of the new
1381 // intent.
1382 top.task.setIntent(r.intent, r.info);
1383 }
1384 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1385 r, top.task);
1386 top.deliverNewIntentLocked(callingUid, r.intent);
1387 } else {
1388 // A special case: we need to
1389 // start the activity because it is not currently
1390 // running, and the caller has asked to clear the
1391 // current task to have this activity at the top.
1392 addingToTask = true;
1393 // Now pretend like this activity is being started
1394 // by the top of its task, so it is put in the
1395 // right place.
1396 sourceRecord = intentActivity;
1397 }
1398 } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1399 // In this case the top activity on the task is the
1400 // same as the one being launched, so we take that
1401 // as a request to bring the task to the foreground.
1402 // If the top activity in the task is the root
1403 // activity, deliver this new intent to it if it
1404 // desires.
1405 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1406 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1407 && intentActivity.realActivity.equals(r.realActivity)) {
1408 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1409 intentActivity.task);
1410 if (intentActivity.frontOfTask) {
1411 intentActivity.task.setIntent(r.intent, r.info);
1412 }
1413 intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1414 } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1415 // In this case we are launching the root activity
1416 // of the task, but with a different intent. We
1417 // should start a new instance on top.
1418 addingToTask = true;
1419 sourceRecord = intentActivity;
1420 }
1421 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1422 // In this case an activity is being launched in to an
1423 // existing task, without resetting that task. This
1424 // is typically the situation of launching an activity
1425 // from a notification or shortcut. We want to place
1426 // the new activity on top of the current task.
1427 addingToTask = true;
1428 sourceRecord = intentActivity;
1429 } else if (!intentActivity.task.rootWasReset) {
1430 // In this case we are launching in to an existing task
1431 // that has not yet been started from its front door.
1432 // The current task has been brought to the front.
1433 // Ideally, we'd probably like to place this new task
1434 // at the bottom of its stack, but that's a little hard
1435 // to do with the current organization of the code so
1436 // for now we'll just drop it.
1437 intentActivity.task.setIntent(r.intent, r.info);
1438 }
1439 if (!addingToTask && reuseTask == null) {
1440 // We didn't do anything... but it was needed (a.k.a., client
1441 // don't use that intent!) And for paranoia, make
1442 // sure we have correctly resumed the top activity.
1443 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001444 setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1445 targetStack.resumeTopActivityLocked(null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001446 } else {
1447 ActivityOptions.abort(options);
1448 }
Craig Mautner29219d92013-04-16 20:19:12 -07001449 if (r.task == null) Slog.v(TAG,
1450 "startActivityUncheckedLocked: task left null",
1451 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001452 return ActivityManager.START_TASK_TO_FRONT;
1453 }
1454 }
1455 }
1456 }
1457
1458 //String uri = r.intent.toURI();
1459 //Intent intent2 = new Intent(uri);
1460 //Slog.i(TAG, "Given intent: " + r.intent);
1461 //Slog.i(TAG, "URI is: " + uri);
1462 //Slog.i(TAG, "To intent: " + intent2);
1463
1464 if (r.packageName != null) {
1465 // If the activity being launched is the same as the one currently
1466 // at the top, then we need to check if it should only be launched
1467 // once.
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001468 ActivityStack topStack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001469 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001470 if (top != null && r.resultTo == null) {
1471 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1472 if (top.app != null && top.app.thread != null) {
1473 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1474 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1475 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1476 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1477 top.task);
1478 // For paranoia, make sure we have correctly
1479 // resumed the top activity.
1480 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001481 setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001482 resumeTopActivitiesLocked();
Craig Mautner8849a5e2013-04-02 16:41:03 -07001483 }
1484 ActivityOptions.abort(options);
1485 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1486 // We don't need to start a new activity, and
1487 // the client said not to do anything if that
1488 // is the case, so this is it!
Craig Mautner29219d92013-04-16 20:19:12 -07001489 if (r.task == null) Slog.v(TAG,
1490 "startActivityUncheckedLocked: task left null",
1491 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001492 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1493 }
1494 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner29219d92013-04-16 20:19:12 -07001495 if (r.task == null) Slog.v(TAG,
1496 "startActivityUncheckedLocked: task left null",
1497 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001498 return ActivityManager.START_DELIVERED_TO_TOP;
1499 }
1500 }
1501 }
1502 }
1503
1504 } else {
1505 if (r.resultTo != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001506 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1507 r.requestCode, Activity.RESULT_CANCELED, null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001508 }
1509 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001510 if (r.task == null) Slog.v(TAG,
1511 "startActivityUncheckedLocked: task left null",
1512 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001513 return ActivityManager.START_CLASS_NOT_FOUND;
1514 }
1515
1516 boolean newTask = false;
1517 boolean keepCurTransition = false;
1518
1519 // Should this be considered a new task?
1520 if (r.resultTo == null && !addingToTask
1521 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001522 targetStack = getCorrectStack(r);
1523 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001524 if (reuseTask == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001525 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1526 null, true);
1527 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1528 r.task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001529 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001530 r.setTask(reuseTask, reuseTask, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001531 }
1532 newTask = true;
1533 if (!movedHome) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001534 if ((launchFlags &
1535 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1536 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1537 // Caller wants to appear on home activity, so before starting
1538 // their own activity we will bring home to the front.
1539 r.mLaunchHomeTaskNext = true;
1540 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001541 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001542 } else if (sourceRecord != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001543 targetStack = sourceRecord.task.stack;
1544 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001545 if (!addingToTask &&
1546 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1547 // In this case, we are adding the activity to an existing
1548 // task, but the caller has asked to clear that task if the
1549 // activity is already running.
1550 ActivityRecord top = sourceRecord.task.performClearTaskLocked(r, launchFlags);
1551 keepCurTransition = true;
1552 if (top != null) {
1553 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1554 top.deliverNewIntentLocked(callingUid, r.intent);
1555 // For paranoia, make sure we have correctly
1556 // resumed the top activity.
1557 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001558 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001559 targetStack.resumeTopActivityLocked(null);
1560 }
1561 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001562 if (r.task == null) Slog.v(TAG,
1563 "startActivityUncheckedLocked: task left null",
1564 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001565 return ActivityManager.START_DELIVERED_TO_TOP;
1566 }
1567 } else if (!addingToTask &&
1568 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1569 // In this case, we are launching an activity in our own task
1570 // that may already be running somewhere in the history, and
1571 // we want to shuffle it to the front of the stack if so.
1572 final ActivityRecord top =
1573 targetStack.findActivityInHistoryLocked(r, sourceRecord.task);
1574 if (top != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001575 final TaskRecord task = top.task;
1576 task.moveActivityToFrontLocked(top);
1577 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001578 top.updateOptionsLocked(options);
1579 top.deliverNewIntentLocked(callingUid, r.intent);
1580 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001581 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001582 targetStack.resumeTopActivityLocked(null);
1583 }
Craig Mautner29219d92013-04-16 20:19:12 -07001584 if (r.task == null) Slog.v(TAG,
1585 "startActivityUncheckedLocked: task left null",
1586 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001587 return ActivityManager.START_DELIVERED_TO_TOP;
1588 }
1589 }
1590 // An existing activity is starting this new activity, so we want
1591 // to keep the new one in the same task as the one that is starting
1592 // it.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001593 r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001594 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1595 + " in existing task " + r.task);
1596
1597 } else {
1598 // This not being started from an existing activity, and not part
1599 // of a new task... just put it in the top task, though these days
1600 // this case should never happen.
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001601 ActivityStack lastStack = getLastStack();
1602 targetStack = lastStack != null ? lastStack : mHomeStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001603 moveHomeStack(targetStack.isHomeStack());
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001604 ActivityRecord prev = lastStack == null ? null : targetStack.topActivity();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001605 r.setTask(prev != null ? prev.task
1606 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1607 null, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001608 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1609 + " in new guessed " + r.task);
1610 }
1611
1612 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1613 intent, r.getUriPermissionsLocked());
1614
1615 if (newTask) {
1616 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1617 }
1618 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001619 setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001620 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
1621 return ActivityManager.START_SUCCESS;
1622 }
1623
Craig Mautnerf3333272013-04-22 10:55:53 -07001624 // Checked.
1625 final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
1626 Configuration config) {
1627 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
1628
1629 ActivityRecord res = null;
1630
1631 ArrayList<ActivityRecord> stops = null;
1632 ArrayList<ActivityRecord> finishes = null;
1633 ArrayList<UserStartedState> startingUsers = null;
1634 int NS = 0;
1635 int NF = 0;
1636 IApplicationThread sendThumbnail = null;
1637 boolean booting = false;
1638 boolean enableScreen = false;
1639 boolean activityRemoved = false;
1640
1641 ActivityRecord r = ActivityRecord.forToken(token);
1642 if (r != null) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07001643 if (DEBUG_IDLE) Slog.d(TAG, "activityIdleInternalLocked: Callers=" +
1644 Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07001645 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
1646 r.finishLaunchTickingLocked();
1647 res = r.task.stack.activityIdleInternalLocked(token, fromTimeout, config);
1648 if (res != null) {
1649 if (fromTimeout) {
1650 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
1651 }
1652
1653 // This is a hack to semi-deal with a race condition
1654 // in the client where it can be constructed with a
1655 // newer configuration from when we asked it to launch.
1656 // We'll update with whatever configuration it now says
1657 // it used to launch.
1658 if (config != null) {
1659 r.configuration = config;
1660 }
1661
1662 // We are now idle. If someone is waiting for a thumbnail from
1663 // us, we can now deliver.
1664 r.idle = true;
1665 if (allResumedActivitiesIdle()) {
1666 mService.scheduleAppGcsLocked();
1667 }
1668 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
1669 sendThumbnail = r.app.thread;
1670 r.thumbnailNeeded = false;
1671 }
1672
1673 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
1674 if (!mService.mBooted && isFrontStack(r.task.stack)) {
1675 mService.mBooted = true;
1676 enableScreen = true;
1677 }
1678 } else if (fromTimeout) {
1679 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
1680 }
1681 }
1682
1683 // Atomically retrieve all of the other things to do.
1684 stops = processStoppingActivitiesLocked(true);
1685 NS = stops != null ? stops.size() : 0;
1686 if ((NF=mFinishingActivities.size()) > 0) {
1687 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
1688 mFinishingActivities.clear();
1689 }
1690
1691 final ArrayList<ActivityRecord> thumbnails;
1692 final int NT = mCancelledThumbnails.size();
1693 if (NT > 0) {
1694 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
1695 mCancelledThumbnails.clear();
1696 } else {
1697 thumbnails = null;
1698 }
1699
1700 if (isFrontStack(mHomeStack)) {
1701 booting = mService.mBooting;
1702 mService.mBooting = false;
1703 }
1704
1705 if (mStartingUsers.size() > 0) {
1706 startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
1707 mStartingUsers.clear();
1708 }
1709
1710 // Perform the following actions from unsynchronized state.
1711 final IApplicationThread thumbnailThread = sendThumbnail;
1712 mHandler.post(new Runnable() {
1713 @Override
1714 public void run() {
1715 if (thumbnailThread != null) {
1716 try {
1717 thumbnailThread.requestThumbnail(token);
1718 } catch (Exception e) {
1719 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
1720 mService.sendPendingThumbnail(null, token, null, null, true);
1721 }
1722 }
1723
1724 // Report back to any thumbnail receivers.
1725 for (int i = 0; i < NT; i++) {
1726 ActivityRecord r = thumbnails.get(i);
1727 mService.sendPendingThumbnail(r, null, null, null, true);
1728 }
1729 }
1730 });
1731
1732 // Stop any activities that are scheduled to do so but have been
1733 // waiting for the next one to start.
1734 for (int i = 0; i < NS; i++) {
1735 r = stops.get(i);
1736 final ActivityStack stack = r.task.stack;
1737 if (r.finishing) {
1738 stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
1739 } else {
1740 stack.stopActivityLocked(r);
1741 }
1742 }
1743
1744 // Finish any activities that are scheduled to do so but have been
1745 // waiting for the next one to start.
1746 for (int i = 0; i < NF; i++) {
1747 r = finishes.get(i);
1748 activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle");
1749 }
1750
1751 if (booting) {
1752 mService.finishBooting();
1753 } else if (startingUsers != null) {
1754 for (int i = 0; i < startingUsers.size(); i++) {
1755 mService.finishUserSwitch(startingUsers.get(i));
1756 }
1757 }
1758
1759 mService.trimApplications();
1760 //dump();
1761 //mWindowManager.dump();
1762
1763 if (enableScreen) {
1764 mService.enableScreenAfterBoot();
1765 }
1766
1767 if (activityRemoved) {
Craig Mautner05d29032013-05-03 13:40:13 -07001768 resumeTopActivitiesLocked();
Craig Mautnerf3333272013-04-22 10:55:53 -07001769 }
1770
1771 return res;
1772 }
1773
Craig Mautner8d341ef2013-03-26 09:03:27 -07001774 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
1775 // Just in case.
1776 final int numStacks = mStacks.size();
1777 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Craig Mautnere79d42682013-04-01 19:01:53 -07001778 mStacks.get(stackNdx).handleAppDiedLocked(app, restarting);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001779 }
1780 }
1781
1782 void closeSystemDialogsLocked() {
1783 final int numStacks = mStacks.size();
1784 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1785 final ActivityStack stack = mStacks.get(stackNdx);
1786 stack.closeSystemDialogsLocked();
1787 }
1788 }
1789
1790 /**
1791 * @return true if some activity was finished (or would have finished if doit were true).
1792 */
1793 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1794 boolean didSomething = false;
1795 final int numStacks = mStacks.size();
1796 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1797 final ActivityStack stack = mStacks.get(stackNdx);
1798 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1799 didSomething = true;
1800 }
1801 }
1802 return didSomething;
1803 }
1804
Craig Mautner05d29032013-05-03 13:40:13 -07001805 boolean resumeTopActivitiesLocked() {
1806 return resumeTopActivitiesLocked(null, null, null);
1807 }
1808
1809 boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
1810 Bundle targetOptions) {
1811 if (targetStack == null) {
1812 targetStack = getFocusedStack();
1813 }
1814 boolean result = false;
Craig Mautnerdbcb31f2013-04-02 12:32:53 -07001815 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001816 final ActivityStack stack = mStacks.get(stackNdx);
1817 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07001818 if (stack == targetStack) {
1819 result = stack.resumeTopActivityLocked(target, targetOptions);
1820 } else {
1821 stack.resumeTopActivityLocked(null);
1822 }
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001823 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001824 }
Craig Mautner05d29032013-05-03 13:40:13 -07001825 return result;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001826 }
1827
1828 void finishTopRunningActivityLocked(ProcessRecord app) {
1829 final int numStacks = mStacks.size();
1830 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1831 final ActivityStack stack = mStacks.get(stackNdx);
1832 stack.finishTopRunningActivityLocked(app);
1833 }
1834 }
1835
Craig Mautner8d341ef2013-03-26 09:03:27 -07001836 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
1837 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1838 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
1839 return;
1840 }
1841 }
1842 }
1843
Craig Mautner967212c2013-04-13 21:10:58 -07001844 ActivityStack getStack(int stackId) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001845 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1846 final ActivityStack stack = mStacks.get(stackNdx);
1847 if (stack.getStackId() == stackId) {
1848 return stack;
1849 }
1850 }
1851 return null;
1852 }
1853
Craig Mautner967212c2013-04-13 21:10:58 -07001854 ArrayList<ActivityStack> getStacks() {
1855 return new ArrayList<ActivityStack>(mStacks);
1856 }
1857
1858 int createStack() {
Craig Mautner858d8a62013-04-23 17:08:34 -07001859 while (true) {
1860 if (++mLastStackId <= HOME_STACK_ID) {
1861 mLastStackId = HOME_STACK_ID + 1;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001862 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001863 if (getStack(mLastStackId) == null) {
1864 break;
1865 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001866 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001867 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
1868 return mLastStackId;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001869 }
1870
1871 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
1872 final ActivityStack stack = getStack(stackId);
1873 if (stack == null) {
1874 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
1875 return;
1876 }
1877 stack.moveTask(taskId, toTop);
Craig Mautner05d29032013-05-03 13:40:13 -07001878 resumeTopActivitiesLocked();
Craig Mautner8d341ef2013-03-26 09:03:27 -07001879 }
1880
Craig Mautner8849a5e2013-04-02 16:41:03 -07001881 ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
1882 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1883 final ActivityRecord ar = mStacks.get(stackNdx).findTaskLocked(intent, info);
1884 if (ar != null) {
1885 return ar;
1886 }
1887 }
1888 return null;
1889 }
1890
1891 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
1892 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1893 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
1894 if (ar != null) {
1895 return ar;
1896 }
1897 }
1898 return null;
1899 }
1900
Craig Mautner8d341ef2013-03-26 09:03:27 -07001901 void goingToSleepLocked() {
1902 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1903 mStacks.get(stackNdx).stopIfSleepingLocked();
1904 }
1905 }
1906
1907 boolean shutdownLocked(int timeout) {
1908 boolean timedout = false;
1909 final int numStacks = mStacks.size();
1910 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1911 final ActivityStack stack = mStacks.get(stackNdx);
1912 if (stack.mResumedActivity != null) {
1913 stack.stopIfSleepingLocked();
1914 final long endTime = System.currentTimeMillis() + timeout;
1915 while (stack.mResumedActivity != null || stack.mPausingActivity != null) {
1916 long delay = endTime - System.currentTimeMillis();
1917 if (delay <= 0) {
1918 Slog.w(TAG, "Activity manager shutdown timed out");
1919 timedout = true;
1920 break;
1921 }
1922 try {
1923 mService.wait();
1924 } catch (InterruptedException e) {
1925 }
1926 }
1927 }
1928 }
1929 return timedout;
1930 }
1931
1932 void comeOutOfSleepIfNeededLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001933 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001934 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001935 stack.awakeFromSleepingLocked();
1936 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07001937 resumeTopActivitiesLocked();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001938 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001939 }
1940 }
1941
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001942 boolean reportResumedActivityLocked(ActivityRecord r) {
1943 final ActivityStack stack = r.task.stack;
1944 if (isFrontStack(stack)) {
Jeff Sharkey5782da72013-04-25 14:32:30 -07001945 mService.updateUsageStats(r, true);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001946 mService.setFocusedActivityLocked(r);
1947 }
1948 if (allResumedActivitiesComplete()) {
1949 ensureActivitiesVisibleLocked(null, 0);
1950 mWindowManager.executeAppTransition();
1951 return true;
1952 }
1953 return false;
1954 }
1955
Craig Mautner8d341ef2013-03-26 09:03:27 -07001956 void handleAppCrashLocked(ProcessRecord app) {
1957 final int numStacks = mStacks.size();
1958 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1959 final ActivityStack stack = mStacks.get(stackNdx);
1960 stack.handleAppCrashLocked(app);
1961 }
1962 }
1963
Craig Mautnerde4ef022013-04-07 19:01:33 -07001964 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
Craig Mautner580ea812013-04-25 12:58:38 -07001965 // First the front stacks. In case any are not fullscreen and are in front of home.
1966 boolean showHomeBehindStack = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001967 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner580ea812013-04-25 12:58:38 -07001968 final ActivityStack stack = mStacks.get(stackNdx);
1969 if (isFrontStack(stack)) {
1970 showHomeBehindStack =
1971 stack.ensureActivitiesVisibleLocked(starting, configChanges);
1972 }
1973 }
1974 // Now do back stacks.
1975 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1976 final ActivityStack stack = mStacks.get(stackNdx);
1977 if (!isFrontStack(stack)) {
1978 stack.ensureActivitiesVisibleLocked(starting, configChanges, showHomeBehindStack);
1979 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001980 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001981 }
1982
1983 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
1984 final int numStacks = mStacks.size();
1985 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1986 final ActivityStack stack = mStacks.get(stackNdx);
1987 stack.scheduleDestroyActivities(app, false, reason);
1988 }
1989 }
1990
1991 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner858d8a62013-04-23 17:08:34 -07001992 mUserStates.put(mCurrentUser, new UserState());
Craig Mautner2420ead2013-04-01 17:13:20 -07001993 mCurrentUser = userId;
Craig Mautner858d8a62013-04-23 17:08:34 -07001994 UserState userState = mUserStates.get(userId);
1995 if (userState != null) {
1996 userState.restore();
1997 mUserStates.delete(userId);
1998 } else {
1999 mFocusedStack = null;
2000 mStackState = STACK_STATE_HOME_IN_FRONT;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002001 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002002
2003 mStartingUsers.add(uss);
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002004 boolean haveActivities = mHomeStack.switchUserLocked(userId);
Craig Mautner858d8a62013-04-23 17:08:34 -07002005
2006 resumeTopActivitiesLocked();
2007
Craig Mautner8d341ef2013-03-26 09:03:27 -07002008 return haveActivities;
Craig Mautner2219a1b2013-03-25 09:44:30 -07002009 }
2010
Craig Mautnerde4ef022013-04-07 19:01:33 -07002011 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
2012 int N = mStoppingActivities.size();
2013 if (N <= 0) return null;
2014
2015 ArrayList<ActivityRecord> stops = null;
2016
2017 final boolean nowVisible = allResumedActivitiesVisible();
2018 for (int i=0; i<N; i++) {
2019 ActivityRecord s = mStoppingActivities.get(i);
2020 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
2021 + nowVisible + " waitingVisible=" + s.waitingVisible
2022 + " finishing=" + s.finishing);
2023 if (s.waitingVisible && nowVisible) {
2024 mWaitingVisibleActivities.remove(s);
2025 s.waitingVisible = false;
2026 if (s.finishing) {
2027 // If this activity is finishing, it is sitting on top of
2028 // everyone else but we now know it is no longer needed...
2029 // so get rid of it. Otherwise, we need to go through the
2030 // normal flow and hide it once we determine that it is
2031 // hidden by the activities in front of it.
2032 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002033 mWindowManager.setAppVisibility(s.appToken, false);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002034 }
2035 }
2036 if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
2037 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
2038 if (stops == null) {
2039 stops = new ArrayList<ActivityRecord>();
2040 }
2041 stops.add(s);
2042 mStoppingActivities.remove(i);
2043 N--;
2044 i--;
2045 }
2046 }
2047
2048 return stops;
2049 }
2050
Craig Mautnercf910b02013-04-23 11:23:27 -07002051 void validateTopActivitiesLocked() {
2052 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2053 final ActivityStack stack = mStacks.get(stackNdx);
2054 final ActivityRecord r = stack.topRunningActivityLocked(null);
2055 if (isFrontStack(stack)) {
2056 if (r == null) {
2057 Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
2058 } else {
2059 if (stack.mPausingActivity != null) {
2060 Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
2061 " state=" + r.state);
2062 }
2063 if (r.state != ActivityState.INITIALIZING &&
2064 r.state != ActivityState.RESUMED) {
2065 Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
2066 " state=" + r.state);
2067 }
2068 }
2069 } else {
2070 if (stack.mResumedActivity != null) {
2071 Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
2072 " state=" + r.state);
2073 }
2074 if (r != null && (r.state == ActivityState.INITIALIZING
2075 || r.state == ActivityState.RESUMED)) {
2076 Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
2077 " state=" + r.state);
2078 }
2079 }
2080 }
2081 }
2082
Craig Mautner27084302013-03-25 08:05:25 -07002083 public void dump(PrintWriter pw, String prefix) {
2084 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
2085 pw.println(mDismissKeyguardOnNextActivity);
2086 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002087
Craig Mautner20e72272013-04-01 13:45:53 -07002088 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002089 return getFocusedStack().getDumpActivitiesLocked(name);
Craig Mautner20e72272013-04-01 13:45:53 -07002090 }
2091
Craig Mautner8d341ef2013-03-26 09:03:27 -07002092 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
2093 boolean dumpClient, String dumpPackage) {
2094 final int numStacks = mStacks.size();
2095 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2096 final ActivityStack stack = mStacks.get(stackNdx);
2097 pw.print(" Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
2098 stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
2099 pw.println(" ");
2100 pw.println(" Running activities (most recent first):");
2101 dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false,
2102 dumpPackage);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002103 if (stack.mGoingToSleepActivities.size() > 0) {
2104 pw.println(" ");
2105 pw.println(" Activities waiting to sleep:");
2106 dumpHistoryList(fd, pw, stack.mGoingToSleepActivities, " ", "Sleep", false,
2107 !dumpAll, false, dumpPackage);
2108 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002109
Craig Mautner8d341ef2013-03-26 09:03:27 -07002110 pw.print(" Stack #"); pw.println(mStacks.indexOf(stack));
2111 if (stack.mPausingActivity != null) {
2112 pw.println(" mPausingActivity: " + stack.mPausingActivity);
2113 }
2114 pw.println(" mResumedActivity: " + stack.mResumedActivity);
2115 if (dumpAll) {
2116 pw.println(" mLastPausedActivity: " + stack.mLastPausedActivity);
2117 pw.println(" mSleepTimeout: " + stack.mSleepTimeout);
2118 }
2119 }
2120
Craig Mautnerf3333272013-04-22 10:55:53 -07002121 if (mFinishingActivities.size() > 0) {
2122 pw.println(" ");
2123 pw.println(" Activities waiting to finish:");
2124 dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll, false,
2125 dumpPackage);
2126 }
2127
Craig Mautnerde4ef022013-04-07 19:01:33 -07002128 if (mStoppingActivities.size() > 0) {
2129 pw.println(" ");
2130 pw.println(" Activities waiting to stop:");
2131 dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, false,
2132 dumpPackage);
2133 }
2134
2135 if (mWaitingVisibleActivities.size() > 0) {
2136 pw.println(" ");
2137 pw.println(" Activities waiting for another to become visible:");
2138 dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
2139 false, dumpPackage);
2140 }
2141
Craig Mautner8d341ef2013-03-26 09:03:27 -07002142 if (dumpAll) {
2143 pw.println(" ");
2144 pw.println(" mCurTaskId: " + mCurTaskId);
2145 }
2146 return true;
2147 }
2148
2149 static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
2150 String prefix, String label, boolean complete, boolean brief, boolean client,
2151 String dumpPackage) {
2152 TaskRecord lastTask = null;
2153 boolean needNL = false;
2154 final String innerPrefix = prefix + " ";
2155 final String[] args = new String[0];
2156 for (int i=list.size()-1; i>=0; i--) {
2157 final ActivityRecord r = list.get(i);
2158 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
2159 continue;
2160 }
2161 final boolean full = !brief && (complete || !r.isInHistory());
2162 if (needNL) {
2163 pw.println(" ");
2164 needNL = false;
2165 }
2166 if (lastTask != r.task) {
2167 lastTask = r.task;
2168 pw.print(prefix);
2169 pw.print(full ? "* " : " ");
2170 pw.println(lastTask);
2171 if (full) {
2172 lastTask.dump(pw, prefix + " ");
2173 } else if (complete) {
2174 // Complete + brief == give a summary. Isn't that obvious?!?
2175 if (lastTask.intent != null) {
2176 pw.print(prefix); pw.print(" ");
2177 pw.println(lastTask.intent.toInsecureStringWithClip());
2178 }
2179 }
2180 }
2181 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
2182 pw.print(" #"); pw.print(i); pw.print(": ");
2183 pw.println(r);
2184 if (full) {
2185 r.dump(pw, innerPrefix);
2186 } else if (complete) {
2187 // Complete + brief == give a summary. Isn't that obvious?!?
2188 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
2189 if (r.app != null) {
2190 pw.print(innerPrefix); pw.println(r.app);
2191 }
2192 }
2193 if (client && r.app != null && r.app.thread != null) {
2194 // flush anything that is already in the PrintWriter since the thread is going
2195 // to write to the file descriptor directly
2196 pw.flush();
2197 try {
2198 TransferPipe tp = new TransferPipe();
2199 try {
2200 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
2201 r.appToken, innerPrefix, args);
2202 // Short timeout, since blocking here can
2203 // deadlock with the application.
2204 tp.go(fd, 2000);
2205 } finally {
2206 tp.kill();
2207 }
2208 } catch (IOException e) {
2209 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
2210 } catch (RemoteException e) {
2211 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
2212 }
2213 needNL = true;
2214 }
2215 }
2216 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002217
Craig Mautnerf3333272013-04-22 10:55:53 -07002218 void scheduleIdleTimeoutLocked(ActivityRecord next) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002219 if (DEBUG_IDLE) Slog.d(TAG, "scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4));
Craig Mautnerc64f73e2013-04-24 16:44:56 -07002220 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
2221 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
Craig Mautnerf3333272013-04-22 10:55:53 -07002222 }
2223
2224 final void scheduleIdleLocked() {
Craig Mautner05d29032013-05-03 13:40:13 -07002225 mHandler.sendEmptyMessage(IDLE_NOW_MSG);
Craig Mautnerf3333272013-04-22 10:55:53 -07002226 }
2227
2228 void removeTimeoutsForActivityLocked(ActivityRecord r) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002229 if (DEBUG_IDLE) Slog.d(TAG, "removeTimeoutsForActivity: Callers=" + Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07002230 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
2231 }
2232
Craig Mautner05d29032013-05-03 13:40:13 -07002233 final void scheduleResumeTopActivities() {
2234 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2235 }
2236
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002237 private final class ActivityStackSupervisorHandler extends Handler {
Craig Mautnerf3333272013-04-22 10:55:53 -07002238
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002239 public ActivityStackSupervisorHandler(Looper looper) {
2240 super(looper);
2241 }
2242
Craig Mautnerf3333272013-04-22 10:55:53 -07002243 void activityIdleInternal(ActivityRecord r) {
2244 synchronized (mService) {
2245 activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
2246 }
2247 }
2248
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002249 @Override
2250 public void handleMessage(Message msg) {
2251 switch (msg.what) {
Craig Mautnerf3333272013-04-22 10:55:53 -07002252 case IDLE_TIMEOUT_MSG: {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002253 if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_TIMEOUT_MSG: Callers=" +
2254 Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07002255 if (mService.mDidDexOpt) {
2256 mService.mDidDexOpt = false;
2257 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2258 nmsg.obj = msg.obj;
2259 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
2260 return;
2261 }
2262 // We don't at this point know if the activity is fullscreen,
2263 // so we need to be conservative and assume it isn't.
2264 activityIdleInternal((ActivityRecord)msg.obj);
2265 } break;
2266 case IDLE_NOW_MSG: {
2267 activityIdleInternal((ActivityRecord)msg.obj);
2268 } break;
Craig Mautner05d29032013-05-03 13:40:13 -07002269 case RESUME_TOP_ACTIVITY_MSG: {
2270 synchronized (mService) {
2271 resumeTopActivitiesLocked();
2272 }
2273 } break;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002274 }
2275 }
2276 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002277
2278 private final class UserState {
2279 final ActivityStack mSavedFocusedStack;
2280 final int mSavedStackState;
2281
2282 public UserState() {
2283 ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2284 mSavedFocusedStack = supervisor.mFocusedStack;
2285 mSavedStackState = supervisor.mStackState;
2286 }
2287
2288 void restore() {
2289 ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2290 supervisor.mFocusedStack = mSavedFocusedStack;
2291 supervisor.mStackState = mSavedStackState;
2292 }
2293 }
Craig Mautner27084302013-03-25 08:05:25 -07002294}