blob: 3e0b5eb04ba7627f29ad23f78007d153c8727d91 [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 Mautner0eea92c2013-05-16 13:35:39 -0700188 /** Set when we have taken too long waiting to go to sleep. */
189 boolean mSleepTimeout = false;
190
191 /**
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700192 * We don't want to allow the device to go to sleep while in the process
193 * of launching an activity. This is primarily to allow alarm intent
194 * receivers to launch an activity and get that to run before the device
195 * goes back to sleep.
196 */
197 final PowerManager.WakeLock mLaunchingActivity;
198
199 /**
Craig Mautner0eea92c2013-05-16 13:35:39 -0700200 * Set when the system is going to sleep, until we have
201 * successfully paused the current activity and released our wake lock.
202 * At that point the system is allowed to actually sleep.
203 */
204 final PowerManager.WakeLock mGoingToSleep;
205
Craig Mautnerac6f8432013-07-17 13:24:59 -0700206 /**
207 * The name of the current home activity for each user.
208 * TODO: Remove entries when user is deleted.
209 */
210 final SparseArray<String> mHomePackageNames = new SparseArray<String>();
211
Craig Mautner2219a1b2013-03-25 09:44:30 -0700212 public ActivityStackSupervisor(ActivityManagerService service, Context context,
213 Looper looper) {
Craig Mautner27084302013-03-25 08:05:25 -0700214 mService = service;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700215 mContext = context;
216 mLooper = looper;
Craig Mautner0eea92c2013-05-16 13:35:39 -0700217 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
218 mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700219 mHandler = new ActivityStackSupervisorHandler(looper);
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700220 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
221 throw new IllegalStateException("Calling must be system uid");
222 }
223 mLaunchingActivity =
224 pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
225 mLaunchingActivity.setReferenceCounted(false);
Craig Mautner2219a1b2013-03-25 09:44:30 -0700226 }
227
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700228 void setWindowManager(WindowManagerService wm) {
229 mWindowManager = wm;
230 mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700231 mStacks.add(mHomeStack);
Craig Mautner27084302013-03-25 08:05:25 -0700232 }
233
234 void dismissKeyguard() {
235 if (mDismissKeyguardOnNextActivity) {
236 mDismissKeyguardOnNextActivity = false;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700237 mWindowManager.dismissKeyguard();
Craig Mautner27084302013-03-25 08:05:25 -0700238 }
239 }
240
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700241 ActivityStack getFocusedStack() {
Craig Mautnerf88c50f2013-04-18 19:25:12 -0700242 if (mFocusedStack == null) {
243 return mHomeStack;
244 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700245 switch (mStackState) {
246 case STACK_STATE_HOME_IN_FRONT:
247 case STACK_STATE_HOME_TO_FRONT:
248 return mHomeStack;
249 case STACK_STATE_HOME_IN_BACK:
250 case STACK_STATE_HOME_TO_BACK:
251 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700252 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700253 }
Craig Mautner20e72272013-04-01 13:45:53 -0700254 }
255
Craig Mautnerde4ef022013-04-07 19:01:33 -0700256 ActivityStack getLastStack() {
257 switch (mStackState) {
258 case STACK_STATE_HOME_IN_FRONT:
259 case STACK_STATE_HOME_TO_BACK:
260 return mHomeStack;
261 case STACK_STATE_HOME_TO_FRONT:
262 case STACK_STATE_HOME_IN_BACK:
263 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700264 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700265 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700266 }
267
Craig Mautnerde4ef022013-04-07 19:01:33 -0700268 boolean isFrontStack(ActivityStack stack) {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700269 return !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
Craig Mautner20e72272013-04-01 13:45:53 -0700270 }
271
Craig Mautnerde4ef022013-04-07 19:01:33 -0700272 void moveHomeStack(boolean toFront) {
273 final boolean homeInFront = isFrontStack(mHomeStack);
274 if (homeInFront ^ toFront) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700275 if (DEBUG_STACK) Slog.d(TAG, "moveHomeTask: mStackState old=" +
276 stackStateToString(mStackState) + " new=" + stackStateToString(homeInFront ?
277 STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700278 mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
279 }
280 }
281
Craig Mautner69ada552013-04-18 13:51:51 -0700282 boolean resumeHomeActivity(ActivityRecord prev) {
283 moveHomeStack(true);
284 if (prev != null) {
285 prev.mLaunchHomeTaskNext = false;
286 }
Craig Mautnera8a90e02013-06-28 15:24:50 -0700287 ActivityRecord r = mHomeStack.topRunningActivityLocked(null);
288 if (r != null) {
289 mService.setFocusedActivityLocked(r);
Craig Mautner05d29032013-05-03 13:40:13 -0700290 return resumeTopActivitiesLocked(mHomeStack, prev, null);
Craig Mautner69ada552013-04-18 13:51:51 -0700291 }
292 return mService.startHomeActivityLocked(mCurrentUser);
293 }
294
Craig Mautnerde4ef022013-04-07 19:01:33 -0700295 final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r,
296 ActivityStack stack) {
297 if (stack == mHomeStack) {
298 return;
299 }
300 if ((sourceRecord == null && getLastStack() == mHomeStack) ||
Craig Mautner86d67a42013-05-14 10:34:38 -0700301 (sourceRecord != null && sourceRecord.isHomeActivity())) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700302 if (r == null) {
303 r = stack.topRunningActivityLocked(null);
304 }
Craig Mautner86d67a42013-05-14 10:34:38 -0700305 if (r != null && !r.isHomeActivity() && r.isRootActivity()) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700306 r.mLaunchHomeTaskNext = true;
307 }
308 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700309 }
310
Craig Mautner27084302013-03-25 08:05:25 -0700311 void setDismissKeyguard(boolean dismiss) {
312 mDismissKeyguardOnNextActivity = dismiss;
313 }
314
Craig Mautner8d341ef2013-03-26 09:03:27 -0700315 TaskRecord anyTaskForIdLocked(int id) {
316 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
317 ActivityStack stack = mStacks.get(stackNdx);
318 TaskRecord task = stack.taskForIdLocked(id);
319 if (task != null) {
320 return task;
321 }
322 }
323 return null;
324 }
325
Craig Mautner6170f732013-04-02 13:05:23 -0700326 ActivityRecord isInAnyStackLocked(IBinder token) {
327 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
328 final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
329 if (r != null) {
330 return r;
331 }
332 }
333 return null;
334 }
335
Craig Mautner8d341ef2013-03-26 09:03:27 -0700336 int getNextTaskId() {
337 do {
338 mCurTaskId++;
339 if (mCurTaskId <= 0) {
340 mCurTaskId = 1;
341 }
342 } while (anyTaskForIdLocked(mCurTaskId) != null);
343 return mCurTaskId;
344 }
345
Craig Mautnerde4ef022013-04-07 19:01:33 -0700346 void removeTask(TaskRecord task) {
Craig Mautnerb3b36ba2013-05-20 13:21:10 -0700347 mWindowManager.removeTask(task.taskId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700348 final ActivityStack stack = task.stack;
Craig Mautnerb3b36ba2013-05-20 13:21:10 -0700349 final ActivityRecord r = stack.mResumedActivity;
350 if (r != null && r.task == task) {
351 stack.mResumedActivity = null;
352 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700353 if (stack.removeTask(task) && !stack.isHomeStack()) {
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700354 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700355 mStacks.remove(stack);
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700356 final int stackId = stack.mStackId;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700357 final int nextStackId = mWindowManager.removeStack(stackId);
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700358 // TODO: Perhaps we need to let the ActivityManager determine the next focus...
Craig Mautnerac6f8432013-07-17 13:24:59 -0700359 if (mFocusedStack == null || mFocusedStack.mStackId == stackId) {
Craig Mautner1602ec22013-05-12 10:24:27 -0700360 // If this is the last app stack, set mFocusedStack to null.
Craig Mautner29219d92013-04-16 20:19:12 -0700361 mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700362 }
363 }
364 }
365
366 ActivityRecord resumedAppLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700367 ActivityStack stack = getFocusedStack();
368 if (stack == null) {
369 return null;
370 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700371 ActivityRecord resumedActivity = stack.mResumedActivity;
372 if (resumedActivity == null || resumedActivity.app == null) {
373 resumedActivity = stack.mPausingActivity;
374 if (resumedActivity == null || resumedActivity.app == null) {
375 resumedActivity = stack.topRunningActivityLocked(null);
376 }
377 }
378 return resumedActivity;
379 }
380
Craig Mautner20e72272013-04-01 13:45:53 -0700381 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
382 boolean didSomething = false;
383 final String processName = app.processName;
384 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
385 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner858d8a62013-04-23 17:08:34 -0700386 if (!isFrontStack(stack)) {
387 continue;
388 }
Craig Mautner20e72272013-04-01 13:45:53 -0700389 ActivityRecord hr = stack.topRunningActivityLocked(null);
390 if (hr != null) {
391 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
392 && processName.equals(hr.processName)) {
393 try {
394 if (headless) {
395 Slog.e(TAG, "Starting activities not supported on headless device: "
396 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700397 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700398 didSomething = true;
399 }
400 } catch (Exception e) {
401 Slog.w(TAG, "Exception in new application when starting activity "
402 + hr.intent.getComponent().flattenToShortString(), e);
403 throw e;
404 }
Craig Mautner20e72272013-04-01 13:45:53 -0700405 }
406 }
407 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -0700408 if (!didSomething) {
409 ensureActivitiesVisibleLocked(null, 0);
410 }
Craig Mautner20e72272013-04-01 13:45:53 -0700411 return didSomething;
412 }
413
414 boolean allResumedActivitiesIdle() {
415 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700416 final ActivityStack stack = mStacks.get(stackNdx);
417 if (!isFrontStack(stack)) {
418 continue;
419 }
420 final ActivityRecord resumedActivity = stack.mResumedActivity;
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700421 if (resumedActivity == null || !resumedActivity.idle) {
Craig Mautner20e72272013-04-01 13:45:53 -0700422 return false;
423 }
424 }
425 return true;
426 }
427
Craig Mautnerde4ef022013-04-07 19:01:33 -0700428 boolean allResumedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700429 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
430 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner967212c2013-04-13 21:10:58 -0700431 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700432 final ActivityRecord r = stack.mResumedActivity;
433 if (r != null && r.state != ActivityState.RESUMED) {
434 return false;
435 }
436 }
437 }
438 // TODO: Not sure if this should check if all Paused are complete too.
439 switch (mStackState) {
440 case STACK_STATE_HOME_TO_BACK:
Craig Mautner76ea2242013-05-15 11:40:05 -0700441 if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
442 stackStateToString(STACK_STATE_HOME_TO_BACK) + " new=" +
443 stackStateToString(STACK_STATE_HOME_IN_BACK));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700444 mStackState = STACK_STATE_HOME_IN_BACK;
445 break;
446 case STACK_STATE_HOME_TO_FRONT:
Craig Mautner76ea2242013-05-15 11:40:05 -0700447 if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
448 stackStateToString(STACK_STATE_HOME_TO_FRONT) + " new=" +
449 stackStateToString(STACK_STATE_HOME_IN_FRONT));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700450 mStackState = STACK_STATE_HOME_IN_FRONT;
451 break;
452 }
453 return true;
454 }
455
456 boolean allResumedActivitiesVisible() {
457 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
458 final ActivityStack stack = mStacks.get(stackNdx);
459 final ActivityRecord r = stack.mResumedActivity;
460 if (r != null && (!r.nowVisible || r.waitingVisible)) {
461 return false;
462 }
463 }
464 return true;
465 }
466
Craig Mautnercf910b02013-04-23 11:23:27 -0700467 boolean pauseBackStacks(boolean userLeaving) {
468 boolean someActivityPaused = false;
469 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
470 final ActivityStack stack = mStacks.get(stackNdx);
471 if (!isFrontStack(stack) && stack.mResumedActivity != null) {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700472 if (DEBUG_STATES) Slog.d(TAG, "pauseBackStacks: stack=" + stack +
473 " mResumedActivity=" + stack.mResumedActivity);
Craig Mautnercf910b02013-04-23 11:23:27 -0700474 stack.startPausingLocked(userLeaving, false);
475 someActivityPaused = true;
476 }
477 }
478 return someActivityPaused;
479 }
480
Craig Mautnerde4ef022013-04-07 19:01:33 -0700481 boolean allPausedActivitiesComplete() {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700482 boolean pausing = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700483 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
484 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner69ada552013-04-18 13:51:51 -0700485 final ActivityRecord r = stack.mPausingActivity;
486 if (r != null && r.state != ActivityState.PAUSED
487 && r.state != ActivityState.STOPPED
488 && r.state != ActivityState.STOPPING) {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700489 if (DEBUG_STATES) {
490 Slog.d(TAG, "allPausedActivitiesComplete: r=" + r + " state=" + r.state);
491 pausing = false;
492 } else {
493 return false;
494 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700495 }
496 }
Craig Mautnerac6f8432013-07-17 13:24:59 -0700497 return pausing;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700498 }
499
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700500 void reportActivityVisibleLocked(ActivityRecord r) {
Craig Mautner858d8a62013-04-23 17:08:34 -0700501 for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700502 WaitResult w = mWaitingActivityVisible.get(i);
503 w.timeout = false;
504 if (r != null) {
505 w.who = new ComponentName(r.info.packageName, r.info.name);
506 }
507 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
508 w.thisTime = w.totalTime;
509 }
510 mService.notifyAll();
511 dismissKeyguard();
512 }
513
514 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
515 long thisTime, long totalTime) {
516 for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
Craig Mautnerc64f73e2013-04-24 16:44:56 -0700517 WaitResult w = mWaitingActivityLaunched.remove(i);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700518 w.timeout = timeout;
519 if (r != null) {
520 w.who = new ComponentName(r.info.packageName, r.info.name);
521 }
522 w.thisTime = thisTime;
523 w.totalTime = totalTime;
524 }
525 mService.notifyAll();
526 }
527
Craig Mautner29219d92013-04-16 20:19:12 -0700528 ActivityRecord topRunningActivityLocked() {
Craig Mautner1602ec22013-05-12 10:24:27 -0700529 final ActivityStack focusedStack = getFocusedStack();
530 ActivityRecord r = focusedStack.topRunningActivityLocked(null);
531 if (r != null) {
532 return r;
Craig Mautner29219d92013-04-16 20:19:12 -0700533 }
Craig Mautner1602ec22013-05-12 10:24:27 -0700534
Craig Mautner29219d92013-04-16 20:19:12 -0700535 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
536 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700537 if (stack != focusedStack && isFrontStack(stack)) {
Craig Mautner29219d92013-04-16 20:19:12 -0700538 r = stack.topRunningActivityLocked(null);
539 if (r != null) {
540 return r;
541 }
542 }
543 }
544 return null;
545 }
546
Craig Mautner20e72272013-04-01 13:45:53 -0700547 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
548 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
549 ActivityRecord r = null;
Craig Mautner20e72272013-04-01 13:45:53 -0700550 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
551 final ActivityStack stack = mStacks.get(stackNdx);
552 final ActivityRecord ar =
553 stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700554 if (isFrontStack(stack)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700555 r = ar;
556 }
557 }
558 return r;
559 }
560
Craig Mautner23ac33b2013-04-01 16:26:35 -0700561 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
562 String profileFile, ParcelFileDescriptor profileFd, int userId) {
563 // Collect information about the target of the Intent.
564 ActivityInfo aInfo;
565 try {
566 ResolveInfo rInfo =
567 AppGlobals.getPackageManager().resolveIntent(
568 intent, resolvedType,
569 PackageManager.MATCH_DEFAULT_ONLY
570 | ActivityManagerService.STOCK_PM_FLAGS, userId);
571 aInfo = rInfo != null ? rInfo.activityInfo : null;
572 } catch (RemoteException e) {
573 aInfo = null;
574 }
575
576 if (aInfo != null) {
577 // Store the found target back into the intent, because now that
578 // we have it we never want to do this again. For example, if the
579 // user navigates back to this point in the history, we should
580 // always restart the exact same activity.
581 intent.setComponent(new ComponentName(
582 aInfo.applicationInfo.packageName, aInfo.name));
583
584 // Don't debug things in the system process
585 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
586 if (!aInfo.processName.equals("system")) {
587 mService.setDebugApp(aInfo.processName, true, false);
588 }
589 }
590
591 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
592 if (!aInfo.processName.equals("system")) {
593 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
594 }
595 }
596
597 if (profileFile != null) {
598 if (!aInfo.processName.equals("system")) {
599 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
600 profileFile, profileFd,
601 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
602 }
603 }
604 }
605 return aInfo;
606 }
607
Craig Mautner2219a1b2013-03-25 09:44:30 -0700608 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700609 moveHomeStack(true);
Craig Mautner6170f732013-04-02 13:05:23 -0700610 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
Craig Mautner2219a1b2013-03-25 09:44:30 -0700611 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700612 }
613
Craig Mautner23ac33b2013-04-01 16:26:35 -0700614 final int startActivityMayWait(IApplicationThread caller, int callingUid,
615 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
616 String resultWho, int requestCode, int startFlags, String profileFile,
617 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
618 Bundle options, int userId) {
619 // Refuse possible leaked file descriptors
620 if (intent != null && intent.hasFileDescriptors()) {
621 throw new IllegalArgumentException("File descriptors passed in Intent");
622 }
623 boolean componentSpecified = intent.getComponent() != null;
624
625 // Don't modify the client's object!
626 intent = new Intent(intent);
627
628 // Collect information about the target of the Intent.
629 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
630 profileFile, profileFd, userId);
631
632 synchronized (mService) {
633 int callingPid;
634 if (callingUid >= 0) {
635 callingPid = -1;
636 } else if (caller == null) {
637 callingPid = Binder.getCallingPid();
638 callingUid = Binder.getCallingUid();
639 } else {
640 callingPid = callingUid = -1;
641 }
642
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700643 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -0700644 stack.mConfigWillChange = config != null
Craig Mautner23ac33b2013-04-01 16:26:35 -0700645 && mService.mConfiguration.diff(config) != 0;
646 if (DEBUG_CONFIGURATION) Slog.v(TAG,
Craig Mautnerde4ef022013-04-07 19:01:33 -0700647 "Starting activity when config will change = " + stack.mConfigWillChange);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700648
649 final long origId = Binder.clearCallingIdentity();
650
651 if (aInfo != null &&
652 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
653 // This may be a heavy-weight process! Check to see if we already
654 // have another, different heavy-weight process running.
655 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
656 if (mService.mHeavyWeightProcess != null &&
657 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
658 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700659 int realCallingUid = callingUid;
660 if (caller != null) {
661 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
662 if (callerApp != null) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700663 realCallingUid = callerApp.info.uid;
664 } else {
665 Slog.w(TAG, "Unable to find app for caller " + caller
Craig Mautner76ea2242013-05-15 11:40:05 -0700666 + " (pid=" + callingPid + ") when starting: "
Craig Mautner23ac33b2013-04-01 16:26:35 -0700667 + intent.toString());
668 ActivityOptions.abort(options);
669 return ActivityManager.START_PERMISSION_DENIED;
670 }
671 }
672
673 IIntentSender target = mService.getIntentSenderLocked(
674 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
675 realCallingUid, userId, null, null, 0, new Intent[] { intent },
676 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
677 | PendingIntent.FLAG_ONE_SHOT, null);
678
679 Intent newIntent = new Intent();
680 if (requestCode >= 0) {
681 // Caller is requesting a result.
682 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
683 }
684 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
685 new IntentSender(target));
686 if (mService.mHeavyWeightProcess.activities.size() > 0) {
687 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
688 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
689 hist.packageName);
690 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
691 hist.task.taskId);
692 }
693 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
694 aInfo.packageName);
695 newIntent.setFlags(intent.getFlags());
696 newIntent.setClassName("android",
697 HeavyWeightSwitcherActivity.class.getName());
698 intent = newIntent;
699 resolvedType = null;
700 caller = null;
701 callingUid = Binder.getCallingUid();
702 callingPid = Binder.getCallingPid();
703 componentSpecified = true;
704 try {
705 ResolveInfo rInfo =
706 AppGlobals.getPackageManager().resolveIntent(
707 intent, null,
708 PackageManager.MATCH_DEFAULT_ONLY
709 | ActivityManagerService.STOCK_PM_FLAGS, userId);
710 aInfo = rInfo != null ? rInfo.activityInfo : null;
711 aInfo = mService.getActivityInfoForUser(aInfo, userId);
712 } catch (RemoteException e) {
713 aInfo = null;
714 }
715 }
716 }
717 }
718
Craig Mautner6170f732013-04-02 13:05:23 -0700719 int res = startActivityLocked(caller, intent, resolvedType,
Craig Mautner23ac33b2013-04-01 16:26:35 -0700720 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
721 callingPackage, startFlags, options, componentSpecified, null);
722
Craig Mautnerde4ef022013-04-07 19:01:33 -0700723 if (stack.mConfigWillChange) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700724 // If the caller also wants to switch to a new configuration,
725 // do so now. This allows a clean switch, as we are waiting
726 // for the current activity to pause (so we will not destroy
727 // it), and have not yet started the next activity.
728 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
729 "updateConfiguration()");
Craig Mautnerde4ef022013-04-07 19:01:33 -0700730 stack.mConfigWillChange = false;
Craig Mautner23ac33b2013-04-01 16:26:35 -0700731 if (DEBUG_CONFIGURATION) Slog.v(TAG,
732 "Updating to new configuration after starting activity.");
733 mService.updateConfigurationLocked(config, null, false, false);
734 }
735
736 Binder.restoreCallingIdentity(origId);
737
738 if (outResult != null) {
739 outResult.result = res;
740 if (res == ActivityManager.START_SUCCESS) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700741 mWaitingActivityLaunched.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700742 do {
743 try {
744 mService.wait();
745 } catch (InterruptedException e) {
746 }
747 } while (!outResult.timeout && outResult.who == null);
748 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700749 ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700750 if (r.nowVisible) {
751 outResult.timeout = false;
752 outResult.who = new ComponentName(r.info.packageName, r.info.name);
753 outResult.totalTime = 0;
754 outResult.thisTime = 0;
755 } else {
756 outResult.thisTime = SystemClock.uptimeMillis();
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700757 mWaitingActivityVisible.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700758 do {
759 try {
760 mService.wait();
761 } catch (InterruptedException e) {
762 }
763 } while (!outResult.timeout && outResult.who == null);
764 }
765 }
766 }
767
768 return res;
769 }
770 }
771
772 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
773 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
774 Bundle options, int userId) {
775 if (intents == null) {
776 throw new NullPointerException("intents is null");
777 }
778 if (resolvedTypes == null) {
779 throw new NullPointerException("resolvedTypes is null");
780 }
781 if (intents.length != resolvedTypes.length) {
782 throw new IllegalArgumentException("intents are length different than resolvedTypes");
783 }
784
Craig Mautner23ac33b2013-04-01 16:26:35 -0700785
786 int callingPid;
787 if (callingUid >= 0) {
788 callingPid = -1;
789 } else if (caller == null) {
790 callingPid = Binder.getCallingPid();
791 callingUid = Binder.getCallingUid();
792 } else {
793 callingPid = callingUid = -1;
794 }
795 final long origId = Binder.clearCallingIdentity();
796 try {
797 synchronized (mService) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700798 ActivityRecord[] outActivity = new ActivityRecord[1];
Craig Mautner23ac33b2013-04-01 16:26:35 -0700799 for (int i=0; i<intents.length; i++) {
800 Intent intent = intents[i];
801 if (intent == null) {
802 continue;
803 }
804
805 // Refuse possible leaked file descriptors
806 if (intent != null && intent.hasFileDescriptors()) {
807 throw new IllegalArgumentException("File descriptors passed in Intent");
808 }
809
810 boolean componentSpecified = intent.getComponent() != null;
811
812 // Don't modify the client's object!
813 intent = new Intent(intent);
814
815 // Collect information about the target of the Intent.
816 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
817 0, null, null, userId);
818 // TODO: New, check if this is correct
819 aInfo = mService.getActivityInfoForUser(aInfo, userId);
820
821 if (aInfo != null &&
822 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
823 != 0) {
824 throw new IllegalArgumentException(
825 "FLAG_CANT_SAVE_STATE not supported here");
826 }
827
828 Bundle theseOptions;
829 if (options != null && i == intents.length-1) {
830 theseOptions = options;
831 } else {
832 theseOptions = null;
833 }
Craig Mautner6170f732013-04-02 13:05:23 -0700834 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Craig Mautner23ac33b2013-04-01 16:26:35 -0700835 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
836 0, theseOptions, componentSpecified, outActivity);
837 if (res < 0) {
838 return res;
839 }
840
841 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
842 }
843 }
844 } finally {
845 Binder.restoreCallingIdentity(origId);
846 }
847
848 return ActivityManager.START_SUCCESS;
849 }
850
Craig Mautner2420ead2013-04-01 17:13:20 -0700851 final boolean realStartActivityLocked(ActivityRecord r,
852 ProcessRecord app, boolean andResume, boolean checkConfig)
853 throws RemoteException {
854
855 r.startFreezingScreenLocked(app, 0);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700856 mWindowManager.setAppVisibility(r.appToken, true);
Craig Mautner2420ead2013-04-01 17:13:20 -0700857
858 // schedule launch ticks to collect information about slow apps.
859 r.startLaunchTickingLocked();
860
861 // Have the window manager re-evaluate the orientation of
862 // the screen based on the new activity order. Note that
863 // as a result of this, it can call back into the activity
864 // manager with a new orientation. We don't care about that,
865 // because the activity is not currently running so we are
866 // just restarting it anyway.
867 if (checkConfig) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700868 Configuration config = mWindowManager.updateOrientationFromAppTokens(
Craig Mautner2420ead2013-04-01 17:13:20 -0700869 mService.mConfiguration,
870 r.mayFreezeScreenLocked(app) ? r.appToken : null);
871 mService.updateConfigurationLocked(config, r, false, false);
872 }
873
874 r.app = app;
875 app.waitingToKill = null;
876 r.launchCount++;
877 r.lastLaunchTime = SystemClock.uptimeMillis();
878
879 if (localLOGV) Slog.v(TAG, "Launching: " + r);
880
881 int idx = app.activities.indexOf(r);
882 if (idx < 0) {
883 app.activities.add(r);
884 }
885 mService.updateLruProcessLocked(app, true);
886
887 final ActivityStack stack = r.task.stack;
888 try {
889 if (app.thread == null) {
890 throw new RemoteException();
891 }
892 List<ResultInfo> results = null;
893 List<Intent> newIntents = null;
894 if (andResume) {
895 results = r.results;
896 newIntents = r.newIntents;
897 }
898 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
899 + " icicle=" + r.icicle
900 + " with results=" + results + " newIntents=" + newIntents
901 + " andResume=" + andResume);
902 if (andResume) {
903 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
904 r.userId, System.identityHashCode(r),
905 r.task.taskId, r.shortComponentName);
906 }
Craig Mautnerac6f8432013-07-17 13:24:59 -0700907 if (r.isHomeActivity() && r.isNotResolverActivity()) {
Craig Mautnere428a7f2013-08-17 17:04:56 -0700908 mService.mHomeProcess.add(app);
Craig Mautner2420ead2013-04-01 17:13:20 -0700909 }
910 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
911 r.sleeping = false;
912 r.forceNewConfig = false;
913 mService.showAskCompatModeDialogLocked(r);
914 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
915 String profileFile = null;
916 ParcelFileDescriptor profileFd = null;
917 boolean profileAutoStop = false;
918 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
919 if (mService.mProfileProc == null || mService.mProfileProc == app) {
920 mService.mProfileProc = app;
921 profileFile = mService.mProfileFile;
922 profileFd = mService.mProfileFd;
923 profileAutoStop = mService.mAutoStopProfiler;
924 }
925 }
926 app.hasShownUi = true;
927 app.pendingUiClean = true;
928 if (profileFd != null) {
929 try {
930 profileFd = profileFd.dup();
931 } catch (IOException e) {
932 if (profileFd != null) {
933 try {
934 profileFd.close();
935 } catch (IOException o) {
936 }
937 profileFd = null;
938 }
939 }
940 }
Dianne Hackborna413dc02013-07-12 12:02:55 -0700941 app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
Craig Mautner2420ead2013-04-01 17:13:20 -0700942 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
943 System.identityHashCode(r), r.info,
Dianne Hackborna413dc02013-07-12 12:02:55 -0700944 new Configuration(mService.mConfiguration), r.compat,
945 app.repProcState, r.icicle, results, newIntents, !andResume,
Craig Mautner2420ead2013-04-01 17:13:20 -0700946 mService.isNextTransitionForward(), profileFile, profileFd,
947 profileAutoStop);
948
949 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
950 // This may be a heavy-weight process! Note that the package
951 // manager will ensure that only activity can run in the main
952 // process of the .apk, which is the only thing that will be
953 // considered heavy-weight.
954 if (app.processName.equals(app.info.packageName)) {
955 if (mService.mHeavyWeightProcess != null
956 && mService.mHeavyWeightProcess != app) {
957 Slog.w(TAG, "Starting new heavy weight process " + app
958 + " when already running "
959 + mService.mHeavyWeightProcess);
960 }
961 mService.mHeavyWeightProcess = app;
962 Message msg = mService.mHandler.obtainMessage(
963 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
964 msg.obj = r;
965 mService.mHandler.sendMessage(msg);
966 }
967 }
968
969 } catch (RemoteException e) {
970 if (r.launchFailed) {
971 // This is the second time we failed -- finish activity
972 // and give up.
973 Slog.e(TAG, "Second failure launching "
974 + r.intent.getComponent().flattenToShortString()
975 + ", giving up", e);
976 mService.appDiedLocked(app, app.pid, app.thread);
977 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
978 "2nd-crash", false);
979 return false;
980 }
981
982 // This is the first time we failed -- restart process and
983 // retry.
984 app.activities.remove(r);
985 throw e;
986 }
987
988 r.launchFailed = false;
989 if (stack.updateLRUListLocked(r)) {
990 Slog.w(TAG, "Activity " + r
991 + " being launched, but already in LRU list");
992 }
993
994 if (andResume) {
995 // As part of the process of launching, ActivityThread also performs
996 // a resume.
997 stack.minimalResumeActivityLocked(r);
998 } else {
999 // This activity is not starting in the resumed state... which
1000 // should look like we asked it to pause+stop (but remain visible),
1001 // and it has done so and reported back the current icicle and
1002 // other state.
1003 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
1004 + " (starting in stopped state)");
1005 r.state = ActivityState.STOPPED;
1006 r.stopped = true;
1007 }
1008
1009 // Launch the new version setup screen if needed. We do this -after-
1010 // launching the initial activity (that is, home), so that it can have
1011 // a chance to initialize itself while in the background, making the
1012 // switch back to it faster and look better.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001013 if (isFrontStack(stack)) {
Craig Mautner2420ead2013-04-01 17:13:20 -07001014 mService.startSetupActivityLocked();
1015 }
1016
1017 return true;
1018 }
1019
Craig Mautnere79d42682013-04-01 19:01:53 -07001020 void startSpecificActivityLocked(ActivityRecord r,
1021 boolean andResume, boolean checkConfig) {
1022 // Is this activity's application already running?
1023 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
1024 r.info.applicationInfo.uid);
1025
1026 r.task.stack.setLaunchTime(r);
1027
1028 if (app != null && app.thread != null) {
1029 try {
Dianne Hackbornd2932242013-08-05 18:18:42 -07001030 app.addPackage(r.info.packageName, mService.mProcessStats);
Craig Mautnere79d42682013-04-01 19:01:53 -07001031 realStartActivityLocked(r, app, andResume, checkConfig);
1032 return;
1033 } catch (RemoteException e) {
1034 Slog.w(TAG, "Exception when starting activity "
1035 + r.intent.getComponent().flattenToShortString(), e);
1036 }
1037
1038 // If a dead object exception was thrown -- fall through to
1039 // restart the application.
1040 }
1041
1042 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
1043 "activity", r.intent.getComponent(), false, false);
1044 }
1045
Craig Mautner6170f732013-04-02 13:05:23 -07001046 final int startActivityLocked(IApplicationThread caller,
1047 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
1048 String resultWho, int requestCode,
1049 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
1050 boolean componentSpecified, ActivityRecord[] outActivity) {
1051 int err = ActivityManager.START_SUCCESS;
1052
1053 ProcessRecord callerApp = null;
1054 if (caller != null) {
1055 callerApp = mService.getRecordForAppLocked(caller);
1056 if (callerApp != null) {
1057 callingPid = callerApp.pid;
1058 callingUid = callerApp.info.uid;
1059 } else {
1060 Slog.w(TAG, "Unable to find app for caller " + caller
1061 + " (pid=" + callingPid + ") when starting: "
1062 + intent.toString());
1063 err = ActivityManager.START_PERMISSION_DENIED;
1064 }
1065 }
1066
1067 if (err == ActivityManager.START_SUCCESS) {
1068 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
1069 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
1070 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
1071 }
1072
1073 ActivityRecord sourceRecord = null;
1074 ActivityRecord resultRecord = null;
1075 if (resultTo != null) {
1076 sourceRecord = isInAnyStackLocked(resultTo);
1077 if (DEBUG_RESULTS) Slog.v(
1078 TAG, "Will send result to " + resultTo + " " + sourceRecord);
1079 if (sourceRecord != null) {
1080 if (requestCode >= 0 && !sourceRecord.finishing) {
1081 resultRecord = sourceRecord;
1082 }
1083 }
1084 }
1085 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
1086
1087 int launchFlags = intent.getFlags();
1088
1089 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
1090 && sourceRecord != null) {
1091 // Transfer the result target from the source activity to the new
1092 // one being started, including any failures.
1093 if (requestCode >= 0) {
1094 ActivityOptions.abort(options);
1095 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
1096 }
1097 resultRecord = sourceRecord.resultTo;
1098 resultWho = sourceRecord.resultWho;
1099 requestCode = sourceRecord.requestCode;
1100 sourceRecord.resultTo = null;
1101 if (resultRecord != null) {
1102 resultRecord.removeResultsLocked(
1103 sourceRecord, resultWho, requestCode);
1104 }
1105 }
1106
1107 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
1108 // We couldn't find a class that can handle the given Intent.
1109 // That's the end of that!
1110 err = ActivityManager.START_INTENT_NOT_RESOLVED;
1111 }
1112
1113 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
1114 // We couldn't find the specific class specified in the Intent.
1115 // Also the end of the line.
1116 err = ActivityManager.START_CLASS_NOT_FOUND;
1117 }
1118
1119 if (err != ActivityManager.START_SUCCESS) {
1120 if (resultRecord != null) {
1121 resultStack.sendActivityResultLocked(-1,
1122 resultRecord, resultWho, requestCode,
1123 Activity.RESULT_CANCELED, null);
1124 }
1125 setDismissKeyguard(false);
1126 ActivityOptions.abort(options);
1127 return err;
1128 }
1129
1130 final int startAnyPerm = mService.checkPermission(
1131 START_ANY_ACTIVITY, callingPid, callingUid);
1132 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
1133 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
1134 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
1135 if (resultRecord != null) {
1136 resultStack.sendActivityResultLocked(-1,
1137 resultRecord, resultWho, requestCode,
1138 Activity.RESULT_CANCELED, null);
1139 }
1140 setDismissKeyguard(false);
1141 String msg;
1142 if (!aInfo.exported) {
1143 msg = "Permission Denial: starting " + intent.toString()
1144 + " from " + callerApp + " (pid=" + callingPid
1145 + ", uid=" + callingUid + ")"
1146 + " not exported from uid " + aInfo.applicationInfo.uid;
1147 } else {
1148 msg = "Permission Denial: starting " + intent.toString()
1149 + " from " + callerApp + " (pid=" + callingPid
1150 + ", uid=" + callingUid + ")"
1151 + " requires " + aInfo.permission;
1152 }
1153 Slog.w(TAG, msg);
1154 throw new SecurityException(msg);
1155 }
1156
Ben Gruverdd72c9e2013-08-06 12:34:17 -07001157 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
Ben Gruverb6223792013-07-29 16:35:40 -07001158 callingPid, resolvedType, aInfo.applicationInfo);
Ben Gruver5e207332013-04-03 17:41:37 -07001159
Craig Mautner6170f732013-04-02 13:05:23 -07001160 if (mService.mController != null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001161 try {
1162 // The Intent we give to the watcher has the extra data
1163 // stripped off, since it can contain private information.
1164 Intent watchIntent = intent.cloneFilter();
Ben Gruver5e207332013-04-03 17:41:37 -07001165 abort |= !mService.mController.activityStarting(watchIntent,
Craig Mautner6170f732013-04-02 13:05:23 -07001166 aInfo.applicationInfo.packageName);
1167 } catch (RemoteException e) {
1168 mService.mController = null;
1169 }
Ben Gruver5e207332013-04-03 17:41:37 -07001170 }
Craig Mautner6170f732013-04-02 13:05:23 -07001171
Ben Gruver5e207332013-04-03 17:41:37 -07001172 if (abort) {
1173 if (resultRecord != null) {
1174 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Craig Mautner6170f732013-04-02 13:05:23 -07001175 Activity.RESULT_CANCELED, null);
Craig Mautner6170f732013-04-02 13:05:23 -07001176 }
Ben Gruver5e207332013-04-03 17:41:37 -07001177 // We pretend to the caller that it was really started, but
1178 // they will just get a cancel result.
1179 setDismissKeyguard(false);
1180 ActivityOptions.abort(options);
1181 return ActivityManager.START_SUCCESS;
Craig Mautner6170f732013-04-02 13:05:23 -07001182 }
1183
1184 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1185 intent, resolvedType, aInfo, mService.mConfiguration,
Craig Mautnerde4ef022013-04-07 19:01:33 -07001186 resultRecord, resultWho, requestCode, componentSpecified, this);
Craig Mautner6170f732013-04-02 13:05:23 -07001187 if (outActivity != null) {
1188 outActivity[0] = r;
1189 }
1190
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001191 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001192 if (stack.mResumedActivity == null
1193 || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
Craig Mautner6170f732013-04-02 13:05:23 -07001194 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1195 PendingActivityLaunch pal =
Craig Mautnerde4ef022013-04-07 19:01:33 -07001196 new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
Craig Mautner6170f732013-04-02 13:05:23 -07001197 mService.mPendingActivityLaunches.add(pal);
1198 setDismissKeyguard(false);
1199 ActivityOptions.abort(options);
1200 return ActivityManager.START_SWITCHES_CANCELED;
1201 }
1202 }
1203
1204 if (mService.mDidAppSwitch) {
1205 // This is the second allowed switch since we stopped switches,
1206 // so now just generally allow switches. Use case: user presses
1207 // home (switches disabled, switch to home, mDidAppSwitch now true);
1208 // user taps a home icon (coming from home so allowed, we hit here
1209 // and now allow anyone to switch again).
1210 mService.mAppSwitchesAllowedTime = 0;
1211 } else {
1212 mService.mDidAppSwitch = true;
1213 }
1214
1215 mService.doPendingActivityLaunchesLocked(false);
1216
Craig Mautner8849a5e2013-04-02 16:41:03 -07001217 err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001218 if (stack.mPausingActivity == null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001219 // Someone asked to have the keyguard dismissed on the next
1220 // activity start, but we are not actually doing an activity
1221 // switch... just dismiss the keyguard now, because we
1222 // probably want to see whatever is behind it.
1223 dismissKeyguard();
1224 }
1225 return err;
1226 }
1227
Craig Mautnerac6f8432013-07-17 13:24:59 -07001228 ActivityStack adjustStackFocus(ActivityRecord r) {
Craig Mautner1d001b62013-06-18 16:52:43 -07001229 final TaskRecord task = r.task;
1230 if (r.isApplicationActivity() || (task != null && task.isApplicationTask())) {
Craig Mautnerac6f8432013-07-17 13:24:59 -07001231 if (task != null) {
1232 if (mFocusedStack != task.stack) {
1233 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1234 "adjustStackFocus: Setting focused stack to r=" + r + " task=" + task);
1235 mFocusedStack = task.stack;
1236 } else {
1237 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1238 "adjustStackFocus: Focused stack already=" + mFocusedStack);
1239 }
1240 return mFocusedStack;
1241 }
1242
1243 if (mFocusedStack != null) {
1244 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1245 "adjustStackFocus: Have a focused stack=" + mFocusedStack);
1246 return mFocusedStack;
1247 }
1248
1249 for (int stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
1250 ActivityStack stack = mStacks.get(stackNdx);
1251 if (!stack.isHomeStack()) {
1252 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1253 "adjustStackFocus: Setting focused stack=" + stack);
1254 mFocusedStack = stack;
1255 return mFocusedStack;
Craig Mautner858d8a62013-04-23 17:08:34 -07001256 }
1257 }
Craig Mautnerac6f8432013-07-17 13:24:59 -07001258
1259 // Time to create the first app stack for this user.
1260 int stackId = mService.createStack(-1, HOME_STACK_ID,
1261 StackBox.TASK_STACK_GOES_OVER, 1.0f);
1262 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack r=" + r +
1263 " stackId=" + stackId);
1264 mFocusedStack = getStack(stackId);
Craig Mautner29219d92013-04-16 20:19:12 -07001265 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001266 }
1267 return mHomeStack;
1268 }
1269
Craig Mautner29219d92013-04-16 20:19:12 -07001270 void setFocusedStack(ActivityRecord r) {
1271 if (r == null) {
1272 return;
1273 }
Craig Mautner86d67a42013-05-14 10:34:38 -07001274 if (!r.isApplicationActivity() || (r.task != null && !r.task.isApplicationTask())) {
Craig Mautner29219d92013-04-16 20:19:12 -07001275 if (mStackState != STACK_STATE_HOME_IN_FRONT) {
Craig Mautnere7c58b62013-06-12 20:19:00 -07001276 if (DEBUG_STACK || DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: mStackState old=" +
Craig Mautner76ea2242013-05-15 11:40:05 -07001277 stackStateToString(mStackState) + " new=" +
1278 stackStateToString(STACK_STATE_HOME_TO_FRONT) +
1279 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001280 mStackState = STACK_STATE_HOME_TO_FRONT;
1281 }
1282 } else {
Craig Mautnerac6f8432013-07-17 13:24:59 -07001283 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1284 "setFocusedStack: Setting focused stack to r=" + r + " task=" + r.task +
1285 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001286 mFocusedStack = r.task.stack;
1287 if (mStackState != STACK_STATE_HOME_IN_BACK) {
Craig Mautner76ea2242013-05-15 11:40:05 -07001288 if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
1289 stackStateToString(mStackState) + " new=" +
1290 stackStateToString(STACK_STATE_HOME_TO_BACK) +
1291 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001292 mStackState = STACK_STATE_HOME_TO_BACK;
1293 }
1294 }
1295 }
1296
Craig Mautner8849a5e2013-04-02 16:41:03 -07001297 final int startActivityUncheckedLocked(ActivityRecord r,
1298 ActivityRecord sourceRecord, int startFlags, boolean doResume,
1299 Bundle options) {
1300 final Intent intent = r.intent;
1301 final int callingUid = r.launchedFromUid;
1302
1303 int launchFlags = intent.getFlags();
1304
Craig Mautner8849a5e2013-04-02 16:41:03 -07001305 // We'll invoke onUserLeaving before onPause only if the launching
1306 // activity did not explicitly state that this is an automated launch.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001307 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1308 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001309
1310 // If the caller has asked not to resume at this point, we make note
1311 // of this in the record so that we can skip it when trying to find
1312 // the top running activity.
1313 if (!doResume) {
1314 r.delayedResume = true;
1315 }
1316
1317 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1318
1319 // If the onlyIfNeeded flag is set, then we can do this if the activity
1320 // being launched is the same as the one making the call... or, as
1321 // a special case, if we do not know the caller then we count the
1322 // current top activity as the caller.
1323 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1324 ActivityRecord checkedCaller = sourceRecord;
1325 if (checkedCaller == null) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001326 checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001327 }
1328 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1329 // Caller is not the same as launcher, so always needed.
1330 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1331 }
1332 }
1333
1334 if (sourceRecord == null) {
1335 // This activity is not being started from another... in this
1336 // case we -always- start a new task.
1337 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Craig Mautner29219d92013-04-16 20:19:12 -07001338 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1339 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001340 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1341 }
1342 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1343 // The original activity who is starting us is running as a single
1344 // instance... this new activity it is starting must go on its
1345 // own task.
1346 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1347 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1348 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1349 // The activity being started is a single instance... it always
1350 // gets launched into its own task.
1351 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1352 }
1353
Craig Mautnerde4ef022013-04-07 19:01:33 -07001354 final ActivityStack sourceStack;
Craig Mautner525f3d92013-05-07 14:01:50 -07001355 TaskRecord sourceTask;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001356 if (sourceRecord != null) {
1357 sourceTask = sourceRecord.task;
1358 sourceStack = sourceTask.stack;
1359 } else {
1360 sourceTask = null;
1361 sourceStack = null;
1362 }
1363
Craig Mautner8849a5e2013-04-02 16:41:03 -07001364 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1365 // For whatever reason this activity is being launched into a new
1366 // task... yet the caller has requested a result back. Well, that
1367 // is pretty messed up, so instead immediately send back a cancel
1368 // and let the new task continue launched as normal without a
1369 // dependency on its originator.
1370 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1371 r.resultTo.task.stack.sendActivityResultLocked(-1,
1372 r.resultTo, r.resultWho, r.requestCode,
1373 Activity.RESULT_CANCELED, null);
1374 r.resultTo = null;
1375 }
1376
1377 boolean addingToTask = false;
1378 boolean movedHome = false;
1379 TaskRecord reuseTask = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001380 ActivityStack targetStack;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001381 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1382 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1383 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1384 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1385 // If bring to front is requested, and no result is requested, and
1386 // we can find a task that was started with this same
1387 // component, then instead of launching bring that one to the front.
1388 if (r.resultTo == null) {
1389 // See if there is a task to bring to the front. If this is
1390 // a SINGLE_INSTANCE activity, there can be one and only one
1391 // instance of it in the history, and it is always in its own
1392 // unique task, so we do a special search.
1393 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
Craig Mautnerac6f8432013-07-17 13:24:59 -07001394 ? findTaskLocked(r)
Craig Mautner8849a5e2013-04-02 16:41:03 -07001395 : findActivityLocked(intent, r.info);
1396 if (intentActivity != null) {
Craig Mautner29219d92013-04-16 20:19:12 -07001397 if (r.task == null) {
1398 r.task = intentActivity.task;
1399 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001400 targetStack = intentActivity.task.stack;
Craig Mautner0f922742013-08-06 08:44:42 -07001401 targetStack.mLastPausedActivity = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001402 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001403 if (intentActivity.task.intent == null) {
1404 // This task was started because of movement of
1405 // the activity based on affinity... now that we
1406 // are actually launching it, we can assign the
1407 // base intent.
1408 intentActivity.task.setIntent(intent, r.info);
1409 }
1410 // If the target task is not in the front, then we need
1411 // to bring it to the front... except... well, with
1412 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
1413 // to have the same behavior as if a new instance was
1414 // being started, which means not bringing it to the front
1415 // if the caller is not itself in the front.
Craig Mautner165640b2013-04-20 10:34:33 -07001416 final ActivityStack lastStack = getLastStack();
1417 ActivityRecord curTop = lastStack == null?
1418 null : lastStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001419 if (curTop != null && curTop.task != intentActivity.task) {
1420 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Craig Mautnerd0f964f2013-08-07 11:16:33 -07001421 if (sourceRecord == null || (sourceStack.topActivity() != null &&
1422 sourceStack.topActivity().task == sourceRecord.task)) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001423 // We really do want to push this one into the
1424 // user's face, right now.
1425 movedHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001426 if ((launchFlags &
Craig Mautner29219d92013-04-16 20:19:12 -07001427 (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1428 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
Craig Mautnere12a4a62013-08-29 12:24:56 -07001429 // Caller wants to appear on home activity.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001430 r.mLaunchHomeTaskNext = true;
1431 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001432 targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1433 options = null;
1434 }
1435 }
1436 // If the caller has requested that the target task be
1437 // reset, then do so.
1438 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1439 intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1440 }
1441 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1442 // We don't need to start a new activity, and
1443 // the client said not to do anything if that
1444 // is the case, so this is it! And for paranoia, make
1445 // sure we have correctly resumed the top activity.
1446 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001447 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001448 resumeTopActivitiesLocked(targetStack, null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001449 } else {
1450 ActivityOptions.abort(options);
1451 }
Craig Mautner29219d92013-04-16 20:19:12 -07001452 if (r.task == null) Slog.v(TAG,
1453 "startActivityUncheckedLocked: task left null",
1454 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001455 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1456 }
1457 if ((launchFlags &
1458 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1459 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1460 // The caller has requested to completely replace any
1461 // existing task with its new activity. Well that should
1462 // not be too hard...
1463 reuseTask = intentActivity.task;
1464 reuseTask.performClearTaskLocked();
1465 reuseTask.setIntent(r.intent, r.info);
1466 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1467 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1468 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1469 // In this situation we want to remove all activities
1470 // from the task up to the one being started. In most
1471 // cases this means we are resetting the task to its
1472 // initial state.
1473 ActivityRecord top =
1474 intentActivity.task.performClearTaskLocked(r, launchFlags);
1475 if (top != null) {
1476 if (top.frontOfTask) {
1477 // Activity aliases may mean we use different
1478 // intents for the top activity, so make sure
1479 // the task now has the identity of the new
1480 // intent.
1481 top.task.setIntent(r.intent, r.info);
1482 }
1483 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1484 r, top.task);
1485 top.deliverNewIntentLocked(callingUid, r.intent);
1486 } else {
1487 // A special case: we need to
1488 // start the activity because it is not currently
1489 // running, and the caller has asked to clear the
1490 // current task to have this activity at the top.
1491 addingToTask = true;
1492 // Now pretend like this activity is being started
1493 // by the top of its task, so it is put in the
1494 // right place.
1495 sourceRecord = intentActivity;
1496 }
1497 } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1498 // In this case the top activity on the task is the
1499 // same as the one being launched, so we take that
1500 // as a request to bring the task to the foreground.
1501 // If the top activity in the task is the root
1502 // activity, deliver this new intent to it if it
1503 // desires.
1504 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1505 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1506 && intentActivity.realActivity.equals(r.realActivity)) {
1507 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1508 intentActivity.task);
1509 if (intentActivity.frontOfTask) {
1510 intentActivity.task.setIntent(r.intent, r.info);
1511 }
1512 intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1513 } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1514 // In this case we are launching the root activity
1515 // of the task, but with a different intent. We
1516 // should start a new instance on top.
1517 addingToTask = true;
1518 sourceRecord = intentActivity;
1519 }
1520 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1521 // In this case an activity is being launched in to an
1522 // existing task, without resetting that task. This
1523 // is typically the situation of launching an activity
1524 // from a notification or shortcut. We want to place
1525 // the new activity on top of the current task.
1526 addingToTask = true;
1527 sourceRecord = intentActivity;
1528 } else if (!intentActivity.task.rootWasReset) {
1529 // In this case we are launching in to an existing task
1530 // that has not yet been started from its front door.
1531 // The current task has been brought to the front.
1532 // Ideally, we'd probably like to place this new task
1533 // at the bottom of its stack, but that's a little hard
1534 // to do with the current organization of the code so
1535 // for now we'll just drop it.
1536 intentActivity.task.setIntent(r.intent, r.info);
1537 }
1538 if (!addingToTask && reuseTask == null) {
1539 // We didn't do anything... but it was needed (a.k.a., client
1540 // don't use that intent!) And for paranoia, make
1541 // sure we have correctly resumed the top activity.
1542 if (doResume) {
Craig Mautnere12a4a62013-08-29 12:24:56 -07001543 // Reset flag so it gets correctly reevaluated.
1544 intentActivity.mLaunchHomeTaskNext = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001545 setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1546 targetStack.resumeTopActivityLocked(null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001547 } else {
1548 ActivityOptions.abort(options);
1549 }
Craig Mautner29219d92013-04-16 20:19:12 -07001550 if (r.task == null) Slog.v(TAG,
1551 "startActivityUncheckedLocked: task left null",
1552 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001553 return ActivityManager.START_TASK_TO_FRONT;
1554 }
1555 }
1556 }
1557 }
1558
1559 //String uri = r.intent.toURI();
1560 //Intent intent2 = new Intent(uri);
1561 //Slog.i(TAG, "Given intent: " + r.intent);
1562 //Slog.i(TAG, "URI is: " + uri);
1563 //Slog.i(TAG, "To intent: " + intent2);
1564
1565 if (r.packageName != null) {
1566 // If the activity being launched is the same as the one currently
1567 // at the top, then we need to check if it should only be launched
1568 // once.
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001569 ActivityStack topStack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001570 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001571 if (top != null && r.resultTo == null) {
1572 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1573 if (top.app != null && top.app.thread != null) {
1574 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1575 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1576 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1577 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1578 top.task);
1579 // For paranoia, make sure we have correctly
1580 // resumed the top activity.
Craig Mautner0f922742013-08-06 08:44:42 -07001581 topStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001582 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001583 setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001584 resumeTopActivitiesLocked();
Craig Mautner8849a5e2013-04-02 16:41:03 -07001585 }
1586 ActivityOptions.abort(options);
1587 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1588 // We don't need to start a new activity, and
1589 // the client said not to do anything if that
1590 // is the case, so this is it!
Craig Mautner29219d92013-04-16 20:19:12 -07001591 if (r.task == null) Slog.v(TAG,
1592 "startActivityUncheckedLocked: task left null",
1593 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001594 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1595 }
1596 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner29219d92013-04-16 20:19:12 -07001597 if (r.task == null) Slog.v(TAG,
1598 "startActivityUncheckedLocked: task left null",
1599 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001600 return ActivityManager.START_DELIVERED_TO_TOP;
1601 }
1602 }
1603 }
1604 }
1605
1606 } else {
1607 if (r.resultTo != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001608 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1609 r.requestCode, Activity.RESULT_CANCELED, null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001610 }
1611 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001612 if (r.task == null) Slog.v(TAG,
1613 "startActivityUncheckedLocked: task left null",
1614 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001615 return ActivityManager.START_CLASS_NOT_FOUND;
1616 }
1617
1618 boolean newTask = false;
1619 boolean keepCurTransition = false;
1620
1621 // Should this be considered a new task?
1622 if (r.resultTo == null && !addingToTask
1623 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Craig Mautnerac6f8432013-07-17 13:24:59 -07001624 targetStack = adjustStackFocus(r);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001625 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001626 if (reuseTask == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001627 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1628 null, true);
1629 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1630 r.task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001631 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001632 r.setTask(reuseTask, reuseTask, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001633 }
1634 newTask = true;
1635 if (!movedHome) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001636 if ((launchFlags &
1637 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1638 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1639 // Caller wants to appear on home activity, so before starting
1640 // their own activity we will bring home to the front.
1641 r.mLaunchHomeTaskNext = true;
1642 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001643 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001644 } else if (sourceRecord != null) {
Craig Mautner525f3d92013-05-07 14:01:50 -07001645 sourceTask = sourceRecord.task;
1646 targetStack = sourceTask.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001647 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001648 if (!addingToTask &&
1649 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1650 // In this case, we are adding the activity to an existing
1651 // task, but the caller has asked to clear that task if the
1652 // activity is already running.
Craig Mautner525f3d92013-05-07 14:01:50 -07001653 ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001654 keepCurTransition = true;
1655 if (top != null) {
1656 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1657 top.deliverNewIntentLocked(callingUid, r.intent);
1658 // For paranoia, make sure we have correctly
1659 // resumed the top activity.
Craig Mautner0f922742013-08-06 08:44:42 -07001660 targetStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001661 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001662 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001663 targetStack.resumeTopActivityLocked(null);
1664 }
1665 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001666 if (r.task == null) Slog.v(TAG,
1667 "startActivityUncheckedLocked: task left null",
1668 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001669 return ActivityManager.START_DELIVERED_TO_TOP;
1670 }
1671 } else if (!addingToTask &&
1672 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1673 // In this case, we are launching an activity in our own task
1674 // that may already be running somewhere in the history, and
1675 // we want to shuffle it to the front of the stack if so.
Craig Mautner525f3d92013-05-07 14:01:50 -07001676 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001677 if (top != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001678 final TaskRecord task = top.task;
1679 task.moveActivityToFrontLocked(top);
1680 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001681 top.updateOptionsLocked(options);
1682 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner0f922742013-08-06 08:44:42 -07001683 targetStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001684 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001685 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001686 targetStack.resumeTopActivityLocked(null);
1687 }
1688 return ActivityManager.START_DELIVERED_TO_TOP;
1689 }
1690 }
1691 // An existing activity is starting this new activity, so we want
1692 // to keep the new one in the same task as the one that is starting
1693 // it.
Craig Mautner525f3d92013-05-07 14:01:50 -07001694 r.setTask(sourceTask, sourceRecord.thumbHolder, false);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001695 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1696 + " in existing task " + r.task);
1697
1698 } else {
1699 // This not being started from an existing activity, and not part
1700 // of a new task... just put it in the top task, though these days
1701 // this case should never happen.
Craig Mautnerac6f8432013-07-17 13:24:59 -07001702 targetStack = adjustStackFocus(r);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001703 moveHomeStack(targetStack.isHomeStack());
Craig Mautner1602ec22013-05-12 10:24:27 -07001704 ActivityRecord prev = targetStack.topActivity();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001705 r.setTask(prev != null ? prev.task
1706 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1707 null, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001708 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1709 + " in new guessed " + r.task);
1710 }
1711
1712 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1713 intent, r.getUriPermissionsLocked());
1714
1715 if (newTask) {
1716 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1717 }
1718 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001719 setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
Craig Mautner0f922742013-08-06 08:44:42 -07001720 targetStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001721 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
Craig Mautner1d001b62013-06-18 16:52:43 -07001722 mService.setFocusedActivityLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001723 return ActivityManager.START_SUCCESS;
1724 }
1725
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001726 void acquireLaunchWakelock() {
1727 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
1728 throw new IllegalStateException("Calling must be system uid");
1729 }
1730 mLaunchingActivity.acquire();
1731 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
1732 // To be safe, don't allow the wake lock to be held for too long.
1733 mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
1734 }
1735 }
1736
Craig Mautnerf3333272013-04-22 10:55:53 -07001737 // Checked.
1738 final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
1739 Configuration config) {
1740 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
1741
Craig Mautnerf3333272013-04-22 10:55:53 -07001742 ArrayList<ActivityRecord> stops = null;
1743 ArrayList<ActivityRecord> finishes = null;
1744 ArrayList<UserStartedState> startingUsers = null;
1745 int NS = 0;
1746 int NF = 0;
1747 IApplicationThread sendThumbnail = null;
1748 boolean booting = false;
1749 boolean enableScreen = false;
1750 boolean activityRemoved = false;
1751
1752 ActivityRecord r = ActivityRecord.forToken(token);
1753 if (r != null) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07001754 if (DEBUG_IDLE) Slog.d(TAG, "activityIdleInternalLocked: Callers=" +
1755 Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07001756 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
1757 r.finishLaunchTickingLocked();
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001758 if (fromTimeout) {
1759 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
Craig Mautnerf3333272013-04-22 10:55:53 -07001760 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001761
1762 // This is a hack to semi-deal with a race condition
1763 // in the client where it can be constructed with a
1764 // newer configuration from when we asked it to launch.
1765 // We'll update with whatever configuration it now says
1766 // it used to launch.
1767 if (config != null) {
1768 r.configuration = config;
1769 }
1770
1771 // We are now idle. If someone is waiting for a thumbnail from
1772 // us, we can now deliver.
1773 r.idle = true;
1774
1775 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
1776 sendThumbnail = r.app.thread;
1777 r.thumbnailNeeded = false;
1778 }
1779
1780 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
1781 if (!mService.mBooted && isFrontStack(r.task.stack)) {
1782 mService.mBooted = true;
1783 enableScreen = true;
1784 }
1785 }
1786
1787 if (allResumedActivitiesIdle()) {
1788 if (r != null) {
1789 mService.scheduleAppGcsLocked();
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001790 }
1791
1792 if (mLaunchingActivity.isHeld()) {
1793 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
1794 if (VALIDATE_WAKE_LOCK_CALLER &&
1795 Binder.getCallingUid() != Process.myUid()) {
1796 throw new IllegalStateException("Calling must be system uid");
1797 }
1798 mLaunchingActivity.release();
1799 }
1800 ensureActivitiesVisibleLocked(null, 0);
Craig Mautnerf3333272013-04-22 10:55:53 -07001801 }
1802
1803 // Atomically retrieve all of the other things to do.
1804 stops = processStoppingActivitiesLocked(true);
1805 NS = stops != null ? stops.size() : 0;
1806 if ((NF=mFinishingActivities.size()) > 0) {
1807 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
1808 mFinishingActivities.clear();
1809 }
1810
1811 final ArrayList<ActivityRecord> thumbnails;
1812 final int NT = mCancelledThumbnails.size();
1813 if (NT > 0) {
1814 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
1815 mCancelledThumbnails.clear();
1816 } else {
1817 thumbnails = null;
1818 }
1819
1820 if (isFrontStack(mHomeStack)) {
1821 booting = mService.mBooting;
1822 mService.mBooting = false;
1823 }
1824
1825 if (mStartingUsers.size() > 0) {
1826 startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
1827 mStartingUsers.clear();
1828 }
1829
1830 // Perform the following actions from unsynchronized state.
1831 final IApplicationThread thumbnailThread = sendThumbnail;
1832 mHandler.post(new Runnable() {
1833 @Override
1834 public void run() {
1835 if (thumbnailThread != null) {
1836 try {
1837 thumbnailThread.requestThumbnail(token);
1838 } catch (Exception e) {
1839 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
1840 mService.sendPendingThumbnail(null, token, null, null, true);
1841 }
1842 }
1843
1844 // Report back to any thumbnail receivers.
1845 for (int i = 0; i < NT; i++) {
1846 ActivityRecord r = thumbnails.get(i);
1847 mService.sendPendingThumbnail(r, null, null, null, true);
1848 }
1849 }
1850 });
1851
1852 // Stop any activities that are scheduled to do so but have been
1853 // waiting for the next one to start.
1854 for (int i = 0; i < NS; i++) {
1855 r = stops.get(i);
1856 final ActivityStack stack = r.task.stack;
1857 if (r.finishing) {
1858 stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
1859 } else {
1860 stack.stopActivityLocked(r);
1861 }
1862 }
1863
1864 // Finish any activities that are scheduled to do so but have been
1865 // waiting for the next one to start.
1866 for (int i = 0; i < NF; i++) {
1867 r = finishes.get(i);
1868 activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle");
1869 }
1870
1871 if (booting) {
1872 mService.finishBooting();
1873 } else if (startingUsers != null) {
1874 for (int i = 0; i < startingUsers.size(); i++) {
1875 mService.finishUserSwitch(startingUsers.get(i));
1876 }
1877 }
1878
1879 mService.trimApplications();
1880 //dump();
1881 //mWindowManager.dump();
1882
1883 if (enableScreen) {
1884 mService.enableScreenAfterBoot();
1885 }
1886
1887 if (activityRemoved) {
Craig Mautner05d29032013-05-03 13:40:13 -07001888 resumeTopActivitiesLocked();
Craig Mautnerf3333272013-04-22 10:55:53 -07001889 }
1890
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001891 return r;
Craig Mautnerf3333272013-04-22 10:55:53 -07001892 }
1893
Craig Mautner8d341ef2013-03-26 09:03:27 -07001894 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
1895 // Just in case.
1896 final int numStacks = mStacks.size();
1897 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Craig Mautnere79d42682013-04-01 19:01:53 -07001898 mStacks.get(stackNdx).handleAppDiedLocked(app, restarting);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001899 }
1900 }
1901
1902 void closeSystemDialogsLocked() {
1903 final int numStacks = mStacks.size();
1904 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1905 final ActivityStack stack = mStacks.get(stackNdx);
1906 stack.closeSystemDialogsLocked();
1907 }
1908 }
1909
1910 /**
1911 * @return true if some activity was finished (or would have finished if doit were true).
1912 */
1913 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1914 boolean didSomething = false;
1915 final int numStacks = mStacks.size();
1916 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1917 final ActivityStack stack = mStacks.get(stackNdx);
1918 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1919 didSomething = true;
1920 }
1921 }
1922 return didSomething;
1923 }
1924
Dianne Hackborna413dc02013-07-12 12:02:55 -07001925 void updatePreviousProcessLocked(ActivityRecord r) {
1926 // Now that this process has stopped, we may want to consider
1927 // it to be the previous app to try to keep around in case
1928 // the user wants to return to it.
1929
1930 // First, found out what is currently the foreground app, so that
1931 // we don't blow away the previous app if this activity is being
1932 // hosted by the process that is actually still the foreground.
1933 ProcessRecord fgApp = null;
1934 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1935 final ActivityStack stack = mStacks.get(stackNdx);
1936 if (isFrontStack(stack)) {
1937 if (stack.mResumedActivity != null) {
1938 fgApp = stack.mResumedActivity.app;
1939 } else if (stack.mPausingActivity != null) {
1940 fgApp = stack.mPausingActivity.app;
1941 }
1942 break;
1943 }
1944 }
1945
1946 // Now set this one as the previous process, only if that really
1947 // makes sense to.
1948 if (r.app != null && fgApp != null && r.app != fgApp
1949 && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
Craig Mautnere428a7f2013-08-17 17:04:56 -07001950 && !mService.mHomeProcess.contains(r.app)) {
Dianne Hackborna413dc02013-07-12 12:02:55 -07001951 mService.mPreviousProcess = r.app;
1952 mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
1953 }
1954 }
1955
Craig Mautner05d29032013-05-03 13:40:13 -07001956 boolean resumeTopActivitiesLocked() {
1957 return resumeTopActivitiesLocked(null, null, null);
1958 }
1959
1960 boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
1961 Bundle targetOptions) {
1962 if (targetStack == null) {
1963 targetStack = getFocusedStack();
1964 }
1965 boolean result = false;
Craig Mautnerdbcb31f2013-04-02 12:32:53 -07001966 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001967 final ActivityStack stack = mStacks.get(stackNdx);
1968 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07001969 if (stack == targetStack) {
1970 result = stack.resumeTopActivityLocked(target, targetOptions);
1971 } else {
1972 stack.resumeTopActivityLocked(null);
1973 }
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001974 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001975 }
Craig Mautner05d29032013-05-03 13:40:13 -07001976 return result;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001977 }
1978
1979 void finishTopRunningActivityLocked(ProcessRecord app) {
1980 final int numStacks = mStacks.size();
1981 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1982 final ActivityStack stack = mStacks.get(stackNdx);
1983 stack.finishTopRunningActivityLocked(app);
1984 }
1985 }
1986
Craig Mautner8d341ef2013-03-26 09:03:27 -07001987 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
1988 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1989 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001990 if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack=" +
Craig Mautner1d001b62013-06-18 16:52:43 -07001991 mStacks.get(stackNdx));
Craig Mautner8d341ef2013-03-26 09:03:27 -07001992 return;
1993 }
1994 }
1995 }
1996
Craig Mautner967212c2013-04-13 21:10:58 -07001997 ActivityStack getStack(int stackId) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001998 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1999 final ActivityStack stack = mStacks.get(stackNdx);
2000 if (stack.getStackId() == stackId) {
2001 return stack;
2002 }
2003 }
2004 return null;
2005 }
2006
Craig Mautner967212c2013-04-13 21:10:58 -07002007 ArrayList<ActivityStack> getStacks() {
2008 return new ArrayList<ActivityStack>(mStacks);
2009 }
2010
2011 int createStack() {
Craig Mautner858d8a62013-04-23 17:08:34 -07002012 while (true) {
2013 if (++mLastStackId <= HOME_STACK_ID) {
2014 mLastStackId = HOME_STACK_ID + 1;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002015 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002016 if (getStack(mLastStackId) == null) {
2017 break;
2018 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002019 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002020 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
2021 return mLastStackId;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002022 }
2023
2024 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07002025 final TaskRecord task = anyTaskForIdLocked(taskId);
2026 if (task == null) {
2027 return;
2028 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002029 final ActivityStack stack = getStack(stackId);
2030 if (stack == null) {
2031 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
2032 return;
2033 }
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07002034 removeTask(task);
2035 stack.addTask(task, toTop);
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07002036 mWindowManager.addTask(taskId, stackId, toTop);
Craig Mautner05d29032013-05-03 13:40:13 -07002037 resumeTopActivitiesLocked();
Craig Mautner8d341ef2013-03-26 09:03:27 -07002038 }
2039
Craig Mautnerac6f8432013-07-17 13:24:59 -07002040 ActivityRecord findTaskLocked(ActivityRecord r) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07002041 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerac6f8432013-07-17 13:24:59 -07002042 final ActivityStack stack = mStacks.get(stackNdx);
2043 if (!r.isApplicationActivity() && !stack.isHomeStack()) {
2044 continue;
2045 }
2046 final ActivityRecord ar = stack.findTaskLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07002047 if (ar != null) {
2048 return ar;
2049 }
2050 }
2051 return null;
2052 }
2053
2054 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
2055 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2056 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
2057 if (ar != null) {
2058 return ar;
2059 }
2060 }
2061 return null;
2062 }
2063
Craig Mautner8d341ef2013-03-26 09:03:27 -07002064 void goingToSleepLocked() {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002065 scheduleSleepTimeout();
2066 if (!mGoingToSleep.isHeld()) {
2067 mGoingToSleep.acquire();
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002068 if (mLaunchingActivity.isHeld()) {
2069 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
2070 throw new IllegalStateException("Calling must be system uid");
Craig Mautner0eea92c2013-05-16 13:35:39 -07002071 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002072 mLaunchingActivity.release();
2073 mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
Craig Mautner0eea92c2013-05-16 13:35:39 -07002074 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002075 }
2076 }
2077
2078 boolean shutdownLocked(int timeout) {
2079 boolean timedout = false;
Craig Mautner0eea92c2013-05-16 13:35:39 -07002080 goingToSleepLocked();
2081 checkReadyForSleepLocked();
2082
2083 final long endTime = System.currentTimeMillis() + timeout;
2084 while (true) {
2085 boolean cantShutdown = false;
2086 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2087 cantShutdown |= mStacks.get(stackNdx).checkReadyForSleepLocked();
2088 }
2089 if (cantShutdown) {
2090 long timeRemaining = endTime - System.currentTimeMillis();
2091 if (timeRemaining > 0) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002092 try {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002093 mService.wait(timeRemaining);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002094 } catch (InterruptedException e) {
2095 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002096 } else {
2097 Slog.w(TAG, "Activity manager shutdown timed out");
2098 timedout = true;
2099 break;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002100 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002101 } else {
2102 break;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002103 }
2104 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002105
2106 // Force checkReadyForSleep to complete.
2107 mSleepTimeout = true;
2108 checkReadyForSleepLocked();
2109
Craig Mautner8d341ef2013-03-26 09:03:27 -07002110 return timedout;
2111 }
2112
2113 void comeOutOfSleepIfNeededLocked() {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002114 removeSleepTimeouts();
2115 if (mGoingToSleep.isHeld()) {
2116 mGoingToSleep.release();
2117 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002118 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002119 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002120 stack.awakeFromSleepingLocked();
2121 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07002122 resumeTopActivitiesLocked();
Craig Mautnerde4ef022013-04-07 19:01:33 -07002123 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002124 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002125 mGoingToSleepActivities.clear();
2126 }
2127
2128 void activitySleptLocked(ActivityRecord r) {
2129 mGoingToSleepActivities.remove(r);
2130 checkReadyForSleepLocked();
2131 }
2132
2133 void checkReadyForSleepLocked() {
2134 if (!mService.isSleepingOrShuttingDown()) {
2135 // Do not care.
2136 return;
2137 }
2138
2139 if (!mSleepTimeout) {
2140 boolean dontSleep = false;
2141 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2142 dontSleep |= mStacks.get(stackNdx).checkReadyForSleepLocked();
2143 }
2144
2145 if (mStoppingActivities.size() > 0) {
2146 // Still need to tell some activities to stop; can't sleep yet.
2147 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
2148 + mStoppingActivities.size() + " activities");
2149 scheduleIdleLocked();
2150 dontSleep = true;
2151 }
2152
2153 if (mGoingToSleepActivities.size() > 0) {
2154 // Still need to tell some activities to sleep; can't sleep yet.
2155 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
2156 + mGoingToSleepActivities.size() + " activities");
2157 dontSleep = true;
2158 }
2159
2160 if (dontSleep) {
2161 return;
2162 }
2163 }
2164
2165 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2166 mStacks.get(stackNdx).goToSleep();
2167 }
2168
2169 removeSleepTimeouts();
2170
2171 if (mGoingToSleep.isHeld()) {
2172 mGoingToSleep.release();
2173 }
2174 if (mService.mShuttingDown) {
2175 mService.notifyAll();
2176 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002177 }
2178
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002179 boolean reportResumedActivityLocked(ActivityRecord r) {
2180 final ActivityStack stack = r.task.stack;
2181 if (isFrontStack(stack)) {
Jeff Sharkey5782da72013-04-25 14:32:30 -07002182 mService.updateUsageStats(r, true);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002183 }
2184 if (allResumedActivitiesComplete()) {
2185 ensureActivitiesVisibleLocked(null, 0);
2186 mWindowManager.executeAppTransition();
2187 return true;
2188 }
2189 return false;
2190 }
2191
Craig Mautner8d341ef2013-03-26 09:03:27 -07002192 void handleAppCrashLocked(ProcessRecord app) {
2193 final int numStacks = mStacks.size();
2194 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2195 final ActivityStack stack = mStacks.get(stackNdx);
2196 stack.handleAppCrashLocked(app);
2197 }
2198 }
2199
Craig Mautnerde4ef022013-04-07 19:01:33 -07002200 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
Craig Mautner580ea812013-04-25 12:58:38 -07002201 // First the front stacks. In case any are not fullscreen and are in front of home.
2202 boolean showHomeBehindStack = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07002203 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner580ea812013-04-25 12:58:38 -07002204 final ActivityStack stack = mStacks.get(stackNdx);
2205 if (isFrontStack(stack)) {
2206 showHomeBehindStack =
2207 stack.ensureActivitiesVisibleLocked(starting, configChanges);
2208 }
2209 }
2210 // Now do back stacks.
2211 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2212 final ActivityStack stack = mStacks.get(stackNdx);
2213 if (!isFrontStack(stack)) {
2214 stack.ensureActivitiesVisibleLocked(starting, configChanges, showHomeBehindStack);
2215 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002216 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002217 }
2218
2219 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
2220 final int numStacks = mStacks.size();
2221 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2222 final ActivityStack stack = mStacks.get(stackNdx);
2223 stack.scheduleDestroyActivities(app, false, reason);
2224 }
2225 }
2226
2227 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner2420ead2013-04-01 17:13:20 -07002228 mCurrentUser = userId;
Craig Mautnerac6f8432013-07-17 13:24:59 -07002229
2230 final String homePackageName = mService.getHomePackageName();
2231 if (homePackageName != null) {
2232 setHomePackageName(mCurrentUser, homePackageName);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002233 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002234
2235 mStartingUsers.add(uss);
Craig Mautnerac6f8432013-07-17 13:24:59 -07002236 boolean haveActivities = false;
2237 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2238 haveActivities |= mStacks.get(stackNdx).switchUserLocked(userId);
2239 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002240
2241 resumeTopActivitiesLocked();
2242
Craig Mautner8d341ef2013-03-26 09:03:27 -07002243 return haveActivities;
Craig Mautner2219a1b2013-03-25 09:44:30 -07002244 }
2245
Craig Mautnerde4ef022013-04-07 19:01:33 -07002246 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
2247 int N = mStoppingActivities.size();
2248 if (N <= 0) return null;
2249
2250 ArrayList<ActivityRecord> stops = null;
2251
2252 final boolean nowVisible = allResumedActivitiesVisible();
2253 for (int i=0; i<N; i++) {
2254 ActivityRecord s = mStoppingActivities.get(i);
2255 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
2256 + nowVisible + " waitingVisible=" + s.waitingVisible
2257 + " finishing=" + s.finishing);
2258 if (s.waitingVisible && nowVisible) {
2259 mWaitingVisibleActivities.remove(s);
2260 s.waitingVisible = false;
2261 if (s.finishing) {
2262 // If this activity is finishing, it is sitting on top of
2263 // everyone else but we now know it is no longer needed...
2264 // so get rid of it. Otherwise, we need to go through the
2265 // normal flow and hide it once we determine that it is
2266 // hidden by the activities in front of it.
2267 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002268 mWindowManager.setAppVisibility(s.appToken, false);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002269 }
2270 }
2271 if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
2272 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
2273 if (stops == null) {
2274 stops = new ArrayList<ActivityRecord>();
2275 }
2276 stops.add(s);
2277 mStoppingActivities.remove(i);
2278 N--;
2279 i--;
2280 }
2281 }
2282
2283 return stops;
2284 }
2285
Craig Mautnercf910b02013-04-23 11:23:27 -07002286 void validateTopActivitiesLocked() {
2287 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2288 final ActivityStack stack = mStacks.get(stackNdx);
2289 final ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002290 final ActivityState state = r == null ? ActivityState.DESTROYED : r.state;
Craig Mautnercf910b02013-04-23 11:23:27 -07002291 if (isFrontStack(stack)) {
2292 if (r == null) {
2293 Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
2294 } else {
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002295 final ActivityRecord pausing = stack.mPausingActivity;
2296 if (pausing != null && pausing == r) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002297 Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002298 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002299 }
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002300 if (state != ActivityState.INITIALIZING && state != ActivityState.RESUMED) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002301 Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002302 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002303 }
2304 }
2305 } else {
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002306 final ActivityRecord resumed = stack.mResumedActivity;
2307 if (resumed != null && resumed == r) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002308 Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002309 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002310 }
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002311 if (r != null && (state == ActivityState.INITIALIZING
2312 || state == ActivityState.RESUMED)) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002313 Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002314 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002315 }
2316 }
2317 }
2318 }
2319
Craig Mautner76ea2242013-05-15 11:40:05 -07002320 private static String stackStateToString(int stackState) {
2321 switch (stackState) {
2322 case STACK_STATE_HOME_IN_FRONT: return "STACK_STATE_HOME_IN_FRONT";
2323 case STACK_STATE_HOME_TO_BACK: return "STACK_STATE_HOME_TO_BACK";
2324 case STACK_STATE_HOME_IN_BACK: return "STACK_STATE_HOME_IN_BACK";
2325 case STACK_STATE_HOME_TO_FRONT: return "STACK_STATE_HOME_TO_FRONT";
2326 default: return "Unknown stackState=" + stackState;
2327 }
2328 }
2329
Craig Mautner27084302013-03-25 08:05:25 -07002330 public void dump(PrintWriter pw, String prefix) {
2331 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
2332 pw.println(mDismissKeyguardOnNextActivity);
Craig Mautner76ea2242013-05-15 11:40:05 -07002333 pw.print(prefix); pw.print("mStackState="); pw.println(stackStateToString(mStackState));
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002334 pw.print(prefix); pw.println("mSleepTimeout: " + mSleepTimeout);
2335 pw.print(prefix); pw.println("mCurTaskId: " + mCurTaskId);
Craig Mautnerac6f8432013-07-17 13:24:59 -07002336 pw.print(prefix); pw.print("mHomePackageNames:");
2337 for (int i = 0; i < mHomePackageNames.size(); ++i) {
2338 pw.print(" ("); pw.print(mHomePackageNames.keyAt(i)); pw.print(",");
2339 pw.print(mHomePackageNames.valueAt(i)); pw.print(")");
2340 }
2341 pw.println();
Craig Mautner27084302013-03-25 08:05:25 -07002342 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002343
Craig Mautner20e72272013-04-01 13:45:53 -07002344 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002345 return getFocusedStack().getDumpActivitiesLocked(name);
Craig Mautner20e72272013-04-01 13:45:53 -07002346 }
2347
Dianne Hackborn390517b2013-05-30 15:03:32 -07002348 static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
2349 boolean needSep, String prefix) {
2350 if (activity != null) {
2351 if (dumpPackage == null || dumpPackage.equals(activity.packageName)) {
2352 if (needSep) {
2353 pw.println();
Dianne Hackborn390517b2013-05-30 15:03:32 -07002354 }
2355 pw.print(prefix);
2356 pw.println(activity);
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002357 return true;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002358 }
2359 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002360 return false;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002361 }
2362
Craig Mautner8d341ef2013-03-26 09:03:27 -07002363 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
2364 boolean dumpClient, String dumpPackage) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002365 boolean printed = false;
2366 boolean needSep = false;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002367 final int numStacks = mStacks.size();
2368 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2369 final ActivityStack stack = mStacks.get(stackNdx);
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002370 StringBuilder stackHeader = new StringBuilder(128);
2371 stackHeader.append(" Stack #");
2372 stackHeader.append(mStacks.indexOf(stack));
2373 stackHeader.append(":");
2374 printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, needSep,
2375 stackHeader.toString());
2376 printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll,
2377 false, dumpPackage, true, " Running activities (most recent first):", null);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002378
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002379 needSep = printed;
2380 boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002381 " mPausingActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002382 if (pr) {
2383 printed = true;
2384 needSep = false;
2385 }
2386 pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002387 " mResumedActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002388 if (pr) {
2389 printed = true;
2390 needSep = false;
2391 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002392 if (dumpAll) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002393 pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002394 " mLastPausedActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002395 if (pr) {
2396 printed = true;
Craig Mautner0f922742013-08-06 08:44:42 -07002397 needSep = true;
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002398 }
Craig Mautner0f922742013-08-06 08:44:42 -07002399 printed |= printThisActivity(pw, stack.mLastNoHistoryActivity, dumpPackage,
2400 needSep, " mLastNoHistoryActivity: ");
Craig Mautner8d341ef2013-03-26 09:03:27 -07002401 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002402 needSep = printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002403 }
2404
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002405 printed |= dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll,
2406 false, dumpPackage, true, " Activities waiting to finish:", null);
2407 printed |= dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll,
2408 false, dumpPackage, true, " Activities waiting to stop:", null);
2409 printed |= dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
2410 false, dumpPackage, true, " Activities waiting for another to become visible:",
2411 null);
2412 printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll,
2413 false, dumpPackage, true, " Activities waiting to sleep:", null);
2414 printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll,
2415 false, dumpPackage, true, " Activities waiting to sleep:", null);
Craig Mautnerf3333272013-04-22 10:55:53 -07002416
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002417 return printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002418 }
2419
Dianne Hackborn390517b2013-05-30 15:03:32 -07002420 static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
Craig Mautner8d341ef2013-03-26 09:03:27 -07002421 String prefix, String label, boolean complete, boolean brief, boolean client,
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002422 String dumpPackage, boolean needNL, String header1, String header2) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002423 TaskRecord lastTask = null;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002424 String innerPrefix = null;
2425 String[] args = null;
2426 boolean printed = false;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002427 for (int i=list.size()-1; i>=0; i--) {
2428 final ActivityRecord r = list.get(i);
2429 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
2430 continue;
2431 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07002432 if (innerPrefix == null) {
2433 innerPrefix = prefix + " ";
2434 args = new String[0];
2435 }
2436 printed = true;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002437 final boolean full = !brief && (complete || !r.isInHistory());
2438 if (needNL) {
Dianne Hackborn390517b2013-05-30 15:03:32 -07002439 pw.println("");
Craig Mautner8d341ef2013-03-26 09:03:27 -07002440 needNL = false;
2441 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002442 if (header1 != null) {
2443 pw.println(header1);
2444 header1 = null;
2445 }
2446 if (header2 != null) {
2447 pw.println(header2);
2448 header2 = null;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002449 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002450 if (lastTask != r.task) {
2451 lastTask = r.task;
2452 pw.print(prefix);
2453 pw.print(full ? "* " : " ");
2454 pw.println(lastTask);
2455 if (full) {
2456 lastTask.dump(pw, prefix + " ");
2457 } else if (complete) {
2458 // Complete + brief == give a summary. Isn't that obvious?!?
2459 if (lastTask.intent != null) {
2460 pw.print(prefix); pw.print(" ");
2461 pw.println(lastTask.intent.toInsecureStringWithClip());
2462 }
2463 }
2464 }
2465 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
2466 pw.print(" #"); pw.print(i); pw.print(": ");
2467 pw.println(r);
2468 if (full) {
2469 r.dump(pw, innerPrefix);
2470 } else if (complete) {
2471 // Complete + brief == give a summary. Isn't that obvious?!?
2472 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
2473 if (r.app != null) {
2474 pw.print(innerPrefix); pw.println(r.app);
2475 }
2476 }
2477 if (client && r.app != null && r.app.thread != null) {
2478 // flush anything that is already in the PrintWriter since the thread is going
2479 // to write to the file descriptor directly
2480 pw.flush();
2481 try {
2482 TransferPipe tp = new TransferPipe();
2483 try {
2484 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
2485 r.appToken, innerPrefix, args);
2486 // Short timeout, since blocking here can
2487 // deadlock with the application.
2488 tp.go(fd, 2000);
2489 } finally {
2490 tp.kill();
2491 }
2492 } catch (IOException e) {
2493 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
2494 } catch (RemoteException e) {
2495 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
2496 }
2497 needNL = true;
2498 }
2499 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07002500 return printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002501 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002502
Craig Mautnerf3333272013-04-22 10:55:53 -07002503 void scheduleIdleTimeoutLocked(ActivityRecord next) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002504 if (DEBUG_IDLE) Slog.d(TAG, "scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4));
Craig Mautnerc64f73e2013-04-24 16:44:56 -07002505 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
2506 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
Craig Mautnerf3333272013-04-22 10:55:53 -07002507 }
2508
2509 final void scheduleIdleLocked() {
Craig Mautner05d29032013-05-03 13:40:13 -07002510 mHandler.sendEmptyMessage(IDLE_NOW_MSG);
Craig Mautnerf3333272013-04-22 10:55:53 -07002511 }
2512
2513 void removeTimeoutsForActivityLocked(ActivityRecord r) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002514 if (DEBUG_IDLE) Slog.d(TAG, "removeTimeoutsForActivity: Callers=" + Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07002515 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
2516 }
2517
Craig Mautner05d29032013-05-03 13:40:13 -07002518 final void scheduleResumeTopActivities() {
2519 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2520 }
2521
Craig Mautner0eea92c2013-05-16 13:35:39 -07002522 void removeSleepTimeouts() {
2523 mSleepTimeout = false;
2524 mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
2525 }
2526
2527 final void scheduleSleepTimeout() {
2528 removeSleepTimeouts();
2529 mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT);
2530 }
2531
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002532 private final class ActivityStackSupervisorHandler extends Handler {
Craig Mautnerf3333272013-04-22 10:55:53 -07002533
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002534 public ActivityStackSupervisorHandler(Looper looper) {
2535 super(looper);
2536 }
2537
Craig Mautnerf3333272013-04-22 10:55:53 -07002538 void activityIdleInternal(ActivityRecord r) {
2539 synchronized (mService) {
2540 activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
2541 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002542 }
2543
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002544 @Override
2545 public void handleMessage(Message msg) {
2546 switch (msg.what) {
Craig Mautnerf3333272013-04-22 10:55:53 -07002547 case IDLE_TIMEOUT_MSG: {
Craig Mautner5eda9b32013-07-02 11:58:16 -07002548 if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_TIMEOUT_MSG: r=" + msg.obj);
Craig Mautnerf3333272013-04-22 10:55:53 -07002549 if (mService.mDidDexOpt) {
2550 mService.mDidDexOpt = false;
2551 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2552 nmsg.obj = msg.obj;
2553 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
2554 return;
2555 }
2556 // We don't at this point know if the activity is fullscreen,
2557 // so we need to be conservative and assume it isn't.
2558 activityIdleInternal((ActivityRecord)msg.obj);
2559 } break;
2560 case IDLE_NOW_MSG: {
Craig Mautner5eda9b32013-07-02 11:58:16 -07002561 if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_NOW_MSG: r=" + msg.obj);
Craig Mautnerf3333272013-04-22 10:55:53 -07002562 activityIdleInternal((ActivityRecord)msg.obj);
2563 } break;
Craig Mautner05d29032013-05-03 13:40:13 -07002564 case RESUME_TOP_ACTIVITY_MSG: {
2565 synchronized (mService) {
2566 resumeTopActivitiesLocked();
2567 }
2568 } break;
Craig Mautner0eea92c2013-05-16 13:35:39 -07002569 case SLEEP_TIMEOUT_MSG: {
2570 synchronized (mService) {
2571 if (mService.isSleepingOrShuttingDown()) {
2572 Slog.w(TAG, "Sleep timeout! Sleeping now.");
2573 mSleepTimeout = true;
2574 checkReadyForSleepLocked();
2575 }
2576 }
2577 } break;
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002578 case LAUNCH_TIMEOUT_MSG: {
2579 if (mService.mDidDexOpt) {
2580 mService.mDidDexOpt = false;
2581 mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
2582 return;
2583 }
2584 synchronized (mService) {
2585 if (mLaunchingActivity.isHeld()) {
2586 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
2587 if (VALIDATE_WAKE_LOCK_CALLER
2588 && Binder.getCallingUid() != Process.myUid()) {
2589 throw new IllegalStateException("Calling must be system uid");
2590 }
2591 mLaunchingActivity.release();
2592 }
2593 }
2594 } break;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002595 }
2596 }
2597 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002598
Craig Mautnerac6f8432013-07-17 13:24:59 -07002599 String getHomePackageName() {
2600 return mHomePackageNames.get(mCurrentUser);
2601 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002602
Craig Mautnerac6f8432013-07-17 13:24:59 -07002603 void setHomePackageName(int userId, String homePackageName) {
2604 if (DEBUG_SWITCH) Slog.d(TAG, "setHomePackageName: user=" + userId + " package="
2605 + homePackageName);
2606 mHomePackageNames.put(userId, homePackageName);
Craig Mautner858d8a62013-04-23 17:08:34 -07002607 }
Craig Mautner27084302013-03-25 08:05:25 -07002608}