blob: a6389819ded1079258be911038b2a0282ea31a6c [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 Mautner0eea92c2013-05-16 13:35:39 -070025import static com.android.server.am.ActivityManagerService.DEBUG_PAUSE;
Craig Mautner6170f732013-04-02 13:05:23 -070026import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
Craig Mautner0eea92c2013-05-16 13:35:39 -070027import static com.android.server.am.ActivityManagerService.DEBUG_STACK;
Craig Mautner2420ead2013-04-01 17:13:20 -070028import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
Craig Mautner8849a5e2013-04-02 16:41:03 -070029import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
30import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
Craig Mautner05d29032013-05-03 13:40:13 -070031import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
Craig Mautner8d341ef2013-03-26 09:03:27 -070032import static com.android.server.am.ActivityManagerService.TAG;
33
Craig Mautner2420ead2013-04-01 17:13:20 -070034import android.app.Activity;
Craig Mautner23ac33b2013-04-01 16:26:35 -070035import android.app.ActivityManager;
36import android.app.ActivityOptions;
37import android.app.AppGlobals;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070038import android.app.IActivityManager;
Craig Mautner23ac33b2013-04-01 16:26:35 -070039import android.app.IApplicationThread;
Craig Mautner20e72272013-04-01 13:45:53 -070040import android.app.IThumbnailReceiver;
Craig Mautner23ac33b2013-04-01 16:26:35 -070041import android.app.PendingIntent;
Craig Mautner20e72272013-04-01 13:45:53 -070042import android.app.ActivityManager.RunningTaskInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070043import android.app.IActivityManager.WaitResult;
Craig Mautner2420ead2013-04-01 17:13:20 -070044import android.app.ResultInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070045import android.content.ComponentName;
Craig Mautner2219a1b2013-03-25 09:44:30 -070046import android.content.Context;
Craig Mautner23ac33b2013-04-01 16:26:35 -070047import android.content.IIntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070048import android.content.Intent;
Craig Mautner23ac33b2013-04-01 16:26:35 -070049import android.content.IntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070050import android.content.pm.ActivityInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070051import android.content.pm.ApplicationInfo;
52import android.content.pm.PackageManager;
53import android.content.pm.ResolveInfo;
54import android.content.res.Configuration;
55import android.os.Binder;
Craig Mautner8d341ef2013-03-26 09:03:27 -070056import android.os.Bundle;
Craig Mautnerb59dcfd2013-05-06 13:12:58 -070057import android.os.Debug;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070058import android.os.Handler;
Craig Mautner23ac33b2013-04-01 16:26:35 -070059import android.os.IBinder;
Craig Mautner2219a1b2013-03-25 09:44:30 -070060import android.os.Looper;
Craig Mautner2420ead2013-04-01 17:13:20 -070061import android.os.Message;
Craig Mautner23ac33b2013-04-01 16:26:35 -070062import android.os.ParcelFileDescriptor;
Craig Mautner0eea92c2013-05-16 13:35:39 -070063import android.os.PowerManager;
Craig Mautner8d341ef2013-03-26 09:03:27 -070064import android.os.RemoteException;
Craig Mautner23ac33b2013-04-01 16:26:35 -070065import android.os.SystemClock;
Craig Mautner6170f732013-04-02 13:05:23 -070066import android.os.UserHandle;
Craig Mautner2420ead2013-04-01 17:13:20 -070067import android.util.EventLog;
Craig Mautner8d341ef2013-03-26 09:03:27 -070068import android.util.Slog;
Craig Mautner858d8a62013-04-23 17:08:34 -070069import android.util.SparseArray;
Craig Mautner2219a1b2013-03-25 09:44:30 -070070
Craig Mautner23ac33b2013-04-01 16:26:35 -070071import com.android.internal.app.HeavyWeightSwitcherActivity;
Craig Mautner6170f732013-04-02 13:05:23 -070072import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
Craig Mautner2420ead2013-04-01 17:13:20 -070073import com.android.server.am.ActivityStack.ActivityState;
Craig Mautnerde4ef022013-04-07 19:01:33 -070074import com.android.server.wm.StackBox;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070075import com.android.server.wm.WindowManagerService;
Craig Mautner23ac33b2013-04-01 16:26:35 -070076
Craig Mautner8d341ef2013-03-26 09:03:27 -070077import java.io.FileDescriptor;
78import java.io.IOException;
Craig Mautner27084302013-03-25 08:05:25 -070079import java.io.PrintWriter;
Craig Mautner2219a1b2013-03-25 09:44:30 -070080import java.util.ArrayList;
Craig Mautner8d341ef2013-03-26 09:03:27 -070081import java.util.List;
Craig Mautner27084302013-03-25 08:05:25 -070082
83public class ActivityStackSupervisor {
Craig Mautnerde4ef022013-04-07 19:01:33 -070084 static final boolean DEBUG = ActivityManagerService.DEBUG || false;
85 static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
86 static final boolean DEBUG_APP = DEBUG || false;
87 static final boolean DEBUG_SAVED_STATE = DEBUG || false;
88 static final boolean DEBUG_STATES = DEBUG || false;
Craig Mautnerb59dcfd2013-05-06 13:12:58 -070089 static final boolean DEBUG_IDLE = DEBUG || false;
Craig Mautner2420ead2013-04-01 17:13:20 -070090
Craig Mautner2219a1b2013-03-25 09:44:30 -070091 public static final int HOME_STACK_ID = 0;
Craig Mautner27084302013-03-25 08:05:25 -070092
Craig Mautnerf3333272013-04-22 10:55:53 -070093 /** How long we wait until giving up on the last activity telling us it is idle. */
94 static final int IDLE_TIMEOUT = 10*1000;
95
Craig Mautner0eea92c2013-05-16 13:35:39 -070096 /** How long we can hold the sleep wake lock before giving up. */
97 static final int SLEEP_TIMEOUT = 5*1000;
98
Craig Mautner05d29032013-05-03 13:40:13 -070099 static final int IDLE_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG;
100 static final int IDLE_NOW_MSG = FIRST_SUPERVISOR_STACK_MSG + 1;
101 static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2;
Craig Mautner0eea92c2013-05-16 13:35:39 -0700102 static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3;
Craig Mautnerf3333272013-04-22 10:55:53 -0700103
Craig Mautner27084302013-03-25 08:05:25 -0700104 final ActivityManagerService mService;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700105 final Context mContext;
106 final Looper mLooper;
Craig Mautner27084302013-03-25 08:05:25 -0700107
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700108 final ActivityStackSupervisorHandler mHandler;
109
110 /** Short cut */
111 WindowManagerService mWindowManager;
112
Craig Mautner27084302013-03-25 08:05:25 -0700113 /** Dismiss the keyguard after the next activity is displayed? */
114 private boolean mDismissKeyguardOnNextActivity = false;
115
Craig Mautner8d341ef2013-03-26 09:03:27 -0700116 /** Identifier counter for all ActivityStacks */
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700117 private int mLastStackId = HOME_STACK_ID;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700118
119 /** Task identifier that activities are currently being started in. Incremented each time a
120 * new task is created. */
121 private int mCurTaskId = 0;
122
Craig Mautner2420ead2013-04-01 17:13:20 -0700123 /** The current user */
124 private int mCurrentUser;
125
Craig Mautner8d341ef2013-03-26 09:03:27 -0700126 /** The stack containing the launcher app */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700127 private ActivityStack mHomeStack;
Craig Mautner20e72272013-04-01 13:45:53 -0700128
Craig Mautnerde4ef022013-04-07 19:01:33 -0700129 /** The non-home stack currently receiving input or launching the next activity. If home is
Craig Mautner41c0f352013-05-28 08:39:25 -0700130 * in front then mHomeStack overrides mFocusedStack.
131 * DO NOT ACCESS DIRECTLY - It may be null, use getFocusedStack() */
Craig Mautner29219d92013-04-16 20:19:12 -0700132 private ActivityStack mFocusedStack;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700133
134 /** All the non-launcher stacks */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700135 private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
136
Craig Mautnerde4ef022013-04-07 19:01:33 -0700137 private static final int STACK_STATE_HOME_IN_FRONT = 0;
138 private static final int STACK_STATE_HOME_TO_BACK = 1;
139 private static final int STACK_STATE_HOME_IN_BACK = 2;
140 private static final int STACK_STATE_HOME_TO_FRONT = 3;
141 private int mStackState = STACK_STATE_HOME_IN_FRONT;
142
143 /** List of activities that are waiting for a new activity to become visible before completing
144 * whatever operation they are supposed to do. */
145 final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();
146
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700147 /** List of processes waiting to find out about the next visible activity. */
148 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible =
149 new ArrayList<IActivityManager.WaitResult>();
150
151 /** List of processes waiting to find out about the next launched activity. */
152 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched =
153 new ArrayList<IActivityManager.WaitResult>();
154
Craig Mautnerde4ef022013-04-07 19:01:33 -0700155 /** List of activities that are ready to be stopped, but waiting for the next activity to
156 * settle down before doing so. */
157 final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();
158
Craig Mautnerf3333272013-04-22 10:55:53 -0700159 /** List of activities that are ready to be finished, but waiting for the previous activity to
160 * settle down before doing so. It contains ActivityRecord objects. */
161 final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<ActivityRecord>();
162
Craig Mautner0eea92c2013-05-16 13:35:39 -0700163 /** List of activities that are in the process of going to sleep. */
164 final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<ActivityRecord>();
165
Craig Mautnerf3333272013-04-22 10:55:53 -0700166 /** List of ActivityRecord objects that have been finished and must still report back to a
167 * pending thumbnail receiver. */
168 final ArrayList<ActivityRecord> mCancelledThumbnails = new ArrayList<ActivityRecord>();
169
170 /** Used on user changes */
171 final ArrayList<UserStartedState> mStartingUsers = new ArrayList<UserStartedState>();
172
Craig Mautnerde4ef022013-04-07 19:01:33 -0700173 /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity
174 * is being brought in front of us. */
175 boolean mUserLeaving = false;
176
Craig Mautner858d8a62013-04-23 17:08:34 -0700177 /** Stacks belonging to users other than mCurrentUser. Indexed by userId. */
178 final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
179
Craig Mautner0eea92c2013-05-16 13:35:39 -0700180 /** Set when we have taken too long waiting to go to sleep. */
181 boolean mSleepTimeout = false;
182
183 /**
184 * Set when the system is going to sleep, until we have
185 * successfully paused the current activity and released our wake lock.
186 * At that point the system is allowed to actually sleep.
187 */
188 final PowerManager.WakeLock mGoingToSleep;
189
Craig Mautner2219a1b2013-03-25 09:44:30 -0700190 public ActivityStackSupervisor(ActivityManagerService service, Context context,
191 Looper looper) {
Craig Mautner27084302013-03-25 08:05:25 -0700192 mService = service;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700193 mContext = context;
194 mLooper = looper;
Craig Mautner0eea92c2013-05-16 13:35:39 -0700195 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
196 mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700197 mHandler = new ActivityStackSupervisorHandler(looper);
Craig Mautner2219a1b2013-03-25 09:44:30 -0700198 }
199
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700200 void setWindowManager(WindowManagerService wm) {
201 mWindowManager = wm;
202 mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700203 mStacks.add(mHomeStack);
Craig Mautner27084302013-03-25 08:05:25 -0700204 }
205
206 void dismissKeyguard() {
207 if (mDismissKeyguardOnNextActivity) {
208 mDismissKeyguardOnNextActivity = false;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700209 mWindowManager.dismissKeyguard();
Craig Mautner27084302013-03-25 08:05:25 -0700210 }
211 }
212
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700213 ActivityStack getFocusedStack() {
Craig Mautnerf88c50f2013-04-18 19:25:12 -0700214 if (mFocusedStack == null) {
215 return mHomeStack;
216 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700217 switch (mStackState) {
218 case STACK_STATE_HOME_IN_FRONT:
219 case STACK_STATE_HOME_TO_FRONT:
220 return mHomeStack;
221 case STACK_STATE_HOME_IN_BACK:
222 case STACK_STATE_HOME_TO_BACK:
223 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700224 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700225 }
Craig Mautner20e72272013-04-01 13:45:53 -0700226 }
227
Craig Mautnerde4ef022013-04-07 19:01:33 -0700228 ActivityStack getLastStack() {
229 switch (mStackState) {
230 case STACK_STATE_HOME_IN_FRONT:
231 case STACK_STATE_HOME_TO_BACK:
232 return mHomeStack;
233 case STACK_STATE_HOME_TO_FRONT:
234 case STACK_STATE_HOME_IN_BACK:
235 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700236 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700237 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700238 }
239
Craig Mautnerde4ef022013-04-07 19:01:33 -0700240 boolean isFrontStack(ActivityStack stack) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700241 return (stack.mCurrentUser == mCurrentUser) &&
242 !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
Craig Mautner20e72272013-04-01 13:45:53 -0700243 }
244
Craig Mautnerde4ef022013-04-07 19:01:33 -0700245 void moveHomeStack(boolean toFront) {
246 final boolean homeInFront = isFrontStack(mHomeStack);
247 if (homeInFront ^ toFront) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700248 if (DEBUG_STACK) Slog.d(TAG, "moveHomeTask: mStackState old=" +
249 stackStateToString(mStackState) + " new=" + stackStateToString(homeInFront ?
250 STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700251 mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
252 }
253 }
254
Craig Mautner69ada552013-04-18 13:51:51 -0700255 boolean resumeHomeActivity(ActivityRecord prev) {
256 moveHomeStack(true);
257 if (prev != null) {
258 prev.mLaunchHomeTaskNext = false;
259 }
260 if (mHomeStack.topRunningActivityLocked(null) != null) {
Craig Mautner05d29032013-05-03 13:40:13 -0700261 return resumeTopActivitiesLocked(mHomeStack, prev, null);
Craig Mautner69ada552013-04-18 13:51:51 -0700262 }
263 return mService.startHomeActivityLocked(mCurrentUser);
264 }
265
Craig Mautnerde4ef022013-04-07 19:01:33 -0700266 final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r,
267 ActivityStack stack) {
268 if (stack == mHomeStack) {
269 return;
270 }
271 if ((sourceRecord == null && getLastStack() == mHomeStack) ||
Craig Mautner86d67a42013-05-14 10:34:38 -0700272 (sourceRecord != null && sourceRecord.isHomeActivity())) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700273 if (r == null) {
274 r = stack.topRunningActivityLocked(null);
275 }
Craig Mautner86d67a42013-05-14 10:34:38 -0700276 if (r != null && !r.isHomeActivity() && r.isRootActivity()) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700277 r.mLaunchHomeTaskNext = true;
278 }
279 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700280 }
281
Craig Mautner27084302013-03-25 08:05:25 -0700282 void setDismissKeyguard(boolean dismiss) {
283 mDismissKeyguardOnNextActivity = dismiss;
284 }
285
Craig Mautner8d341ef2013-03-26 09:03:27 -0700286 TaskRecord anyTaskForIdLocked(int id) {
287 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
288 ActivityStack stack = mStacks.get(stackNdx);
289 TaskRecord task = stack.taskForIdLocked(id);
290 if (task != null) {
291 return task;
292 }
293 }
294 return null;
295 }
296
Craig Mautner6170f732013-04-02 13:05:23 -0700297 ActivityRecord isInAnyStackLocked(IBinder token) {
298 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
299 final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
300 if (r != null) {
301 return r;
302 }
303 }
304 return null;
305 }
306
Craig Mautner8d341ef2013-03-26 09:03:27 -0700307 int getNextTaskId() {
308 do {
309 mCurTaskId++;
310 if (mCurTaskId <= 0) {
311 mCurTaskId = 1;
312 }
313 } while (anyTaskForIdLocked(mCurTaskId) != null);
314 return mCurTaskId;
315 }
316
Craig Mautnerde4ef022013-04-07 19:01:33 -0700317 void removeTask(TaskRecord task) {
Craig Mautnerb3b36ba2013-05-20 13:21:10 -0700318 mWindowManager.removeTask(task.taskId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700319 final ActivityStack stack = task.stack;
Craig Mautnerb3b36ba2013-05-20 13:21:10 -0700320 final ActivityRecord r = stack.mResumedActivity;
321 if (r != null && r.task == task) {
322 stack.mResumedActivity = null;
323 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700324 if (stack.removeTask(task) && !stack.isHomeStack()) {
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700325 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700326 mStacks.remove(stack);
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700327 final int stackId = stack.mStackId;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700328 final int nextStackId = mWindowManager.removeStack(stackId);
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700329 // TODO: Perhaps we need to let the ActivityManager determine the next focus...
Craig Mautner41c0f352013-05-28 08:39:25 -0700330 if (getFocusedStack().mStackId == stackId) {
Craig Mautner1602ec22013-05-12 10:24:27 -0700331 // If this is the last app stack, set mFocusedStack to null.
Craig Mautner29219d92013-04-16 20:19:12 -0700332 mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700333 }
334 }
335 }
336
337 ActivityRecord resumedAppLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700338 ActivityStack stack = getFocusedStack();
339 if (stack == null) {
340 return null;
341 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700342 ActivityRecord resumedActivity = stack.mResumedActivity;
343 if (resumedActivity == null || resumedActivity.app == null) {
344 resumedActivity = stack.mPausingActivity;
345 if (resumedActivity == null || resumedActivity.app == null) {
346 resumedActivity = stack.topRunningActivityLocked(null);
347 }
348 }
349 return resumedActivity;
350 }
351
Craig Mautner20e72272013-04-01 13:45:53 -0700352 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
353 boolean didSomething = false;
354 final String processName = app.processName;
355 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
356 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner858d8a62013-04-23 17:08:34 -0700357 if (!isFrontStack(stack)) {
358 continue;
359 }
Craig Mautner20e72272013-04-01 13:45:53 -0700360 ActivityRecord hr = stack.topRunningActivityLocked(null);
361 if (hr != null) {
362 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
363 && processName.equals(hr.processName)) {
364 try {
365 if (headless) {
366 Slog.e(TAG, "Starting activities not supported on headless device: "
367 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700368 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700369 didSomething = true;
370 }
371 } catch (Exception e) {
372 Slog.w(TAG, "Exception in new application when starting activity "
373 + hr.intent.getComponent().flattenToShortString(), e);
374 throw e;
375 }
Craig Mautner20e72272013-04-01 13:45:53 -0700376 }
377 }
378 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -0700379 if (!didSomething) {
380 ensureActivitiesVisibleLocked(null, 0);
381 }
Craig Mautner20e72272013-04-01 13:45:53 -0700382 return didSomething;
383 }
384
385 boolean allResumedActivitiesIdle() {
386 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700387 final ActivityRecord resumedActivity = mStacks.get(stackNdx).mResumedActivity;
388 if (resumedActivity == null || !resumedActivity.idle) {
Craig Mautner20e72272013-04-01 13:45:53 -0700389 return false;
390 }
391 }
392 return true;
393 }
394
Craig Mautnerde4ef022013-04-07 19:01:33 -0700395 boolean allResumedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700396 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
397 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner967212c2013-04-13 21:10:58 -0700398 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700399 final ActivityRecord r = stack.mResumedActivity;
400 if (r != null && r.state != ActivityState.RESUMED) {
401 return false;
402 }
403 }
404 }
405 // TODO: Not sure if this should check if all Paused are complete too.
406 switch (mStackState) {
407 case STACK_STATE_HOME_TO_BACK:
Craig Mautner76ea2242013-05-15 11:40:05 -0700408 if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
409 stackStateToString(STACK_STATE_HOME_TO_BACK) + " new=" +
410 stackStateToString(STACK_STATE_HOME_IN_BACK));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700411 mStackState = STACK_STATE_HOME_IN_BACK;
412 break;
413 case STACK_STATE_HOME_TO_FRONT:
Craig Mautner76ea2242013-05-15 11:40:05 -0700414 if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
415 stackStateToString(STACK_STATE_HOME_TO_FRONT) + " new=" +
416 stackStateToString(STACK_STATE_HOME_IN_FRONT));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700417 mStackState = STACK_STATE_HOME_IN_FRONT;
418 break;
419 }
420 return true;
421 }
422
423 boolean allResumedActivitiesVisible() {
424 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
425 final ActivityStack stack = mStacks.get(stackNdx);
426 final ActivityRecord r = stack.mResumedActivity;
427 if (r != null && (!r.nowVisible || r.waitingVisible)) {
428 return false;
429 }
430 }
431 return true;
432 }
433
Craig Mautnercf910b02013-04-23 11:23:27 -0700434 boolean pauseBackStacks(boolean userLeaving) {
435 boolean someActivityPaused = false;
436 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
437 final ActivityStack stack = mStacks.get(stackNdx);
438 if (!isFrontStack(stack) && stack.mResumedActivity != null) {
439 stack.startPausingLocked(userLeaving, false);
440 someActivityPaused = true;
441 }
442 }
443 return someActivityPaused;
444 }
445
Craig Mautnerde4ef022013-04-07 19:01:33 -0700446 boolean allPausedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700447 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
448 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner69ada552013-04-18 13:51:51 -0700449 final ActivityRecord r = stack.mPausingActivity;
450 if (r != null && r.state != ActivityState.PAUSED
451 && r.state != ActivityState.STOPPED
452 && r.state != ActivityState.STOPPING) {
453 return false;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700454 }
455 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700456 return true;
457 }
458
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700459 void reportActivityVisibleLocked(ActivityRecord r) {
Craig Mautner858d8a62013-04-23 17:08:34 -0700460 for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700461 WaitResult w = mWaitingActivityVisible.get(i);
462 w.timeout = false;
463 if (r != null) {
464 w.who = new ComponentName(r.info.packageName, r.info.name);
465 }
466 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
467 w.thisTime = w.totalTime;
468 }
469 mService.notifyAll();
470 dismissKeyguard();
471 }
472
473 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
474 long thisTime, long totalTime) {
475 for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
Craig Mautnerc64f73e2013-04-24 16:44:56 -0700476 WaitResult w = mWaitingActivityLaunched.remove(i);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700477 w.timeout = timeout;
478 if (r != null) {
479 w.who = new ComponentName(r.info.packageName, r.info.name);
480 }
481 w.thisTime = thisTime;
482 w.totalTime = totalTime;
483 }
484 mService.notifyAll();
485 }
486
Craig Mautner29219d92013-04-16 20:19:12 -0700487 ActivityRecord topRunningActivityLocked() {
Craig Mautner1602ec22013-05-12 10:24:27 -0700488 final ActivityStack focusedStack = getFocusedStack();
489 ActivityRecord r = focusedStack.topRunningActivityLocked(null);
490 if (r != null) {
491 return r;
Craig Mautner29219d92013-04-16 20:19:12 -0700492 }
Craig Mautner1602ec22013-05-12 10:24:27 -0700493
Craig Mautner29219d92013-04-16 20:19:12 -0700494 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
495 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner1602ec22013-05-12 10:24:27 -0700496 if (stack.mCurrentUser == mCurrentUser && stack != focusedStack &&
497 isFrontStack(stack)) {
Craig Mautner29219d92013-04-16 20:19:12 -0700498 r = stack.topRunningActivityLocked(null);
499 if (r != null) {
500 return r;
501 }
502 }
503 }
504 return null;
505 }
506
Craig Mautner20e72272013-04-01 13:45:53 -0700507 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
508 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
509 ActivityRecord r = null;
Craig Mautner20e72272013-04-01 13:45:53 -0700510 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
511 final ActivityStack stack = mStacks.get(stackNdx);
512 final ActivityRecord ar =
513 stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700514 if (isFrontStack(stack)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700515 r = ar;
516 }
517 }
518 return r;
519 }
520
Craig Mautner23ac33b2013-04-01 16:26:35 -0700521 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
522 String profileFile, ParcelFileDescriptor profileFd, int userId) {
523 // Collect information about the target of the Intent.
524 ActivityInfo aInfo;
525 try {
526 ResolveInfo rInfo =
527 AppGlobals.getPackageManager().resolveIntent(
528 intent, resolvedType,
529 PackageManager.MATCH_DEFAULT_ONLY
530 | ActivityManagerService.STOCK_PM_FLAGS, userId);
531 aInfo = rInfo != null ? rInfo.activityInfo : null;
532 } catch (RemoteException e) {
533 aInfo = null;
534 }
535
536 if (aInfo != null) {
537 // Store the found target back into the intent, because now that
538 // we have it we never want to do this again. For example, if the
539 // user navigates back to this point in the history, we should
540 // always restart the exact same activity.
541 intent.setComponent(new ComponentName(
542 aInfo.applicationInfo.packageName, aInfo.name));
543
544 // Don't debug things in the system process
545 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
546 if (!aInfo.processName.equals("system")) {
547 mService.setDebugApp(aInfo.processName, true, false);
548 }
549 }
550
551 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
552 if (!aInfo.processName.equals("system")) {
553 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
554 }
555 }
556
557 if (profileFile != null) {
558 if (!aInfo.processName.equals("system")) {
559 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
560 profileFile, profileFd,
561 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
562 }
563 }
564 }
565 return aInfo;
566 }
567
Craig Mautner2219a1b2013-03-25 09:44:30 -0700568 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700569 moveHomeStack(true);
Craig Mautner6170f732013-04-02 13:05:23 -0700570 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
Craig Mautner2219a1b2013-03-25 09:44:30 -0700571 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700572 }
573
Craig Mautner23ac33b2013-04-01 16:26:35 -0700574 final int startActivityMayWait(IApplicationThread caller, int callingUid,
575 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
576 String resultWho, int requestCode, int startFlags, String profileFile,
577 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
578 Bundle options, int userId) {
579 // Refuse possible leaked file descriptors
580 if (intent != null && intent.hasFileDescriptors()) {
581 throw new IllegalArgumentException("File descriptors passed in Intent");
582 }
583 boolean componentSpecified = intent.getComponent() != null;
584
585 // Don't modify the client's object!
586 intent = new Intent(intent);
587
588 // Collect information about the target of the Intent.
589 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
590 profileFile, profileFd, userId);
591
592 synchronized (mService) {
593 int callingPid;
594 if (callingUid >= 0) {
595 callingPid = -1;
596 } else if (caller == null) {
597 callingPid = Binder.getCallingPid();
598 callingUid = Binder.getCallingUid();
599 } else {
600 callingPid = callingUid = -1;
601 }
602
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700603 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -0700604 stack.mConfigWillChange = config != null
Craig Mautner23ac33b2013-04-01 16:26:35 -0700605 && mService.mConfiguration.diff(config) != 0;
606 if (DEBUG_CONFIGURATION) Slog.v(TAG,
Craig Mautnerde4ef022013-04-07 19:01:33 -0700607 "Starting activity when config will change = " + stack.mConfigWillChange);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700608
609 final long origId = Binder.clearCallingIdentity();
610
611 if (aInfo != null &&
612 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
613 // This may be a heavy-weight process! Check to see if we already
614 // have another, different heavy-weight process running.
615 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
616 if (mService.mHeavyWeightProcess != null &&
617 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
618 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700619 int realCallingUid = callingUid;
620 if (caller != null) {
621 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
622 if (callerApp != null) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700623 realCallingUid = callerApp.info.uid;
624 } else {
625 Slog.w(TAG, "Unable to find app for caller " + caller
Craig Mautner76ea2242013-05-15 11:40:05 -0700626 + " (pid=" + callingPid + ") when starting: "
Craig Mautner23ac33b2013-04-01 16:26:35 -0700627 + intent.toString());
628 ActivityOptions.abort(options);
629 return ActivityManager.START_PERMISSION_DENIED;
630 }
631 }
632
633 IIntentSender target = mService.getIntentSenderLocked(
634 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
635 realCallingUid, userId, null, null, 0, new Intent[] { intent },
636 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
637 | PendingIntent.FLAG_ONE_SHOT, null);
638
639 Intent newIntent = new Intent();
640 if (requestCode >= 0) {
641 // Caller is requesting a result.
642 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
643 }
644 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
645 new IntentSender(target));
646 if (mService.mHeavyWeightProcess.activities.size() > 0) {
647 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
648 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
649 hist.packageName);
650 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
651 hist.task.taskId);
652 }
653 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
654 aInfo.packageName);
655 newIntent.setFlags(intent.getFlags());
656 newIntent.setClassName("android",
657 HeavyWeightSwitcherActivity.class.getName());
658 intent = newIntent;
659 resolvedType = null;
660 caller = null;
661 callingUid = Binder.getCallingUid();
662 callingPid = Binder.getCallingPid();
663 componentSpecified = true;
664 try {
665 ResolveInfo rInfo =
666 AppGlobals.getPackageManager().resolveIntent(
667 intent, null,
668 PackageManager.MATCH_DEFAULT_ONLY
669 | ActivityManagerService.STOCK_PM_FLAGS, userId);
670 aInfo = rInfo != null ? rInfo.activityInfo : null;
671 aInfo = mService.getActivityInfoForUser(aInfo, userId);
672 } catch (RemoteException e) {
673 aInfo = null;
674 }
675 }
676 }
677 }
678
Craig Mautner6170f732013-04-02 13:05:23 -0700679 int res = startActivityLocked(caller, intent, resolvedType,
Craig Mautner23ac33b2013-04-01 16:26:35 -0700680 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
681 callingPackage, startFlags, options, componentSpecified, null);
682
Craig Mautnerde4ef022013-04-07 19:01:33 -0700683 if (stack.mConfigWillChange) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700684 // If the caller also wants to switch to a new configuration,
685 // do so now. This allows a clean switch, as we are waiting
686 // for the current activity to pause (so we will not destroy
687 // it), and have not yet started the next activity.
688 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
689 "updateConfiguration()");
Craig Mautnerde4ef022013-04-07 19:01:33 -0700690 stack.mConfigWillChange = false;
Craig Mautner23ac33b2013-04-01 16:26:35 -0700691 if (DEBUG_CONFIGURATION) Slog.v(TAG,
692 "Updating to new configuration after starting activity.");
693 mService.updateConfigurationLocked(config, null, false, false);
694 }
695
696 Binder.restoreCallingIdentity(origId);
697
698 if (outResult != null) {
699 outResult.result = res;
700 if (res == ActivityManager.START_SUCCESS) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700701 mWaitingActivityLaunched.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700702 do {
703 try {
704 mService.wait();
705 } catch (InterruptedException e) {
706 }
707 } while (!outResult.timeout && outResult.who == null);
708 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700709 ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700710 if (r.nowVisible) {
711 outResult.timeout = false;
712 outResult.who = new ComponentName(r.info.packageName, r.info.name);
713 outResult.totalTime = 0;
714 outResult.thisTime = 0;
715 } else {
716 outResult.thisTime = SystemClock.uptimeMillis();
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700717 mWaitingActivityVisible.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700718 do {
719 try {
720 mService.wait();
721 } catch (InterruptedException e) {
722 }
723 } while (!outResult.timeout && outResult.who == null);
724 }
725 }
726 }
727
728 return res;
729 }
730 }
731
732 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
733 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
734 Bundle options, int userId) {
735 if (intents == null) {
736 throw new NullPointerException("intents is null");
737 }
738 if (resolvedTypes == null) {
739 throw new NullPointerException("resolvedTypes is null");
740 }
741 if (intents.length != resolvedTypes.length) {
742 throw new IllegalArgumentException("intents are length different than resolvedTypes");
743 }
744
Craig Mautner23ac33b2013-04-01 16:26:35 -0700745
746 int callingPid;
747 if (callingUid >= 0) {
748 callingPid = -1;
749 } else if (caller == null) {
750 callingPid = Binder.getCallingPid();
751 callingUid = Binder.getCallingUid();
752 } else {
753 callingPid = callingUid = -1;
754 }
755 final long origId = Binder.clearCallingIdentity();
756 try {
757 synchronized (mService) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700758 ActivityRecord[] outActivity = new ActivityRecord[1];
Craig Mautner23ac33b2013-04-01 16:26:35 -0700759 for (int i=0; i<intents.length; i++) {
760 Intent intent = intents[i];
761 if (intent == null) {
762 continue;
763 }
764
765 // Refuse possible leaked file descriptors
766 if (intent != null && intent.hasFileDescriptors()) {
767 throw new IllegalArgumentException("File descriptors passed in Intent");
768 }
769
770 boolean componentSpecified = intent.getComponent() != null;
771
772 // Don't modify the client's object!
773 intent = new Intent(intent);
774
775 // Collect information about the target of the Intent.
776 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
777 0, null, null, userId);
778 // TODO: New, check if this is correct
779 aInfo = mService.getActivityInfoForUser(aInfo, userId);
780
781 if (aInfo != null &&
782 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
783 != 0) {
784 throw new IllegalArgumentException(
785 "FLAG_CANT_SAVE_STATE not supported here");
786 }
787
788 Bundle theseOptions;
789 if (options != null && i == intents.length-1) {
790 theseOptions = options;
791 } else {
792 theseOptions = null;
793 }
Craig Mautner6170f732013-04-02 13:05:23 -0700794 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Craig Mautner23ac33b2013-04-01 16:26:35 -0700795 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
796 0, theseOptions, componentSpecified, outActivity);
797 if (res < 0) {
798 return res;
799 }
800
801 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
802 }
803 }
804 } finally {
805 Binder.restoreCallingIdentity(origId);
806 }
807
808 return ActivityManager.START_SUCCESS;
809 }
810
Craig Mautner2420ead2013-04-01 17:13:20 -0700811 final boolean realStartActivityLocked(ActivityRecord r,
812 ProcessRecord app, boolean andResume, boolean checkConfig)
813 throws RemoteException {
814
815 r.startFreezingScreenLocked(app, 0);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700816 mWindowManager.setAppVisibility(r.appToken, true);
Craig Mautner2420ead2013-04-01 17:13:20 -0700817
818 // schedule launch ticks to collect information about slow apps.
819 r.startLaunchTickingLocked();
820
821 // Have the window manager re-evaluate the orientation of
822 // the screen based on the new activity order. Note that
823 // as a result of this, it can call back into the activity
824 // manager with a new orientation. We don't care about that,
825 // because the activity is not currently running so we are
826 // just restarting it anyway.
827 if (checkConfig) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700828 Configuration config = mWindowManager.updateOrientationFromAppTokens(
Craig Mautner2420ead2013-04-01 17:13:20 -0700829 mService.mConfiguration,
830 r.mayFreezeScreenLocked(app) ? r.appToken : null);
831 mService.updateConfigurationLocked(config, r, false, false);
832 }
833
834 r.app = app;
835 app.waitingToKill = null;
836 r.launchCount++;
837 r.lastLaunchTime = SystemClock.uptimeMillis();
838
839 if (localLOGV) Slog.v(TAG, "Launching: " + r);
840
841 int idx = app.activities.indexOf(r);
842 if (idx < 0) {
843 app.activities.add(r);
844 }
845 mService.updateLruProcessLocked(app, true);
846
847 final ActivityStack stack = r.task.stack;
848 try {
849 if (app.thread == null) {
850 throw new RemoteException();
851 }
852 List<ResultInfo> results = null;
853 List<Intent> newIntents = null;
854 if (andResume) {
855 results = r.results;
856 newIntents = r.newIntents;
857 }
858 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
859 + " icicle=" + r.icicle
860 + " with results=" + results + " newIntents=" + newIntents
861 + " andResume=" + andResume);
862 if (andResume) {
863 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
864 r.userId, System.identityHashCode(r),
865 r.task.taskId, r.shortComponentName);
866 }
Craig Mautner86d67a42013-05-14 10:34:38 -0700867 if (r.isHomeActivity()) {
Craig Mautner2420ead2013-04-01 17:13:20 -0700868 mService.mHomeProcess = app;
869 }
870 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
871 r.sleeping = false;
872 r.forceNewConfig = false;
873 mService.showAskCompatModeDialogLocked(r);
874 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
875 String profileFile = null;
876 ParcelFileDescriptor profileFd = null;
877 boolean profileAutoStop = false;
878 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
879 if (mService.mProfileProc == null || mService.mProfileProc == app) {
880 mService.mProfileProc = app;
881 profileFile = mService.mProfileFile;
882 profileFd = mService.mProfileFd;
883 profileAutoStop = mService.mAutoStopProfiler;
884 }
885 }
886 app.hasShownUi = true;
887 app.pendingUiClean = true;
888 if (profileFd != null) {
889 try {
890 profileFd = profileFd.dup();
891 } catch (IOException e) {
892 if (profileFd != null) {
893 try {
894 profileFd.close();
895 } catch (IOException o) {
896 }
897 profileFd = null;
898 }
899 }
900 }
901 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
902 System.identityHashCode(r), r.info,
903 new Configuration(mService.mConfiguration),
904 r.compat, r.icicle, results, newIntents, !andResume,
905 mService.isNextTransitionForward(), profileFile, profileFd,
906 profileAutoStop);
907
908 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
909 // This may be a heavy-weight process! Note that the package
910 // manager will ensure that only activity can run in the main
911 // process of the .apk, which is the only thing that will be
912 // considered heavy-weight.
913 if (app.processName.equals(app.info.packageName)) {
914 if (mService.mHeavyWeightProcess != null
915 && mService.mHeavyWeightProcess != app) {
916 Slog.w(TAG, "Starting new heavy weight process " + app
917 + " when already running "
918 + mService.mHeavyWeightProcess);
919 }
920 mService.mHeavyWeightProcess = app;
921 Message msg = mService.mHandler.obtainMessage(
922 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
923 msg.obj = r;
924 mService.mHandler.sendMessage(msg);
925 }
926 }
927
928 } catch (RemoteException e) {
929 if (r.launchFailed) {
930 // This is the second time we failed -- finish activity
931 // and give up.
932 Slog.e(TAG, "Second failure launching "
933 + r.intent.getComponent().flattenToShortString()
934 + ", giving up", e);
935 mService.appDiedLocked(app, app.pid, app.thread);
936 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
937 "2nd-crash", false);
938 return false;
939 }
940
941 // This is the first time we failed -- restart process and
942 // retry.
943 app.activities.remove(r);
944 throw e;
945 }
946
947 r.launchFailed = false;
948 if (stack.updateLRUListLocked(r)) {
949 Slog.w(TAG, "Activity " + r
950 + " being launched, but already in LRU list");
951 }
952
953 if (andResume) {
954 // As part of the process of launching, ActivityThread also performs
955 // a resume.
956 stack.minimalResumeActivityLocked(r);
957 } else {
958 // This activity is not starting in the resumed state... which
959 // should look like we asked it to pause+stop (but remain visible),
960 // and it has done so and reported back the current icicle and
961 // other state.
962 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
963 + " (starting in stopped state)");
964 r.state = ActivityState.STOPPED;
965 r.stopped = true;
966 }
967
968 // Launch the new version setup screen if needed. We do this -after-
969 // launching the initial activity (that is, home), so that it can have
970 // a chance to initialize itself while in the background, making the
971 // switch back to it faster and look better.
Craig Mautnerde4ef022013-04-07 19:01:33 -0700972 if (isFrontStack(stack)) {
Craig Mautner2420ead2013-04-01 17:13:20 -0700973 mService.startSetupActivityLocked();
974 }
975
976 return true;
977 }
978
Craig Mautnere79d42682013-04-01 19:01:53 -0700979 void startSpecificActivityLocked(ActivityRecord r,
980 boolean andResume, boolean checkConfig) {
981 // Is this activity's application already running?
982 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
983 r.info.applicationInfo.uid);
984
985 r.task.stack.setLaunchTime(r);
986
987 if (app != null && app.thread != null) {
988 try {
989 app.addPackage(r.info.packageName);
990 realStartActivityLocked(r, app, andResume, checkConfig);
991 return;
992 } catch (RemoteException e) {
993 Slog.w(TAG, "Exception when starting activity "
994 + r.intent.getComponent().flattenToShortString(), e);
995 }
996
997 // If a dead object exception was thrown -- fall through to
998 // restart the application.
999 }
1000
1001 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
1002 "activity", r.intent.getComponent(), false, false);
1003 }
1004
Craig Mautner6170f732013-04-02 13:05:23 -07001005 final int startActivityLocked(IApplicationThread caller,
1006 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
1007 String resultWho, int requestCode,
1008 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
1009 boolean componentSpecified, ActivityRecord[] outActivity) {
1010 int err = ActivityManager.START_SUCCESS;
1011
1012 ProcessRecord callerApp = null;
1013 if (caller != null) {
1014 callerApp = mService.getRecordForAppLocked(caller);
1015 if (callerApp != null) {
1016 callingPid = callerApp.pid;
1017 callingUid = callerApp.info.uid;
1018 } else {
1019 Slog.w(TAG, "Unable to find app for caller " + caller
1020 + " (pid=" + callingPid + ") when starting: "
1021 + intent.toString());
1022 err = ActivityManager.START_PERMISSION_DENIED;
1023 }
1024 }
1025
1026 if (err == ActivityManager.START_SUCCESS) {
1027 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
1028 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
1029 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
1030 }
1031
1032 ActivityRecord sourceRecord = null;
1033 ActivityRecord resultRecord = null;
1034 if (resultTo != null) {
1035 sourceRecord = isInAnyStackLocked(resultTo);
1036 if (DEBUG_RESULTS) Slog.v(
1037 TAG, "Will send result to " + resultTo + " " + sourceRecord);
1038 if (sourceRecord != null) {
1039 if (requestCode >= 0 && !sourceRecord.finishing) {
1040 resultRecord = sourceRecord;
1041 }
1042 }
1043 }
1044 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
1045
1046 int launchFlags = intent.getFlags();
1047
1048 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
1049 && sourceRecord != null) {
1050 // Transfer the result target from the source activity to the new
1051 // one being started, including any failures.
1052 if (requestCode >= 0) {
1053 ActivityOptions.abort(options);
1054 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
1055 }
1056 resultRecord = sourceRecord.resultTo;
1057 resultWho = sourceRecord.resultWho;
1058 requestCode = sourceRecord.requestCode;
1059 sourceRecord.resultTo = null;
1060 if (resultRecord != null) {
1061 resultRecord.removeResultsLocked(
1062 sourceRecord, resultWho, requestCode);
1063 }
1064 }
1065
1066 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
1067 // We couldn't find a class that can handle the given Intent.
1068 // That's the end of that!
1069 err = ActivityManager.START_INTENT_NOT_RESOLVED;
1070 }
1071
1072 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
1073 // We couldn't find the specific class specified in the Intent.
1074 // Also the end of the line.
1075 err = ActivityManager.START_CLASS_NOT_FOUND;
1076 }
1077
1078 if (err != ActivityManager.START_SUCCESS) {
1079 if (resultRecord != null) {
1080 resultStack.sendActivityResultLocked(-1,
1081 resultRecord, resultWho, requestCode,
1082 Activity.RESULT_CANCELED, null);
1083 }
1084 setDismissKeyguard(false);
1085 ActivityOptions.abort(options);
1086 return err;
1087 }
1088
1089 final int startAnyPerm = mService.checkPermission(
1090 START_ANY_ACTIVITY, callingPid, callingUid);
1091 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
1092 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
1093 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
1094 if (resultRecord != null) {
1095 resultStack.sendActivityResultLocked(-1,
1096 resultRecord, resultWho, requestCode,
1097 Activity.RESULT_CANCELED, null);
1098 }
1099 setDismissKeyguard(false);
1100 String msg;
1101 if (!aInfo.exported) {
1102 msg = "Permission Denial: starting " + intent.toString()
1103 + " from " + callerApp + " (pid=" + callingPid
1104 + ", uid=" + callingUid + ")"
1105 + " not exported from uid " + aInfo.applicationInfo.uid;
1106 } else {
1107 msg = "Permission Denial: starting " + intent.toString()
1108 + " from " + callerApp + " (pid=" + callingPid
1109 + ", uid=" + callingUid + ")"
1110 + " requires " + aInfo.permission;
1111 }
1112 Slog.w(TAG, msg);
1113 throw new SecurityException(msg);
1114 }
1115
Ben Gruver6617c3c2013-04-03 18:45:22 -07001116 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
Ben Gruver7b879f42013-04-08 14:56:55 -07001117 callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo);
Ben Gruver5e207332013-04-03 17:41:37 -07001118
Craig Mautner6170f732013-04-02 13:05:23 -07001119 if (mService.mController != null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001120 try {
1121 // The Intent we give to the watcher has the extra data
1122 // stripped off, since it can contain private information.
1123 Intent watchIntent = intent.cloneFilter();
Ben Gruver5e207332013-04-03 17:41:37 -07001124 abort |= !mService.mController.activityStarting(watchIntent,
Craig Mautner6170f732013-04-02 13:05:23 -07001125 aInfo.applicationInfo.packageName);
1126 } catch (RemoteException e) {
1127 mService.mController = null;
1128 }
Ben Gruver5e207332013-04-03 17:41:37 -07001129 }
Craig Mautner6170f732013-04-02 13:05:23 -07001130
Ben Gruver5e207332013-04-03 17:41:37 -07001131 if (abort) {
1132 if (resultRecord != null) {
1133 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Craig Mautner6170f732013-04-02 13:05:23 -07001134 Activity.RESULT_CANCELED, null);
Craig Mautner6170f732013-04-02 13:05:23 -07001135 }
Ben Gruver5e207332013-04-03 17:41:37 -07001136 // We pretend to the caller that it was really started, but
1137 // they will just get a cancel result.
1138 setDismissKeyguard(false);
1139 ActivityOptions.abort(options);
1140 return ActivityManager.START_SUCCESS;
Craig Mautner6170f732013-04-02 13:05:23 -07001141 }
1142
1143 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1144 intent, resolvedType, aInfo, mService.mConfiguration,
Craig Mautnerde4ef022013-04-07 19:01:33 -07001145 resultRecord, resultWho, requestCode, componentSpecified, this);
Craig Mautner6170f732013-04-02 13:05:23 -07001146 if (outActivity != null) {
1147 outActivity[0] = r;
1148 }
1149
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001150 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001151 if (stack.mResumedActivity == null
1152 || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
Craig Mautner6170f732013-04-02 13:05:23 -07001153 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1154 PendingActivityLaunch pal =
Craig Mautnerde4ef022013-04-07 19:01:33 -07001155 new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
Craig Mautner6170f732013-04-02 13:05:23 -07001156 mService.mPendingActivityLaunches.add(pal);
1157 setDismissKeyguard(false);
1158 ActivityOptions.abort(options);
1159 return ActivityManager.START_SWITCHES_CANCELED;
1160 }
1161 }
1162
1163 if (mService.mDidAppSwitch) {
1164 // This is the second allowed switch since we stopped switches,
1165 // so now just generally allow switches. Use case: user presses
1166 // home (switches disabled, switch to home, mDidAppSwitch now true);
1167 // user taps a home icon (coming from home so allowed, we hit here
1168 // and now allow anyone to switch again).
1169 mService.mAppSwitchesAllowedTime = 0;
1170 } else {
1171 mService.mDidAppSwitch = true;
1172 }
1173
1174 mService.doPendingActivityLaunchesLocked(false);
1175
Craig Mautner8849a5e2013-04-02 16:41:03 -07001176 err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001177 if (stack.mPausingActivity == null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001178 // Someone asked to have the keyguard dismissed on the next
1179 // activity start, but we are not actually doing an activity
1180 // switch... just dismiss the keyguard now, because we
1181 // probably want to see whatever is behind it.
1182 dismissKeyguard();
1183 }
1184 return err;
1185 }
1186
Craig Mautnerde4ef022013-04-07 19:01:33 -07001187 ActivityStack getCorrectStack(ActivityRecord r) {
Craig Mautner86d67a42013-05-14 10:34:38 -07001188 if (r.isApplicationActivity() || (r.task != null && r.task.isApplicationTask())) {
Craig Mautner858d8a62013-04-23 17:08:34 -07001189 int stackNdx;
1190 for (stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
1191 if (mStacks.get(stackNdx).mCurrentUser == mCurrentUser) {
1192 break;
1193 }
1194 }
1195 if (stackNdx == 0) {
1196 // Time to create the first app stack for this user.
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001197 int stackId = mService.createStack(-1, HOME_STACK_ID,
1198 StackBox.TASK_STACK_GOES_OVER, 1.0f);
Craig Mautner29219d92013-04-16 20:19:12 -07001199 mFocusedStack = getStack(stackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001200 }
Craig Mautner29219d92013-04-16 20:19:12 -07001201 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001202 }
1203 return mHomeStack;
1204 }
1205
Craig Mautner29219d92013-04-16 20:19:12 -07001206 void setFocusedStack(ActivityRecord r) {
1207 if (r == null) {
1208 return;
1209 }
Craig Mautner86d67a42013-05-14 10:34:38 -07001210 if (!r.isApplicationActivity() || (r.task != null && !r.task.isApplicationTask())) {
Craig Mautner29219d92013-04-16 20:19:12 -07001211 if (mStackState != STACK_STATE_HOME_IN_FRONT) {
Craig Mautner76ea2242013-05-15 11:40:05 -07001212 if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
1213 stackStateToString(mStackState) + " new=" +
1214 stackStateToString(STACK_STATE_HOME_TO_FRONT) +
1215 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001216 mStackState = STACK_STATE_HOME_TO_FRONT;
1217 }
1218 } else {
1219 mFocusedStack = r.task.stack;
1220 if (mStackState != STACK_STATE_HOME_IN_BACK) {
Craig Mautner76ea2242013-05-15 11:40:05 -07001221 if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
1222 stackStateToString(mStackState) + " new=" +
1223 stackStateToString(STACK_STATE_HOME_TO_BACK) +
1224 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001225 mStackState = STACK_STATE_HOME_TO_BACK;
1226 }
1227 }
1228 }
1229
Craig Mautner8849a5e2013-04-02 16:41:03 -07001230 final int startActivityUncheckedLocked(ActivityRecord r,
1231 ActivityRecord sourceRecord, int startFlags, boolean doResume,
1232 Bundle options) {
1233 final Intent intent = r.intent;
1234 final int callingUid = r.launchedFromUid;
1235
1236 int launchFlags = intent.getFlags();
1237
Craig Mautner8849a5e2013-04-02 16:41:03 -07001238 // We'll invoke onUserLeaving before onPause only if the launching
1239 // activity did not explicitly state that this is an automated launch.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001240 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1241 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001242
1243 // If the caller has asked not to resume at this point, we make note
1244 // of this in the record so that we can skip it when trying to find
1245 // the top running activity.
1246 if (!doResume) {
1247 r.delayedResume = true;
1248 }
1249
1250 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1251
1252 // If the onlyIfNeeded flag is set, then we can do this if the activity
1253 // being launched is the same as the one making the call... or, as
1254 // a special case, if we do not know the caller then we count the
1255 // current top activity as the caller.
1256 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1257 ActivityRecord checkedCaller = sourceRecord;
1258 if (checkedCaller == null) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001259 checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001260 }
1261 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1262 // Caller is not the same as launcher, so always needed.
1263 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1264 }
1265 }
1266
1267 if (sourceRecord == null) {
1268 // This activity is not being started from another... in this
1269 // case we -always- start a new task.
1270 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Craig Mautner29219d92013-04-16 20:19:12 -07001271 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1272 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001273 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1274 }
1275 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1276 // The original activity who is starting us is running as a single
1277 // instance... this new activity it is starting must go on its
1278 // own task.
1279 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1280 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1281 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1282 // The activity being started is a single instance... it always
1283 // gets launched into its own task.
1284 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1285 }
1286
Craig Mautnerde4ef022013-04-07 19:01:33 -07001287 final ActivityStack sourceStack;
Craig Mautner525f3d92013-05-07 14:01:50 -07001288 TaskRecord sourceTask;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001289 if (sourceRecord != null) {
1290 sourceTask = sourceRecord.task;
1291 sourceStack = sourceTask.stack;
1292 } else {
1293 sourceTask = null;
1294 sourceStack = null;
1295 }
1296
Craig Mautner8849a5e2013-04-02 16:41:03 -07001297 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1298 // For whatever reason this activity is being launched into a new
1299 // task... yet the caller has requested a result back. Well, that
1300 // is pretty messed up, so instead immediately send back a cancel
1301 // and let the new task continue launched as normal without a
1302 // dependency on its originator.
1303 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1304 r.resultTo.task.stack.sendActivityResultLocked(-1,
1305 r.resultTo, r.resultWho, r.requestCode,
1306 Activity.RESULT_CANCELED, null);
1307 r.resultTo = null;
1308 }
1309
1310 boolean addingToTask = false;
1311 boolean movedHome = false;
1312 TaskRecord reuseTask = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001313 ActivityStack targetStack;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001314 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1315 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1316 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1317 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1318 // If bring to front is requested, and no result is requested, and
1319 // we can find a task that was started with this same
1320 // component, then instead of launching bring that one to the front.
1321 if (r.resultTo == null) {
1322 // See if there is a task to bring to the front. If this is
1323 // a SINGLE_INSTANCE activity, there can be one and only one
1324 // instance of it in the history, and it is always in its own
1325 // unique task, so we do a special search.
1326 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
1327 ? findTaskLocked(intent, r.info)
1328 : findActivityLocked(intent, r.info);
1329 if (intentActivity != null) {
Craig Mautner29219d92013-04-16 20:19:12 -07001330 if (r.task == null) {
1331 r.task = intentActivity.task;
1332 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001333 targetStack = intentActivity.task.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001334 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001335 if (intentActivity.task.intent == null) {
1336 // This task was started because of movement of
1337 // the activity based on affinity... now that we
1338 // are actually launching it, we can assign the
1339 // base intent.
1340 intentActivity.task.setIntent(intent, r.info);
1341 }
1342 // If the target task is not in the front, then we need
1343 // to bring it to the front... except... well, with
1344 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
1345 // to have the same behavior as if a new instance was
1346 // being started, which means not bringing it to the front
1347 // if the caller is not itself in the front.
Craig Mautner165640b2013-04-20 10:34:33 -07001348 final ActivityStack lastStack = getLastStack();
1349 ActivityRecord curTop = lastStack == null?
1350 null : lastStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001351 if (curTop != null && curTop.task != intentActivity.task) {
1352 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001353 if (sourceRecord == null || sourceStack.topActivity() == sourceRecord) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001354 // We really do want to push this one into the
1355 // user's face, right now.
1356 movedHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001357 if ((launchFlags &
Craig Mautner29219d92013-04-16 20:19:12 -07001358 (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1359 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001360 // Caller wants to appear on home activity, so before starting
1361 // their own activity we will bring home to the front.
1362 r.mLaunchHomeTaskNext = true;
1363 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001364 targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1365 options = null;
1366 }
1367 }
1368 // If the caller has requested that the target task be
1369 // reset, then do so.
1370 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1371 intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1372 }
1373 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1374 // We don't need to start a new activity, and
1375 // the client said not to do anything if that
1376 // is the case, so this is it! And for paranoia, make
1377 // sure we have correctly resumed the top activity.
1378 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001379 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001380 resumeTopActivitiesLocked(targetStack, null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001381 } else {
1382 ActivityOptions.abort(options);
1383 }
Craig Mautner29219d92013-04-16 20:19:12 -07001384 if (r.task == null) Slog.v(TAG,
1385 "startActivityUncheckedLocked: task left null",
1386 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001387 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1388 }
1389 if ((launchFlags &
1390 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1391 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1392 // The caller has requested to completely replace any
1393 // existing task with its new activity. Well that should
1394 // not be too hard...
1395 reuseTask = intentActivity.task;
1396 reuseTask.performClearTaskLocked();
1397 reuseTask.setIntent(r.intent, r.info);
1398 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1399 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1400 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1401 // In this situation we want to remove all activities
1402 // from the task up to the one being started. In most
1403 // cases this means we are resetting the task to its
1404 // initial state.
1405 ActivityRecord top =
1406 intentActivity.task.performClearTaskLocked(r, launchFlags);
1407 if (top != null) {
1408 if (top.frontOfTask) {
1409 // Activity aliases may mean we use different
1410 // intents for the top activity, so make sure
1411 // the task now has the identity of the new
1412 // intent.
1413 top.task.setIntent(r.intent, r.info);
1414 }
1415 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1416 r, top.task);
1417 top.deliverNewIntentLocked(callingUid, r.intent);
1418 } else {
1419 // A special case: we need to
1420 // start the activity because it is not currently
1421 // running, and the caller has asked to clear the
1422 // current task to have this activity at the top.
1423 addingToTask = true;
1424 // Now pretend like this activity is being started
1425 // by the top of its task, so it is put in the
1426 // right place.
1427 sourceRecord = intentActivity;
1428 }
1429 } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1430 // In this case the top activity on the task is the
1431 // same as the one being launched, so we take that
1432 // as a request to bring the task to the foreground.
1433 // If the top activity in the task is the root
1434 // activity, deliver this new intent to it if it
1435 // desires.
1436 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1437 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1438 && intentActivity.realActivity.equals(r.realActivity)) {
1439 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1440 intentActivity.task);
1441 if (intentActivity.frontOfTask) {
1442 intentActivity.task.setIntent(r.intent, r.info);
1443 }
1444 intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1445 } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1446 // In this case we are launching the root activity
1447 // of the task, but with a different intent. We
1448 // should start a new instance on top.
1449 addingToTask = true;
1450 sourceRecord = intentActivity;
1451 }
1452 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1453 // In this case an activity is being launched in to an
1454 // existing task, without resetting that task. This
1455 // is typically the situation of launching an activity
1456 // from a notification or shortcut. We want to place
1457 // the new activity on top of the current task.
1458 addingToTask = true;
1459 sourceRecord = intentActivity;
1460 } else if (!intentActivity.task.rootWasReset) {
1461 // In this case we are launching in to an existing task
1462 // that has not yet been started from its front door.
1463 // The current task has been brought to the front.
1464 // Ideally, we'd probably like to place this new task
1465 // at the bottom of its stack, but that's a little hard
1466 // to do with the current organization of the code so
1467 // for now we'll just drop it.
1468 intentActivity.task.setIntent(r.intent, r.info);
1469 }
1470 if (!addingToTask && reuseTask == null) {
1471 // We didn't do anything... but it was needed (a.k.a., client
1472 // don't use that intent!) And for paranoia, make
1473 // sure we have correctly resumed the top activity.
1474 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001475 setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1476 targetStack.resumeTopActivityLocked(null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001477 } else {
1478 ActivityOptions.abort(options);
1479 }
Craig Mautner29219d92013-04-16 20:19:12 -07001480 if (r.task == null) Slog.v(TAG,
1481 "startActivityUncheckedLocked: task left null",
1482 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001483 return ActivityManager.START_TASK_TO_FRONT;
1484 }
1485 }
1486 }
1487 }
1488
1489 //String uri = r.intent.toURI();
1490 //Intent intent2 = new Intent(uri);
1491 //Slog.i(TAG, "Given intent: " + r.intent);
1492 //Slog.i(TAG, "URI is: " + uri);
1493 //Slog.i(TAG, "To intent: " + intent2);
1494
1495 if (r.packageName != null) {
1496 // If the activity being launched is the same as the one currently
1497 // at the top, then we need to check if it should only be launched
1498 // once.
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001499 ActivityStack topStack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001500 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001501 if (top != null && r.resultTo == null) {
1502 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1503 if (top.app != null && top.app.thread != null) {
1504 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1505 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1506 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1507 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1508 top.task);
1509 // For paranoia, make sure we have correctly
1510 // resumed the top activity.
1511 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001512 setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001513 resumeTopActivitiesLocked();
Craig Mautner8849a5e2013-04-02 16:41:03 -07001514 }
1515 ActivityOptions.abort(options);
1516 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1517 // We don't need to start a new activity, and
1518 // the client said not to do anything if that
1519 // is the case, so this is it!
Craig Mautner29219d92013-04-16 20:19:12 -07001520 if (r.task == null) Slog.v(TAG,
1521 "startActivityUncheckedLocked: task left null",
1522 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001523 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1524 }
1525 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner29219d92013-04-16 20:19:12 -07001526 if (r.task == null) Slog.v(TAG,
1527 "startActivityUncheckedLocked: task left null",
1528 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001529 return ActivityManager.START_DELIVERED_TO_TOP;
1530 }
1531 }
1532 }
1533 }
1534
1535 } else {
1536 if (r.resultTo != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001537 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1538 r.requestCode, Activity.RESULT_CANCELED, null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001539 }
1540 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001541 if (r.task == null) Slog.v(TAG,
1542 "startActivityUncheckedLocked: task left null",
1543 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001544 return ActivityManager.START_CLASS_NOT_FOUND;
1545 }
1546
1547 boolean newTask = false;
1548 boolean keepCurTransition = false;
1549
1550 // Should this be considered a new task?
1551 if (r.resultTo == null && !addingToTask
1552 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001553 targetStack = getCorrectStack(r);
1554 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001555 if (reuseTask == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001556 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1557 null, true);
1558 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1559 r.task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001560 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001561 r.setTask(reuseTask, reuseTask, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001562 }
1563 newTask = true;
1564 if (!movedHome) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001565 if ((launchFlags &
1566 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1567 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1568 // Caller wants to appear on home activity, so before starting
1569 // their own activity we will bring home to the front.
1570 r.mLaunchHomeTaskNext = true;
1571 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001572 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001573 } else if (sourceRecord != null) {
Craig Mautner525f3d92013-05-07 14:01:50 -07001574 sourceTask = sourceRecord.task;
1575 targetStack = sourceTask.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001576 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001577 if (!addingToTask &&
1578 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1579 // In this case, we are adding the activity to an existing
1580 // task, but the caller has asked to clear that task if the
1581 // activity is already running.
Craig Mautner525f3d92013-05-07 14:01:50 -07001582 ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001583 keepCurTransition = true;
1584 if (top != null) {
1585 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1586 top.deliverNewIntentLocked(callingUid, r.intent);
1587 // For paranoia, make sure we have correctly
1588 // resumed the top activity.
1589 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001590 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001591 targetStack.resumeTopActivityLocked(null);
1592 }
1593 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001594 if (r.task == null) Slog.v(TAG,
1595 "startActivityUncheckedLocked: task left null",
1596 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001597 return ActivityManager.START_DELIVERED_TO_TOP;
1598 }
1599 } else if (!addingToTask &&
1600 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1601 // In this case, we are launching an activity in our own task
1602 // that may already be running somewhere in the history, and
1603 // we want to shuffle it to the front of the stack if so.
Craig Mautner525f3d92013-05-07 14:01:50 -07001604 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001605 if (top != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001606 final TaskRecord task = top.task;
1607 task.moveActivityToFrontLocked(top);
1608 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001609 top.updateOptionsLocked(options);
1610 top.deliverNewIntentLocked(callingUid, r.intent);
1611 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001612 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001613 targetStack.resumeTopActivityLocked(null);
1614 }
Craig Mautner29219d92013-04-16 20:19:12 -07001615 if (r.task == null) Slog.v(TAG,
1616 "startActivityUncheckedLocked: task left null",
1617 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001618 return ActivityManager.START_DELIVERED_TO_TOP;
1619 }
1620 }
1621 // An existing activity is starting this new activity, so we want
1622 // to keep the new one in the same task as the one that is starting
1623 // it.
Craig Mautner525f3d92013-05-07 14:01:50 -07001624 r.setTask(sourceTask, sourceRecord.thumbHolder, false);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001625 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1626 + " in existing task " + r.task);
1627
1628 } else {
1629 // This not being started from an existing activity, and not part
1630 // of a new task... just put it in the top task, though these days
1631 // this case should never happen.
Craig Mautner1602ec22013-05-12 10:24:27 -07001632 targetStack = getCorrectStack(r);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001633 moveHomeStack(targetStack.isHomeStack());
Craig Mautner1602ec22013-05-12 10:24:27 -07001634 ActivityRecord prev = targetStack.topActivity();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001635 r.setTask(prev != null ? prev.task
1636 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1637 null, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001638 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1639 + " in new guessed " + r.task);
1640 }
1641
1642 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1643 intent, r.getUriPermissionsLocked());
1644
1645 if (newTask) {
1646 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1647 }
1648 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001649 setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001650 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
1651 return ActivityManager.START_SUCCESS;
1652 }
1653
Craig Mautnerf3333272013-04-22 10:55:53 -07001654 // Checked.
1655 final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
1656 Configuration config) {
1657 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
1658
1659 ActivityRecord res = null;
1660
1661 ArrayList<ActivityRecord> stops = null;
1662 ArrayList<ActivityRecord> finishes = null;
1663 ArrayList<UserStartedState> startingUsers = null;
1664 int NS = 0;
1665 int NF = 0;
1666 IApplicationThread sendThumbnail = null;
1667 boolean booting = false;
1668 boolean enableScreen = false;
1669 boolean activityRemoved = false;
1670
1671 ActivityRecord r = ActivityRecord.forToken(token);
1672 if (r != null) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07001673 if (DEBUG_IDLE) Slog.d(TAG, "activityIdleInternalLocked: Callers=" +
1674 Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07001675 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
1676 r.finishLaunchTickingLocked();
Craig Mautner525f3d92013-05-07 14:01:50 -07001677 res = r.task.stack.activityIdleInternalLocked(token);
Craig Mautnerf3333272013-04-22 10:55:53 -07001678 if (res != null) {
1679 if (fromTimeout) {
1680 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
1681 }
1682
1683 // This is a hack to semi-deal with a race condition
1684 // in the client where it can be constructed with a
1685 // newer configuration from when we asked it to launch.
1686 // We'll update with whatever configuration it now says
1687 // it used to launch.
1688 if (config != null) {
1689 r.configuration = config;
1690 }
1691
1692 // We are now idle. If someone is waiting for a thumbnail from
1693 // us, we can now deliver.
1694 r.idle = true;
1695 if (allResumedActivitiesIdle()) {
1696 mService.scheduleAppGcsLocked();
1697 }
1698 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
1699 sendThumbnail = r.app.thread;
1700 r.thumbnailNeeded = false;
1701 }
1702
1703 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
1704 if (!mService.mBooted && isFrontStack(r.task.stack)) {
1705 mService.mBooted = true;
1706 enableScreen = true;
1707 }
1708 } else if (fromTimeout) {
1709 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
1710 }
1711 }
1712
1713 // Atomically retrieve all of the other things to do.
1714 stops = processStoppingActivitiesLocked(true);
1715 NS = stops != null ? stops.size() : 0;
1716 if ((NF=mFinishingActivities.size()) > 0) {
1717 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
1718 mFinishingActivities.clear();
1719 }
1720
1721 final ArrayList<ActivityRecord> thumbnails;
1722 final int NT = mCancelledThumbnails.size();
1723 if (NT > 0) {
1724 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
1725 mCancelledThumbnails.clear();
1726 } else {
1727 thumbnails = null;
1728 }
1729
1730 if (isFrontStack(mHomeStack)) {
1731 booting = mService.mBooting;
1732 mService.mBooting = false;
1733 }
1734
1735 if (mStartingUsers.size() > 0) {
1736 startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
1737 mStartingUsers.clear();
1738 }
1739
1740 // Perform the following actions from unsynchronized state.
1741 final IApplicationThread thumbnailThread = sendThumbnail;
1742 mHandler.post(new Runnable() {
1743 @Override
1744 public void run() {
1745 if (thumbnailThread != null) {
1746 try {
1747 thumbnailThread.requestThumbnail(token);
1748 } catch (Exception e) {
1749 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
1750 mService.sendPendingThumbnail(null, token, null, null, true);
1751 }
1752 }
1753
1754 // Report back to any thumbnail receivers.
1755 for (int i = 0; i < NT; i++) {
1756 ActivityRecord r = thumbnails.get(i);
1757 mService.sendPendingThumbnail(r, null, null, null, true);
1758 }
1759 }
1760 });
1761
1762 // Stop any activities that are scheduled to do so but have been
1763 // waiting for the next one to start.
1764 for (int i = 0; i < NS; i++) {
1765 r = stops.get(i);
1766 final ActivityStack stack = r.task.stack;
1767 if (r.finishing) {
1768 stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
1769 } else {
1770 stack.stopActivityLocked(r);
1771 }
1772 }
1773
1774 // Finish any activities that are scheduled to do so but have been
1775 // waiting for the next one to start.
1776 for (int i = 0; i < NF; i++) {
1777 r = finishes.get(i);
1778 activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle");
1779 }
1780
1781 if (booting) {
1782 mService.finishBooting();
1783 } else if (startingUsers != null) {
1784 for (int i = 0; i < startingUsers.size(); i++) {
1785 mService.finishUserSwitch(startingUsers.get(i));
1786 }
1787 }
1788
1789 mService.trimApplications();
1790 //dump();
1791 //mWindowManager.dump();
1792
1793 if (enableScreen) {
1794 mService.enableScreenAfterBoot();
1795 }
1796
1797 if (activityRemoved) {
Craig Mautner05d29032013-05-03 13:40:13 -07001798 resumeTopActivitiesLocked();
Craig Mautnerf3333272013-04-22 10:55:53 -07001799 }
1800
1801 return res;
1802 }
1803
Craig Mautner8d341ef2013-03-26 09:03:27 -07001804 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
1805 // Just in case.
1806 final int numStacks = mStacks.size();
1807 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Craig Mautnere79d42682013-04-01 19:01:53 -07001808 mStacks.get(stackNdx).handleAppDiedLocked(app, restarting);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001809 }
1810 }
1811
1812 void closeSystemDialogsLocked() {
1813 final int numStacks = mStacks.size();
1814 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1815 final ActivityStack stack = mStacks.get(stackNdx);
1816 stack.closeSystemDialogsLocked();
1817 }
1818 }
1819
1820 /**
1821 * @return true if some activity was finished (or would have finished if doit were true).
1822 */
1823 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1824 boolean didSomething = false;
1825 final int numStacks = mStacks.size();
1826 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1827 final ActivityStack stack = mStacks.get(stackNdx);
1828 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1829 didSomething = true;
1830 }
1831 }
1832 return didSomething;
1833 }
1834
Craig Mautner05d29032013-05-03 13:40:13 -07001835 boolean resumeTopActivitiesLocked() {
1836 return resumeTopActivitiesLocked(null, null, null);
1837 }
1838
1839 boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
1840 Bundle targetOptions) {
1841 if (targetStack == null) {
1842 targetStack = getFocusedStack();
1843 }
1844 boolean result = false;
Craig Mautnerdbcb31f2013-04-02 12:32:53 -07001845 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001846 final ActivityStack stack = mStacks.get(stackNdx);
1847 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07001848 if (stack == targetStack) {
1849 result = stack.resumeTopActivityLocked(target, targetOptions);
1850 } else {
1851 stack.resumeTopActivityLocked(null);
1852 }
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001853 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001854 }
Craig Mautner05d29032013-05-03 13:40:13 -07001855 return result;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001856 }
1857
1858 void finishTopRunningActivityLocked(ProcessRecord app) {
1859 final int numStacks = mStacks.size();
1860 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1861 final ActivityStack stack = mStacks.get(stackNdx);
1862 stack.finishTopRunningActivityLocked(app);
1863 }
1864 }
1865
Craig Mautner8d341ef2013-03-26 09:03:27 -07001866 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
1867 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1868 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
1869 return;
1870 }
1871 }
1872 }
1873
Craig Mautner967212c2013-04-13 21:10:58 -07001874 ActivityStack getStack(int stackId) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001875 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1876 final ActivityStack stack = mStacks.get(stackNdx);
1877 if (stack.getStackId() == stackId) {
1878 return stack;
1879 }
1880 }
1881 return null;
1882 }
1883
Craig Mautner967212c2013-04-13 21:10:58 -07001884 ArrayList<ActivityStack> getStacks() {
1885 return new ArrayList<ActivityStack>(mStacks);
1886 }
1887
1888 int createStack() {
Craig Mautner858d8a62013-04-23 17:08:34 -07001889 while (true) {
1890 if (++mLastStackId <= HOME_STACK_ID) {
1891 mLastStackId = HOME_STACK_ID + 1;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001892 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001893 if (getStack(mLastStackId) == null) {
1894 break;
1895 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001896 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001897 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
1898 return mLastStackId;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001899 }
1900
1901 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07001902 final TaskRecord task = anyTaskForIdLocked(taskId);
1903 if (task == null) {
1904 return;
1905 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001906 final ActivityStack stack = getStack(stackId);
1907 if (stack == null) {
1908 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
1909 return;
1910 }
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07001911 removeTask(task);
1912 stack.addTask(task, toTop);
1913 if (toTop) {
1914 moveHomeStack(stack.isHomeStack());
1915 setFocusedStack(task.getTopActivity());
1916 }
1917 mWindowManager.addTask(taskId, stackId, toTop);
Craig Mautner05d29032013-05-03 13:40:13 -07001918 resumeTopActivitiesLocked();
Craig Mautner8d341ef2013-03-26 09:03:27 -07001919 }
1920
Craig Mautner8849a5e2013-04-02 16:41:03 -07001921 ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
1922 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1923 final ActivityRecord ar = mStacks.get(stackNdx).findTaskLocked(intent, info);
1924 if (ar != null) {
1925 return ar;
1926 }
1927 }
1928 return null;
1929 }
1930
1931 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
1932 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1933 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
1934 if (ar != null) {
1935 return ar;
1936 }
1937 }
1938 return null;
1939 }
1940
Craig Mautner8d341ef2013-03-26 09:03:27 -07001941 void goingToSleepLocked() {
Craig Mautner0eea92c2013-05-16 13:35:39 -07001942 scheduleSleepTimeout();
1943 if (!mGoingToSleep.isHeld()) {
1944 mGoingToSleep.acquire();
1945 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1946 final ActivityStack stack = mStacks.get(stackNdx);
1947 if (stack.mResumedActivity != null) {
1948 stack.stopIfSleepingLocked();
1949 }
1950 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001951 }
1952 }
1953
1954 boolean shutdownLocked(int timeout) {
1955 boolean timedout = false;
Craig Mautner0eea92c2013-05-16 13:35:39 -07001956 goingToSleepLocked();
1957 checkReadyForSleepLocked();
1958
1959 final long endTime = System.currentTimeMillis() + timeout;
1960 while (true) {
1961 boolean cantShutdown = false;
1962 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1963 cantShutdown |= mStacks.get(stackNdx).checkReadyForSleepLocked();
1964 }
1965 if (cantShutdown) {
1966 long timeRemaining = endTime - System.currentTimeMillis();
1967 if (timeRemaining > 0) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001968 try {
Craig Mautner0eea92c2013-05-16 13:35:39 -07001969 mService.wait(timeRemaining);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001970 } catch (InterruptedException e) {
1971 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07001972 } else {
1973 Slog.w(TAG, "Activity manager shutdown timed out");
1974 timedout = true;
1975 break;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001976 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07001977 } else {
1978 break;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001979 }
1980 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07001981
1982 // Force checkReadyForSleep to complete.
1983 mSleepTimeout = true;
1984 checkReadyForSleepLocked();
1985
Craig Mautner8d341ef2013-03-26 09:03:27 -07001986 return timedout;
1987 }
1988
1989 void comeOutOfSleepIfNeededLocked() {
Craig Mautner0eea92c2013-05-16 13:35:39 -07001990 removeSleepTimeouts();
1991 if (mGoingToSleep.isHeld()) {
1992 mGoingToSleep.release();
1993 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001994 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001995 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001996 stack.awakeFromSleepingLocked();
1997 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07001998 resumeTopActivitiesLocked();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001999 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002000 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002001 mGoingToSleepActivities.clear();
2002 }
2003
2004 void activitySleptLocked(ActivityRecord r) {
2005 mGoingToSleepActivities.remove(r);
2006 checkReadyForSleepLocked();
2007 }
2008
2009 void checkReadyForSleepLocked() {
2010 if (!mService.isSleepingOrShuttingDown()) {
2011 // Do not care.
2012 return;
2013 }
2014
2015 if (!mSleepTimeout) {
2016 boolean dontSleep = false;
2017 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2018 dontSleep |= mStacks.get(stackNdx).checkReadyForSleepLocked();
2019 }
2020
2021 if (mStoppingActivities.size() > 0) {
2022 // Still need to tell some activities to stop; can't sleep yet.
2023 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
2024 + mStoppingActivities.size() + " activities");
2025 scheduleIdleLocked();
2026 dontSleep = true;
2027 }
2028
2029 if (mGoingToSleepActivities.size() > 0) {
2030 // Still need to tell some activities to sleep; can't sleep yet.
2031 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
2032 + mGoingToSleepActivities.size() + " activities");
2033 dontSleep = true;
2034 }
2035
2036 if (dontSleep) {
2037 return;
2038 }
2039 }
2040
2041 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2042 mStacks.get(stackNdx).goToSleep();
2043 }
2044
2045 removeSleepTimeouts();
2046
2047 if (mGoingToSleep.isHeld()) {
2048 mGoingToSleep.release();
2049 }
2050 if (mService.mShuttingDown) {
2051 mService.notifyAll();
2052 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002053 }
2054
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002055 boolean reportResumedActivityLocked(ActivityRecord r) {
2056 final ActivityStack stack = r.task.stack;
2057 if (isFrontStack(stack)) {
Jeff Sharkey5782da72013-04-25 14:32:30 -07002058 mService.updateUsageStats(r, true);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002059 mService.setFocusedActivityLocked(r);
2060 }
2061 if (allResumedActivitiesComplete()) {
2062 ensureActivitiesVisibleLocked(null, 0);
2063 mWindowManager.executeAppTransition();
2064 return true;
2065 }
2066 return false;
2067 }
2068
Craig Mautner8d341ef2013-03-26 09:03:27 -07002069 void handleAppCrashLocked(ProcessRecord app) {
2070 final int numStacks = mStacks.size();
2071 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2072 final ActivityStack stack = mStacks.get(stackNdx);
2073 stack.handleAppCrashLocked(app);
2074 }
2075 }
2076
Craig Mautnerde4ef022013-04-07 19:01:33 -07002077 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
Craig Mautner580ea812013-04-25 12:58:38 -07002078 // First the front stacks. In case any are not fullscreen and are in front of home.
2079 boolean showHomeBehindStack = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07002080 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner580ea812013-04-25 12:58:38 -07002081 final ActivityStack stack = mStacks.get(stackNdx);
2082 if (isFrontStack(stack)) {
2083 showHomeBehindStack =
2084 stack.ensureActivitiesVisibleLocked(starting, configChanges);
2085 }
2086 }
2087 // Now do back stacks.
2088 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2089 final ActivityStack stack = mStacks.get(stackNdx);
2090 if (!isFrontStack(stack)) {
2091 stack.ensureActivitiesVisibleLocked(starting, configChanges, showHomeBehindStack);
2092 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002093 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002094 }
2095
2096 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
2097 final int numStacks = mStacks.size();
2098 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2099 final ActivityStack stack = mStacks.get(stackNdx);
2100 stack.scheduleDestroyActivities(app, false, reason);
2101 }
2102 }
2103
2104 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner858d8a62013-04-23 17:08:34 -07002105 mUserStates.put(mCurrentUser, new UserState());
Craig Mautner2420ead2013-04-01 17:13:20 -07002106 mCurrentUser = userId;
Craig Mautner858d8a62013-04-23 17:08:34 -07002107 UserState userState = mUserStates.get(userId);
2108 if (userState != null) {
2109 userState.restore();
2110 mUserStates.delete(userId);
2111 } else {
2112 mFocusedStack = null;
Craig Mautner76ea2242013-05-15 11:40:05 -07002113 if (DEBUG_STACK) Slog.d(TAG, "switchUserLocked: mStackState=" +
2114 stackStateToString(STACK_STATE_HOME_IN_FRONT));
Craig Mautner858d8a62013-04-23 17:08:34 -07002115 mStackState = STACK_STATE_HOME_IN_FRONT;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002116 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002117
2118 mStartingUsers.add(uss);
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002119 boolean haveActivities = mHomeStack.switchUserLocked(userId);
Craig Mautner858d8a62013-04-23 17:08:34 -07002120
2121 resumeTopActivitiesLocked();
2122
Craig Mautner8d341ef2013-03-26 09:03:27 -07002123 return haveActivities;
Craig Mautner2219a1b2013-03-25 09:44:30 -07002124 }
2125
Craig Mautnerde4ef022013-04-07 19:01:33 -07002126 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
2127 int N = mStoppingActivities.size();
2128 if (N <= 0) return null;
2129
2130 ArrayList<ActivityRecord> stops = null;
2131
2132 final boolean nowVisible = allResumedActivitiesVisible();
2133 for (int i=0; i<N; i++) {
2134 ActivityRecord s = mStoppingActivities.get(i);
2135 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
2136 + nowVisible + " waitingVisible=" + s.waitingVisible
2137 + " finishing=" + s.finishing);
2138 if (s.waitingVisible && nowVisible) {
2139 mWaitingVisibleActivities.remove(s);
2140 s.waitingVisible = false;
2141 if (s.finishing) {
2142 // If this activity is finishing, it is sitting on top of
2143 // everyone else but we now know it is no longer needed...
2144 // so get rid of it. Otherwise, we need to go through the
2145 // normal flow and hide it once we determine that it is
2146 // hidden by the activities in front of it.
2147 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002148 mWindowManager.setAppVisibility(s.appToken, false);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002149 }
2150 }
2151 if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
2152 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
2153 if (stops == null) {
2154 stops = new ArrayList<ActivityRecord>();
2155 }
2156 stops.add(s);
2157 mStoppingActivities.remove(i);
2158 N--;
2159 i--;
2160 }
2161 }
2162
2163 return stops;
2164 }
2165
Craig Mautnercf910b02013-04-23 11:23:27 -07002166 void validateTopActivitiesLocked() {
2167 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2168 final ActivityStack stack = mStacks.get(stackNdx);
2169 final ActivityRecord r = stack.topRunningActivityLocked(null);
2170 if (isFrontStack(stack)) {
2171 if (r == null) {
2172 Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
2173 } else {
2174 if (stack.mPausingActivity != null) {
2175 Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
2176 " state=" + r.state);
2177 }
2178 if (r.state != ActivityState.INITIALIZING &&
2179 r.state != ActivityState.RESUMED) {
2180 Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
2181 " state=" + r.state);
2182 }
2183 }
2184 } else {
2185 if (stack.mResumedActivity != null) {
2186 Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
2187 " state=" + r.state);
2188 }
2189 if (r != null && (r.state == ActivityState.INITIALIZING
2190 || r.state == ActivityState.RESUMED)) {
2191 Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
2192 " state=" + r.state);
2193 }
2194 }
2195 }
2196 }
2197
Craig Mautner76ea2242013-05-15 11:40:05 -07002198 private static String stackStateToString(int stackState) {
2199 switch (stackState) {
2200 case STACK_STATE_HOME_IN_FRONT: return "STACK_STATE_HOME_IN_FRONT";
2201 case STACK_STATE_HOME_TO_BACK: return "STACK_STATE_HOME_TO_BACK";
2202 case STACK_STATE_HOME_IN_BACK: return "STACK_STATE_HOME_IN_BACK";
2203 case STACK_STATE_HOME_TO_FRONT: return "STACK_STATE_HOME_TO_FRONT";
2204 default: return "Unknown stackState=" + stackState;
2205 }
2206 }
2207
Craig Mautner27084302013-03-25 08:05:25 -07002208 public void dump(PrintWriter pw, String prefix) {
2209 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
2210 pw.println(mDismissKeyguardOnNextActivity);
Craig Mautner76ea2242013-05-15 11:40:05 -07002211 pw.print(prefix); pw.print("mStackState="); pw.println(stackStateToString(mStackState));
Craig Mautner27084302013-03-25 08:05:25 -07002212 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002213
Craig Mautner20e72272013-04-01 13:45:53 -07002214 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002215 return getFocusedStack().getDumpActivitiesLocked(name);
Craig Mautner20e72272013-04-01 13:45:53 -07002216 }
2217
Dianne Hackborn390517b2013-05-30 15:03:32 -07002218 static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
2219 boolean needSep, String prefix) {
2220 if (activity != null) {
2221 if (dumpPackage == null || dumpPackage.equals(activity.packageName)) {
2222 if (needSep) {
2223 pw.println();
2224 needSep = false;
2225 }
2226 pw.print(prefix);
2227 pw.println(activity);
2228 }
2229 }
2230 return needSep;
2231 }
2232
Craig Mautner8d341ef2013-03-26 09:03:27 -07002233 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
2234 boolean dumpClient, String dumpPackage) {
2235 final int numStacks = mStacks.size();
2236 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2237 final ActivityStack stack = mStacks.get(stackNdx);
Dianne Hackborn390517b2013-05-30 15:03:32 -07002238 if (stackNdx != 0) {
2239 pw.println();
2240 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002241 pw.print(" Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
Dianne Hackborn390517b2013-05-30 15:03:32 -07002242 stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, false);
2243 dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false,
2244 dumpPackage, true, " Running activities (most recent first):");
Craig Mautner8d341ef2013-03-26 09:03:27 -07002245
Dianne Hackborn390517b2013-05-30 15:03:32 -07002246 boolean needSep = true;
2247 needSep = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
2248 " mPausingActivity: ");
2249 needSep = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
2250 " mResumedActivity: ");
Craig Mautner8d341ef2013-03-26 09:03:27 -07002251 if (dumpAll) {
Dianne Hackborn390517b2013-05-30 15:03:32 -07002252 printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
2253 " mLastPausedActivity: ");
Craig Mautner8d341ef2013-03-26 09:03:27 -07002254 }
2255 }
2256
Dianne Hackborn390517b2013-05-30 15:03:32 -07002257 dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll, false,
2258 dumpPackage, true, " Activities waiting to finish:");
2259 dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, false,
2260 dumpPackage, true, " Activities waiting to stop:");
2261 dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
2262 false, dumpPackage, true, " Activities waiting for another to become visible:");
2263 dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll, false,
2264 dumpPackage, true, " Activities waiting to sleep:");
2265 dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll, false,
2266 dumpPackage, true, " Activities waiting to sleep:");
Craig Mautnerf3333272013-04-22 10:55:53 -07002267
Dianne Hackborn390517b2013-05-30 15:03:32 -07002268 if (dumpPackage == null) {
2269 pw.println();
2270 pw.print(" mStackState="); pw.println(stackStateToString(mStackState));
2271 if (dumpAll) {
2272 pw.println(" mSleepTimeout: " + mSleepTimeout);
2273 }
2274 if (dumpAll) {
2275 pw.println(" mCurTaskId: " + mCurTaskId);
2276 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002277 }
2278 return true;
2279 }
2280
Dianne Hackborn390517b2013-05-30 15:03:32 -07002281 static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
Craig Mautner8d341ef2013-03-26 09:03:27 -07002282 String prefix, String label, boolean complete, boolean brief, boolean client,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002283 String dumpPackage, boolean needNL, String header) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002284 TaskRecord lastTask = null;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002285 String innerPrefix = null;
2286 String[] args = null;
2287 boolean printed = false;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002288 for (int i=list.size()-1; i>=0; i--) {
2289 final ActivityRecord r = list.get(i);
2290 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
2291 continue;
2292 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07002293 if (innerPrefix == null) {
2294 innerPrefix = prefix + " ";
2295 args = new String[0];
2296 }
2297 printed = true;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002298 final boolean full = !brief && (complete || !r.isInHistory());
2299 if (needNL) {
Dianne Hackborn390517b2013-05-30 15:03:32 -07002300 pw.println("");
Craig Mautner8d341ef2013-03-26 09:03:27 -07002301 needNL = false;
2302 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07002303 if (header != null) {
2304 pw.println(header);
2305 header = null;
2306 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002307 if (lastTask != r.task) {
2308 lastTask = r.task;
2309 pw.print(prefix);
2310 pw.print(full ? "* " : " ");
2311 pw.println(lastTask);
2312 if (full) {
2313 lastTask.dump(pw, prefix + " ");
2314 } else if (complete) {
2315 // Complete + brief == give a summary. Isn't that obvious?!?
2316 if (lastTask.intent != null) {
2317 pw.print(prefix); pw.print(" ");
2318 pw.println(lastTask.intent.toInsecureStringWithClip());
2319 }
2320 }
2321 }
2322 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
2323 pw.print(" #"); pw.print(i); pw.print(": ");
2324 pw.println(r);
2325 if (full) {
2326 r.dump(pw, innerPrefix);
2327 } else if (complete) {
2328 // Complete + brief == give a summary. Isn't that obvious?!?
2329 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
2330 if (r.app != null) {
2331 pw.print(innerPrefix); pw.println(r.app);
2332 }
2333 }
2334 if (client && r.app != null && r.app.thread != null) {
2335 // flush anything that is already in the PrintWriter since the thread is going
2336 // to write to the file descriptor directly
2337 pw.flush();
2338 try {
2339 TransferPipe tp = new TransferPipe();
2340 try {
2341 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
2342 r.appToken, innerPrefix, args);
2343 // Short timeout, since blocking here can
2344 // deadlock with the application.
2345 tp.go(fd, 2000);
2346 } finally {
2347 tp.kill();
2348 }
2349 } catch (IOException e) {
2350 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
2351 } catch (RemoteException e) {
2352 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
2353 }
2354 needNL = true;
2355 }
2356 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07002357 return printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002358 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002359
Craig Mautnerf3333272013-04-22 10:55:53 -07002360 void scheduleIdleTimeoutLocked(ActivityRecord next) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002361 if (DEBUG_IDLE) Slog.d(TAG, "scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4));
Craig Mautnerc64f73e2013-04-24 16:44:56 -07002362 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
2363 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
Craig Mautnerf3333272013-04-22 10:55:53 -07002364 }
2365
2366 final void scheduleIdleLocked() {
Craig Mautner05d29032013-05-03 13:40:13 -07002367 mHandler.sendEmptyMessage(IDLE_NOW_MSG);
Craig Mautnerf3333272013-04-22 10:55:53 -07002368 }
2369
2370 void removeTimeoutsForActivityLocked(ActivityRecord r) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002371 if (DEBUG_IDLE) Slog.d(TAG, "removeTimeoutsForActivity: Callers=" + Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07002372 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
2373 }
2374
Craig Mautner05d29032013-05-03 13:40:13 -07002375 final void scheduleResumeTopActivities() {
2376 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2377 }
2378
Craig Mautner0eea92c2013-05-16 13:35:39 -07002379 void removeSleepTimeouts() {
2380 mSleepTimeout = false;
2381 mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
2382 }
2383
2384 final void scheduleSleepTimeout() {
2385 removeSleepTimeouts();
2386 mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT);
2387 }
2388
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002389 private final class ActivityStackSupervisorHandler extends Handler {
Craig Mautnerf3333272013-04-22 10:55:53 -07002390
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002391 public ActivityStackSupervisorHandler(Looper looper) {
2392 super(looper);
2393 }
2394
Craig Mautnerf3333272013-04-22 10:55:53 -07002395 void activityIdleInternal(ActivityRecord r) {
2396 synchronized (mService) {
2397 activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
2398 }
2399 }
2400
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002401 @Override
2402 public void handleMessage(Message msg) {
2403 switch (msg.what) {
Craig Mautnerf3333272013-04-22 10:55:53 -07002404 case IDLE_TIMEOUT_MSG: {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002405 if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_TIMEOUT_MSG: Callers=" +
2406 Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07002407 if (mService.mDidDexOpt) {
2408 mService.mDidDexOpt = false;
2409 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2410 nmsg.obj = msg.obj;
2411 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
2412 return;
2413 }
2414 // We don't at this point know if the activity is fullscreen,
2415 // so we need to be conservative and assume it isn't.
2416 activityIdleInternal((ActivityRecord)msg.obj);
2417 } break;
2418 case IDLE_NOW_MSG: {
2419 activityIdleInternal((ActivityRecord)msg.obj);
2420 } break;
Craig Mautner05d29032013-05-03 13:40:13 -07002421 case RESUME_TOP_ACTIVITY_MSG: {
2422 synchronized (mService) {
2423 resumeTopActivitiesLocked();
2424 }
2425 } break;
Craig Mautner0eea92c2013-05-16 13:35:39 -07002426 case SLEEP_TIMEOUT_MSG: {
2427 synchronized (mService) {
2428 if (mService.isSleepingOrShuttingDown()) {
2429 Slog.w(TAG, "Sleep timeout! Sleeping now.");
2430 mSleepTimeout = true;
2431 checkReadyForSleepLocked();
2432 }
2433 }
2434 } break;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002435 }
2436 }
2437 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002438
2439 private final class UserState {
2440 final ActivityStack mSavedFocusedStack;
2441 final int mSavedStackState;
2442
2443 public UserState() {
2444 ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2445 mSavedFocusedStack = supervisor.mFocusedStack;
2446 mSavedStackState = supervisor.mStackState;
2447 }
2448
2449 void restore() {
2450 ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2451 supervisor.mFocusedStack = mSavedFocusedStack;
Craig Mautner76ea2242013-05-15 11:40:05 -07002452 if (DEBUG_STACK) Slog.d(TAG, "UserState.restore: mStackState old=" +
2453 stackStateToString(mSavedStackState));
Craig Mautner858d8a62013-04-23 17:08:34 -07002454 supervisor.mStackState = mSavedStackState;
2455 }
2456 }
Craig Mautner27084302013-03-25 08:05:25 -07002457}