blob: 8d1a6654bc64083ae33ad70001050bd4648a69f0 [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 Mautnere7c58b62013-06-12 20:19:00 -070025import static com.android.server.am.ActivityManagerService.DEBUG_FOCUS;
Craig Mautner0eea92c2013-05-16 13:35:39 -070026import static com.android.server.am.ActivityManagerService.DEBUG_PAUSE;
Craig Mautner6170f732013-04-02 13:05:23 -070027import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
Craig Mautner0eea92c2013-05-16 13:35:39 -070028import static com.android.server.am.ActivityManagerService.DEBUG_STACK;
Craig Mautner2420ead2013-04-01 17:13:20 -070029import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
Craig Mautner8849a5e2013-04-02 16:41:03 -070030import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
31import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
Craig Mautner05d29032013-05-03 13:40:13 -070032import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
Craig Mautner8d341ef2013-03-26 09:03:27 -070033import static com.android.server.am.ActivityManagerService.TAG;
34
Craig Mautner2420ead2013-04-01 17:13:20 -070035import android.app.Activity;
Craig Mautner23ac33b2013-04-01 16:26:35 -070036import android.app.ActivityManager;
37import android.app.ActivityOptions;
38import android.app.AppGlobals;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070039import android.app.IActivityManager;
Craig Mautner23ac33b2013-04-01 16:26:35 -070040import android.app.IApplicationThread;
Craig Mautner20e72272013-04-01 13:45:53 -070041import android.app.IThumbnailReceiver;
Craig Mautner23ac33b2013-04-01 16:26:35 -070042import android.app.PendingIntent;
Craig Mautner20e72272013-04-01 13:45:53 -070043import android.app.ActivityManager.RunningTaskInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070044import android.app.IActivityManager.WaitResult;
Craig Mautner2420ead2013-04-01 17:13:20 -070045import android.app.ResultInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070046import android.content.ComponentName;
Craig Mautner2219a1b2013-03-25 09:44:30 -070047import android.content.Context;
Craig Mautner23ac33b2013-04-01 16:26:35 -070048import android.content.IIntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070049import android.content.Intent;
Craig Mautner23ac33b2013-04-01 16:26:35 -070050import android.content.IntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070051import android.content.pm.ActivityInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070052import android.content.pm.ApplicationInfo;
53import android.content.pm.PackageManager;
54import android.content.pm.ResolveInfo;
55import android.content.res.Configuration;
56import android.os.Binder;
Craig Mautner8d341ef2013-03-26 09:03:27 -070057import android.os.Bundle;
Craig Mautnerb59dcfd2013-05-06 13:12:58 -070058import android.os.Debug;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070059import android.os.Handler;
Craig Mautner23ac33b2013-04-01 16:26:35 -070060import android.os.IBinder;
Craig Mautner2219a1b2013-03-25 09:44:30 -070061import android.os.Looper;
Craig Mautner2420ead2013-04-01 17:13:20 -070062import android.os.Message;
Craig Mautner23ac33b2013-04-01 16:26:35 -070063import android.os.ParcelFileDescriptor;
Craig Mautner0eea92c2013-05-16 13:35:39 -070064import android.os.PowerManager;
Craig Mautner7ea5bd42013-07-05 15:27:08 -070065import android.os.Process;
Craig Mautner8d341ef2013-03-26 09:03:27 -070066import android.os.RemoteException;
Craig Mautner23ac33b2013-04-01 16:26:35 -070067import android.os.SystemClock;
Craig Mautner6170f732013-04-02 13:05:23 -070068import android.os.UserHandle;
Craig Mautner2420ead2013-04-01 17:13:20 -070069import android.util.EventLog;
Craig Mautner8d341ef2013-03-26 09:03:27 -070070import android.util.Slog;
Craig Mautner858d8a62013-04-23 17:08:34 -070071import android.util.SparseArray;
Craig Mautner2219a1b2013-03-25 09:44:30 -070072
Craig Mautner23ac33b2013-04-01 16:26:35 -070073import com.android.internal.app.HeavyWeightSwitcherActivity;
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070074import com.android.internal.os.TransferPipe;
Craig Mautner6170f732013-04-02 13:05:23 -070075import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
Craig Mautner2420ead2013-04-01 17:13:20 -070076import com.android.server.am.ActivityStack.ActivityState;
Craig Mautnerde4ef022013-04-07 19:01:33 -070077import com.android.server.wm.StackBox;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070078import com.android.server.wm.WindowManagerService;
Craig Mautner23ac33b2013-04-01 16:26:35 -070079
Craig Mautner8d341ef2013-03-26 09:03:27 -070080import java.io.FileDescriptor;
81import java.io.IOException;
Craig Mautner27084302013-03-25 08:05:25 -070082import java.io.PrintWriter;
Craig Mautner2219a1b2013-03-25 09:44:30 -070083import java.util.ArrayList;
Craig Mautner8d341ef2013-03-26 09:03:27 -070084import java.util.List;
Craig Mautner27084302013-03-25 08:05:25 -070085
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070086public final class ActivityStackSupervisor {
Craig Mautnerde4ef022013-04-07 19:01:33 -070087 static final boolean DEBUG = ActivityManagerService.DEBUG || false;
88 static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
89 static final boolean DEBUG_APP = DEBUG || false;
90 static final boolean DEBUG_SAVED_STATE = DEBUG || false;
91 static final boolean DEBUG_STATES = DEBUG || false;
Craig Mautnerb59dcfd2013-05-06 13:12:58 -070092 static final boolean DEBUG_IDLE = DEBUG || false;
Craig Mautner2420ead2013-04-01 17:13:20 -070093
Craig Mautner2219a1b2013-03-25 09:44:30 -070094 public static final int HOME_STACK_ID = 0;
Craig Mautner27084302013-03-25 08:05:25 -070095
Craig Mautnerf3333272013-04-22 10:55:53 -070096 /** How long we wait until giving up on the last activity telling us it is idle. */
97 static final int IDLE_TIMEOUT = 10*1000;
98
Craig Mautner0eea92c2013-05-16 13:35:39 -070099 /** How long we can hold the sleep wake lock before giving up. */
100 static final int SLEEP_TIMEOUT = 5*1000;
101
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700102 // How long we can hold the launch wake lock before giving up.
103 static final int LAUNCH_TIMEOUT = 10*1000;
104
Craig Mautner05d29032013-05-03 13:40:13 -0700105 static final int IDLE_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG;
106 static final int IDLE_NOW_MSG = FIRST_SUPERVISOR_STACK_MSG + 1;
107 static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2;
Craig Mautner0eea92c2013-05-16 13:35:39 -0700108 static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3;
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700109 static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 4;
110
111 // For debugging to make sure the caller when acquiring/releasing our
112 // wake lock is the system process.
113 static final boolean VALIDATE_WAKE_LOCK_CALLER = false;
Craig Mautnerf3333272013-04-22 10:55:53 -0700114
Craig Mautner27084302013-03-25 08:05:25 -0700115 final ActivityManagerService mService;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700116 final Context mContext;
117 final Looper mLooper;
Craig Mautner27084302013-03-25 08:05:25 -0700118
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700119 final ActivityStackSupervisorHandler mHandler;
120
121 /** Short cut */
122 WindowManagerService mWindowManager;
123
Craig Mautner27084302013-03-25 08:05:25 -0700124 /** Dismiss the keyguard after the next activity is displayed? */
125 private boolean mDismissKeyguardOnNextActivity = false;
126
Craig Mautner8d341ef2013-03-26 09:03:27 -0700127 /** Identifier counter for all ActivityStacks */
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700128 private int mLastStackId = HOME_STACK_ID;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700129
130 /** Task identifier that activities are currently being started in. Incremented each time a
131 * new task is created. */
132 private int mCurTaskId = 0;
133
Craig Mautner2420ead2013-04-01 17:13:20 -0700134 /** The current user */
135 private int mCurrentUser;
136
Craig Mautner8d341ef2013-03-26 09:03:27 -0700137 /** The stack containing the launcher app */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700138 private ActivityStack mHomeStack;
Craig Mautner20e72272013-04-01 13:45:53 -0700139
Craig Mautnerde4ef022013-04-07 19:01:33 -0700140 /** The non-home stack currently receiving input or launching the next activity. If home is
Craig Mautner41c0f352013-05-28 08:39:25 -0700141 * in front then mHomeStack overrides mFocusedStack.
142 * DO NOT ACCESS DIRECTLY - It may be null, use getFocusedStack() */
Craig Mautner29219d92013-04-16 20:19:12 -0700143 private ActivityStack mFocusedStack;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700144
145 /** All the non-launcher stacks */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700146 private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
147
Craig Mautnerde4ef022013-04-07 19:01:33 -0700148 private static final int STACK_STATE_HOME_IN_FRONT = 0;
149 private static final int STACK_STATE_HOME_TO_BACK = 1;
150 private static final int STACK_STATE_HOME_IN_BACK = 2;
151 private static final int STACK_STATE_HOME_TO_FRONT = 3;
152 private int mStackState = STACK_STATE_HOME_IN_FRONT;
153
154 /** List of activities that are waiting for a new activity to become visible before completing
155 * whatever operation they are supposed to do. */
156 final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();
157
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700158 /** List of processes waiting to find out about the next visible activity. */
159 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible =
160 new ArrayList<IActivityManager.WaitResult>();
161
162 /** List of processes waiting to find out about the next launched activity. */
163 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched =
164 new ArrayList<IActivityManager.WaitResult>();
165
Craig Mautnerde4ef022013-04-07 19:01:33 -0700166 /** List of activities that are ready to be stopped, but waiting for the next activity to
167 * settle down before doing so. */
168 final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();
169
Craig Mautnerf3333272013-04-22 10:55:53 -0700170 /** List of activities that are ready to be finished, but waiting for the previous activity to
171 * settle down before doing so. It contains ActivityRecord objects. */
172 final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<ActivityRecord>();
173
Craig Mautner0eea92c2013-05-16 13:35:39 -0700174 /** List of activities that are in the process of going to sleep. */
175 final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<ActivityRecord>();
176
Craig Mautnerf3333272013-04-22 10:55:53 -0700177 /** List of ActivityRecord objects that have been finished and must still report back to a
178 * pending thumbnail receiver. */
179 final ArrayList<ActivityRecord> mCancelledThumbnails = new ArrayList<ActivityRecord>();
180
181 /** Used on user changes */
182 final ArrayList<UserStartedState> mStartingUsers = new ArrayList<UserStartedState>();
183
Craig Mautnerde4ef022013-04-07 19:01:33 -0700184 /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity
185 * is being brought in front of us. */
186 boolean mUserLeaving = false;
187
Craig Mautner858d8a62013-04-23 17:08:34 -0700188 /** Stacks belonging to users other than mCurrentUser. Indexed by userId. */
189 final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
190
Craig Mautner0eea92c2013-05-16 13:35:39 -0700191 /** Set when we have taken too long waiting to go to sleep. */
192 boolean mSleepTimeout = false;
193
194 /**
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700195 * We don't want to allow the device to go to sleep while in the process
196 * of launching an activity. This is primarily to allow alarm intent
197 * receivers to launch an activity and get that to run before the device
198 * goes back to sleep.
199 */
200 final PowerManager.WakeLock mLaunchingActivity;
201
202 /**
Craig Mautner0eea92c2013-05-16 13:35:39 -0700203 * Set when the system is going to sleep, until we have
204 * successfully paused the current activity and released our wake lock.
205 * At that point the system is allowed to actually sleep.
206 */
207 final PowerManager.WakeLock mGoingToSleep;
208
Craig Mautner2219a1b2013-03-25 09:44:30 -0700209 public ActivityStackSupervisor(ActivityManagerService service, Context context,
210 Looper looper) {
Craig Mautner27084302013-03-25 08:05:25 -0700211 mService = service;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700212 mContext = context;
213 mLooper = looper;
Craig Mautner0eea92c2013-05-16 13:35:39 -0700214 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
215 mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700216 mHandler = new ActivityStackSupervisorHandler(looper);
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700217 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
218 throw new IllegalStateException("Calling must be system uid");
219 }
220 mLaunchingActivity =
221 pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
222 mLaunchingActivity.setReferenceCounted(false);
Craig Mautner2219a1b2013-03-25 09:44:30 -0700223 }
224
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700225 void setWindowManager(WindowManagerService wm) {
226 mWindowManager = wm;
227 mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700228 mStacks.add(mHomeStack);
Craig Mautner27084302013-03-25 08:05:25 -0700229 }
230
231 void dismissKeyguard() {
232 if (mDismissKeyguardOnNextActivity) {
233 mDismissKeyguardOnNextActivity = false;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700234 mWindowManager.dismissKeyguard();
Craig Mautner27084302013-03-25 08:05:25 -0700235 }
236 }
237
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700238 ActivityStack getFocusedStack() {
Craig Mautnerf88c50f2013-04-18 19:25:12 -0700239 if (mFocusedStack == null) {
240 return mHomeStack;
241 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700242 switch (mStackState) {
243 case STACK_STATE_HOME_IN_FRONT:
244 case STACK_STATE_HOME_TO_FRONT:
245 return mHomeStack;
246 case STACK_STATE_HOME_IN_BACK:
247 case STACK_STATE_HOME_TO_BACK:
248 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700249 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700250 }
Craig Mautner20e72272013-04-01 13:45:53 -0700251 }
252
Craig Mautnerde4ef022013-04-07 19:01:33 -0700253 ActivityStack getLastStack() {
254 switch (mStackState) {
255 case STACK_STATE_HOME_IN_FRONT:
256 case STACK_STATE_HOME_TO_BACK:
257 return mHomeStack;
258 case STACK_STATE_HOME_TO_FRONT:
259 case STACK_STATE_HOME_IN_BACK:
260 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700261 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700262 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700263 }
264
Craig Mautnerde4ef022013-04-07 19:01:33 -0700265 boolean isFrontStack(ActivityStack stack) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700266 return (stack.mCurrentUser == mCurrentUser) &&
267 !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
Craig Mautner20e72272013-04-01 13:45:53 -0700268 }
269
Craig Mautnerde4ef022013-04-07 19:01:33 -0700270 void moveHomeStack(boolean toFront) {
271 final boolean homeInFront = isFrontStack(mHomeStack);
272 if (homeInFront ^ toFront) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700273 if (DEBUG_STACK) Slog.d(TAG, "moveHomeTask: mStackState old=" +
274 stackStateToString(mStackState) + " new=" + stackStateToString(homeInFront ?
275 STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700276 mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
277 }
278 }
279
Craig Mautner69ada552013-04-18 13:51:51 -0700280 boolean resumeHomeActivity(ActivityRecord prev) {
281 moveHomeStack(true);
282 if (prev != null) {
283 prev.mLaunchHomeTaskNext = false;
284 }
Craig Mautnera8a90e02013-06-28 15:24:50 -0700285 ActivityRecord r = mHomeStack.topRunningActivityLocked(null);
286 if (r != null) {
287 mService.setFocusedActivityLocked(r);
Craig Mautner05d29032013-05-03 13:40:13 -0700288 return resumeTopActivitiesLocked(mHomeStack, prev, null);
Craig Mautner69ada552013-04-18 13:51:51 -0700289 }
290 return mService.startHomeActivityLocked(mCurrentUser);
291 }
292
Craig Mautnerde4ef022013-04-07 19:01:33 -0700293 final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r,
294 ActivityStack stack) {
295 if (stack == mHomeStack) {
296 return;
297 }
298 if ((sourceRecord == null && getLastStack() == mHomeStack) ||
Craig Mautner86d67a42013-05-14 10:34:38 -0700299 (sourceRecord != null && sourceRecord.isHomeActivity())) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700300 if (r == null) {
301 r = stack.topRunningActivityLocked(null);
302 }
Craig Mautner86d67a42013-05-14 10:34:38 -0700303 if (r != null && !r.isHomeActivity() && r.isRootActivity()) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700304 r.mLaunchHomeTaskNext = true;
305 }
306 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700307 }
308
Craig Mautner27084302013-03-25 08:05:25 -0700309 void setDismissKeyguard(boolean dismiss) {
310 mDismissKeyguardOnNextActivity = dismiss;
311 }
312
Craig Mautner8d341ef2013-03-26 09:03:27 -0700313 TaskRecord anyTaskForIdLocked(int id) {
314 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
315 ActivityStack stack = mStacks.get(stackNdx);
316 TaskRecord task = stack.taskForIdLocked(id);
317 if (task != null) {
318 return task;
319 }
320 }
321 return null;
322 }
323
Craig Mautner6170f732013-04-02 13:05:23 -0700324 ActivityRecord isInAnyStackLocked(IBinder token) {
325 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
326 final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
327 if (r != null) {
328 return r;
329 }
330 }
331 return null;
332 }
333
Craig Mautner8d341ef2013-03-26 09:03:27 -0700334 int getNextTaskId() {
335 do {
336 mCurTaskId++;
337 if (mCurTaskId <= 0) {
338 mCurTaskId = 1;
339 }
340 } while (anyTaskForIdLocked(mCurTaskId) != null);
341 return mCurTaskId;
342 }
343
Craig Mautnerde4ef022013-04-07 19:01:33 -0700344 void removeTask(TaskRecord task) {
Craig Mautnerb3b36ba2013-05-20 13:21:10 -0700345 mWindowManager.removeTask(task.taskId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700346 final ActivityStack stack = task.stack;
Craig Mautnerb3b36ba2013-05-20 13:21:10 -0700347 final ActivityRecord r = stack.mResumedActivity;
348 if (r != null && r.task == task) {
349 stack.mResumedActivity = null;
350 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700351 if (stack.removeTask(task) && !stack.isHomeStack()) {
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700352 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700353 mStacks.remove(stack);
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700354 final int stackId = stack.mStackId;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700355 final int nextStackId = mWindowManager.removeStack(stackId);
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700356 // TODO: Perhaps we need to let the ActivityManager determine the next focus...
Craig Mautner41c0f352013-05-28 08:39:25 -0700357 if (getFocusedStack().mStackId == stackId) {
Craig Mautner1602ec22013-05-12 10:24:27 -0700358 // If this is the last app stack, set mFocusedStack to null.
Craig Mautner29219d92013-04-16 20:19:12 -0700359 mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700360 }
361 }
362 }
363
364 ActivityRecord resumedAppLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700365 ActivityStack stack = getFocusedStack();
366 if (stack == null) {
367 return null;
368 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700369 ActivityRecord resumedActivity = stack.mResumedActivity;
370 if (resumedActivity == null || resumedActivity.app == null) {
371 resumedActivity = stack.mPausingActivity;
372 if (resumedActivity == null || resumedActivity.app == null) {
373 resumedActivity = stack.topRunningActivityLocked(null);
374 }
375 }
376 return resumedActivity;
377 }
378
Craig Mautner20e72272013-04-01 13:45:53 -0700379 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
380 boolean didSomething = false;
381 final String processName = app.processName;
382 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
383 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner858d8a62013-04-23 17:08:34 -0700384 if (!isFrontStack(stack)) {
385 continue;
386 }
Craig Mautner20e72272013-04-01 13:45:53 -0700387 ActivityRecord hr = stack.topRunningActivityLocked(null);
388 if (hr != null) {
389 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
390 && processName.equals(hr.processName)) {
391 try {
392 if (headless) {
393 Slog.e(TAG, "Starting activities not supported on headless device: "
394 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700395 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700396 didSomething = true;
397 }
398 } catch (Exception e) {
399 Slog.w(TAG, "Exception in new application when starting activity "
400 + hr.intent.getComponent().flattenToShortString(), e);
401 throw e;
402 }
Craig Mautner20e72272013-04-01 13:45:53 -0700403 }
404 }
405 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -0700406 if (!didSomething) {
407 ensureActivitiesVisibleLocked(null, 0);
408 }
Craig Mautner20e72272013-04-01 13:45:53 -0700409 return didSomething;
410 }
411
412 boolean allResumedActivitiesIdle() {
413 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700414 final ActivityStack stack = mStacks.get(stackNdx);
415 if (!isFrontStack(stack)) {
416 continue;
417 }
418 final ActivityRecord resumedActivity = stack.mResumedActivity;
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700419 if (resumedActivity == null || !resumedActivity.idle) {
Craig Mautner20e72272013-04-01 13:45:53 -0700420 return false;
421 }
422 }
423 return true;
424 }
425
Craig Mautnerde4ef022013-04-07 19:01:33 -0700426 boolean allResumedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700427 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
428 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner967212c2013-04-13 21:10:58 -0700429 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700430 final ActivityRecord r = stack.mResumedActivity;
431 if (r != null && r.state != ActivityState.RESUMED) {
432 return false;
433 }
434 }
435 }
436 // TODO: Not sure if this should check if all Paused are complete too.
437 switch (mStackState) {
438 case STACK_STATE_HOME_TO_BACK:
Craig Mautner76ea2242013-05-15 11:40:05 -0700439 if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
440 stackStateToString(STACK_STATE_HOME_TO_BACK) + " new=" +
441 stackStateToString(STACK_STATE_HOME_IN_BACK));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700442 mStackState = STACK_STATE_HOME_IN_BACK;
443 break;
444 case STACK_STATE_HOME_TO_FRONT:
Craig Mautner76ea2242013-05-15 11:40:05 -0700445 if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
446 stackStateToString(STACK_STATE_HOME_TO_FRONT) + " new=" +
447 stackStateToString(STACK_STATE_HOME_IN_FRONT));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700448 mStackState = STACK_STATE_HOME_IN_FRONT;
449 break;
450 }
451 return true;
452 }
453
454 boolean allResumedActivitiesVisible() {
455 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
456 final ActivityStack stack = mStacks.get(stackNdx);
457 final ActivityRecord r = stack.mResumedActivity;
458 if (r != null && (!r.nowVisible || r.waitingVisible)) {
459 return false;
460 }
461 }
462 return true;
463 }
464
Craig Mautnercf910b02013-04-23 11:23:27 -0700465 boolean pauseBackStacks(boolean userLeaving) {
466 boolean someActivityPaused = false;
467 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
468 final ActivityStack stack = mStacks.get(stackNdx);
469 if (!isFrontStack(stack) && stack.mResumedActivity != null) {
470 stack.startPausingLocked(userLeaving, false);
471 someActivityPaused = true;
472 }
473 }
474 return someActivityPaused;
475 }
476
Craig Mautnerde4ef022013-04-07 19:01:33 -0700477 boolean allPausedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700478 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
479 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner69ada552013-04-18 13:51:51 -0700480 final ActivityRecord r = stack.mPausingActivity;
481 if (r != null && r.state != ActivityState.PAUSED
482 && r.state != ActivityState.STOPPED
483 && r.state != ActivityState.STOPPING) {
484 return false;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700485 }
486 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700487 return true;
488 }
489
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700490 void reportActivityVisibleLocked(ActivityRecord r) {
Craig Mautner858d8a62013-04-23 17:08:34 -0700491 for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700492 WaitResult w = mWaitingActivityVisible.get(i);
493 w.timeout = false;
494 if (r != null) {
495 w.who = new ComponentName(r.info.packageName, r.info.name);
496 }
497 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
498 w.thisTime = w.totalTime;
499 }
500 mService.notifyAll();
501 dismissKeyguard();
502 }
503
504 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
505 long thisTime, long totalTime) {
506 for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
Craig Mautnerc64f73e2013-04-24 16:44:56 -0700507 WaitResult w = mWaitingActivityLaunched.remove(i);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700508 w.timeout = timeout;
509 if (r != null) {
510 w.who = new ComponentName(r.info.packageName, r.info.name);
511 }
512 w.thisTime = thisTime;
513 w.totalTime = totalTime;
514 }
515 mService.notifyAll();
516 }
517
Craig Mautner29219d92013-04-16 20:19:12 -0700518 ActivityRecord topRunningActivityLocked() {
Craig Mautner1602ec22013-05-12 10:24:27 -0700519 final ActivityStack focusedStack = getFocusedStack();
520 ActivityRecord r = focusedStack.topRunningActivityLocked(null);
521 if (r != null) {
522 return r;
Craig Mautner29219d92013-04-16 20:19:12 -0700523 }
Craig Mautner1602ec22013-05-12 10:24:27 -0700524
Craig Mautner29219d92013-04-16 20:19:12 -0700525 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
526 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner1602ec22013-05-12 10:24:27 -0700527 if (stack.mCurrentUser == mCurrentUser && stack != focusedStack &&
528 isFrontStack(stack)) {
Craig Mautner29219d92013-04-16 20:19:12 -0700529 r = stack.topRunningActivityLocked(null);
530 if (r != null) {
531 return r;
532 }
533 }
534 }
535 return null;
536 }
537
Craig Mautner20e72272013-04-01 13:45:53 -0700538 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
539 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
540 ActivityRecord r = null;
Craig Mautner20e72272013-04-01 13:45:53 -0700541 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
542 final ActivityStack stack = mStacks.get(stackNdx);
543 final ActivityRecord ar =
544 stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700545 if (isFrontStack(stack)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700546 r = ar;
547 }
548 }
549 return r;
550 }
551
Craig Mautner23ac33b2013-04-01 16:26:35 -0700552 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
553 String profileFile, ParcelFileDescriptor profileFd, int userId) {
554 // Collect information about the target of the Intent.
555 ActivityInfo aInfo;
556 try {
557 ResolveInfo rInfo =
558 AppGlobals.getPackageManager().resolveIntent(
559 intent, resolvedType,
560 PackageManager.MATCH_DEFAULT_ONLY
561 | ActivityManagerService.STOCK_PM_FLAGS, userId);
562 aInfo = rInfo != null ? rInfo.activityInfo : null;
563 } catch (RemoteException e) {
564 aInfo = null;
565 }
566
567 if (aInfo != null) {
568 // Store the found target back into the intent, because now that
569 // we have it we never want to do this again. For example, if the
570 // user navigates back to this point in the history, we should
571 // always restart the exact same activity.
572 intent.setComponent(new ComponentName(
573 aInfo.applicationInfo.packageName, aInfo.name));
574
575 // Don't debug things in the system process
576 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
577 if (!aInfo.processName.equals("system")) {
578 mService.setDebugApp(aInfo.processName, true, false);
579 }
580 }
581
582 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
583 if (!aInfo.processName.equals("system")) {
584 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
585 }
586 }
587
588 if (profileFile != null) {
589 if (!aInfo.processName.equals("system")) {
590 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
591 profileFile, profileFd,
592 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
593 }
594 }
595 }
596 return aInfo;
597 }
598
Craig Mautner2219a1b2013-03-25 09:44:30 -0700599 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700600 moveHomeStack(true);
Craig Mautner6170f732013-04-02 13:05:23 -0700601 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
Craig Mautner2219a1b2013-03-25 09:44:30 -0700602 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700603 }
604
Craig Mautner23ac33b2013-04-01 16:26:35 -0700605 final int startActivityMayWait(IApplicationThread caller, int callingUid,
606 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
607 String resultWho, int requestCode, int startFlags, String profileFile,
608 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
609 Bundle options, int userId) {
610 // Refuse possible leaked file descriptors
611 if (intent != null && intent.hasFileDescriptors()) {
612 throw new IllegalArgumentException("File descriptors passed in Intent");
613 }
614 boolean componentSpecified = intent.getComponent() != null;
615
616 // Don't modify the client's object!
617 intent = new Intent(intent);
618
619 // Collect information about the target of the Intent.
620 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
621 profileFile, profileFd, userId);
622
623 synchronized (mService) {
624 int callingPid;
625 if (callingUid >= 0) {
626 callingPid = -1;
627 } else if (caller == null) {
628 callingPid = Binder.getCallingPid();
629 callingUid = Binder.getCallingUid();
630 } else {
631 callingPid = callingUid = -1;
632 }
633
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700634 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -0700635 stack.mConfigWillChange = config != null
Craig Mautner23ac33b2013-04-01 16:26:35 -0700636 && mService.mConfiguration.diff(config) != 0;
637 if (DEBUG_CONFIGURATION) Slog.v(TAG,
Craig Mautnerde4ef022013-04-07 19:01:33 -0700638 "Starting activity when config will change = " + stack.mConfigWillChange);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700639
640 final long origId = Binder.clearCallingIdentity();
641
642 if (aInfo != null &&
643 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
644 // This may be a heavy-weight process! Check to see if we already
645 // have another, different heavy-weight process running.
646 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
647 if (mService.mHeavyWeightProcess != null &&
648 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
649 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700650 int realCallingUid = callingUid;
651 if (caller != null) {
652 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
653 if (callerApp != null) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700654 realCallingUid = callerApp.info.uid;
655 } else {
656 Slog.w(TAG, "Unable to find app for caller " + caller
Craig Mautner76ea2242013-05-15 11:40:05 -0700657 + " (pid=" + callingPid + ") when starting: "
Craig Mautner23ac33b2013-04-01 16:26:35 -0700658 + intent.toString());
659 ActivityOptions.abort(options);
660 return ActivityManager.START_PERMISSION_DENIED;
661 }
662 }
663
664 IIntentSender target = mService.getIntentSenderLocked(
665 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
666 realCallingUid, userId, null, null, 0, new Intent[] { intent },
667 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
668 | PendingIntent.FLAG_ONE_SHOT, null);
669
670 Intent newIntent = new Intent();
671 if (requestCode >= 0) {
672 // Caller is requesting a result.
673 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
674 }
675 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
676 new IntentSender(target));
677 if (mService.mHeavyWeightProcess.activities.size() > 0) {
678 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
679 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
680 hist.packageName);
681 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
682 hist.task.taskId);
683 }
684 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
685 aInfo.packageName);
686 newIntent.setFlags(intent.getFlags());
687 newIntent.setClassName("android",
688 HeavyWeightSwitcherActivity.class.getName());
689 intent = newIntent;
690 resolvedType = null;
691 caller = null;
692 callingUid = Binder.getCallingUid();
693 callingPid = Binder.getCallingPid();
694 componentSpecified = true;
695 try {
696 ResolveInfo rInfo =
697 AppGlobals.getPackageManager().resolveIntent(
698 intent, null,
699 PackageManager.MATCH_DEFAULT_ONLY
700 | ActivityManagerService.STOCK_PM_FLAGS, userId);
701 aInfo = rInfo != null ? rInfo.activityInfo : null;
702 aInfo = mService.getActivityInfoForUser(aInfo, userId);
703 } catch (RemoteException e) {
704 aInfo = null;
705 }
706 }
707 }
708 }
709
Craig Mautner6170f732013-04-02 13:05:23 -0700710 int res = startActivityLocked(caller, intent, resolvedType,
Craig Mautner23ac33b2013-04-01 16:26:35 -0700711 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
712 callingPackage, startFlags, options, componentSpecified, null);
713
Craig Mautnerde4ef022013-04-07 19:01:33 -0700714 if (stack.mConfigWillChange) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700715 // If the caller also wants to switch to a new configuration,
716 // do so now. This allows a clean switch, as we are waiting
717 // for the current activity to pause (so we will not destroy
718 // it), and have not yet started the next activity.
719 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
720 "updateConfiguration()");
Craig Mautnerde4ef022013-04-07 19:01:33 -0700721 stack.mConfigWillChange = false;
Craig Mautner23ac33b2013-04-01 16:26:35 -0700722 if (DEBUG_CONFIGURATION) Slog.v(TAG,
723 "Updating to new configuration after starting activity.");
724 mService.updateConfigurationLocked(config, null, false, false);
725 }
726
727 Binder.restoreCallingIdentity(origId);
728
729 if (outResult != null) {
730 outResult.result = res;
731 if (res == ActivityManager.START_SUCCESS) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700732 mWaitingActivityLaunched.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700733 do {
734 try {
735 mService.wait();
736 } catch (InterruptedException e) {
737 }
738 } while (!outResult.timeout && outResult.who == null);
739 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700740 ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700741 if (r.nowVisible) {
742 outResult.timeout = false;
743 outResult.who = new ComponentName(r.info.packageName, r.info.name);
744 outResult.totalTime = 0;
745 outResult.thisTime = 0;
746 } else {
747 outResult.thisTime = SystemClock.uptimeMillis();
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700748 mWaitingActivityVisible.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700749 do {
750 try {
751 mService.wait();
752 } catch (InterruptedException e) {
753 }
754 } while (!outResult.timeout && outResult.who == null);
755 }
756 }
757 }
758
759 return res;
760 }
761 }
762
763 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
764 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
765 Bundle options, int userId) {
766 if (intents == null) {
767 throw new NullPointerException("intents is null");
768 }
769 if (resolvedTypes == null) {
770 throw new NullPointerException("resolvedTypes is null");
771 }
772 if (intents.length != resolvedTypes.length) {
773 throw new IllegalArgumentException("intents are length different than resolvedTypes");
774 }
775
Craig Mautner23ac33b2013-04-01 16:26:35 -0700776
777 int callingPid;
778 if (callingUid >= 0) {
779 callingPid = -1;
780 } else if (caller == null) {
781 callingPid = Binder.getCallingPid();
782 callingUid = Binder.getCallingUid();
783 } else {
784 callingPid = callingUid = -1;
785 }
786 final long origId = Binder.clearCallingIdentity();
787 try {
788 synchronized (mService) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700789 ActivityRecord[] outActivity = new ActivityRecord[1];
Craig Mautner23ac33b2013-04-01 16:26:35 -0700790 for (int i=0; i<intents.length; i++) {
791 Intent intent = intents[i];
792 if (intent == null) {
793 continue;
794 }
795
796 // Refuse possible leaked file descriptors
797 if (intent != null && intent.hasFileDescriptors()) {
798 throw new IllegalArgumentException("File descriptors passed in Intent");
799 }
800
801 boolean componentSpecified = intent.getComponent() != null;
802
803 // Don't modify the client's object!
804 intent = new Intent(intent);
805
806 // Collect information about the target of the Intent.
807 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
808 0, null, null, userId);
809 // TODO: New, check if this is correct
810 aInfo = mService.getActivityInfoForUser(aInfo, userId);
811
812 if (aInfo != null &&
813 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
814 != 0) {
815 throw new IllegalArgumentException(
816 "FLAG_CANT_SAVE_STATE not supported here");
817 }
818
819 Bundle theseOptions;
820 if (options != null && i == intents.length-1) {
821 theseOptions = options;
822 } else {
823 theseOptions = null;
824 }
Craig Mautner6170f732013-04-02 13:05:23 -0700825 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Craig Mautner23ac33b2013-04-01 16:26:35 -0700826 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
827 0, theseOptions, componentSpecified, outActivity);
828 if (res < 0) {
829 return res;
830 }
831
832 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
833 }
834 }
835 } finally {
836 Binder.restoreCallingIdentity(origId);
837 }
838
839 return ActivityManager.START_SUCCESS;
840 }
841
Craig Mautner2420ead2013-04-01 17:13:20 -0700842 final boolean realStartActivityLocked(ActivityRecord r,
843 ProcessRecord app, boolean andResume, boolean checkConfig)
844 throws RemoteException {
845
846 r.startFreezingScreenLocked(app, 0);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700847 mWindowManager.setAppVisibility(r.appToken, true);
Craig Mautner2420ead2013-04-01 17:13:20 -0700848
849 // schedule launch ticks to collect information about slow apps.
850 r.startLaunchTickingLocked();
851
852 // Have the window manager re-evaluate the orientation of
853 // the screen based on the new activity order. Note that
854 // as a result of this, it can call back into the activity
855 // manager with a new orientation. We don't care about that,
856 // because the activity is not currently running so we are
857 // just restarting it anyway.
858 if (checkConfig) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700859 Configuration config = mWindowManager.updateOrientationFromAppTokens(
Craig Mautner2420ead2013-04-01 17:13:20 -0700860 mService.mConfiguration,
861 r.mayFreezeScreenLocked(app) ? r.appToken : null);
862 mService.updateConfigurationLocked(config, r, false, false);
863 }
864
865 r.app = app;
866 app.waitingToKill = null;
867 r.launchCount++;
868 r.lastLaunchTime = SystemClock.uptimeMillis();
869
870 if (localLOGV) Slog.v(TAG, "Launching: " + r);
871
872 int idx = app.activities.indexOf(r);
873 if (idx < 0) {
874 app.activities.add(r);
875 }
876 mService.updateLruProcessLocked(app, true);
877
878 final ActivityStack stack = r.task.stack;
879 try {
880 if (app.thread == null) {
881 throw new RemoteException();
882 }
883 List<ResultInfo> results = null;
884 List<Intent> newIntents = null;
885 if (andResume) {
886 results = r.results;
887 newIntents = r.newIntents;
888 }
889 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
890 + " icicle=" + r.icicle
891 + " with results=" + results + " newIntents=" + newIntents
892 + " andResume=" + andResume);
893 if (andResume) {
894 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
895 r.userId, System.identityHashCode(r),
896 r.task.taskId, r.shortComponentName);
897 }
Craig Mautner86d67a42013-05-14 10:34:38 -0700898 if (r.isHomeActivity()) {
Craig Mautner2420ead2013-04-01 17:13:20 -0700899 mService.mHomeProcess = app;
900 }
901 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
902 r.sleeping = false;
903 r.forceNewConfig = false;
904 mService.showAskCompatModeDialogLocked(r);
905 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
906 String profileFile = null;
907 ParcelFileDescriptor profileFd = null;
908 boolean profileAutoStop = false;
909 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
910 if (mService.mProfileProc == null || mService.mProfileProc == app) {
911 mService.mProfileProc = app;
912 profileFile = mService.mProfileFile;
913 profileFd = mService.mProfileFd;
914 profileAutoStop = mService.mAutoStopProfiler;
915 }
916 }
917 app.hasShownUi = true;
918 app.pendingUiClean = true;
919 if (profileFd != null) {
920 try {
921 profileFd = profileFd.dup();
922 } catch (IOException e) {
923 if (profileFd != null) {
924 try {
925 profileFd.close();
926 } catch (IOException o) {
927 }
928 profileFd = null;
929 }
930 }
931 }
Dianne Hackborna413dc02013-07-12 12:02:55 -0700932 app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
Craig Mautner2420ead2013-04-01 17:13:20 -0700933 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
934 System.identityHashCode(r), r.info,
Dianne Hackborna413dc02013-07-12 12:02:55 -0700935 new Configuration(mService.mConfiguration), r.compat,
936 app.repProcState, r.icicle, results, newIntents, !andResume,
Craig Mautner2420ead2013-04-01 17:13:20 -0700937 mService.isNextTransitionForward(), profileFile, profileFd,
938 profileAutoStop);
939
940 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
941 // This may be a heavy-weight process! Note that the package
942 // manager will ensure that only activity can run in the main
943 // process of the .apk, which is the only thing that will be
944 // considered heavy-weight.
945 if (app.processName.equals(app.info.packageName)) {
946 if (mService.mHeavyWeightProcess != null
947 && mService.mHeavyWeightProcess != app) {
948 Slog.w(TAG, "Starting new heavy weight process " + app
949 + " when already running "
950 + mService.mHeavyWeightProcess);
951 }
952 mService.mHeavyWeightProcess = app;
953 Message msg = mService.mHandler.obtainMessage(
954 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
955 msg.obj = r;
956 mService.mHandler.sendMessage(msg);
957 }
958 }
959
960 } catch (RemoteException e) {
961 if (r.launchFailed) {
962 // This is the second time we failed -- finish activity
963 // and give up.
964 Slog.e(TAG, "Second failure launching "
965 + r.intent.getComponent().flattenToShortString()
966 + ", giving up", e);
967 mService.appDiedLocked(app, app.pid, app.thread);
968 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
969 "2nd-crash", false);
970 return false;
971 }
972
973 // This is the first time we failed -- restart process and
974 // retry.
975 app.activities.remove(r);
976 throw e;
977 }
978
979 r.launchFailed = false;
980 if (stack.updateLRUListLocked(r)) {
981 Slog.w(TAG, "Activity " + r
982 + " being launched, but already in LRU list");
983 }
984
985 if (andResume) {
986 // As part of the process of launching, ActivityThread also performs
987 // a resume.
988 stack.minimalResumeActivityLocked(r);
989 } else {
990 // This activity is not starting in the resumed state... which
991 // should look like we asked it to pause+stop (but remain visible),
992 // and it has done so and reported back the current icicle and
993 // other state.
994 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
995 + " (starting in stopped state)");
996 r.state = ActivityState.STOPPED;
997 r.stopped = true;
998 }
999
1000 // Launch the new version setup screen if needed. We do this -after-
1001 // launching the initial activity (that is, home), so that it can have
1002 // a chance to initialize itself while in the background, making the
1003 // switch back to it faster and look better.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001004 if (isFrontStack(stack)) {
Craig Mautner2420ead2013-04-01 17:13:20 -07001005 mService.startSetupActivityLocked();
1006 }
1007
1008 return true;
1009 }
1010
Craig Mautnere79d42682013-04-01 19:01:53 -07001011 void startSpecificActivityLocked(ActivityRecord r,
1012 boolean andResume, boolean checkConfig) {
1013 // Is this activity's application already running?
1014 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
1015 r.info.applicationInfo.uid);
1016
1017 r.task.stack.setLaunchTime(r);
1018
1019 if (app != null && app.thread != null) {
1020 try {
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001021 app.addPackage(r.info.packageName, mService.mProcessTracker);
Craig Mautnere79d42682013-04-01 19:01:53 -07001022 realStartActivityLocked(r, app, andResume, checkConfig);
1023 return;
1024 } catch (RemoteException e) {
1025 Slog.w(TAG, "Exception when starting activity "
1026 + r.intent.getComponent().flattenToShortString(), e);
1027 }
1028
1029 // If a dead object exception was thrown -- fall through to
1030 // restart the application.
1031 }
1032
1033 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
1034 "activity", r.intent.getComponent(), false, false);
1035 }
1036
Craig Mautner6170f732013-04-02 13:05:23 -07001037 final int startActivityLocked(IApplicationThread caller,
1038 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
1039 String resultWho, int requestCode,
1040 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
1041 boolean componentSpecified, ActivityRecord[] outActivity) {
1042 int err = ActivityManager.START_SUCCESS;
1043
1044 ProcessRecord callerApp = null;
1045 if (caller != null) {
1046 callerApp = mService.getRecordForAppLocked(caller);
1047 if (callerApp != null) {
1048 callingPid = callerApp.pid;
1049 callingUid = callerApp.info.uid;
1050 } else {
1051 Slog.w(TAG, "Unable to find app for caller " + caller
1052 + " (pid=" + callingPid + ") when starting: "
1053 + intent.toString());
1054 err = ActivityManager.START_PERMISSION_DENIED;
1055 }
1056 }
1057
1058 if (err == ActivityManager.START_SUCCESS) {
1059 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
1060 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
1061 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
1062 }
1063
1064 ActivityRecord sourceRecord = null;
1065 ActivityRecord resultRecord = null;
1066 if (resultTo != null) {
1067 sourceRecord = isInAnyStackLocked(resultTo);
1068 if (DEBUG_RESULTS) Slog.v(
1069 TAG, "Will send result to " + resultTo + " " + sourceRecord);
1070 if (sourceRecord != null) {
1071 if (requestCode >= 0 && !sourceRecord.finishing) {
1072 resultRecord = sourceRecord;
1073 }
1074 }
1075 }
1076 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
1077
1078 int launchFlags = intent.getFlags();
1079
1080 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
1081 && sourceRecord != null) {
1082 // Transfer the result target from the source activity to the new
1083 // one being started, including any failures.
1084 if (requestCode >= 0) {
1085 ActivityOptions.abort(options);
1086 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
1087 }
1088 resultRecord = sourceRecord.resultTo;
1089 resultWho = sourceRecord.resultWho;
1090 requestCode = sourceRecord.requestCode;
1091 sourceRecord.resultTo = null;
1092 if (resultRecord != null) {
1093 resultRecord.removeResultsLocked(
1094 sourceRecord, resultWho, requestCode);
1095 }
1096 }
1097
1098 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
1099 // We couldn't find a class that can handle the given Intent.
1100 // That's the end of that!
1101 err = ActivityManager.START_INTENT_NOT_RESOLVED;
1102 }
1103
1104 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
1105 // We couldn't find the specific class specified in the Intent.
1106 // Also the end of the line.
1107 err = ActivityManager.START_CLASS_NOT_FOUND;
1108 }
1109
1110 if (err != ActivityManager.START_SUCCESS) {
1111 if (resultRecord != null) {
1112 resultStack.sendActivityResultLocked(-1,
1113 resultRecord, resultWho, requestCode,
1114 Activity.RESULT_CANCELED, null);
1115 }
1116 setDismissKeyguard(false);
1117 ActivityOptions.abort(options);
1118 return err;
1119 }
1120
1121 final int startAnyPerm = mService.checkPermission(
1122 START_ANY_ACTIVITY, callingPid, callingUid);
1123 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
1124 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
1125 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
1126 if (resultRecord != null) {
1127 resultStack.sendActivityResultLocked(-1,
1128 resultRecord, resultWho, requestCode,
1129 Activity.RESULT_CANCELED, null);
1130 }
1131 setDismissKeyguard(false);
1132 String msg;
1133 if (!aInfo.exported) {
1134 msg = "Permission Denial: starting " + intent.toString()
1135 + " from " + callerApp + " (pid=" + callingPid
1136 + ", uid=" + callingUid + ")"
1137 + " not exported from uid " + aInfo.applicationInfo.uid;
1138 } else {
1139 msg = "Permission Denial: starting " + intent.toString()
1140 + " from " + callerApp + " (pid=" + callingPid
1141 + ", uid=" + callingUid + ")"
1142 + " requires " + aInfo.permission;
1143 }
1144 Slog.w(TAG, msg);
1145 throw new SecurityException(msg);
1146 }
1147
Ben Gruver6617c3c2013-04-03 18:45:22 -07001148 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
Ben Gruver7b879f42013-04-08 14:56:55 -07001149 callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo);
Ben Gruver5e207332013-04-03 17:41:37 -07001150
Craig Mautner6170f732013-04-02 13:05:23 -07001151 if (mService.mController != null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001152 try {
1153 // The Intent we give to the watcher has the extra data
1154 // stripped off, since it can contain private information.
1155 Intent watchIntent = intent.cloneFilter();
Ben Gruver5e207332013-04-03 17:41:37 -07001156 abort |= !mService.mController.activityStarting(watchIntent,
Craig Mautner6170f732013-04-02 13:05:23 -07001157 aInfo.applicationInfo.packageName);
1158 } catch (RemoteException e) {
1159 mService.mController = null;
1160 }
Ben Gruver5e207332013-04-03 17:41:37 -07001161 }
Craig Mautner6170f732013-04-02 13:05:23 -07001162
Ben Gruver5e207332013-04-03 17:41:37 -07001163 if (abort) {
1164 if (resultRecord != null) {
1165 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Craig Mautner6170f732013-04-02 13:05:23 -07001166 Activity.RESULT_CANCELED, null);
Craig Mautner6170f732013-04-02 13:05:23 -07001167 }
Ben Gruver5e207332013-04-03 17:41:37 -07001168 // We pretend to the caller that it was really started, but
1169 // they will just get a cancel result.
1170 setDismissKeyguard(false);
1171 ActivityOptions.abort(options);
1172 return ActivityManager.START_SUCCESS;
Craig Mautner6170f732013-04-02 13:05:23 -07001173 }
1174
1175 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1176 intent, resolvedType, aInfo, mService.mConfiguration,
Craig Mautnerde4ef022013-04-07 19:01:33 -07001177 resultRecord, resultWho, requestCode, componentSpecified, this);
Craig Mautner6170f732013-04-02 13:05:23 -07001178 if (outActivity != null) {
1179 outActivity[0] = r;
1180 }
1181
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001182 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001183 if (stack.mResumedActivity == null
1184 || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
Craig Mautner6170f732013-04-02 13:05:23 -07001185 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1186 PendingActivityLaunch pal =
Craig Mautnerde4ef022013-04-07 19:01:33 -07001187 new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
Craig Mautner6170f732013-04-02 13:05:23 -07001188 mService.mPendingActivityLaunches.add(pal);
1189 setDismissKeyguard(false);
1190 ActivityOptions.abort(options);
1191 return ActivityManager.START_SWITCHES_CANCELED;
1192 }
1193 }
1194
1195 if (mService.mDidAppSwitch) {
1196 // This is the second allowed switch since we stopped switches,
1197 // so now just generally allow switches. Use case: user presses
1198 // home (switches disabled, switch to home, mDidAppSwitch now true);
1199 // user taps a home icon (coming from home so allowed, we hit here
1200 // and now allow anyone to switch again).
1201 mService.mAppSwitchesAllowedTime = 0;
1202 } else {
1203 mService.mDidAppSwitch = true;
1204 }
1205
1206 mService.doPendingActivityLaunchesLocked(false);
1207
Craig Mautner8849a5e2013-04-02 16:41:03 -07001208 err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001209 if (stack.mPausingActivity == null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001210 // Someone asked to have the keyguard dismissed on the next
1211 // activity start, but we are not actually doing an activity
1212 // switch... just dismiss the keyguard now, because we
1213 // probably want to see whatever is behind it.
1214 dismissKeyguard();
1215 }
1216 return err;
1217 }
1218
Craig Mautnerde4ef022013-04-07 19:01:33 -07001219 ActivityStack getCorrectStack(ActivityRecord r) {
Craig Mautner1d001b62013-06-18 16:52:43 -07001220 final TaskRecord task = r.task;
1221 if (r.isApplicationActivity() || (task != null && task.isApplicationTask())) {
Craig Mautner858d8a62013-04-23 17:08:34 -07001222 int stackNdx;
1223 for (stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
1224 if (mStacks.get(stackNdx).mCurrentUser == mCurrentUser) {
1225 break;
1226 }
1227 }
1228 if (stackNdx == 0) {
1229 // Time to create the first app stack for this user.
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001230 int stackId = mService.createStack(-1, HOME_STACK_ID,
1231 StackBox.TASK_STACK_GOES_OVER, 1.0f);
Craig Mautnere7c58b62013-06-12 20:19:00 -07001232 if (DEBUG_FOCUS) Slog.d(TAG, "getCorrectStack: New stack r=" + r + " stackId="
1233 + stackId);
Craig Mautner29219d92013-04-16 20:19:12 -07001234 mFocusedStack = getStack(stackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001235 }
Craig Mautner1d001b62013-06-18 16:52:43 -07001236 if (task != null) {
Craig Mautnere7c58b62013-06-12 20:19:00 -07001237 if (DEBUG_FOCUS) Slog.d(TAG, "getCorrectStack: Setting focused stack to r=" +
1238 r + " task=" + task);
Craig Mautner1d001b62013-06-18 16:52:43 -07001239 mFocusedStack = task.stack;
1240 }
Craig Mautner29219d92013-04-16 20:19:12 -07001241 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001242 }
1243 return mHomeStack;
1244 }
1245
Craig Mautner29219d92013-04-16 20:19:12 -07001246 void setFocusedStack(ActivityRecord r) {
1247 if (r == null) {
1248 return;
1249 }
Craig Mautner86d67a42013-05-14 10:34:38 -07001250 if (!r.isApplicationActivity() || (r.task != null && !r.task.isApplicationTask())) {
Craig Mautner29219d92013-04-16 20:19:12 -07001251 if (mStackState != STACK_STATE_HOME_IN_FRONT) {
Craig Mautnere7c58b62013-06-12 20:19:00 -07001252 if (DEBUG_STACK || DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: mStackState old=" +
Craig Mautner76ea2242013-05-15 11:40:05 -07001253 stackStateToString(mStackState) + " new=" +
1254 stackStateToString(STACK_STATE_HOME_TO_FRONT) +
1255 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001256 mStackState = STACK_STATE_HOME_TO_FRONT;
1257 }
1258 } else {
Craig Mautnere7c58b62013-06-12 20:19:00 -07001259 if (DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: Setting focused stack to r=" +
1260 r + " task=" + r.task + " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001261 mFocusedStack = r.task.stack;
1262 if (mStackState != STACK_STATE_HOME_IN_BACK) {
Craig Mautner76ea2242013-05-15 11:40:05 -07001263 if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
1264 stackStateToString(mStackState) + " new=" +
1265 stackStateToString(STACK_STATE_HOME_TO_BACK) +
1266 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001267 mStackState = STACK_STATE_HOME_TO_BACK;
1268 }
1269 }
1270 }
1271
Craig Mautner8849a5e2013-04-02 16:41:03 -07001272 final int startActivityUncheckedLocked(ActivityRecord r,
1273 ActivityRecord sourceRecord, int startFlags, boolean doResume,
1274 Bundle options) {
1275 final Intent intent = r.intent;
1276 final int callingUid = r.launchedFromUid;
1277
1278 int launchFlags = intent.getFlags();
1279
Craig Mautner8849a5e2013-04-02 16:41:03 -07001280 // We'll invoke onUserLeaving before onPause only if the launching
1281 // activity did not explicitly state that this is an automated launch.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001282 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1283 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001284
1285 // If the caller has asked not to resume at this point, we make note
1286 // of this in the record so that we can skip it when trying to find
1287 // the top running activity.
1288 if (!doResume) {
1289 r.delayedResume = true;
1290 }
1291
1292 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1293
1294 // If the onlyIfNeeded flag is set, then we can do this if the activity
1295 // being launched is the same as the one making the call... or, as
1296 // a special case, if we do not know the caller then we count the
1297 // current top activity as the caller.
1298 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1299 ActivityRecord checkedCaller = sourceRecord;
1300 if (checkedCaller == null) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001301 checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001302 }
1303 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1304 // Caller is not the same as launcher, so always needed.
1305 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1306 }
1307 }
1308
1309 if (sourceRecord == null) {
1310 // This activity is not being started from another... in this
1311 // case we -always- start a new task.
1312 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Craig Mautner29219d92013-04-16 20:19:12 -07001313 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1314 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001315 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1316 }
1317 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1318 // The original activity who is starting us is running as a single
1319 // instance... this new activity it is starting must go on its
1320 // own task.
1321 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1322 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1323 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1324 // The activity being started is a single instance... it always
1325 // gets launched into its own task.
1326 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1327 }
1328
Craig Mautnerde4ef022013-04-07 19:01:33 -07001329 final ActivityStack sourceStack;
Craig Mautner525f3d92013-05-07 14:01:50 -07001330 TaskRecord sourceTask;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001331 if (sourceRecord != null) {
1332 sourceTask = sourceRecord.task;
1333 sourceStack = sourceTask.stack;
1334 } else {
1335 sourceTask = null;
1336 sourceStack = null;
1337 }
1338
Craig Mautner8849a5e2013-04-02 16:41:03 -07001339 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1340 // For whatever reason this activity is being launched into a new
1341 // task... yet the caller has requested a result back. Well, that
1342 // is pretty messed up, so instead immediately send back a cancel
1343 // and let the new task continue launched as normal without a
1344 // dependency on its originator.
1345 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1346 r.resultTo.task.stack.sendActivityResultLocked(-1,
1347 r.resultTo, r.resultWho, r.requestCode,
1348 Activity.RESULT_CANCELED, null);
1349 r.resultTo = null;
1350 }
1351
1352 boolean addingToTask = false;
1353 boolean movedHome = false;
1354 TaskRecord reuseTask = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001355 ActivityStack targetStack;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001356 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1357 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1358 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1359 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1360 // If bring to front is requested, and no result is requested, and
1361 // we can find a task that was started with this same
1362 // component, then instead of launching bring that one to the front.
1363 if (r.resultTo == null) {
1364 // See if there is a task to bring to the front. If this is
1365 // a SINGLE_INSTANCE activity, there can be one and only one
1366 // instance of it in the history, and it is always in its own
1367 // unique task, so we do a special search.
1368 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
1369 ? findTaskLocked(intent, r.info)
1370 : findActivityLocked(intent, r.info);
1371 if (intentActivity != null) {
Craig Mautner29219d92013-04-16 20:19:12 -07001372 if (r.task == null) {
1373 r.task = intentActivity.task;
1374 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001375 targetStack = intentActivity.task.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001376 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001377 if (intentActivity.task.intent == null) {
1378 // This task was started because of movement of
1379 // the activity based on affinity... now that we
1380 // are actually launching it, we can assign the
1381 // base intent.
1382 intentActivity.task.setIntent(intent, r.info);
1383 }
1384 // If the target task is not in the front, then we need
1385 // to bring it to the front... except... well, with
1386 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
1387 // to have the same behavior as if a new instance was
1388 // being started, which means not bringing it to the front
1389 // if the caller is not itself in the front.
Craig Mautner165640b2013-04-20 10:34:33 -07001390 final ActivityStack lastStack = getLastStack();
1391 ActivityRecord curTop = lastStack == null?
1392 null : lastStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001393 if (curTop != null && curTop.task != intentActivity.task) {
1394 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001395 if (sourceRecord == null || sourceStack.topActivity() == sourceRecord) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001396 // We really do want to push this one into the
1397 // user's face, right now.
1398 movedHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001399 if ((launchFlags &
Craig Mautner29219d92013-04-16 20:19:12 -07001400 (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1401 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001402 // Caller wants to appear on home activity, so before starting
1403 // their own activity we will bring home to the front.
1404 r.mLaunchHomeTaskNext = true;
1405 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001406 targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1407 options = null;
1408 }
1409 }
1410 // If the caller has requested that the target task be
1411 // reset, then do so.
1412 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1413 intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1414 }
1415 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1416 // We don't need to start a new activity, and
1417 // the client said not to do anything if that
1418 // is the case, so this is it! And for paranoia, make
1419 // sure we have correctly resumed the top activity.
1420 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001421 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001422 resumeTopActivitiesLocked(targetStack, null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001423 } else {
1424 ActivityOptions.abort(options);
1425 }
Craig Mautner29219d92013-04-16 20:19:12 -07001426 if (r.task == null) Slog.v(TAG,
1427 "startActivityUncheckedLocked: task left null",
1428 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001429 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1430 }
1431 if ((launchFlags &
1432 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1433 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1434 // The caller has requested to completely replace any
1435 // existing task with its new activity. Well that should
1436 // not be too hard...
1437 reuseTask = intentActivity.task;
1438 reuseTask.performClearTaskLocked();
1439 reuseTask.setIntent(r.intent, r.info);
1440 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1441 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1442 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1443 // In this situation we want to remove all activities
1444 // from the task up to the one being started. In most
1445 // cases this means we are resetting the task to its
1446 // initial state.
1447 ActivityRecord top =
1448 intentActivity.task.performClearTaskLocked(r, launchFlags);
1449 if (top != null) {
1450 if (top.frontOfTask) {
1451 // Activity aliases may mean we use different
1452 // intents for the top activity, so make sure
1453 // the task now has the identity of the new
1454 // intent.
1455 top.task.setIntent(r.intent, r.info);
1456 }
1457 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1458 r, top.task);
1459 top.deliverNewIntentLocked(callingUid, r.intent);
1460 } else {
1461 // A special case: we need to
1462 // start the activity because it is not currently
1463 // running, and the caller has asked to clear the
1464 // current task to have this activity at the top.
1465 addingToTask = true;
1466 // Now pretend like this activity is being started
1467 // by the top of its task, so it is put in the
1468 // right place.
1469 sourceRecord = intentActivity;
1470 }
1471 } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1472 // In this case the top activity on the task is the
1473 // same as the one being launched, so we take that
1474 // as a request to bring the task to the foreground.
1475 // If the top activity in the task is the root
1476 // activity, deliver this new intent to it if it
1477 // desires.
1478 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1479 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1480 && intentActivity.realActivity.equals(r.realActivity)) {
1481 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1482 intentActivity.task);
1483 if (intentActivity.frontOfTask) {
1484 intentActivity.task.setIntent(r.intent, r.info);
1485 }
1486 intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1487 } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1488 // In this case we are launching the root activity
1489 // of the task, but with a different intent. We
1490 // should start a new instance on top.
1491 addingToTask = true;
1492 sourceRecord = intentActivity;
1493 }
1494 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1495 // In this case an activity is being launched in to an
1496 // existing task, without resetting that task. This
1497 // is typically the situation of launching an activity
1498 // from a notification or shortcut. We want to place
1499 // the new activity on top of the current task.
1500 addingToTask = true;
1501 sourceRecord = intentActivity;
1502 } else if (!intentActivity.task.rootWasReset) {
1503 // In this case we are launching in to an existing task
1504 // that has not yet been started from its front door.
1505 // The current task has been brought to the front.
1506 // Ideally, we'd probably like to place this new task
1507 // at the bottom of its stack, but that's a little hard
1508 // to do with the current organization of the code so
1509 // for now we'll just drop it.
1510 intentActivity.task.setIntent(r.intent, r.info);
1511 }
1512 if (!addingToTask && reuseTask == null) {
1513 // We didn't do anything... but it was needed (a.k.a., client
1514 // don't use that intent!) And for paranoia, make
1515 // sure we have correctly resumed the top activity.
1516 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001517 setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1518 targetStack.resumeTopActivityLocked(null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001519 } else {
1520 ActivityOptions.abort(options);
1521 }
Craig Mautner29219d92013-04-16 20:19:12 -07001522 if (r.task == null) Slog.v(TAG,
1523 "startActivityUncheckedLocked: task left null",
1524 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001525 return ActivityManager.START_TASK_TO_FRONT;
1526 }
1527 }
1528 }
1529 }
1530
1531 //String uri = r.intent.toURI();
1532 //Intent intent2 = new Intent(uri);
1533 //Slog.i(TAG, "Given intent: " + r.intent);
1534 //Slog.i(TAG, "URI is: " + uri);
1535 //Slog.i(TAG, "To intent: " + intent2);
1536
1537 if (r.packageName != null) {
1538 // If the activity being launched is the same as the one currently
1539 // at the top, then we need to check if it should only be launched
1540 // once.
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001541 ActivityStack topStack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001542 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001543 if (top != null && r.resultTo == null) {
1544 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1545 if (top.app != null && top.app.thread != null) {
1546 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1547 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1548 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1549 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1550 top.task);
1551 // For paranoia, make sure we have correctly
1552 // resumed the top activity.
1553 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001554 setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001555 resumeTopActivitiesLocked();
Craig Mautner8849a5e2013-04-02 16:41:03 -07001556 }
1557 ActivityOptions.abort(options);
1558 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1559 // We don't need to start a new activity, and
1560 // the client said not to do anything if that
1561 // is the case, so this is it!
Craig Mautner29219d92013-04-16 20:19:12 -07001562 if (r.task == null) Slog.v(TAG,
1563 "startActivityUncheckedLocked: task left null",
1564 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001565 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1566 }
1567 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner29219d92013-04-16 20:19:12 -07001568 if (r.task == null) Slog.v(TAG,
1569 "startActivityUncheckedLocked: task left null",
1570 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001571 return ActivityManager.START_DELIVERED_TO_TOP;
1572 }
1573 }
1574 }
1575 }
1576
1577 } else {
1578 if (r.resultTo != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001579 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1580 r.requestCode, Activity.RESULT_CANCELED, null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001581 }
1582 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001583 if (r.task == null) Slog.v(TAG,
1584 "startActivityUncheckedLocked: task left null",
1585 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001586 return ActivityManager.START_CLASS_NOT_FOUND;
1587 }
1588
1589 boolean newTask = false;
1590 boolean keepCurTransition = false;
1591
1592 // Should this be considered a new task?
1593 if (r.resultTo == null && !addingToTask
1594 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001595 targetStack = getCorrectStack(r);
1596 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001597 if (reuseTask == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001598 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1599 null, true);
1600 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1601 r.task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001602 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001603 r.setTask(reuseTask, reuseTask, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001604 }
1605 newTask = true;
1606 if (!movedHome) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001607 if ((launchFlags &
1608 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1609 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1610 // Caller wants to appear on home activity, so before starting
1611 // their own activity we will bring home to the front.
1612 r.mLaunchHomeTaskNext = true;
1613 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001614 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001615 } else if (sourceRecord != null) {
Craig Mautner525f3d92013-05-07 14:01:50 -07001616 sourceTask = sourceRecord.task;
1617 targetStack = sourceTask.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001618 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001619 if (!addingToTask &&
1620 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1621 // In this case, we are adding the activity to an existing
1622 // task, but the caller has asked to clear that task if the
1623 // activity is already running.
Craig Mautner525f3d92013-05-07 14:01:50 -07001624 ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001625 keepCurTransition = true;
1626 if (top != null) {
1627 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1628 top.deliverNewIntentLocked(callingUid, r.intent);
1629 // For paranoia, make sure we have correctly
1630 // resumed the top activity.
1631 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001632 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001633 targetStack.resumeTopActivityLocked(null);
1634 }
1635 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001636 if (r.task == null) Slog.v(TAG,
1637 "startActivityUncheckedLocked: task left null",
1638 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001639 return ActivityManager.START_DELIVERED_TO_TOP;
1640 }
1641 } else if (!addingToTask &&
1642 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1643 // In this case, we are launching an activity in our own task
1644 // that may already be running somewhere in the history, and
1645 // we want to shuffle it to the front of the stack if so.
Craig Mautner525f3d92013-05-07 14:01:50 -07001646 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001647 if (top != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001648 final TaskRecord task = top.task;
1649 task.moveActivityToFrontLocked(top);
1650 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001651 top.updateOptionsLocked(options);
1652 top.deliverNewIntentLocked(callingUid, r.intent);
1653 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001654 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001655 targetStack.resumeTopActivityLocked(null);
1656 }
Craig Mautner29219d92013-04-16 20:19:12 -07001657 if (r.task == null) Slog.v(TAG,
1658 "startActivityUncheckedLocked: task left null",
1659 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001660 return ActivityManager.START_DELIVERED_TO_TOP;
1661 }
1662 }
1663 // An existing activity is starting this new activity, so we want
1664 // to keep the new one in the same task as the one that is starting
1665 // it.
Craig Mautner525f3d92013-05-07 14:01:50 -07001666 r.setTask(sourceTask, sourceRecord.thumbHolder, false);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001667 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1668 + " in existing task " + r.task);
1669
1670 } else {
1671 // This not being started from an existing activity, and not part
1672 // of a new task... just put it in the top task, though these days
1673 // this case should never happen.
Craig Mautner1602ec22013-05-12 10:24:27 -07001674 targetStack = getCorrectStack(r);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001675 moveHomeStack(targetStack.isHomeStack());
Craig Mautner1602ec22013-05-12 10:24:27 -07001676 ActivityRecord prev = targetStack.topActivity();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001677 r.setTask(prev != null ? prev.task
1678 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1679 null, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001680 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1681 + " in new guessed " + r.task);
1682 }
1683
1684 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1685 intent, r.getUriPermissionsLocked());
1686
1687 if (newTask) {
1688 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1689 }
1690 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001691 setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001692 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
Craig Mautner1d001b62013-06-18 16:52:43 -07001693 mService.setFocusedActivityLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001694 return ActivityManager.START_SUCCESS;
1695 }
1696
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001697 void acquireLaunchWakelock() {
1698 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
1699 throw new IllegalStateException("Calling must be system uid");
1700 }
1701 mLaunchingActivity.acquire();
1702 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
1703 // To be safe, don't allow the wake lock to be held for too long.
1704 mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
1705 }
1706 }
1707
Craig Mautnerf3333272013-04-22 10:55:53 -07001708 // Checked.
1709 final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
1710 Configuration config) {
1711 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
1712
Craig Mautnerf3333272013-04-22 10:55:53 -07001713 ArrayList<ActivityRecord> stops = null;
1714 ArrayList<ActivityRecord> finishes = null;
1715 ArrayList<UserStartedState> startingUsers = null;
1716 int NS = 0;
1717 int NF = 0;
1718 IApplicationThread sendThumbnail = null;
1719 boolean booting = false;
1720 boolean enableScreen = false;
1721 boolean activityRemoved = false;
1722
1723 ActivityRecord r = ActivityRecord.forToken(token);
1724 if (r != null) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07001725 if (DEBUG_IDLE) Slog.d(TAG, "activityIdleInternalLocked: Callers=" +
1726 Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07001727 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
1728 r.finishLaunchTickingLocked();
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001729 if (fromTimeout) {
1730 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
Craig Mautnerf3333272013-04-22 10:55:53 -07001731 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001732
1733 // This is a hack to semi-deal with a race condition
1734 // in the client where it can be constructed with a
1735 // newer configuration from when we asked it to launch.
1736 // We'll update with whatever configuration it now says
1737 // it used to launch.
1738 if (config != null) {
1739 r.configuration = config;
1740 }
1741
1742 // We are now idle. If someone is waiting for a thumbnail from
1743 // us, we can now deliver.
1744 r.idle = true;
1745
1746 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
1747 sendThumbnail = r.app.thread;
1748 r.thumbnailNeeded = false;
1749 }
1750
1751 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
1752 if (!mService.mBooted && isFrontStack(r.task.stack)) {
1753 mService.mBooted = true;
1754 enableScreen = true;
1755 }
1756 }
1757
1758 if (allResumedActivitiesIdle()) {
1759 if (r != null) {
1760 mService.scheduleAppGcsLocked();
1761 mService.requestPssLocked(r.app, SystemClock.uptimeMillis(), false);
1762 }
1763
1764 if (mLaunchingActivity.isHeld()) {
1765 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
1766 if (VALIDATE_WAKE_LOCK_CALLER &&
1767 Binder.getCallingUid() != Process.myUid()) {
1768 throw new IllegalStateException("Calling must be system uid");
1769 }
1770 mLaunchingActivity.release();
1771 }
1772 ensureActivitiesVisibleLocked(null, 0);
Craig Mautnerf3333272013-04-22 10:55:53 -07001773 }
1774
1775 // Atomically retrieve all of the other things to do.
1776 stops = processStoppingActivitiesLocked(true);
1777 NS = stops != null ? stops.size() : 0;
1778 if ((NF=mFinishingActivities.size()) > 0) {
1779 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
1780 mFinishingActivities.clear();
1781 }
1782
1783 final ArrayList<ActivityRecord> thumbnails;
1784 final int NT = mCancelledThumbnails.size();
1785 if (NT > 0) {
1786 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
1787 mCancelledThumbnails.clear();
1788 } else {
1789 thumbnails = null;
1790 }
1791
1792 if (isFrontStack(mHomeStack)) {
1793 booting = mService.mBooting;
1794 mService.mBooting = false;
1795 }
1796
1797 if (mStartingUsers.size() > 0) {
1798 startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
1799 mStartingUsers.clear();
1800 }
1801
1802 // Perform the following actions from unsynchronized state.
1803 final IApplicationThread thumbnailThread = sendThumbnail;
1804 mHandler.post(new Runnable() {
1805 @Override
1806 public void run() {
1807 if (thumbnailThread != null) {
1808 try {
1809 thumbnailThread.requestThumbnail(token);
1810 } catch (Exception e) {
1811 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
1812 mService.sendPendingThumbnail(null, token, null, null, true);
1813 }
1814 }
1815
1816 // Report back to any thumbnail receivers.
1817 for (int i = 0; i < NT; i++) {
1818 ActivityRecord r = thumbnails.get(i);
1819 mService.sendPendingThumbnail(r, null, null, null, true);
1820 }
1821 }
1822 });
1823
1824 // Stop any activities that are scheduled to do so but have been
1825 // waiting for the next one to start.
1826 for (int i = 0; i < NS; i++) {
1827 r = stops.get(i);
1828 final ActivityStack stack = r.task.stack;
1829 if (r.finishing) {
1830 stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
1831 } else {
1832 stack.stopActivityLocked(r);
1833 }
1834 }
1835
1836 // Finish any activities that are scheduled to do so but have been
1837 // waiting for the next one to start.
1838 for (int i = 0; i < NF; i++) {
1839 r = finishes.get(i);
1840 activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle");
1841 }
1842
1843 if (booting) {
1844 mService.finishBooting();
1845 } else if (startingUsers != null) {
1846 for (int i = 0; i < startingUsers.size(); i++) {
1847 mService.finishUserSwitch(startingUsers.get(i));
1848 }
1849 }
1850
1851 mService.trimApplications();
1852 //dump();
1853 //mWindowManager.dump();
1854
1855 if (enableScreen) {
1856 mService.enableScreenAfterBoot();
1857 }
1858
1859 if (activityRemoved) {
Craig Mautner05d29032013-05-03 13:40:13 -07001860 resumeTopActivitiesLocked();
Craig Mautnerf3333272013-04-22 10:55:53 -07001861 }
1862
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001863 return r;
Craig Mautnerf3333272013-04-22 10:55:53 -07001864 }
1865
Craig Mautner8d341ef2013-03-26 09:03:27 -07001866 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
1867 // Just in case.
1868 final int numStacks = mStacks.size();
1869 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Craig Mautnere79d42682013-04-01 19:01:53 -07001870 mStacks.get(stackNdx).handleAppDiedLocked(app, restarting);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001871 }
1872 }
1873
1874 void closeSystemDialogsLocked() {
1875 final int numStacks = mStacks.size();
1876 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1877 final ActivityStack stack = mStacks.get(stackNdx);
1878 stack.closeSystemDialogsLocked();
1879 }
1880 }
1881
1882 /**
1883 * @return true if some activity was finished (or would have finished if doit were true).
1884 */
1885 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1886 boolean didSomething = false;
1887 final int numStacks = mStacks.size();
1888 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1889 final ActivityStack stack = mStacks.get(stackNdx);
1890 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1891 didSomething = true;
1892 }
1893 }
1894 return didSomething;
1895 }
1896
Dianne Hackborna413dc02013-07-12 12:02:55 -07001897 void updatePreviousProcessLocked(ActivityRecord r) {
1898 // Now that this process has stopped, we may want to consider
1899 // it to be the previous app to try to keep around in case
1900 // the user wants to return to it.
1901
1902 // First, found out what is currently the foreground app, so that
1903 // we don't blow away the previous app if this activity is being
1904 // hosted by the process that is actually still the foreground.
1905 ProcessRecord fgApp = null;
1906 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1907 final ActivityStack stack = mStacks.get(stackNdx);
1908 if (isFrontStack(stack)) {
1909 if (stack.mResumedActivity != null) {
1910 fgApp = stack.mResumedActivity.app;
1911 } else if (stack.mPausingActivity != null) {
1912 fgApp = stack.mPausingActivity.app;
1913 }
1914 break;
1915 }
1916 }
1917
1918 // Now set this one as the previous process, only if that really
1919 // makes sense to.
1920 if (r.app != null && fgApp != null && r.app != fgApp
1921 && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
1922 && r.app != mService.mHomeProcess) {
1923 mService.mPreviousProcess = r.app;
1924 mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
1925 }
1926 }
1927
Craig Mautner05d29032013-05-03 13:40:13 -07001928 boolean resumeTopActivitiesLocked() {
1929 return resumeTopActivitiesLocked(null, null, null);
1930 }
1931
1932 boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
1933 Bundle targetOptions) {
1934 if (targetStack == null) {
1935 targetStack = getFocusedStack();
1936 }
1937 boolean result = false;
Craig Mautnerdbcb31f2013-04-02 12:32:53 -07001938 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001939 final ActivityStack stack = mStacks.get(stackNdx);
1940 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07001941 if (stack == targetStack) {
1942 result = stack.resumeTopActivityLocked(target, targetOptions);
1943 } else {
1944 stack.resumeTopActivityLocked(null);
1945 }
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001946 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001947 }
Craig Mautner05d29032013-05-03 13:40:13 -07001948 return result;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001949 }
1950
1951 void finishTopRunningActivityLocked(ProcessRecord app) {
1952 final int numStacks = mStacks.size();
1953 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1954 final ActivityStack stack = mStacks.get(stackNdx);
1955 stack.finishTopRunningActivityLocked(app);
1956 }
1957 }
1958
Craig Mautner8d341ef2013-03-26 09:03:27 -07001959 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
1960 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1961 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001962 if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack=" +
Craig Mautner1d001b62013-06-18 16:52:43 -07001963 mStacks.get(stackNdx));
Craig Mautner8d341ef2013-03-26 09:03:27 -07001964 return;
1965 }
1966 }
1967 }
1968
Craig Mautner967212c2013-04-13 21:10:58 -07001969 ActivityStack getStack(int stackId) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001970 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1971 final ActivityStack stack = mStacks.get(stackNdx);
1972 if (stack.getStackId() == stackId) {
1973 return stack;
1974 }
1975 }
1976 return null;
1977 }
1978
Craig Mautner967212c2013-04-13 21:10:58 -07001979 ArrayList<ActivityStack> getStacks() {
1980 return new ArrayList<ActivityStack>(mStacks);
1981 }
1982
1983 int createStack() {
Craig Mautner858d8a62013-04-23 17:08:34 -07001984 while (true) {
1985 if (++mLastStackId <= HOME_STACK_ID) {
1986 mLastStackId = HOME_STACK_ID + 1;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001987 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001988 if (getStack(mLastStackId) == null) {
1989 break;
1990 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001991 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001992 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
1993 return mLastStackId;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001994 }
1995
1996 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07001997 final TaskRecord task = anyTaskForIdLocked(taskId);
1998 if (task == null) {
1999 return;
2000 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002001 final ActivityStack stack = getStack(stackId);
2002 if (stack == null) {
2003 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
2004 return;
2005 }
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07002006 removeTask(task);
2007 stack.addTask(task, toTop);
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07002008 mWindowManager.addTask(taskId, stackId, toTop);
Craig Mautner05d29032013-05-03 13:40:13 -07002009 resumeTopActivitiesLocked();
Craig Mautner8d341ef2013-03-26 09:03:27 -07002010 }
2011
Craig Mautner8849a5e2013-04-02 16:41:03 -07002012 ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
2013 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2014 final ActivityRecord ar = mStacks.get(stackNdx).findTaskLocked(intent, info);
2015 if (ar != null) {
2016 return ar;
2017 }
2018 }
2019 return null;
2020 }
2021
2022 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
2023 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2024 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
2025 if (ar != null) {
2026 return ar;
2027 }
2028 }
2029 return null;
2030 }
2031
Craig Mautner8d341ef2013-03-26 09:03:27 -07002032 void goingToSleepLocked() {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002033 scheduleSleepTimeout();
2034 if (!mGoingToSleep.isHeld()) {
2035 mGoingToSleep.acquire();
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002036 if (mLaunchingActivity.isHeld()) {
2037 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
2038 throw new IllegalStateException("Calling must be system uid");
Craig Mautner0eea92c2013-05-16 13:35:39 -07002039 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002040 mLaunchingActivity.release();
2041 mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
Craig Mautner0eea92c2013-05-16 13:35:39 -07002042 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002043 }
2044 }
2045
2046 boolean shutdownLocked(int timeout) {
2047 boolean timedout = false;
Craig Mautner0eea92c2013-05-16 13:35:39 -07002048 goingToSleepLocked();
2049 checkReadyForSleepLocked();
2050
2051 final long endTime = System.currentTimeMillis() + timeout;
2052 while (true) {
2053 boolean cantShutdown = false;
2054 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2055 cantShutdown |= mStacks.get(stackNdx).checkReadyForSleepLocked();
2056 }
2057 if (cantShutdown) {
2058 long timeRemaining = endTime - System.currentTimeMillis();
2059 if (timeRemaining > 0) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002060 try {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002061 mService.wait(timeRemaining);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002062 } catch (InterruptedException e) {
2063 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002064 } else {
2065 Slog.w(TAG, "Activity manager shutdown timed out");
2066 timedout = true;
2067 break;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002068 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002069 } else {
2070 break;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002071 }
2072 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002073
2074 // Force checkReadyForSleep to complete.
2075 mSleepTimeout = true;
2076 checkReadyForSleepLocked();
2077
Craig Mautner8d341ef2013-03-26 09:03:27 -07002078 return timedout;
2079 }
2080
2081 void comeOutOfSleepIfNeededLocked() {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002082 removeSleepTimeouts();
2083 if (mGoingToSleep.isHeld()) {
2084 mGoingToSleep.release();
2085 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002086 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002087 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002088 stack.awakeFromSleepingLocked();
2089 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07002090 resumeTopActivitiesLocked();
Craig Mautnerde4ef022013-04-07 19:01:33 -07002091 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002092 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002093 mGoingToSleepActivities.clear();
2094 }
2095
2096 void activitySleptLocked(ActivityRecord r) {
2097 mGoingToSleepActivities.remove(r);
2098 checkReadyForSleepLocked();
2099 }
2100
2101 void checkReadyForSleepLocked() {
2102 if (!mService.isSleepingOrShuttingDown()) {
2103 // Do not care.
2104 return;
2105 }
2106
2107 if (!mSleepTimeout) {
2108 boolean dontSleep = false;
2109 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2110 dontSleep |= mStacks.get(stackNdx).checkReadyForSleepLocked();
2111 }
2112
2113 if (mStoppingActivities.size() > 0) {
2114 // Still need to tell some activities to stop; can't sleep yet.
2115 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
2116 + mStoppingActivities.size() + " activities");
2117 scheduleIdleLocked();
2118 dontSleep = true;
2119 }
2120
2121 if (mGoingToSleepActivities.size() > 0) {
2122 // Still need to tell some activities to sleep; can't sleep yet.
2123 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
2124 + mGoingToSleepActivities.size() + " activities");
2125 dontSleep = true;
2126 }
2127
2128 if (dontSleep) {
2129 return;
2130 }
2131 }
2132
2133 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2134 mStacks.get(stackNdx).goToSleep();
2135 }
2136
2137 removeSleepTimeouts();
2138
2139 if (mGoingToSleep.isHeld()) {
2140 mGoingToSleep.release();
2141 }
2142 if (mService.mShuttingDown) {
2143 mService.notifyAll();
2144 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002145 }
2146
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002147 boolean reportResumedActivityLocked(ActivityRecord r) {
2148 final ActivityStack stack = r.task.stack;
2149 if (isFrontStack(stack)) {
Jeff Sharkey5782da72013-04-25 14:32:30 -07002150 mService.updateUsageStats(r, true);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002151 }
2152 if (allResumedActivitiesComplete()) {
2153 ensureActivitiesVisibleLocked(null, 0);
2154 mWindowManager.executeAppTransition();
2155 return true;
2156 }
2157 return false;
2158 }
2159
Craig Mautner8d341ef2013-03-26 09:03:27 -07002160 void handleAppCrashLocked(ProcessRecord app) {
2161 final int numStacks = mStacks.size();
2162 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2163 final ActivityStack stack = mStacks.get(stackNdx);
2164 stack.handleAppCrashLocked(app);
2165 }
2166 }
2167
Craig Mautnerde4ef022013-04-07 19:01:33 -07002168 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
Craig Mautner580ea812013-04-25 12:58:38 -07002169 // First the front stacks. In case any are not fullscreen and are in front of home.
2170 boolean showHomeBehindStack = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07002171 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner580ea812013-04-25 12:58:38 -07002172 final ActivityStack stack = mStacks.get(stackNdx);
2173 if (isFrontStack(stack)) {
2174 showHomeBehindStack =
2175 stack.ensureActivitiesVisibleLocked(starting, configChanges);
2176 }
2177 }
2178 // Now do back stacks.
2179 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2180 final ActivityStack stack = mStacks.get(stackNdx);
2181 if (!isFrontStack(stack)) {
2182 stack.ensureActivitiesVisibleLocked(starting, configChanges, showHomeBehindStack);
2183 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002184 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002185 }
2186
2187 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
2188 final int numStacks = mStacks.size();
2189 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2190 final ActivityStack stack = mStacks.get(stackNdx);
2191 stack.scheduleDestroyActivities(app, false, reason);
2192 }
2193 }
2194
2195 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner858d8a62013-04-23 17:08:34 -07002196 mUserStates.put(mCurrentUser, new UserState());
Craig Mautner2420ead2013-04-01 17:13:20 -07002197 mCurrentUser = userId;
Craig Mautner858d8a62013-04-23 17:08:34 -07002198 UserState userState = mUserStates.get(userId);
2199 if (userState != null) {
2200 userState.restore();
2201 mUserStates.delete(userId);
2202 } else {
2203 mFocusedStack = null;
Craig Mautner76ea2242013-05-15 11:40:05 -07002204 if (DEBUG_STACK) Slog.d(TAG, "switchUserLocked: mStackState=" +
2205 stackStateToString(STACK_STATE_HOME_IN_FRONT));
Craig Mautner858d8a62013-04-23 17:08:34 -07002206 mStackState = STACK_STATE_HOME_IN_FRONT;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002207 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002208
2209 mStartingUsers.add(uss);
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002210 boolean haveActivities = mHomeStack.switchUserLocked(userId);
Craig Mautner858d8a62013-04-23 17:08:34 -07002211
2212 resumeTopActivitiesLocked();
2213
Craig Mautner8d341ef2013-03-26 09:03:27 -07002214 return haveActivities;
Craig Mautner2219a1b2013-03-25 09:44:30 -07002215 }
2216
Craig Mautnerde4ef022013-04-07 19:01:33 -07002217 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
2218 int N = mStoppingActivities.size();
2219 if (N <= 0) return null;
2220
2221 ArrayList<ActivityRecord> stops = null;
2222
2223 final boolean nowVisible = allResumedActivitiesVisible();
2224 for (int i=0; i<N; i++) {
2225 ActivityRecord s = mStoppingActivities.get(i);
2226 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
2227 + nowVisible + " waitingVisible=" + s.waitingVisible
2228 + " finishing=" + s.finishing);
2229 if (s.waitingVisible && nowVisible) {
2230 mWaitingVisibleActivities.remove(s);
2231 s.waitingVisible = false;
2232 if (s.finishing) {
2233 // If this activity is finishing, it is sitting on top of
2234 // everyone else but we now know it is no longer needed...
2235 // so get rid of it. Otherwise, we need to go through the
2236 // normal flow and hide it once we determine that it is
2237 // hidden by the activities in front of it.
2238 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002239 mWindowManager.setAppVisibility(s.appToken, false);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002240 }
2241 }
2242 if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
2243 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
2244 if (stops == null) {
2245 stops = new ArrayList<ActivityRecord>();
2246 }
2247 stops.add(s);
2248 mStoppingActivities.remove(i);
2249 N--;
2250 i--;
2251 }
2252 }
2253
2254 return stops;
2255 }
2256
Craig Mautnercf910b02013-04-23 11:23:27 -07002257 void validateTopActivitiesLocked() {
2258 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2259 final ActivityStack stack = mStacks.get(stackNdx);
2260 final ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002261 final ActivityState state = r == null ? ActivityState.DESTROYED : r.state;
Craig Mautnercf910b02013-04-23 11:23:27 -07002262 if (isFrontStack(stack)) {
2263 if (r == null) {
2264 Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
2265 } else {
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002266 final ActivityRecord pausing = stack.mPausingActivity;
2267 if (pausing != null && pausing == r) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002268 Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002269 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002270 }
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002271 if (state != ActivityState.INITIALIZING && state != ActivityState.RESUMED) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002272 Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002273 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002274 }
2275 }
2276 } else {
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002277 final ActivityRecord resumed = stack.mResumedActivity;
2278 if (resumed != null && resumed == r) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002279 Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002280 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002281 }
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002282 if (r != null && (state == ActivityState.INITIALIZING
2283 || state == ActivityState.RESUMED)) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002284 Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002285 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002286 }
2287 }
2288 }
2289 }
2290
Craig Mautner76ea2242013-05-15 11:40:05 -07002291 private static String stackStateToString(int stackState) {
2292 switch (stackState) {
2293 case STACK_STATE_HOME_IN_FRONT: return "STACK_STATE_HOME_IN_FRONT";
2294 case STACK_STATE_HOME_TO_BACK: return "STACK_STATE_HOME_TO_BACK";
2295 case STACK_STATE_HOME_IN_BACK: return "STACK_STATE_HOME_IN_BACK";
2296 case STACK_STATE_HOME_TO_FRONT: return "STACK_STATE_HOME_TO_FRONT";
2297 default: return "Unknown stackState=" + stackState;
2298 }
2299 }
2300
Craig Mautner27084302013-03-25 08:05:25 -07002301 public void dump(PrintWriter pw, String prefix) {
2302 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
2303 pw.println(mDismissKeyguardOnNextActivity);
Craig Mautner76ea2242013-05-15 11:40:05 -07002304 pw.print(prefix); pw.print("mStackState="); pw.println(stackStateToString(mStackState));
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002305 pw.print(prefix); pw.println("mSleepTimeout: " + mSleepTimeout);
2306 pw.print(prefix); pw.println("mCurTaskId: " + mCurTaskId);
Craig Mautner27084302013-03-25 08:05:25 -07002307 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002308
Craig Mautner20e72272013-04-01 13:45:53 -07002309 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002310 return getFocusedStack().getDumpActivitiesLocked(name);
Craig Mautner20e72272013-04-01 13:45:53 -07002311 }
2312
Dianne Hackborn390517b2013-05-30 15:03:32 -07002313 static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
2314 boolean needSep, String prefix) {
2315 if (activity != null) {
2316 if (dumpPackage == null || dumpPackage.equals(activity.packageName)) {
2317 if (needSep) {
2318 pw.println();
Dianne Hackborn390517b2013-05-30 15:03:32 -07002319 }
2320 pw.print(prefix);
2321 pw.println(activity);
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002322 return true;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002323 }
2324 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002325 return false;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002326 }
2327
Craig Mautner8d341ef2013-03-26 09:03:27 -07002328 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
2329 boolean dumpClient, String dumpPackage) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002330 boolean printed = false;
2331 boolean needSep = false;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002332 final int numStacks = mStacks.size();
2333 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2334 final ActivityStack stack = mStacks.get(stackNdx);
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002335 StringBuilder stackHeader = new StringBuilder(128);
2336 stackHeader.append(" Stack #");
2337 stackHeader.append(mStacks.indexOf(stack));
2338 stackHeader.append(":");
2339 printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, needSep,
2340 stackHeader.toString());
2341 printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll,
2342 false, dumpPackage, true, " Running activities (most recent first):", null);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002343
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002344 needSep = printed;
2345 boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002346 " mPausingActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002347 if (pr) {
2348 printed = true;
2349 needSep = false;
2350 }
2351 pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002352 " mResumedActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002353 if (pr) {
2354 printed = true;
2355 needSep = false;
2356 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002357 if (dumpAll) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002358 pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002359 " mLastPausedActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002360 if (pr) {
2361 printed = true;
2362 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002363 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002364 needSep = printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002365 }
2366
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002367 printed |= dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll,
2368 false, dumpPackage, true, " Activities waiting to finish:", null);
2369 printed |= dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll,
2370 false, dumpPackage, true, " Activities waiting to stop:", null);
2371 printed |= dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
2372 false, dumpPackage, true, " Activities waiting for another to become visible:",
2373 null);
2374 printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll,
2375 false, dumpPackage, true, " Activities waiting to sleep:", null);
2376 printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll,
2377 false, dumpPackage, true, " Activities waiting to sleep:", null);
Craig Mautnerf3333272013-04-22 10:55:53 -07002378
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002379 return printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002380 }
2381
Dianne Hackborn390517b2013-05-30 15:03:32 -07002382 static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
Craig Mautner8d341ef2013-03-26 09:03:27 -07002383 String prefix, String label, boolean complete, boolean brief, boolean client,
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002384 String dumpPackage, boolean needNL, String header1, String header2) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002385 TaskRecord lastTask = null;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002386 String innerPrefix = null;
2387 String[] args = null;
2388 boolean printed = false;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002389 for (int i=list.size()-1; i>=0; i--) {
2390 final ActivityRecord r = list.get(i);
2391 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
2392 continue;
2393 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07002394 if (innerPrefix == null) {
2395 innerPrefix = prefix + " ";
2396 args = new String[0];
2397 }
2398 printed = true;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002399 final boolean full = !brief && (complete || !r.isInHistory());
2400 if (needNL) {
Dianne Hackborn390517b2013-05-30 15:03:32 -07002401 pw.println("");
Craig Mautner8d341ef2013-03-26 09:03:27 -07002402 needNL = false;
2403 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002404 if (header1 != null) {
2405 pw.println(header1);
2406 header1 = null;
2407 }
2408 if (header2 != null) {
2409 pw.println(header2);
2410 header2 = null;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002411 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002412 if (lastTask != r.task) {
2413 lastTask = r.task;
2414 pw.print(prefix);
2415 pw.print(full ? "* " : " ");
2416 pw.println(lastTask);
2417 if (full) {
2418 lastTask.dump(pw, prefix + " ");
2419 } else if (complete) {
2420 // Complete + brief == give a summary. Isn't that obvious?!?
2421 if (lastTask.intent != null) {
2422 pw.print(prefix); pw.print(" ");
2423 pw.println(lastTask.intent.toInsecureStringWithClip());
2424 }
2425 }
2426 }
2427 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
2428 pw.print(" #"); pw.print(i); pw.print(": ");
2429 pw.println(r);
2430 if (full) {
2431 r.dump(pw, innerPrefix);
2432 } else if (complete) {
2433 // Complete + brief == give a summary. Isn't that obvious?!?
2434 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
2435 if (r.app != null) {
2436 pw.print(innerPrefix); pw.println(r.app);
2437 }
2438 }
2439 if (client && r.app != null && r.app.thread != null) {
2440 // flush anything that is already in the PrintWriter since the thread is going
2441 // to write to the file descriptor directly
2442 pw.flush();
2443 try {
2444 TransferPipe tp = new TransferPipe();
2445 try {
2446 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
2447 r.appToken, innerPrefix, args);
2448 // Short timeout, since blocking here can
2449 // deadlock with the application.
2450 tp.go(fd, 2000);
2451 } finally {
2452 tp.kill();
2453 }
2454 } catch (IOException e) {
2455 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
2456 } catch (RemoteException e) {
2457 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
2458 }
2459 needNL = true;
2460 }
2461 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07002462 return printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002463 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002464
Craig Mautnerf3333272013-04-22 10:55:53 -07002465 void scheduleIdleTimeoutLocked(ActivityRecord next) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002466 if (DEBUG_IDLE) Slog.d(TAG, "scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4));
Craig Mautnerc64f73e2013-04-24 16:44:56 -07002467 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
2468 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
Craig Mautnerf3333272013-04-22 10:55:53 -07002469 }
2470
2471 final void scheduleIdleLocked() {
Craig Mautner05d29032013-05-03 13:40:13 -07002472 mHandler.sendEmptyMessage(IDLE_NOW_MSG);
Craig Mautnerf3333272013-04-22 10:55:53 -07002473 }
2474
2475 void removeTimeoutsForActivityLocked(ActivityRecord r) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002476 if (DEBUG_IDLE) Slog.d(TAG, "removeTimeoutsForActivity: Callers=" + Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07002477 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
2478 }
2479
Craig Mautner05d29032013-05-03 13:40:13 -07002480 final void scheduleResumeTopActivities() {
2481 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2482 }
2483
Craig Mautner0eea92c2013-05-16 13:35:39 -07002484 void removeSleepTimeouts() {
2485 mSleepTimeout = false;
2486 mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
2487 }
2488
2489 final void scheduleSleepTimeout() {
2490 removeSleepTimeouts();
2491 mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT);
2492 }
2493
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002494 private final class ActivityStackSupervisorHandler extends Handler {
Craig Mautnerf3333272013-04-22 10:55:53 -07002495
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002496 public ActivityStackSupervisorHandler(Looper looper) {
2497 super(looper);
2498 }
2499
Craig Mautnerf3333272013-04-22 10:55:53 -07002500 void activityIdleInternal(ActivityRecord r) {
2501 synchronized (mService) {
2502 activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
2503 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002504 }
2505
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002506 @Override
2507 public void handleMessage(Message msg) {
2508 switch (msg.what) {
Craig Mautnerf3333272013-04-22 10:55:53 -07002509 case IDLE_TIMEOUT_MSG: {
Craig Mautner5eda9b32013-07-02 11:58:16 -07002510 if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_TIMEOUT_MSG: r=" + msg.obj);
Craig Mautnerf3333272013-04-22 10:55:53 -07002511 if (mService.mDidDexOpt) {
2512 mService.mDidDexOpt = false;
2513 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2514 nmsg.obj = msg.obj;
2515 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
2516 return;
2517 }
2518 // We don't at this point know if the activity is fullscreen,
2519 // so we need to be conservative and assume it isn't.
2520 activityIdleInternal((ActivityRecord)msg.obj);
2521 } break;
2522 case IDLE_NOW_MSG: {
Craig Mautner5eda9b32013-07-02 11:58:16 -07002523 if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_NOW_MSG: r=" + msg.obj);
Craig Mautnerf3333272013-04-22 10:55:53 -07002524 activityIdleInternal((ActivityRecord)msg.obj);
2525 } break;
Craig Mautner05d29032013-05-03 13:40:13 -07002526 case RESUME_TOP_ACTIVITY_MSG: {
2527 synchronized (mService) {
2528 resumeTopActivitiesLocked();
2529 }
2530 } break;
Craig Mautner0eea92c2013-05-16 13:35:39 -07002531 case SLEEP_TIMEOUT_MSG: {
2532 synchronized (mService) {
2533 if (mService.isSleepingOrShuttingDown()) {
2534 Slog.w(TAG, "Sleep timeout! Sleeping now.");
2535 mSleepTimeout = true;
2536 checkReadyForSleepLocked();
2537 }
2538 }
2539 } break;
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002540 case LAUNCH_TIMEOUT_MSG: {
2541 if (mService.mDidDexOpt) {
2542 mService.mDidDexOpt = false;
2543 mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
2544 return;
2545 }
2546 synchronized (mService) {
2547 if (mLaunchingActivity.isHeld()) {
2548 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
2549 if (VALIDATE_WAKE_LOCK_CALLER
2550 && Binder.getCallingUid() != Process.myUid()) {
2551 throw new IllegalStateException("Calling must be system uid");
2552 }
2553 mLaunchingActivity.release();
2554 }
2555 }
2556 } break;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002557 }
2558 }
2559 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002560
2561 private final class UserState {
2562 final ActivityStack mSavedFocusedStack;
2563 final int mSavedStackState;
2564
2565 public UserState() {
2566 ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2567 mSavedFocusedStack = supervisor.mFocusedStack;
2568 mSavedStackState = supervisor.mStackState;
2569 }
2570
2571 void restore() {
2572 ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2573 supervisor.mFocusedStack = mSavedFocusedStack;
Craig Mautner76ea2242013-05-15 11:40:05 -07002574 if (DEBUG_STACK) Slog.d(TAG, "UserState.restore: mStackState old=" +
2575 stackStateToString(mSavedStackState));
Craig Mautner858d8a62013-04-23 17:08:34 -07002576 supervisor.mStackState = mSavedStackState;
2577 }
2578 }
Craig Mautner27084302013-03-25 08:05:25 -07002579}