blob: dd125656dd92c7f67c05a304bb94c053d6365f22 [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 Mautner2420ead2013-04-01 17:13:20 -0700908 mService.mHomeProcess = app;
909 }
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 Hackborn78a369c2013-06-11 17:10:32 -07001030 app.addPackage(r.info.packageName, mService.mProcessTracker);
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 Gruver6617c3c2013-04-03 18:45:22 -07001157 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
Ben Gruver7b879f42013-04-08 14:56:55 -07001158 callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo);
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 Mautnerde4ef022013-04-07 19:01:33 -07001421 if (sourceRecord == null || sourceStack.topActivity() == sourceRecord) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001422 // We really do want to push this one into the
1423 // user's face, right now.
1424 movedHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001425 if ((launchFlags &
Craig Mautner29219d92013-04-16 20:19:12 -07001426 (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1427 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001428 // Caller wants to appear on home activity, so before starting
1429 // their own activity we will bring home to the front.
1430 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 Mautnerde4ef022013-04-07 19:01:33 -07001543 setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1544 targetStack.resumeTopActivityLocked(null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001545 } else {
1546 ActivityOptions.abort(options);
1547 }
Craig Mautner29219d92013-04-16 20:19:12 -07001548 if (r.task == null) Slog.v(TAG,
1549 "startActivityUncheckedLocked: task left null",
1550 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001551 return ActivityManager.START_TASK_TO_FRONT;
1552 }
1553 }
1554 }
1555 }
1556
1557 //String uri = r.intent.toURI();
1558 //Intent intent2 = new Intent(uri);
1559 //Slog.i(TAG, "Given intent: " + r.intent);
1560 //Slog.i(TAG, "URI is: " + uri);
1561 //Slog.i(TAG, "To intent: " + intent2);
1562
1563 if (r.packageName != null) {
1564 // If the activity being launched is the same as the one currently
1565 // at the top, then we need to check if it should only be launched
1566 // once.
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001567 ActivityStack topStack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001568 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001569 if (top != null && r.resultTo == null) {
1570 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1571 if (top.app != null && top.app.thread != null) {
1572 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1573 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1574 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1575 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1576 top.task);
1577 // For paranoia, make sure we have correctly
1578 // resumed the top activity.
Craig Mautner0f922742013-08-06 08:44:42 -07001579 topStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001580 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001581 setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001582 resumeTopActivitiesLocked();
Craig Mautner8849a5e2013-04-02 16:41:03 -07001583 }
1584 ActivityOptions.abort(options);
1585 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1586 // We don't need to start a new activity, and
1587 // the client said not to do anything if that
1588 // is the case, so this is it!
Craig Mautner29219d92013-04-16 20:19:12 -07001589 if (r.task == null) Slog.v(TAG,
1590 "startActivityUncheckedLocked: task left null",
1591 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001592 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1593 }
1594 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner29219d92013-04-16 20:19:12 -07001595 if (r.task == null) Slog.v(TAG,
1596 "startActivityUncheckedLocked: task left null",
1597 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001598 return ActivityManager.START_DELIVERED_TO_TOP;
1599 }
1600 }
1601 }
1602 }
1603
1604 } else {
1605 if (r.resultTo != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001606 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1607 r.requestCode, Activity.RESULT_CANCELED, null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001608 }
1609 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001610 if (r.task == null) Slog.v(TAG,
1611 "startActivityUncheckedLocked: task left null",
1612 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001613 return ActivityManager.START_CLASS_NOT_FOUND;
1614 }
1615
1616 boolean newTask = false;
1617 boolean keepCurTransition = false;
1618
1619 // Should this be considered a new task?
1620 if (r.resultTo == null && !addingToTask
1621 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Craig Mautnerac6f8432013-07-17 13:24:59 -07001622 targetStack = adjustStackFocus(r);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001623 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001624 if (reuseTask == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001625 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1626 null, true);
1627 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1628 r.task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001629 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001630 r.setTask(reuseTask, reuseTask, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001631 }
1632 newTask = true;
1633 if (!movedHome) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001634 if ((launchFlags &
1635 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1636 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1637 // Caller wants to appear on home activity, so before starting
1638 // their own activity we will bring home to the front.
1639 r.mLaunchHomeTaskNext = true;
1640 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001641 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001642 } else if (sourceRecord != null) {
Craig Mautner525f3d92013-05-07 14:01:50 -07001643 sourceTask = sourceRecord.task;
1644 targetStack = sourceTask.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001645 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001646 if (!addingToTask &&
1647 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1648 // In this case, we are adding the activity to an existing
1649 // task, but the caller has asked to clear that task if the
1650 // activity is already running.
Craig Mautner525f3d92013-05-07 14:01:50 -07001651 ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001652 keepCurTransition = true;
1653 if (top != null) {
1654 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1655 top.deliverNewIntentLocked(callingUid, r.intent);
1656 // For paranoia, make sure we have correctly
1657 // resumed the top activity.
Craig Mautner0f922742013-08-06 08:44:42 -07001658 targetStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001659 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001660 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001661 targetStack.resumeTopActivityLocked(null);
1662 }
1663 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001664 if (r.task == null) Slog.v(TAG,
1665 "startActivityUncheckedLocked: task left null",
1666 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001667 return ActivityManager.START_DELIVERED_TO_TOP;
1668 }
1669 } else if (!addingToTask &&
1670 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1671 // In this case, we are launching an activity in our own task
1672 // that may already be running somewhere in the history, and
1673 // we want to shuffle it to the front of the stack if so.
Craig Mautner525f3d92013-05-07 14:01:50 -07001674 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001675 if (top != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001676 final TaskRecord task = top.task;
1677 task.moveActivityToFrontLocked(top);
1678 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001679 top.updateOptionsLocked(options);
1680 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner0f922742013-08-06 08:44:42 -07001681 targetStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001682 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001683 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001684 targetStack.resumeTopActivityLocked(null);
1685 }
Craig Mautner29219d92013-04-16 20:19:12 -07001686 if (r.task == null) Slog.v(TAG,
1687 "startActivityUncheckedLocked: task left null",
1688 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001689 return ActivityManager.START_DELIVERED_TO_TOP;
1690 }
1691 }
1692 // An existing activity is starting this new activity, so we want
1693 // to keep the new one in the same task as the one that is starting
1694 // it.
Craig Mautner525f3d92013-05-07 14:01:50 -07001695 r.setTask(sourceTask, sourceRecord.thumbHolder, false);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001696 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1697 + " in existing task " + r.task);
1698
1699 } else {
1700 // This not being started from an existing activity, and not part
1701 // of a new task... just put it in the top task, though these days
1702 // this case should never happen.
Craig Mautnerac6f8432013-07-17 13:24:59 -07001703 targetStack = adjustStackFocus(r);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001704 moveHomeStack(targetStack.isHomeStack());
Craig Mautner1602ec22013-05-12 10:24:27 -07001705 ActivityRecord prev = targetStack.topActivity();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001706 r.setTask(prev != null ? prev.task
1707 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1708 null, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001709 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1710 + " in new guessed " + r.task);
1711 }
1712
1713 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1714 intent, r.getUriPermissionsLocked());
1715
1716 if (newTask) {
1717 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1718 }
1719 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001720 setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
Craig Mautner0f922742013-08-06 08:44:42 -07001721 targetStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001722 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
Craig Mautner1d001b62013-06-18 16:52:43 -07001723 mService.setFocusedActivityLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001724 return ActivityManager.START_SUCCESS;
1725 }
1726
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001727 void acquireLaunchWakelock() {
1728 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
1729 throw new IllegalStateException("Calling must be system uid");
1730 }
1731 mLaunchingActivity.acquire();
1732 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
1733 // To be safe, don't allow the wake lock to be held for too long.
1734 mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
1735 }
1736 }
1737
Craig Mautnerf3333272013-04-22 10:55:53 -07001738 // Checked.
1739 final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
1740 Configuration config) {
1741 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
1742
Craig Mautnerf3333272013-04-22 10:55:53 -07001743 ArrayList<ActivityRecord> stops = null;
1744 ArrayList<ActivityRecord> finishes = null;
1745 ArrayList<UserStartedState> startingUsers = null;
1746 int NS = 0;
1747 int NF = 0;
1748 IApplicationThread sendThumbnail = null;
1749 boolean booting = false;
1750 boolean enableScreen = false;
1751 boolean activityRemoved = false;
1752
1753 ActivityRecord r = ActivityRecord.forToken(token);
1754 if (r != null) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07001755 if (DEBUG_IDLE) Slog.d(TAG, "activityIdleInternalLocked: Callers=" +
1756 Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07001757 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
1758 r.finishLaunchTickingLocked();
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001759 if (fromTimeout) {
1760 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
Craig Mautnerf3333272013-04-22 10:55:53 -07001761 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001762
1763 // This is a hack to semi-deal with a race condition
1764 // in the client where it can be constructed with a
1765 // newer configuration from when we asked it to launch.
1766 // We'll update with whatever configuration it now says
1767 // it used to launch.
1768 if (config != null) {
1769 r.configuration = config;
1770 }
1771
1772 // We are now idle. If someone is waiting for a thumbnail from
1773 // us, we can now deliver.
1774 r.idle = true;
1775
1776 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
1777 sendThumbnail = r.app.thread;
1778 r.thumbnailNeeded = false;
1779 }
1780
1781 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
1782 if (!mService.mBooted && isFrontStack(r.task.stack)) {
1783 mService.mBooted = true;
1784 enableScreen = true;
1785 }
1786 }
1787
1788 if (allResumedActivitiesIdle()) {
1789 if (r != null) {
1790 mService.scheduleAppGcsLocked();
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001791 }
1792
1793 if (mLaunchingActivity.isHeld()) {
1794 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
1795 if (VALIDATE_WAKE_LOCK_CALLER &&
1796 Binder.getCallingUid() != Process.myUid()) {
1797 throw new IllegalStateException("Calling must be system uid");
1798 }
1799 mLaunchingActivity.release();
1800 }
1801 ensureActivitiesVisibleLocked(null, 0);
Craig Mautnerf3333272013-04-22 10:55:53 -07001802 }
1803
1804 // Atomically retrieve all of the other things to do.
1805 stops = processStoppingActivitiesLocked(true);
1806 NS = stops != null ? stops.size() : 0;
1807 if ((NF=mFinishingActivities.size()) > 0) {
1808 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
1809 mFinishingActivities.clear();
1810 }
1811
1812 final ArrayList<ActivityRecord> thumbnails;
1813 final int NT = mCancelledThumbnails.size();
1814 if (NT > 0) {
1815 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
1816 mCancelledThumbnails.clear();
1817 } else {
1818 thumbnails = null;
1819 }
1820
1821 if (isFrontStack(mHomeStack)) {
1822 booting = mService.mBooting;
1823 mService.mBooting = false;
1824 }
1825
1826 if (mStartingUsers.size() > 0) {
1827 startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
1828 mStartingUsers.clear();
1829 }
1830
1831 // Perform the following actions from unsynchronized state.
1832 final IApplicationThread thumbnailThread = sendThumbnail;
1833 mHandler.post(new Runnable() {
1834 @Override
1835 public void run() {
1836 if (thumbnailThread != null) {
1837 try {
1838 thumbnailThread.requestThumbnail(token);
1839 } catch (Exception e) {
1840 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
1841 mService.sendPendingThumbnail(null, token, null, null, true);
1842 }
1843 }
1844
1845 // Report back to any thumbnail receivers.
1846 for (int i = 0; i < NT; i++) {
1847 ActivityRecord r = thumbnails.get(i);
1848 mService.sendPendingThumbnail(r, null, null, null, true);
1849 }
1850 }
1851 });
1852
1853 // Stop any activities that are scheduled to do so but have been
1854 // waiting for the next one to start.
1855 for (int i = 0; i < NS; i++) {
1856 r = stops.get(i);
1857 final ActivityStack stack = r.task.stack;
1858 if (r.finishing) {
1859 stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
1860 } else {
1861 stack.stopActivityLocked(r);
1862 }
1863 }
1864
1865 // Finish any activities that are scheduled to do so but have been
1866 // waiting for the next one to start.
1867 for (int i = 0; i < NF; i++) {
1868 r = finishes.get(i);
1869 activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle");
1870 }
1871
1872 if (booting) {
1873 mService.finishBooting();
1874 } else if (startingUsers != null) {
1875 for (int i = 0; i < startingUsers.size(); i++) {
1876 mService.finishUserSwitch(startingUsers.get(i));
1877 }
1878 }
1879
1880 mService.trimApplications();
1881 //dump();
1882 //mWindowManager.dump();
1883
1884 if (enableScreen) {
1885 mService.enableScreenAfterBoot();
1886 }
1887
1888 if (activityRemoved) {
Craig Mautner05d29032013-05-03 13:40:13 -07001889 resumeTopActivitiesLocked();
Craig Mautnerf3333272013-04-22 10:55:53 -07001890 }
1891
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001892 return r;
Craig Mautnerf3333272013-04-22 10:55:53 -07001893 }
1894
Craig Mautner8d341ef2013-03-26 09:03:27 -07001895 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
1896 // Just in case.
1897 final int numStacks = mStacks.size();
1898 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Craig Mautnere79d42682013-04-01 19:01:53 -07001899 mStacks.get(stackNdx).handleAppDiedLocked(app, restarting);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001900 }
1901 }
1902
1903 void closeSystemDialogsLocked() {
1904 final int numStacks = mStacks.size();
1905 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1906 final ActivityStack stack = mStacks.get(stackNdx);
1907 stack.closeSystemDialogsLocked();
1908 }
1909 }
1910
1911 /**
1912 * @return true if some activity was finished (or would have finished if doit were true).
1913 */
1914 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1915 boolean didSomething = false;
1916 final int numStacks = mStacks.size();
1917 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1918 final ActivityStack stack = mStacks.get(stackNdx);
1919 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1920 didSomething = true;
1921 }
1922 }
1923 return didSomething;
1924 }
1925
Dianne Hackborna413dc02013-07-12 12:02:55 -07001926 void updatePreviousProcessLocked(ActivityRecord r) {
1927 // Now that this process has stopped, we may want to consider
1928 // it to be the previous app to try to keep around in case
1929 // the user wants to return to it.
1930
1931 // First, found out what is currently the foreground app, so that
1932 // we don't blow away the previous app if this activity is being
1933 // hosted by the process that is actually still the foreground.
1934 ProcessRecord fgApp = null;
1935 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1936 final ActivityStack stack = mStacks.get(stackNdx);
1937 if (isFrontStack(stack)) {
1938 if (stack.mResumedActivity != null) {
1939 fgApp = stack.mResumedActivity.app;
1940 } else if (stack.mPausingActivity != null) {
1941 fgApp = stack.mPausingActivity.app;
1942 }
1943 break;
1944 }
1945 }
1946
1947 // Now set this one as the previous process, only if that really
1948 // makes sense to.
1949 if (r.app != null && fgApp != null && r.app != fgApp
1950 && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
1951 && r.app != mService.mHomeProcess) {
1952 mService.mPreviousProcess = r.app;
1953 mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
1954 }
1955 }
1956
Craig Mautner05d29032013-05-03 13:40:13 -07001957 boolean resumeTopActivitiesLocked() {
1958 return resumeTopActivitiesLocked(null, null, null);
1959 }
1960
1961 boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
1962 Bundle targetOptions) {
1963 if (targetStack == null) {
1964 targetStack = getFocusedStack();
1965 }
1966 boolean result = false;
Craig Mautnerdbcb31f2013-04-02 12:32:53 -07001967 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001968 final ActivityStack stack = mStacks.get(stackNdx);
1969 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07001970 if (stack == targetStack) {
1971 result = stack.resumeTopActivityLocked(target, targetOptions);
1972 } else {
1973 stack.resumeTopActivityLocked(null);
1974 }
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001975 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001976 }
Craig Mautner05d29032013-05-03 13:40:13 -07001977 return result;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001978 }
1979
1980 void finishTopRunningActivityLocked(ProcessRecord app) {
1981 final int numStacks = mStacks.size();
1982 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1983 final ActivityStack stack = mStacks.get(stackNdx);
1984 stack.finishTopRunningActivityLocked(app);
1985 }
1986 }
1987
Craig Mautner8d341ef2013-03-26 09:03:27 -07001988 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
1989 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1990 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001991 if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack=" +
Craig Mautner1d001b62013-06-18 16:52:43 -07001992 mStacks.get(stackNdx));
Craig Mautner8d341ef2013-03-26 09:03:27 -07001993 return;
1994 }
1995 }
1996 }
1997
Craig Mautner967212c2013-04-13 21:10:58 -07001998 ActivityStack getStack(int stackId) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001999 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2000 final ActivityStack stack = mStacks.get(stackNdx);
2001 if (stack.getStackId() == stackId) {
2002 return stack;
2003 }
2004 }
2005 return null;
2006 }
2007
Craig Mautner967212c2013-04-13 21:10:58 -07002008 ArrayList<ActivityStack> getStacks() {
2009 return new ArrayList<ActivityStack>(mStacks);
2010 }
2011
2012 int createStack() {
Craig Mautner858d8a62013-04-23 17:08:34 -07002013 while (true) {
2014 if (++mLastStackId <= HOME_STACK_ID) {
2015 mLastStackId = HOME_STACK_ID + 1;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002016 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002017 if (getStack(mLastStackId) == null) {
2018 break;
2019 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002020 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002021 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
2022 return mLastStackId;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002023 }
2024
2025 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07002026 final TaskRecord task = anyTaskForIdLocked(taskId);
2027 if (task == null) {
2028 return;
2029 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002030 final ActivityStack stack = getStack(stackId);
2031 if (stack == null) {
2032 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
2033 return;
2034 }
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07002035 removeTask(task);
2036 stack.addTask(task, toTop);
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07002037 mWindowManager.addTask(taskId, stackId, toTop);
Craig Mautner05d29032013-05-03 13:40:13 -07002038 resumeTopActivitiesLocked();
Craig Mautner8d341ef2013-03-26 09:03:27 -07002039 }
2040
Craig Mautnerac6f8432013-07-17 13:24:59 -07002041 ActivityRecord findTaskLocked(ActivityRecord r) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07002042 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerac6f8432013-07-17 13:24:59 -07002043 final ActivityStack stack = mStacks.get(stackNdx);
2044 if (!r.isApplicationActivity() && !stack.isHomeStack()) {
2045 continue;
2046 }
2047 final ActivityRecord ar = stack.findTaskLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07002048 if (ar != null) {
2049 return ar;
2050 }
2051 }
2052 return null;
2053 }
2054
2055 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
2056 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2057 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
2058 if (ar != null) {
2059 return ar;
2060 }
2061 }
2062 return null;
2063 }
2064
Craig Mautner8d341ef2013-03-26 09:03:27 -07002065 void goingToSleepLocked() {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002066 scheduleSleepTimeout();
2067 if (!mGoingToSleep.isHeld()) {
2068 mGoingToSleep.acquire();
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002069 if (mLaunchingActivity.isHeld()) {
2070 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
2071 throw new IllegalStateException("Calling must be system uid");
Craig Mautner0eea92c2013-05-16 13:35:39 -07002072 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002073 mLaunchingActivity.release();
2074 mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
Craig Mautner0eea92c2013-05-16 13:35:39 -07002075 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002076 }
2077 }
2078
2079 boolean shutdownLocked(int timeout) {
2080 boolean timedout = false;
Craig Mautner0eea92c2013-05-16 13:35:39 -07002081 goingToSleepLocked();
2082 checkReadyForSleepLocked();
2083
2084 final long endTime = System.currentTimeMillis() + timeout;
2085 while (true) {
2086 boolean cantShutdown = false;
2087 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2088 cantShutdown |= mStacks.get(stackNdx).checkReadyForSleepLocked();
2089 }
2090 if (cantShutdown) {
2091 long timeRemaining = endTime - System.currentTimeMillis();
2092 if (timeRemaining > 0) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002093 try {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002094 mService.wait(timeRemaining);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002095 } catch (InterruptedException e) {
2096 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002097 } else {
2098 Slog.w(TAG, "Activity manager shutdown timed out");
2099 timedout = true;
2100 break;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002101 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002102 } else {
2103 break;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002104 }
2105 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002106
2107 // Force checkReadyForSleep to complete.
2108 mSleepTimeout = true;
2109 checkReadyForSleepLocked();
2110
Craig Mautner8d341ef2013-03-26 09:03:27 -07002111 return timedout;
2112 }
2113
2114 void comeOutOfSleepIfNeededLocked() {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002115 removeSleepTimeouts();
2116 if (mGoingToSleep.isHeld()) {
2117 mGoingToSleep.release();
2118 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002119 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002120 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002121 stack.awakeFromSleepingLocked();
2122 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07002123 resumeTopActivitiesLocked();
Craig Mautnerde4ef022013-04-07 19:01:33 -07002124 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002125 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002126 mGoingToSleepActivities.clear();
2127 }
2128
2129 void activitySleptLocked(ActivityRecord r) {
2130 mGoingToSleepActivities.remove(r);
2131 checkReadyForSleepLocked();
2132 }
2133
2134 void checkReadyForSleepLocked() {
2135 if (!mService.isSleepingOrShuttingDown()) {
2136 // Do not care.
2137 return;
2138 }
2139
2140 if (!mSleepTimeout) {
2141 boolean dontSleep = false;
2142 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2143 dontSleep |= mStacks.get(stackNdx).checkReadyForSleepLocked();
2144 }
2145
2146 if (mStoppingActivities.size() > 0) {
2147 // Still need to tell some activities to stop; can't sleep yet.
2148 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
2149 + mStoppingActivities.size() + " activities");
2150 scheduleIdleLocked();
2151 dontSleep = true;
2152 }
2153
2154 if (mGoingToSleepActivities.size() > 0) {
2155 // Still need to tell some activities to sleep; can't sleep yet.
2156 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
2157 + mGoingToSleepActivities.size() + " activities");
2158 dontSleep = true;
2159 }
2160
2161 if (dontSleep) {
2162 return;
2163 }
2164 }
2165
2166 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2167 mStacks.get(stackNdx).goToSleep();
2168 }
2169
2170 removeSleepTimeouts();
2171
2172 if (mGoingToSleep.isHeld()) {
2173 mGoingToSleep.release();
2174 }
2175 if (mService.mShuttingDown) {
2176 mService.notifyAll();
2177 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002178 }
2179
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002180 boolean reportResumedActivityLocked(ActivityRecord r) {
2181 final ActivityStack stack = r.task.stack;
2182 if (isFrontStack(stack)) {
Jeff Sharkey5782da72013-04-25 14:32:30 -07002183 mService.updateUsageStats(r, true);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002184 }
2185 if (allResumedActivitiesComplete()) {
2186 ensureActivitiesVisibleLocked(null, 0);
2187 mWindowManager.executeAppTransition();
2188 return true;
2189 }
2190 return false;
2191 }
2192
Craig Mautner8d341ef2013-03-26 09:03:27 -07002193 void handleAppCrashLocked(ProcessRecord app) {
2194 final int numStacks = mStacks.size();
2195 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2196 final ActivityStack stack = mStacks.get(stackNdx);
2197 stack.handleAppCrashLocked(app);
2198 }
2199 }
2200
Craig Mautnerde4ef022013-04-07 19:01:33 -07002201 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
Craig Mautner580ea812013-04-25 12:58:38 -07002202 // First the front stacks. In case any are not fullscreen and are in front of home.
2203 boolean showHomeBehindStack = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07002204 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner580ea812013-04-25 12:58:38 -07002205 final ActivityStack stack = mStacks.get(stackNdx);
2206 if (isFrontStack(stack)) {
2207 showHomeBehindStack =
2208 stack.ensureActivitiesVisibleLocked(starting, configChanges);
2209 }
2210 }
2211 // Now do back stacks.
2212 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2213 final ActivityStack stack = mStacks.get(stackNdx);
2214 if (!isFrontStack(stack)) {
2215 stack.ensureActivitiesVisibleLocked(starting, configChanges, showHomeBehindStack);
2216 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002217 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002218 }
2219
2220 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
2221 final int numStacks = mStacks.size();
2222 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2223 final ActivityStack stack = mStacks.get(stackNdx);
2224 stack.scheduleDestroyActivities(app, false, reason);
2225 }
2226 }
2227
2228 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner2420ead2013-04-01 17:13:20 -07002229 mCurrentUser = userId;
Craig Mautnerac6f8432013-07-17 13:24:59 -07002230
2231 final String homePackageName = mService.getHomePackageName();
2232 if (homePackageName != null) {
2233 setHomePackageName(mCurrentUser, homePackageName);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002234 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002235
2236 mStartingUsers.add(uss);
Craig Mautnerac6f8432013-07-17 13:24:59 -07002237 boolean haveActivities = false;
2238 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2239 haveActivities |= mStacks.get(stackNdx).switchUserLocked(userId);
2240 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002241
2242 resumeTopActivitiesLocked();
2243
Craig Mautner8d341ef2013-03-26 09:03:27 -07002244 return haveActivities;
Craig Mautner2219a1b2013-03-25 09:44:30 -07002245 }
2246
Craig Mautnerde4ef022013-04-07 19:01:33 -07002247 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
2248 int N = mStoppingActivities.size();
2249 if (N <= 0) return null;
2250
2251 ArrayList<ActivityRecord> stops = null;
2252
2253 final boolean nowVisible = allResumedActivitiesVisible();
2254 for (int i=0; i<N; i++) {
2255 ActivityRecord s = mStoppingActivities.get(i);
2256 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
2257 + nowVisible + " waitingVisible=" + s.waitingVisible
2258 + " finishing=" + s.finishing);
2259 if (s.waitingVisible && nowVisible) {
2260 mWaitingVisibleActivities.remove(s);
2261 s.waitingVisible = false;
2262 if (s.finishing) {
2263 // If this activity is finishing, it is sitting on top of
2264 // everyone else but we now know it is no longer needed...
2265 // so get rid of it. Otherwise, we need to go through the
2266 // normal flow and hide it once we determine that it is
2267 // hidden by the activities in front of it.
2268 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002269 mWindowManager.setAppVisibility(s.appToken, false);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002270 }
2271 }
2272 if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
2273 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
2274 if (stops == null) {
2275 stops = new ArrayList<ActivityRecord>();
2276 }
2277 stops.add(s);
2278 mStoppingActivities.remove(i);
2279 N--;
2280 i--;
2281 }
2282 }
2283
2284 return stops;
2285 }
2286
Craig Mautnercf910b02013-04-23 11:23:27 -07002287 void validateTopActivitiesLocked() {
2288 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2289 final ActivityStack stack = mStacks.get(stackNdx);
2290 final ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002291 final ActivityState state = r == null ? ActivityState.DESTROYED : r.state;
Craig Mautnercf910b02013-04-23 11:23:27 -07002292 if (isFrontStack(stack)) {
2293 if (r == null) {
2294 Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
2295 } else {
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002296 final ActivityRecord pausing = stack.mPausingActivity;
2297 if (pausing != null && pausing == r) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002298 Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002299 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002300 }
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002301 if (state != ActivityState.INITIALIZING && state != ActivityState.RESUMED) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002302 Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002303 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002304 }
2305 }
2306 } else {
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002307 final ActivityRecord resumed = stack.mResumedActivity;
2308 if (resumed != null && resumed == r) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002309 Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002310 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002311 }
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002312 if (r != null && (state == ActivityState.INITIALIZING
2313 || state == ActivityState.RESUMED)) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002314 Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002315 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002316 }
2317 }
2318 }
2319 }
2320
Craig Mautner76ea2242013-05-15 11:40:05 -07002321 private static String stackStateToString(int stackState) {
2322 switch (stackState) {
2323 case STACK_STATE_HOME_IN_FRONT: return "STACK_STATE_HOME_IN_FRONT";
2324 case STACK_STATE_HOME_TO_BACK: return "STACK_STATE_HOME_TO_BACK";
2325 case STACK_STATE_HOME_IN_BACK: return "STACK_STATE_HOME_IN_BACK";
2326 case STACK_STATE_HOME_TO_FRONT: return "STACK_STATE_HOME_TO_FRONT";
2327 default: return "Unknown stackState=" + stackState;
2328 }
2329 }
2330
Craig Mautner27084302013-03-25 08:05:25 -07002331 public void dump(PrintWriter pw, String prefix) {
2332 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
2333 pw.println(mDismissKeyguardOnNextActivity);
Craig Mautner76ea2242013-05-15 11:40:05 -07002334 pw.print(prefix); pw.print("mStackState="); pw.println(stackStateToString(mStackState));
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002335 pw.print(prefix); pw.println("mSleepTimeout: " + mSleepTimeout);
2336 pw.print(prefix); pw.println("mCurTaskId: " + mCurTaskId);
Craig Mautnerac6f8432013-07-17 13:24:59 -07002337 pw.print(prefix); pw.print("mHomePackageNames:");
2338 for (int i = 0; i < mHomePackageNames.size(); ++i) {
2339 pw.print(" ("); pw.print(mHomePackageNames.keyAt(i)); pw.print(",");
2340 pw.print(mHomePackageNames.valueAt(i)); pw.print(")");
2341 }
2342 pw.println();
Craig Mautner27084302013-03-25 08:05:25 -07002343 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002344
Craig Mautner20e72272013-04-01 13:45:53 -07002345 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002346 return getFocusedStack().getDumpActivitiesLocked(name);
Craig Mautner20e72272013-04-01 13:45:53 -07002347 }
2348
Dianne Hackborn390517b2013-05-30 15:03:32 -07002349 static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
2350 boolean needSep, String prefix) {
2351 if (activity != null) {
2352 if (dumpPackage == null || dumpPackage.equals(activity.packageName)) {
2353 if (needSep) {
2354 pw.println();
Dianne Hackborn390517b2013-05-30 15:03:32 -07002355 }
2356 pw.print(prefix);
2357 pw.println(activity);
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002358 return true;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002359 }
2360 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002361 return false;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002362 }
2363
Craig Mautner8d341ef2013-03-26 09:03:27 -07002364 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
2365 boolean dumpClient, String dumpPackage) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002366 boolean printed = false;
2367 boolean needSep = false;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002368 final int numStacks = mStacks.size();
2369 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2370 final ActivityStack stack = mStacks.get(stackNdx);
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002371 StringBuilder stackHeader = new StringBuilder(128);
2372 stackHeader.append(" Stack #");
2373 stackHeader.append(mStacks.indexOf(stack));
2374 stackHeader.append(":");
2375 printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, needSep,
2376 stackHeader.toString());
2377 printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll,
2378 false, dumpPackage, true, " Running activities (most recent first):", null);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002379
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002380 needSep = printed;
2381 boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002382 " mPausingActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002383 if (pr) {
2384 printed = true;
2385 needSep = false;
2386 }
2387 pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002388 " mResumedActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002389 if (pr) {
2390 printed = true;
2391 needSep = false;
2392 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002393 if (dumpAll) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002394 pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002395 " mLastPausedActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002396 if (pr) {
2397 printed = true;
Craig Mautner0f922742013-08-06 08:44:42 -07002398 needSep = true;
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002399 }
Craig Mautner0f922742013-08-06 08:44:42 -07002400 printed |= printThisActivity(pw, stack.mLastNoHistoryActivity, dumpPackage,
2401 needSep, " mLastNoHistoryActivity: ");
Craig Mautner8d341ef2013-03-26 09:03:27 -07002402 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002403 needSep = printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002404 }
2405
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002406 printed |= dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll,
2407 false, dumpPackage, true, " Activities waiting to finish:", null);
2408 printed |= dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll,
2409 false, dumpPackage, true, " Activities waiting to stop:", null);
2410 printed |= dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
2411 false, dumpPackage, true, " Activities waiting for another to become visible:",
2412 null);
2413 printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll,
2414 false, dumpPackage, true, " Activities waiting to sleep:", null);
2415 printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll,
2416 false, dumpPackage, true, " Activities waiting to sleep:", null);
Craig Mautnerf3333272013-04-22 10:55:53 -07002417
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002418 return printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002419 }
2420
Dianne Hackborn390517b2013-05-30 15:03:32 -07002421 static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
Craig Mautner8d341ef2013-03-26 09:03:27 -07002422 String prefix, String label, boolean complete, boolean brief, boolean client,
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002423 String dumpPackage, boolean needNL, String header1, String header2) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002424 TaskRecord lastTask = null;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002425 String innerPrefix = null;
2426 String[] args = null;
2427 boolean printed = false;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002428 for (int i=list.size()-1; i>=0; i--) {
2429 final ActivityRecord r = list.get(i);
2430 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
2431 continue;
2432 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07002433 if (innerPrefix == null) {
2434 innerPrefix = prefix + " ";
2435 args = new String[0];
2436 }
2437 printed = true;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002438 final boolean full = !brief && (complete || !r.isInHistory());
2439 if (needNL) {
Dianne Hackborn390517b2013-05-30 15:03:32 -07002440 pw.println("");
Craig Mautner8d341ef2013-03-26 09:03:27 -07002441 needNL = false;
2442 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002443 if (header1 != null) {
2444 pw.println(header1);
2445 header1 = null;
2446 }
2447 if (header2 != null) {
2448 pw.println(header2);
2449 header2 = null;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002450 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002451 if (lastTask != r.task) {
2452 lastTask = r.task;
2453 pw.print(prefix);
2454 pw.print(full ? "* " : " ");
2455 pw.println(lastTask);
2456 if (full) {
2457 lastTask.dump(pw, prefix + " ");
2458 } else if (complete) {
2459 // Complete + brief == give a summary. Isn't that obvious?!?
2460 if (lastTask.intent != null) {
2461 pw.print(prefix); pw.print(" ");
2462 pw.println(lastTask.intent.toInsecureStringWithClip());
2463 }
2464 }
2465 }
2466 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
2467 pw.print(" #"); pw.print(i); pw.print(": ");
2468 pw.println(r);
2469 if (full) {
2470 r.dump(pw, innerPrefix);
2471 } else if (complete) {
2472 // Complete + brief == give a summary. Isn't that obvious?!?
2473 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
2474 if (r.app != null) {
2475 pw.print(innerPrefix); pw.println(r.app);
2476 }
2477 }
2478 if (client && r.app != null && r.app.thread != null) {
2479 // flush anything that is already in the PrintWriter since the thread is going
2480 // to write to the file descriptor directly
2481 pw.flush();
2482 try {
2483 TransferPipe tp = new TransferPipe();
2484 try {
2485 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
2486 r.appToken, innerPrefix, args);
2487 // Short timeout, since blocking here can
2488 // deadlock with the application.
2489 tp.go(fd, 2000);
2490 } finally {
2491 tp.kill();
2492 }
2493 } catch (IOException e) {
2494 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
2495 } catch (RemoteException e) {
2496 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
2497 }
2498 needNL = true;
2499 }
2500 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07002501 return printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002502 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002503
Craig Mautnerf3333272013-04-22 10:55:53 -07002504 void scheduleIdleTimeoutLocked(ActivityRecord next) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002505 if (DEBUG_IDLE) Slog.d(TAG, "scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4));
Craig Mautnerc64f73e2013-04-24 16:44:56 -07002506 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
2507 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
Craig Mautnerf3333272013-04-22 10:55:53 -07002508 }
2509
2510 final void scheduleIdleLocked() {
Craig Mautner05d29032013-05-03 13:40:13 -07002511 mHandler.sendEmptyMessage(IDLE_NOW_MSG);
Craig Mautnerf3333272013-04-22 10:55:53 -07002512 }
2513
2514 void removeTimeoutsForActivityLocked(ActivityRecord r) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002515 if (DEBUG_IDLE) Slog.d(TAG, "removeTimeoutsForActivity: Callers=" + Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07002516 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
2517 }
2518
Craig Mautner05d29032013-05-03 13:40:13 -07002519 final void scheduleResumeTopActivities() {
2520 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2521 }
2522
Craig Mautner0eea92c2013-05-16 13:35:39 -07002523 void removeSleepTimeouts() {
2524 mSleepTimeout = false;
2525 mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
2526 }
2527
2528 final void scheduleSleepTimeout() {
2529 removeSleepTimeouts();
2530 mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT);
2531 }
2532
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002533 private final class ActivityStackSupervisorHandler extends Handler {
Craig Mautnerf3333272013-04-22 10:55:53 -07002534
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002535 public ActivityStackSupervisorHandler(Looper looper) {
2536 super(looper);
2537 }
2538
Craig Mautnerf3333272013-04-22 10:55:53 -07002539 void activityIdleInternal(ActivityRecord r) {
2540 synchronized (mService) {
2541 activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
2542 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002543 }
2544
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002545 @Override
2546 public void handleMessage(Message msg) {
2547 switch (msg.what) {
Craig Mautnerf3333272013-04-22 10:55:53 -07002548 case IDLE_TIMEOUT_MSG: {
Craig Mautner5eda9b32013-07-02 11:58:16 -07002549 if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_TIMEOUT_MSG: r=" + msg.obj);
Craig Mautnerf3333272013-04-22 10:55:53 -07002550 if (mService.mDidDexOpt) {
2551 mService.mDidDexOpt = false;
2552 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2553 nmsg.obj = msg.obj;
2554 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
2555 return;
2556 }
2557 // We don't at this point know if the activity is fullscreen,
2558 // so we need to be conservative and assume it isn't.
2559 activityIdleInternal((ActivityRecord)msg.obj);
2560 } break;
2561 case IDLE_NOW_MSG: {
Craig Mautner5eda9b32013-07-02 11:58:16 -07002562 if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_NOW_MSG: r=" + msg.obj);
Craig Mautnerf3333272013-04-22 10:55:53 -07002563 activityIdleInternal((ActivityRecord)msg.obj);
2564 } break;
Craig Mautner05d29032013-05-03 13:40:13 -07002565 case RESUME_TOP_ACTIVITY_MSG: {
2566 synchronized (mService) {
2567 resumeTopActivitiesLocked();
2568 }
2569 } break;
Craig Mautner0eea92c2013-05-16 13:35:39 -07002570 case SLEEP_TIMEOUT_MSG: {
2571 synchronized (mService) {
2572 if (mService.isSleepingOrShuttingDown()) {
2573 Slog.w(TAG, "Sleep timeout! Sleeping now.");
2574 mSleepTimeout = true;
2575 checkReadyForSleepLocked();
2576 }
2577 }
2578 } break;
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002579 case LAUNCH_TIMEOUT_MSG: {
2580 if (mService.mDidDexOpt) {
2581 mService.mDidDexOpt = false;
2582 mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
2583 return;
2584 }
2585 synchronized (mService) {
2586 if (mLaunchingActivity.isHeld()) {
2587 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
2588 if (VALIDATE_WAKE_LOCK_CALLER
2589 && Binder.getCallingUid() != Process.myUid()) {
2590 throw new IllegalStateException("Calling must be system uid");
2591 }
2592 mLaunchingActivity.release();
2593 }
2594 }
2595 } break;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002596 }
2597 }
2598 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002599
Craig Mautnerac6f8432013-07-17 13:24:59 -07002600 String getHomePackageName() {
2601 return mHomePackageNames.get(mCurrentUser);
2602 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002603
Craig Mautnerac6f8432013-07-17 13:24:59 -07002604 void setHomePackageName(int userId, String homePackageName) {
2605 if (DEBUG_SWITCH) Slog.d(TAG, "setHomePackageName: user=" + userId + " package="
2606 + homePackageName);
2607 mHomePackageNames.put(userId, homePackageName);
Craig Mautner858d8a62013-04-23 17:08:34 -07002608 }
Craig Mautner27084302013-03-25 08:05:25 -07002609}