blob: 63f91ac435a256b831898212252c57fb8d639fe3 [file] [log] [blame]
Craig Mautner27084302013-03-25 08:05:25 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Craig Mautner6170f732013-04-02 13:05:23 -070019import static android.Manifest.permission.START_ANY_ACTIVITY;
Craig Mautner29219d92013-04-16 20:19:12 -070020import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
21import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Craig Mautner6170f732013-04-02 13:05:23 -070022import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Craig Mautner2420ead2013-04-01 17:13:20 -070023import static com.android.server.am.ActivityManagerService.localLOGV;
Craig Mautner23ac33b2013-04-01 16:26:35 -070024import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION;
Craig Mautnere7c58b62013-06-12 20:19:00 -070025import static com.android.server.am.ActivityManagerService.DEBUG_FOCUS;
Craig Mautner0eea92c2013-05-16 13:35:39 -070026import static com.android.server.am.ActivityManagerService.DEBUG_PAUSE;
Craig Mautner6170f732013-04-02 13:05:23 -070027import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
Craig Mautner0eea92c2013-05-16 13:35:39 -070028import static com.android.server.am.ActivityManagerService.DEBUG_STACK;
Craig Mautner2420ead2013-04-01 17:13:20 -070029import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
Craig Mautner8849a5e2013-04-02 16:41:03 -070030import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
31import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
Craig Mautner05d29032013-05-03 13:40:13 -070032import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
Craig Mautner8d341ef2013-03-26 09:03:27 -070033import static com.android.server.am.ActivityManagerService.TAG;
34
Craig Mautner2420ead2013-04-01 17:13:20 -070035import android.app.Activity;
Craig Mautner23ac33b2013-04-01 16:26:35 -070036import android.app.ActivityManager;
37import android.app.ActivityOptions;
38import android.app.AppGlobals;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070039import android.app.IActivityManager;
Craig Mautner23ac33b2013-04-01 16:26:35 -070040import android.app.IApplicationThread;
Craig Mautner20e72272013-04-01 13:45:53 -070041import android.app.IThumbnailReceiver;
Craig Mautner23ac33b2013-04-01 16:26:35 -070042import android.app.PendingIntent;
Craig Mautner20e72272013-04-01 13:45:53 -070043import android.app.ActivityManager.RunningTaskInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070044import android.app.IActivityManager.WaitResult;
Craig Mautner2420ead2013-04-01 17:13:20 -070045import android.app.ResultInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070046import android.content.ComponentName;
Craig Mautner2219a1b2013-03-25 09:44:30 -070047import android.content.Context;
Craig Mautner23ac33b2013-04-01 16:26:35 -070048import android.content.IIntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070049import android.content.Intent;
Craig Mautner23ac33b2013-04-01 16:26:35 -070050import android.content.IntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070051import android.content.pm.ActivityInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070052import android.content.pm.ApplicationInfo;
53import android.content.pm.PackageManager;
54import android.content.pm.ResolveInfo;
55import android.content.res.Configuration;
56import android.os.Binder;
Craig Mautner8d341ef2013-03-26 09:03:27 -070057import android.os.Bundle;
Craig Mautnerb59dcfd2013-05-06 13:12:58 -070058import android.os.Debug;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070059import android.os.Handler;
Craig Mautner23ac33b2013-04-01 16:26:35 -070060import android.os.IBinder;
Craig Mautner2219a1b2013-03-25 09:44:30 -070061import android.os.Looper;
Craig Mautner2420ead2013-04-01 17:13:20 -070062import android.os.Message;
Craig Mautner23ac33b2013-04-01 16:26:35 -070063import android.os.ParcelFileDescriptor;
Craig Mautner0eea92c2013-05-16 13:35:39 -070064import android.os.PowerManager;
Craig Mautner7ea5bd42013-07-05 15:27:08 -070065import android.os.Process;
Craig Mautner8d341ef2013-03-26 09:03:27 -070066import android.os.RemoteException;
Craig Mautner23ac33b2013-04-01 16:26:35 -070067import android.os.SystemClock;
Craig Mautner6170f732013-04-02 13:05:23 -070068import android.os.UserHandle;
Craig Mautner2420ead2013-04-01 17:13:20 -070069import android.util.EventLog;
Craig Mautner8d341ef2013-03-26 09:03:27 -070070import android.util.Slog;
Craig Mautner858d8a62013-04-23 17:08:34 -070071import android.util.SparseArray;
Craig Mautner2219a1b2013-03-25 09:44:30 -070072
Craig Mautner23ac33b2013-04-01 16:26:35 -070073import com.android.internal.app.HeavyWeightSwitcherActivity;
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070074import com.android.internal.os.TransferPipe;
Craig Mautner6170f732013-04-02 13:05:23 -070075import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
Craig Mautner2420ead2013-04-01 17:13:20 -070076import com.android.server.am.ActivityStack.ActivityState;
Craig Mautnerde4ef022013-04-07 19:01:33 -070077import com.android.server.wm.StackBox;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070078import com.android.server.wm.WindowManagerService;
Craig Mautner23ac33b2013-04-01 16:26:35 -070079
Craig Mautner8d341ef2013-03-26 09:03:27 -070080import java.io.FileDescriptor;
81import java.io.IOException;
Craig Mautner27084302013-03-25 08:05:25 -070082import java.io.PrintWriter;
Craig Mautner2219a1b2013-03-25 09:44:30 -070083import java.util.ArrayList;
Craig Mautner8d341ef2013-03-26 09:03:27 -070084import java.util.List;
Craig Mautner27084302013-03-25 08:05:25 -070085
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070086public final class ActivityStackSupervisor {
Craig Mautnerde4ef022013-04-07 19:01:33 -070087 static final boolean DEBUG = ActivityManagerService.DEBUG || false;
88 static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
89 static final boolean DEBUG_APP = DEBUG || false;
90 static final boolean DEBUG_SAVED_STATE = DEBUG || false;
91 static final boolean DEBUG_STATES = DEBUG || false;
Craig Mautnerb59dcfd2013-05-06 13:12:58 -070092 static final boolean DEBUG_IDLE = DEBUG || false;
Craig Mautner2420ead2013-04-01 17:13:20 -070093
Craig Mautner2219a1b2013-03-25 09:44:30 -070094 public static final int HOME_STACK_ID = 0;
Craig Mautner27084302013-03-25 08:05:25 -070095
Craig Mautnerf3333272013-04-22 10:55:53 -070096 /** How long we wait until giving up on the last activity telling us it is idle. */
97 static final int IDLE_TIMEOUT = 10*1000;
98
Craig Mautner0eea92c2013-05-16 13:35:39 -070099 /** How long we can hold the sleep wake lock before giving up. */
100 static final int SLEEP_TIMEOUT = 5*1000;
101
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700102 // How long we can hold the launch wake lock before giving up.
103 static final int LAUNCH_TIMEOUT = 10*1000;
104
Craig Mautner05d29032013-05-03 13:40:13 -0700105 static final int IDLE_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG;
106 static final int IDLE_NOW_MSG = FIRST_SUPERVISOR_STACK_MSG + 1;
107 static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2;
Craig Mautner0eea92c2013-05-16 13:35:39 -0700108 static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3;
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700109 static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 4;
110
111 // For debugging to make sure the caller when acquiring/releasing our
112 // wake lock is the system process.
113 static final boolean VALIDATE_WAKE_LOCK_CALLER = false;
Craig Mautnerf3333272013-04-22 10:55:53 -0700114
Craig Mautner27084302013-03-25 08:05:25 -0700115 final ActivityManagerService mService;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700116 final Context mContext;
117 final Looper mLooper;
Craig Mautner27084302013-03-25 08:05:25 -0700118
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700119 final ActivityStackSupervisorHandler mHandler;
120
121 /** Short cut */
122 WindowManagerService mWindowManager;
123
Craig Mautner27084302013-03-25 08:05:25 -0700124 /** Dismiss the keyguard after the next activity is displayed? */
125 private boolean mDismissKeyguardOnNextActivity = false;
126
Craig Mautner8d341ef2013-03-26 09:03:27 -0700127 /** Identifier counter for all ActivityStacks */
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700128 private int mLastStackId = HOME_STACK_ID;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700129
130 /** Task identifier that activities are currently being started in. Incremented each time a
131 * new task is created. */
132 private int mCurTaskId = 0;
133
Craig Mautner2420ead2013-04-01 17:13:20 -0700134 /** The current user */
135 private int mCurrentUser;
136
Craig Mautner8d341ef2013-03-26 09:03:27 -0700137 /** The stack containing the launcher app */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700138 private ActivityStack mHomeStack;
Craig Mautner20e72272013-04-01 13:45:53 -0700139
Craig Mautnerde4ef022013-04-07 19:01:33 -0700140 /** The non-home stack currently receiving input or launching the next activity. If home is
Craig Mautner41c0f352013-05-28 08:39:25 -0700141 * in front then mHomeStack overrides mFocusedStack.
142 * DO NOT ACCESS DIRECTLY - It may be null, use getFocusedStack() */
Craig Mautner29219d92013-04-16 20:19:12 -0700143 private ActivityStack mFocusedStack;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700144
145 /** All the non-launcher stacks */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700146 private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
147
Craig Mautnerde4ef022013-04-07 19:01:33 -0700148 private static final int STACK_STATE_HOME_IN_FRONT = 0;
149 private static final int STACK_STATE_HOME_TO_BACK = 1;
150 private static final int STACK_STATE_HOME_IN_BACK = 2;
151 private static final int STACK_STATE_HOME_TO_FRONT = 3;
152 private int mStackState = STACK_STATE_HOME_IN_FRONT;
153
154 /** List of activities that are waiting for a new activity to become visible before completing
155 * whatever operation they are supposed to do. */
156 final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();
157
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700158 /** List of processes waiting to find out about the next visible activity. */
159 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible =
160 new ArrayList<IActivityManager.WaitResult>();
161
162 /** List of processes waiting to find out about the next launched activity. */
163 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched =
164 new ArrayList<IActivityManager.WaitResult>();
165
Craig Mautnerde4ef022013-04-07 19:01:33 -0700166 /** List of activities that are ready to be stopped, but waiting for the next activity to
167 * settle down before doing so. */
168 final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();
169
Craig Mautnerf3333272013-04-22 10:55:53 -0700170 /** List of activities that are ready to be finished, but waiting for the previous activity to
171 * settle down before doing so. It contains ActivityRecord objects. */
172 final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<ActivityRecord>();
173
Craig Mautner0eea92c2013-05-16 13:35:39 -0700174 /** List of activities that are in the process of going to sleep. */
175 final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<ActivityRecord>();
176
Craig Mautnerf3333272013-04-22 10:55:53 -0700177 /** List of ActivityRecord objects that have been finished and must still report back to a
178 * pending thumbnail receiver. */
179 final ArrayList<ActivityRecord> mCancelledThumbnails = new ArrayList<ActivityRecord>();
180
181 /** Used on user changes */
182 final ArrayList<UserStartedState> mStartingUsers = new ArrayList<UserStartedState>();
183
Craig Mautnerde4ef022013-04-07 19:01:33 -0700184 /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity
185 * is being brought in front of us. */
186 boolean mUserLeaving = false;
187
Craig Mautner858d8a62013-04-23 17:08:34 -0700188 /** Stacks belonging to users other than mCurrentUser. Indexed by userId. */
189 final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
190
Craig Mautner0eea92c2013-05-16 13:35:39 -0700191 /** Set when we have taken too long waiting to go to sleep. */
192 boolean mSleepTimeout = false;
193
194 /**
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700195 * We don't want to allow the device to go to sleep while in the process
196 * of launching an activity. This is primarily to allow alarm intent
197 * receivers to launch an activity and get that to run before the device
198 * goes back to sleep.
199 */
200 final PowerManager.WakeLock mLaunchingActivity;
201
202 /**
Craig Mautner0eea92c2013-05-16 13:35:39 -0700203 * Set when the system is going to sleep, until we have
204 * successfully paused the current activity and released our wake lock.
205 * At that point the system is allowed to actually sleep.
206 */
207 final PowerManager.WakeLock mGoingToSleep;
208
Craig Mautner2219a1b2013-03-25 09:44:30 -0700209 public ActivityStackSupervisor(ActivityManagerService service, Context context,
210 Looper looper) {
Craig Mautner27084302013-03-25 08:05:25 -0700211 mService = service;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700212 mContext = context;
213 mLooper = looper;
Craig Mautner0eea92c2013-05-16 13:35:39 -0700214 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
215 mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700216 mHandler = new ActivityStackSupervisorHandler(looper);
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700217 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
218 throw new IllegalStateException("Calling must be system uid");
219 }
220 mLaunchingActivity =
221 pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
222 mLaunchingActivity.setReferenceCounted(false);
Craig Mautner2219a1b2013-03-25 09:44:30 -0700223 }
224
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700225 void setWindowManager(WindowManagerService wm) {
226 mWindowManager = wm;
227 mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700228 mStacks.add(mHomeStack);
Craig Mautner27084302013-03-25 08:05:25 -0700229 }
230
231 void dismissKeyguard() {
232 if (mDismissKeyguardOnNextActivity) {
233 mDismissKeyguardOnNextActivity = false;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700234 mWindowManager.dismissKeyguard();
Craig Mautner27084302013-03-25 08:05:25 -0700235 }
236 }
237
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700238 ActivityStack getFocusedStack() {
Craig Mautnerf88c50f2013-04-18 19:25:12 -0700239 if (mFocusedStack == null) {
240 return mHomeStack;
241 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700242 switch (mStackState) {
243 case STACK_STATE_HOME_IN_FRONT:
244 case STACK_STATE_HOME_TO_FRONT:
245 return mHomeStack;
246 case STACK_STATE_HOME_IN_BACK:
247 case STACK_STATE_HOME_TO_BACK:
248 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700249 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700250 }
Craig Mautner20e72272013-04-01 13:45:53 -0700251 }
252
Craig Mautnerde4ef022013-04-07 19:01:33 -0700253 ActivityStack getLastStack() {
254 switch (mStackState) {
255 case STACK_STATE_HOME_IN_FRONT:
256 case STACK_STATE_HOME_TO_BACK:
257 return mHomeStack;
258 case STACK_STATE_HOME_TO_FRONT:
259 case STACK_STATE_HOME_IN_BACK:
260 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700261 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700262 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700263 }
264
Craig Mautnerde4ef022013-04-07 19:01:33 -0700265 boolean isFrontStack(ActivityStack stack) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700266 return (stack.mCurrentUser == mCurrentUser) &&
267 !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
Craig Mautner20e72272013-04-01 13:45:53 -0700268 }
269
Craig Mautnerde4ef022013-04-07 19:01:33 -0700270 void moveHomeStack(boolean toFront) {
271 final boolean homeInFront = isFrontStack(mHomeStack);
272 if (homeInFront ^ toFront) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700273 if (DEBUG_STACK) Slog.d(TAG, "moveHomeTask: mStackState old=" +
274 stackStateToString(mStackState) + " new=" + stackStateToString(homeInFront ?
275 STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700276 mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
277 }
278 }
279
Craig Mautner69ada552013-04-18 13:51:51 -0700280 boolean resumeHomeActivity(ActivityRecord prev) {
281 moveHomeStack(true);
282 if (prev != null) {
283 prev.mLaunchHomeTaskNext = false;
284 }
Craig Mautnera8a90e02013-06-28 15:24:50 -0700285 ActivityRecord r = mHomeStack.topRunningActivityLocked(null);
286 if (r != null) {
287 mService.setFocusedActivityLocked(r);
Craig Mautner05d29032013-05-03 13:40:13 -0700288 return resumeTopActivitiesLocked(mHomeStack, prev, null);
Craig Mautner69ada552013-04-18 13:51:51 -0700289 }
290 return mService.startHomeActivityLocked(mCurrentUser);
291 }
292
Craig Mautnerde4ef022013-04-07 19:01:33 -0700293 final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r,
294 ActivityStack stack) {
295 if (stack == mHomeStack) {
296 return;
297 }
298 if ((sourceRecord == null && getLastStack() == mHomeStack) ||
Craig Mautner86d67a42013-05-14 10:34:38 -0700299 (sourceRecord != null && sourceRecord.isHomeActivity())) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700300 if (r == null) {
301 r = stack.topRunningActivityLocked(null);
302 }
Craig Mautner86d67a42013-05-14 10:34:38 -0700303 if (r != null && !r.isHomeActivity() && r.isRootActivity()) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700304 r.mLaunchHomeTaskNext = true;
305 }
306 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700307 }
308
Craig Mautner27084302013-03-25 08:05:25 -0700309 void setDismissKeyguard(boolean dismiss) {
310 mDismissKeyguardOnNextActivity = dismiss;
311 }
312
Craig Mautner8d341ef2013-03-26 09:03:27 -0700313 TaskRecord anyTaskForIdLocked(int id) {
314 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
315 ActivityStack stack = mStacks.get(stackNdx);
316 TaskRecord task = stack.taskForIdLocked(id);
317 if (task != null) {
318 return task;
319 }
320 }
321 return null;
322 }
323
Craig Mautner6170f732013-04-02 13:05:23 -0700324 ActivityRecord isInAnyStackLocked(IBinder token) {
325 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
326 final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
327 if (r != null) {
328 return r;
329 }
330 }
331 return null;
332 }
333
Craig Mautner8d341ef2013-03-26 09:03:27 -0700334 int getNextTaskId() {
335 do {
336 mCurTaskId++;
337 if (mCurTaskId <= 0) {
338 mCurTaskId = 1;
339 }
340 } while (anyTaskForIdLocked(mCurTaskId) != null);
341 return mCurTaskId;
342 }
343
Craig Mautnerde4ef022013-04-07 19:01:33 -0700344 void removeTask(TaskRecord task) {
Craig Mautnerb3b36ba2013-05-20 13:21:10 -0700345 mWindowManager.removeTask(task.taskId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700346 final ActivityStack stack = task.stack;
Craig Mautnerb3b36ba2013-05-20 13:21:10 -0700347 final ActivityRecord r = stack.mResumedActivity;
348 if (r != null && r.task == task) {
349 stack.mResumedActivity = null;
350 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700351 if (stack.removeTask(task) && !stack.isHomeStack()) {
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700352 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700353 mStacks.remove(stack);
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700354 final int stackId = stack.mStackId;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700355 final int nextStackId = mWindowManager.removeStack(stackId);
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700356 // TODO: Perhaps we need to let the ActivityManager determine the next focus...
Craig Mautner41c0f352013-05-28 08:39:25 -0700357 if (getFocusedStack().mStackId == stackId) {
Craig Mautner1602ec22013-05-12 10:24:27 -0700358 // If this is the last app stack, set mFocusedStack to null.
Craig Mautner29219d92013-04-16 20:19:12 -0700359 mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700360 }
361 }
362 }
363
364 ActivityRecord resumedAppLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700365 ActivityStack stack = getFocusedStack();
366 if (stack == null) {
367 return null;
368 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700369 ActivityRecord resumedActivity = stack.mResumedActivity;
370 if (resumedActivity == null || resumedActivity.app == null) {
371 resumedActivity = stack.mPausingActivity;
372 if (resumedActivity == null || resumedActivity.app == null) {
373 resumedActivity = stack.topRunningActivityLocked(null);
374 }
375 }
376 return resumedActivity;
377 }
378
Craig Mautner20e72272013-04-01 13:45:53 -0700379 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
380 boolean didSomething = false;
381 final String processName = app.processName;
382 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
383 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner858d8a62013-04-23 17:08:34 -0700384 if (!isFrontStack(stack)) {
385 continue;
386 }
Craig Mautner20e72272013-04-01 13:45:53 -0700387 ActivityRecord hr = stack.topRunningActivityLocked(null);
388 if (hr != null) {
389 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
390 && processName.equals(hr.processName)) {
391 try {
392 if (headless) {
393 Slog.e(TAG, "Starting activities not supported on headless device: "
394 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700395 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700396 didSomething = true;
397 }
398 } catch (Exception e) {
399 Slog.w(TAG, "Exception in new application when starting activity "
400 + hr.intent.getComponent().flattenToShortString(), e);
401 throw e;
402 }
Craig Mautner20e72272013-04-01 13:45:53 -0700403 }
404 }
405 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -0700406 if (!didSomething) {
407 ensureActivitiesVisibleLocked(null, 0);
408 }
Craig Mautner20e72272013-04-01 13:45:53 -0700409 return didSomething;
410 }
411
412 boolean allResumedActivitiesIdle() {
413 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700414 final ActivityStack stack = mStacks.get(stackNdx);
415 if (!isFrontStack(stack)) {
416 continue;
417 }
418 final ActivityRecord resumedActivity = stack.mResumedActivity;
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700419 if (resumedActivity == null || !resumedActivity.idle) {
Craig Mautner20e72272013-04-01 13:45:53 -0700420 return false;
421 }
422 }
423 return true;
424 }
425
Craig Mautnerde4ef022013-04-07 19:01:33 -0700426 boolean allResumedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700427 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
428 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner967212c2013-04-13 21:10:58 -0700429 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700430 final ActivityRecord r = stack.mResumedActivity;
431 if (r != null && r.state != ActivityState.RESUMED) {
432 return false;
433 }
434 }
435 }
436 // TODO: Not sure if this should check if all Paused are complete too.
437 switch (mStackState) {
438 case STACK_STATE_HOME_TO_BACK:
Craig Mautner76ea2242013-05-15 11:40:05 -0700439 if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
440 stackStateToString(STACK_STATE_HOME_TO_BACK) + " new=" +
441 stackStateToString(STACK_STATE_HOME_IN_BACK));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700442 mStackState = STACK_STATE_HOME_IN_BACK;
443 break;
444 case STACK_STATE_HOME_TO_FRONT:
Craig Mautner76ea2242013-05-15 11:40:05 -0700445 if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
446 stackStateToString(STACK_STATE_HOME_TO_FRONT) + " new=" +
447 stackStateToString(STACK_STATE_HOME_IN_FRONT));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700448 mStackState = STACK_STATE_HOME_IN_FRONT;
449 break;
450 }
451 return true;
452 }
453
454 boolean allResumedActivitiesVisible() {
455 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
456 final ActivityStack stack = mStacks.get(stackNdx);
457 final ActivityRecord r = stack.mResumedActivity;
458 if (r != null && (!r.nowVisible || r.waitingVisible)) {
459 return false;
460 }
461 }
462 return true;
463 }
464
Craig Mautnercf910b02013-04-23 11:23:27 -0700465 boolean pauseBackStacks(boolean userLeaving) {
466 boolean someActivityPaused = false;
467 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
468 final ActivityStack stack = mStacks.get(stackNdx);
469 if (!isFrontStack(stack) && stack.mResumedActivity != null) {
470 stack.startPausingLocked(userLeaving, false);
471 someActivityPaused = true;
472 }
473 }
474 return someActivityPaused;
475 }
476
Craig Mautnerde4ef022013-04-07 19:01:33 -0700477 boolean allPausedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700478 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
479 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner69ada552013-04-18 13:51:51 -0700480 final ActivityRecord r = stack.mPausingActivity;
481 if (r != null && r.state != ActivityState.PAUSED
482 && r.state != ActivityState.STOPPED
483 && r.state != ActivityState.STOPPING) {
484 return false;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700485 }
486 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700487 return true;
488 }
489
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700490 void reportActivityVisibleLocked(ActivityRecord r) {
Craig Mautner858d8a62013-04-23 17:08:34 -0700491 for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700492 WaitResult w = mWaitingActivityVisible.get(i);
493 w.timeout = false;
494 if (r != null) {
495 w.who = new ComponentName(r.info.packageName, r.info.name);
496 }
497 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
498 w.thisTime = w.totalTime;
499 }
500 mService.notifyAll();
501 dismissKeyguard();
502 }
503
504 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
505 long thisTime, long totalTime) {
506 for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
Craig Mautnerc64f73e2013-04-24 16:44:56 -0700507 WaitResult w = mWaitingActivityLaunched.remove(i);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700508 w.timeout = timeout;
509 if (r != null) {
510 w.who = new ComponentName(r.info.packageName, r.info.name);
511 }
512 w.thisTime = thisTime;
513 w.totalTime = totalTime;
514 }
515 mService.notifyAll();
516 }
517
Craig Mautner29219d92013-04-16 20:19:12 -0700518 ActivityRecord topRunningActivityLocked() {
Craig Mautner1602ec22013-05-12 10:24:27 -0700519 final ActivityStack focusedStack = getFocusedStack();
520 ActivityRecord r = focusedStack.topRunningActivityLocked(null);
521 if (r != null) {
522 return r;
Craig Mautner29219d92013-04-16 20:19:12 -0700523 }
Craig Mautner1602ec22013-05-12 10:24:27 -0700524
Craig Mautner29219d92013-04-16 20:19:12 -0700525 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
526 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner1602ec22013-05-12 10:24:27 -0700527 if (stack.mCurrentUser == mCurrentUser && stack != focusedStack &&
528 isFrontStack(stack)) {
Craig Mautner29219d92013-04-16 20:19:12 -0700529 r = stack.topRunningActivityLocked(null);
530 if (r != null) {
531 return r;
532 }
533 }
534 }
535 return null;
536 }
537
Craig Mautner20e72272013-04-01 13:45:53 -0700538 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
539 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
540 ActivityRecord r = null;
Craig Mautner20e72272013-04-01 13:45:53 -0700541 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
542 final ActivityStack stack = mStacks.get(stackNdx);
543 final ActivityRecord ar =
544 stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700545 if (isFrontStack(stack)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700546 r = ar;
547 }
548 }
549 return r;
550 }
551
Craig Mautner23ac33b2013-04-01 16:26:35 -0700552 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
553 String profileFile, ParcelFileDescriptor profileFd, int userId) {
554 // Collect information about the target of the Intent.
555 ActivityInfo aInfo;
556 try {
557 ResolveInfo rInfo =
558 AppGlobals.getPackageManager().resolveIntent(
559 intent, resolvedType,
560 PackageManager.MATCH_DEFAULT_ONLY
561 | ActivityManagerService.STOCK_PM_FLAGS, userId);
562 aInfo = rInfo != null ? rInfo.activityInfo : null;
563 } catch (RemoteException e) {
564 aInfo = null;
565 }
566
567 if (aInfo != null) {
568 // Store the found target back into the intent, because now that
569 // we have it we never want to do this again. For example, if the
570 // user navigates back to this point in the history, we should
571 // always restart the exact same activity.
572 intent.setComponent(new ComponentName(
573 aInfo.applicationInfo.packageName, aInfo.name));
574
575 // Don't debug things in the system process
576 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
577 if (!aInfo.processName.equals("system")) {
578 mService.setDebugApp(aInfo.processName, true, false);
579 }
580 }
581
582 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
583 if (!aInfo.processName.equals("system")) {
584 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
585 }
586 }
587
588 if (profileFile != null) {
589 if (!aInfo.processName.equals("system")) {
590 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
591 profileFile, profileFd,
592 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
593 }
594 }
595 }
596 return aInfo;
597 }
598
Craig Mautner2219a1b2013-03-25 09:44:30 -0700599 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700600 moveHomeStack(true);
Craig Mautner6170f732013-04-02 13:05:23 -0700601 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
Craig Mautner2219a1b2013-03-25 09:44:30 -0700602 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700603 }
604
Craig Mautner23ac33b2013-04-01 16:26:35 -0700605 final int startActivityMayWait(IApplicationThread caller, int callingUid,
606 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
607 String resultWho, int requestCode, int startFlags, String profileFile,
608 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
609 Bundle options, int userId) {
610 // Refuse possible leaked file descriptors
611 if (intent != null && intent.hasFileDescriptors()) {
612 throw new IllegalArgumentException("File descriptors passed in Intent");
613 }
614 boolean componentSpecified = intent.getComponent() != null;
615
616 // Don't modify the client's object!
617 intent = new Intent(intent);
618
619 // Collect information about the target of the Intent.
620 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
621 profileFile, profileFd, userId);
622
623 synchronized (mService) {
624 int callingPid;
625 if (callingUid >= 0) {
626 callingPid = -1;
627 } else if (caller == null) {
628 callingPid = Binder.getCallingPid();
629 callingUid = Binder.getCallingUid();
630 } else {
631 callingPid = callingUid = -1;
632 }
633
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700634 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -0700635 stack.mConfigWillChange = config != null
Craig Mautner23ac33b2013-04-01 16:26:35 -0700636 && mService.mConfiguration.diff(config) != 0;
637 if (DEBUG_CONFIGURATION) Slog.v(TAG,
Craig Mautnerde4ef022013-04-07 19:01:33 -0700638 "Starting activity when config will change = " + stack.mConfigWillChange);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700639
640 final long origId = Binder.clearCallingIdentity();
641
642 if (aInfo != null &&
643 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
644 // This may be a heavy-weight process! Check to see if we already
645 // have another, different heavy-weight process running.
646 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
647 if (mService.mHeavyWeightProcess != null &&
648 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
649 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700650 int realCallingUid = callingUid;
651 if (caller != null) {
652 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
653 if (callerApp != null) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700654 realCallingUid = callerApp.info.uid;
655 } else {
656 Slog.w(TAG, "Unable to find app for caller " + caller
Craig Mautner76ea2242013-05-15 11:40:05 -0700657 + " (pid=" + callingPid + ") when starting: "
Craig Mautner23ac33b2013-04-01 16:26:35 -0700658 + intent.toString());
659 ActivityOptions.abort(options);
660 return ActivityManager.START_PERMISSION_DENIED;
661 }
662 }
663
664 IIntentSender target = mService.getIntentSenderLocked(
665 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
666 realCallingUid, userId, null, null, 0, new Intent[] { intent },
667 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
668 | PendingIntent.FLAG_ONE_SHOT, null);
669
670 Intent newIntent = new Intent();
671 if (requestCode >= 0) {
672 // Caller is requesting a result.
673 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
674 }
675 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
676 new IntentSender(target));
677 if (mService.mHeavyWeightProcess.activities.size() > 0) {
678 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
679 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
680 hist.packageName);
681 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
682 hist.task.taskId);
683 }
684 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
685 aInfo.packageName);
686 newIntent.setFlags(intent.getFlags());
687 newIntent.setClassName("android",
688 HeavyWeightSwitcherActivity.class.getName());
689 intent = newIntent;
690 resolvedType = null;
691 caller = null;
692 callingUid = Binder.getCallingUid();
693 callingPid = Binder.getCallingPid();
694 componentSpecified = true;
695 try {
696 ResolveInfo rInfo =
697 AppGlobals.getPackageManager().resolveIntent(
698 intent, null,
699 PackageManager.MATCH_DEFAULT_ONLY
700 | ActivityManagerService.STOCK_PM_FLAGS, userId);
701 aInfo = rInfo != null ? rInfo.activityInfo : null;
702 aInfo = mService.getActivityInfoForUser(aInfo, userId);
703 } catch (RemoteException e) {
704 aInfo = null;
705 }
706 }
707 }
708 }
709
Craig Mautner6170f732013-04-02 13:05:23 -0700710 int res = startActivityLocked(caller, intent, resolvedType,
Craig Mautner23ac33b2013-04-01 16:26:35 -0700711 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
712 callingPackage, startFlags, options, componentSpecified, null);
713
Craig Mautnerde4ef022013-04-07 19:01:33 -0700714 if (stack.mConfigWillChange) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700715 // If the caller also wants to switch to a new configuration,
716 // do so now. This allows a clean switch, as we are waiting
717 // for the current activity to pause (so we will not destroy
718 // it), and have not yet started the next activity.
719 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
720 "updateConfiguration()");
Craig Mautnerde4ef022013-04-07 19:01:33 -0700721 stack.mConfigWillChange = false;
Craig Mautner23ac33b2013-04-01 16:26:35 -0700722 if (DEBUG_CONFIGURATION) Slog.v(TAG,
723 "Updating to new configuration after starting activity.");
724 mService.updateConfigurationLocked(config, null, false, false);
725 }
726
727 Binder.restoreCallingIdentity(origId);
728
729 if (outResult != null) {
730 outResult.result = res;
731 if (res == ActivityManager.START_SUCCESS) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700732 mWaitingActivityLaunched.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700733 do {
734 try {
735 mService.wait();
736 } catch (InterruptedException e) {
737 }
738 } while (!outResult.timeout && outResult.who == null);
739 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700740 ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700741 if (r.nowVisible) {
742 outResult.timeout = false;
743 outResult.who = new ComponentName(r.info.packageName, r.info.name);
744 outResult.totalTime = 0;
745 outResult.thisTime = 0;
746 } else {
747 outResult.thisTime = SystemClock.uptimeMillis();
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700748 mWaitingActivityVisible.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700749 do {
750 try {
751 mService.wait();
752 } catch (InterruptedException e) {
753 }
754 } while (!outResult.timeout && outResult.who == null);
755 }
756 }
757 }
758
759 return res;
760 }
761 }
762
763 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
764 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
765 Bundle options, int userId) {
766 if (intents == null) {
767 throw new NullPointerException("intents is null");
768 }
769 if (resolvedTypes == null) {
770 throw new NullPointerException("resolvedTypes is null");
771 }
772 if (intents.length != resolvedTypes.length) {
773 throw new IllegalArgumentException("intents are length different than resolvedTypes");
774 }
775
Craig Mautner23ac33b2013-04-01 16:26:35 -0700776
777 int callingPid;
778 if (callingUid >= 0) {
779 callingPid = -1;
780 } else if (caller == null) {
781 callingPid = Binder.getCallingPid();
782 callingUid = Binder.getCallingUid();
783 } else {
784 callingPid = callingUid = -1;
785 }
786 final long origId = Binder.clearCallingIdentity();
787 try {
788 synchronized (mService) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700789 ActivityRecord[] outActivity = new ActivityRecord[1];
Craig Mautner23ac33b2013-04-01 16:26:35 -0700790 for (int i=0; i<intents.length; i++) {
791 Intent intent = intents[i];
792 if (intent == null) {
793 continue;
794 }
795
796 // Refuse possible leaked file descriptors
797 if (intent != null && intent.hasFileDescriptors()) {
798 throw new IllegalArgumentException("File descriptors passed in Intent");
799 }
800
801 boolean componentSpecified = intent.getComponent() != null;
802
803 // Don't modify the client's object!
804 intent = new Intent(intent);
805
806 // Collect information about the target of the Intent.
807 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
808 0, null, null, userId);
809 // TODO: New, check if this is correct
810 aInfo = mService.getActivityInfoForUser(aInfo, userId);
811
812 if (aInfo != null &&
813 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
814 != 0) {
815 throw new IllegalArgumentException(
816 "FLAG_CANT_SAVE_STATE not supported here");
817 }
818
819 Bundle theseOptions;
820 if (options != null && i == intents.length-1) {
821 theseOptions = options;
822 } else {
823 theseOptions = null;
824 }
Craig Mautner6170f732013-04-02 13:05:23 -0700825 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Craig Mautner23ac33b2013-04-01 16:26:35 -0700826 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
827 0, theseOptions, componentSpecified, outActivity);
828 if (res < 0) {
829 return res;
830 }
831
832 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
833 }
834 }
835 } finally {
836 Binder.restoreCallingIdentity(origId);
837 }
838
839 return ActivityManager.START_SUCCESS;
840 }
841
Craig Mautner2420ead2013-04-01 17:13:20 -0700842 final boolean realStartActivityLocked(ActivityRecord r,
843 ProcessRecord app, boolean andResume, boolean checkConfig)
844 throws RemoteException {
845
846 r.startFreezingScreenLocked(app, 0);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700847 mWindowManager.setAppVisibility(r.appToken, true);
Craig Mautner2420ead2013-04-01 17:13:20 -0700848
849 // schedule launch ticks to collect information about slow apps.
850 r.startLaunchTickingLocked();
851
852 // Have the window manager re-evaluate the orientation of
853 // the screen based on the new activity order. Note that
854 // as a result of this, it can call back into the activity
855 // manager with a new orientation. We don't care about that,
856 // because the activity is not currently running so we are
857 // just restarting it anyway.
858 if (checkConfig) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700859 Configuration config = mWindowManager.updateOrientationFromAppTokens(
Craig Mautner2420ead2013-04-01 17:13:20 -0700860 mService.mConfiguration,
861 r.mayFreezeScreenLocked(app) ? r.appToken : null);
862 mService.updateConfigurationLocked(config, r, false, false);
863 }
864
865 r.app = app;
866 app.waitingToKill = null;
867 r.launchCount++;
868 r.lastLaunchTime = SystemClock.uptimeMillis();
869
870 if (localLOGV) Slog.v(TAG, "Launching: " + r);
871
872 int idx = app.activities.indexOf(r);
873 if (idx < 0) {
874 app.activities.add(r);
875 }
876 mService.updateLruProcessLocked(app, true);
877
878 final ActivityStack stack = r.task.stack;
879 try {
880 if (app.thread == null) {
881 throw new RemoteException();
882 }
883 List<ResultInfo> results = null;
884 List<Intent> newIntents = null;
885 if (andResume) {
886 results = r.results;
887 newIntents = r.newIntents;
888 }
889 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
890 + " icicle=" + r.icicle
891 + " with results=" + results + " newIntents=" + newIntents
892 + " andResume=" + andResume);
893 if (andResume) {
894 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
895 r.userId, System.identityHashCode(r),
896 r.task.taskId, r.shortComponentName);
897 }
Craig Mautner86d67a42013-05-14 10:34:38 -0700898 if (r.isHomeActivity()) {
Craig Mautner2420ead2013-04-01 17:13:20 -0700899 mService.mHomeProcess = app;
900 }
901 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
902 r.sleeping = false;
903 r.forceNewConfig = false;
904 mService.showAskCompatModeDialogLocked(r);
905 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
906 String profileFile = null;
907 ParcelFileDescriptor profileFd = null;
908 boolean profileAutoStop = false;
909 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
910 if (mService.mProfileProc == null || mService.mProfileProc == app) {
911 mService.mProfileProc = app;
912 profileFile = mService.mProfileFile;
913 profileFd = mService.mProfileFd;
914 profileAutoStop = mService.mAutoStopProfiler;
915 }
916 }
917 app.hasShownUi = true;
918 app.pendingUiClean = true;
919 if (profileFd != null) {
920 try {
921 profileFd = profileFd.dup();
922 } catch (IOException e) {
923 if (profileFd != null) {
924 try {
925 profileFd.close();
926 } catch (IOException o) {
927 }
928 profileFd = null;
929 }
930 }
931 }
932 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
933 System.identityHashCode(r), r.info,
934 new Configuration(mService.mConfiguration),
935 r.compat, r.icicle, results, newIntents, !andResume,
936 mService.isNextTransitionForward(), profileFile, profileFd,
937 profileAutoStop);
938
939 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
940 // This may be a heavy-weight process! Note that the package
941 // manager will ensure that only activity can run in the main
942 // process of the .apk, which is the only thing that will be
943 // considered heavy-weight.
944 if (app.processName.equals(app.info.packageName)) {
945 if (mService.mHeavyWeightProcess != null
946 && mService.mHeavyWeightProcess != app) {
947 Slog.w(TAG, "Starting new heavy weight process " + app
948 + " when already running "
949 + mService.mHeavyWeightProcess);
950 }
951 mService.mHeavyWeightProcess = app;
952 Message msg = mService.mHandler.obtainMessage(
953 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
954 msg.obj = r;
955 mService.mHandler.sendMessage(msg);
956 }
957 }
958
959 } catch (RemoteException e) {
960 if (r.launchFailed) {
961 // This is the second time we failed -- finish activity
962 // and give up.
963 Slog.e(TAG, "Second failure launching "
964 + r.intent.getComponent().flattenToShortString()
965 + ", giving up", e);
966 mService.appDiedLocked(app, app.pid, app.thread);
967 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
968 "2nd-crash", false);
969 return false;
970 }
971
972 // This is the first time we failed -- restart process and
973 // retry.
974 app.activities.remove(r);
975 throw e;
976 }
977
978 r.launchFailed = false;
979 if (stack.updateLRUListLocked(r)) {
980 Slog.w(TAG, "Activity " + r
981 + " being launched, but already in LRU list");
982 }
983
984 if (andResume) {
985 // As part of the process of launching, ActivityThread also performs
986 // a resume.
987 stack.minimalResumeActivityLocked(r);
988 } else {
989 // This activity is not starting in the resumed state... which
990 // should look like we asked it to pause+stop (but remain visible),
991 // and it has done so and reported back the current icicle and
992 // other state.
993 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
994 + " (starting in stopped state)");
995 r.state = ActivityState.STOPPED;
996 r.stopped = true;
997 }
998
999 // Launch the new version setup screen if needed. We do this -after-
1000 // launching the initial activity (that is, home), so that it can have
1001 // a chance to initialize itself while in the background, making the
1002 // switch back to it faster and look better.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001003 if (isFrontStack(stack)) {
Craig Mautner2420ead2013-04-01 17:13:20 -07001004 mService.startSetupActivityLocked();
1005 }
1006
1007 return true;
1008 }
1009
Craig Mautnere79d42682013-04-01 19:01:53 -07001010 void startSpecificActivityLocked(ActivityRecord r,
1011 boolean andResume, boolean checkConfig) {
1012 // Is this activity's application already running?
1013 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
1014 r.info.applicationInfo.uid);
1015
1016 r.task.stack.setLaunchTime(r);
1017
1018 if (app != null && app.thread != null) {
1019 try {
Dianne Hackborn78a369c2013-06-11 17:10:32 -07001020 app.addPackage(r.info.packageName, mService.mProcessTracker);
Craig Mautnere79d42682013-04-01 19:01:53 -07001021 realStartActivityLocked(r, app, andResume, checkConfig);
1022 return;
1023 } catch (RemoteException e) {
1024 Slog.w(TAG, "Exception when starting activity "
1025 + r.intent.getComponent().flattenToShortString(), e);
1026 }
1027
1028 // If a dead object exception was thrown -- fall through to
1029 // restart the application.
1030 }
1031
1032 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
1033 "activity", r.intent.getComponent(), false, false);
1034 }
1035
Craig Mautner6170f732013-04-02 13:05:23 -07001036 final int startActivityLocked(IApplicationThread caller,
1037 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
1038 String resultWho, int requestCode,
1039 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
1040 boolean componentSpecified, ActivityRecord[] outActivity) {
1041 int err = ActivityManager.START_SUCCESS;
1042
1043 ProcessRecord callerApp = null;
1044 if (caller != null) {
1045 callerApp = mService.getRecordForAppLocked(caller);
1046 if (callerApp != null) {
1047 callingPid = callerApp.pid;
1048 callingUid = callerApp.info.uid;
1049 } else {
1050 Slog.w(TAG, "Unable to find app for caller " + caller
1051 + " (pid=" + callingPid + ") when starting: "
1052 + intent.toString());
1053 err = ActivityManager.START_PERMISSION_DENIED;
1054 }
1055 }
1056
1057 if (err == ActivityManager.START_SUCCESS) {
1058 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
1059 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
1060 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
1061 }
1062
1063 ActivityRecord sourceRecord = null;
1064 ActivityRecord resultRecord = null;
1065 if (resultTo != null) {
1066 sourceRecord = isInAnyStackLocked(resultTo);
1067 if (DEBUG_RESULTS) Slog.v(
1068 TAG, "Will send result to " + resultTo + " " + sourceRecord);
1069 if (sourceRecord != null) {
1070 if (requestCode >= 0 && !sourceRecord.finishing) {
1071 resultRecord = sourceRecord;
1072 }
1073 }
1074 }
1075 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
1076
1077 int launchFlags = intent.getFlags();
1078
1079 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
1080 && sourceRecord != null) {
1081 // Transfer the result target from the source activity to the new
1082 // one being started, including any failures.
1083 if (requestCode >= 0) {
1084 ActivityOptions.abort(options);
1085 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
1086 }
1087 resultRecord = sourceRecord.resultTo;
1088 resultWho = sourceRecord.resultWho;
1089 requestCode = sourceRecord.requestCode;
1090 sourceRecord.resultTo = null;
1091 if (resultRecord != null) {
1092 resultRecord.removeResultsLocked(
1093 sourceRecord, resultWho, requestCode);
1094 }
1095 }
1096
1097 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
1098 // We couldn't find a class that can handle the given Intent.
1099 // That's the end of that!
1100 err = ActivityManager.START_INTENT_NOT_RESOLVED;
1101 }
1102
1103 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
1104 // We couldn't find the specific class specified in the Intent.
1105 // Also the end of the line.
1106 err = ActivityManager.START_CLASS_NOT_FOUND;
1107 }
1108
1109 if (err != ActivityManager.START_SUCCESS) {
1110 if (resultRecord != null) {
1111 resultStack.sendActivityResultLocked(-1,
1112 resultRecord, resultWho, requestCode,
1113 Activity.RESULT_CANCELED, null);
1114 }
1115 setDismissKeyguard(false);
1116 ActivityOptions.abort(options);
1117 return err;
1118 }
1119
1120 final int startAnyPerm = mService.checkPermission(
1121 START_ANY_ACTIVITY, callingPid, callingUid);
1122 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
1123 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
1124 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
1125 if (resultRecord != null) {
1126 resultStack.sendActivityResultLocked(-1,
1127 resultRecord, resultWho, requestCode,
1128 Activity.RESULT_CANCELED, null);
1129 }
1130 setDismissKeyguard(false);
1131 String msg;
1132 if (!aInfo.exported) {
1133 msg = "Permission Denial: starting " + intent.toString()
1134 + " from " + callerApp + " (pid=" + callingPid
1135 + ", uid=" + callingUid + ")"
1136 + " not exported from uid " + aInfo.applicationInfo.uid;
1137 } else {
1138 msg = "Permission Denial: starting " + intent.toString()
1139 + " from " + callerApp + " (pid=" + callingPid
1140 + ", uid=" + callingUid + ")"
1141 + " requires " + aInfo.permission;
1142 }
1143 Slog.w(TAG, msg);
1144 throw new SecurityException(msg);
1145 }
1146
Ben Gruver6617c3c2013-04-03 18:45:22 -07001147 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
Ben Gruver7b879f42013-04-08 14:56:55 -07001148 callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo);
Ben Gruver5e207332013-04-03 17:41:37 -07001149
Craig Mautner6170f732013-04-02 13:05:23 -07001150 if (mService.mController != null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001151 try {
1152 // The Intent we give to the watcher has the extra data
1153 // stripped off, since it can contain private information.
1154 Intent watchIntent = intent.cloneFilter();
Ben Gruver5e207332013-04-03 17:41:37 -07001155 abort |= !mService.mController.activityStarting(watchIntent,
Craig Mautner6170f732013-04-02 13:05:23 -07001156 aInfo.applicationInfo.packageName);
1157 } catch (RemoteException e) {
1158 mService.mController = null;
1159 }
Ben Gruver5e207332013-04-03 17:41:37 -07001160 }
Craig Mautner6170f732013-04-02 13:05:23 -07001161
Ben Gruver5e207332013-04-03 17:41:37 -07001162 if (abort) {
1163 if (resultRecord != null) {
1164 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Craig Mautner6170f732013-04-02 13:05:23 -07001165 Activity.RESULT_CANCELED, null);
Craig Mautner6170f732013-04-02 13:05:23 -07001166 }
Ben Gruver5e207332013-04-03 17:41:37 -07001167 // We pretend to the caller that it was really started, but
1168 // they will just get a cancel result.
1169 setDismissKeyguard(false);
1170 ActivityOptions.abort(options);
1171 return ActivityManager.START_SUCCESS;
Craig Mautner6170f732013-04-02 13:05:23 -07001172 }
1173
1174 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1175 intent, resolvedType, aInfo, mService.mConfiguration,
Craig Mautnerde4ef022013-04-07 19:01:33 -07001176 resultRecord, resultWho, requestCode, componentSpecified, this);
Craig Mautner6170f732013-04-02 13:05:23 -07001177 if (outActivity != null) {
1178 outActivity[0] = r;
1179 }
1180
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001181 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001182 if (stack.mResumedActivity == null
1183 || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
Craig Mautner6170f732013-04-02 13:05:23 -07001184 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1185 PendingActivityLaunch pal =
Craig Mautnerde4ef022013-04-07 19:01:33 -07001186 new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
Craig Mautner6170f732013-04-02 13:05:23 -07001187 mService.mPendingActivityLaunches.add(pal);
1188 setDismissKeyguard(false);
1189 ActivityOptions.abort(options);
1190 return ActivityManager.START_SWITCHES_CANCELED;
1191 }
1192 }
1193
1194 if (mService.mDidAppSwitch) {
1195 // This is the second allowed switch since we stopped switches,
1196 // so now just generally allow switches. Use case: user presses
1197 // home (switches disabled, switch to home, mDidAppSwitch now true);
1198 // user taps a home icon (coming from home so allowed, we hit here
1199 // and now allow anyone to switch again).
1200 mService.mAppSwitchesAllowedTime = 0;
1201 } else {
1202 mService.mDidAppSwitch = true;
1203 }
1204
1205 mService.doPendingActivityLaunchesLocked(false);
1206
Craig Mautner8849a5e2013-04-02 16:41:03 -07001207 err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001208 if (stack.mPausingActivity == null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001209 // Someone asked to have the keyguard dismissed on the next
1210 // activity start, but we are not actually doing an activity
1211 // switch... just dismiss the keyguard now, because we
1212 // probably want to see whatever is behind it.
1213 dismissKeyguard();
1214 }
1215 return err;
1216 }
1217
Craig Mautnerde4ef022013-04-07 19:01:33 -07001218 ActivityStack getCorrectStack(ActivityRecord r) {
Craig Mautner1d001b62013-06-18 16:52:43 -07001219 final TaskRecord task = r.task;
1220 if (r.isApplicationActivity() || (task != null && task.isApplicationTask())) {
Craig Mautner858d8a62013-04-23 17:08:34 -07001221 int stackNdx;
1222 for (stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
1223 if (mStacks.get(stackNdx).mCurrentUser == mCurrentUser) {
1224 break;
1225 }
1226 }
1227 if (stackNdx == 0) {
1228 // Time to create the first app stack for this user.
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001229 int stackId = mService.createStack(-1, HOME_STACK_ID,
1230 StackBox.TASK_STACK_GOES_OVER, 1.0f);
Craig Mautnere7c58b62013-06-12 20:19:00 -07001231 if (DEBUG_FOCUS) Slog.d(TAG, "getCorrectStack: New stack r=" + r + " stackId="
1232 + stackId);
Craig Mautner29219d92013-04-16 20:19:12 -07001233 mFocusedStack = getStack(stackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001234 }
Craig Mautner1d001b62013-06-18 16:52:43 -07001235 if (task != null) {
Craig Mautnere7c58b62013-06-12 20:19:00 -07001236 if (DEBUG_FOCUS) Slog.d(TAG, "getCorrectStack: Setting focused stack to r=" +
1237 r + " task=" + task);
Craig Mautner1d001b62013-06-18 16:52:43 -07001238 mFocusedStack = task.stack;
1239 }
Craig Mautner29219d92013-04-16 20:19:12 -07001240 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001241 }
1242 return mHomeStack;
1243 }
1244
Craig Mautner29219d92013-04-16 20:19:12 -07001245 void setFocusedStack(ActivityRecord r) {
1246 if (r == null) {
1247 return;
1248 }
Craig Mautner86d67a42013-05-14 10:34:38 -07001249 if (!r.isApplicationActivity() || (r.task != null && !r.task.isApplicationTask())) {
Craig Mautner29219d92013-04-16 20:19:12 -07001250 if (mStackState != STACK_STATE_HOME_IN_FRONT) {
Craig Mautnere7c58b62013-06-12 20:19:00 -07001251 if (DEBUG_STACK || DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: mStackState old=" +
Craig Mautner76ea2242013-05-15 11:40:05 -07001252 stackStateToString(mStackState) + " new=" +
1253 stackStateToString(STACK_STATE_HOME_TO_FRONT) +
1254 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001255 mStackState = STACK_STATE_HOME_TO_FRONT;
1256 }
1257 } else {
Craig Mautnere7c58b62013-06-12 20:19:00 -07001258 if (DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: Setting focused stack to r=" +
1259 r + " task=" + r.task + " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001260 mFocusedStack = r.task.stack;
1261 if (mStackState != STACK_STATE_HOME_IN_BACK) {
Craig Mautner76ea2242013-05-15 11:40:05 -07001262 if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
1263 stackStateToString(mStackState) + " new=" +
1264 stackStateToString(STACK_STATE_HOME_TO_BACK) +
1265 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001266 mStackState = STACK_STATE_HOME_TO_BACK;
1267 }
1268 }
1269 }
1270
Craig Mautner8849a5e2013-04-02 16:41:03 -07001271 final int startActivityUncheckedLocked(ActivityRecord r,
1272 ActivityRecord sourceRecord, int startFlags, boolean doResume,
1273 Bundle options) {
1274 final Intent intent = r.intent;
1275 final int callingUid = r.launchedFromUid;
1276
1277 int launchFlags = intent.getFlags();
1278
Craig Mautner8849a5e2013-04-02 16:41:03 -07001279 // We'll invoke onUserLeaving before onPause only if the launching
1280 // activity did not explicitly state that this is an automated launch.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001281 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1282 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001283
1284 // If the caller has asked not to resume at this point, we make note
1285 // of this in the record so that we can skip it when trying to find
1286 // the top running activity.
1287 if (!doResume) {
1288 r.delayedResume = true;
1289 }
1290
1291 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1292
1293 // If the onlyIfNeeded flag is set, then we can do this if the activity
1294 // being launched is the same as the one making the call... or, as
1295 // a special case, if we do not know the caller then we count the
1296 // current top activity as the caller.
1297 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1298 ActivityRecord checkedCaller = sourceRecord;
1299 if (checkedCaller == null) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001300 checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001301 }
1302 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1303 // Caller is not the same as launcher, so always needed.
1304 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1305 }
1306 }
1307
1308 if (sourceRecord == null) {
1309 // This activity is not being started from another... in this
1310 // case we -always- start a new task.
1311 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Craig Mautner29219d92013-04-16 20:19:12 -07001312 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1313 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001314 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1315 }
1316 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1317 // The original activity who is starting us is running as a single
1318 // instance... this new activity it is starting must go on its
1319 // own task.
1320 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1321 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1322 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1323 // The activity being started is a single instance... it always
1324 // gets launched into its own task.
1325 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1326 }
1327
Craig Mautnerde4ef022013-04-07 19:01:33 -07001328 final ActivityStack sourceStack;
Craig Mautner525f3d92013-05-07 14:01:50 -07001329 TaskRecord sourceTask;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001330 if (sourceRecord != null) {
1331 sourceTask = sourceRecord.task;
1332 sourceStack = sourceTask.stack;
1333 } else {
1334 sourceTask = null;
1335 sourceStack = null;
1336 }
1337
Craig Mautner8849a5e2013-04-02 16:41:03 -07001338 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1339 // For whatever reason this activity is being launched into a new
1340 // task... yet the caller has requested a result back. Well, that
1341 // is pretty messed up, so instead immediately send back a cancel
1342 // and let the new task continue launched as normal without a
1343 // dependency on its originator.
1344 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1345 r.resultTo.task.stack.sendActivityResultLocked(-1,
1346 r.resultTo, r.resultWho, r.requestCode,
1347 Activity.RESULT_CANCELED, null);
1348 r.resultTo = null;
1349 }
1350
1351 boolean addingToTask = false;
1352 boolean movedHome = false;
1353 TaskRecord reuseTask = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001354 ActivityStack targetStack;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001355 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1356 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1357 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1358 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1359 // If bring to front is requested, and no result is requested, and
1360 // we can find a task that was started with this same
1361 // component, then instead of launching bring that one to the front.
1362 if (r.resultTo == null) {
1363 // See if there is a task to bring to the front. If this is
1364 // a SINGLE_INSTANCE activity, there can be one and only one
1365 // instance of it in the history, and it is always in its own
1366 // unique task, so we do a special search.
1367 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
1368 ? findTaskLocked(intent, r.info)
1369 : findActivityLocked(intent, r.info);
1370 if (intentActivity != null) {
Craig Mautner29219d92013-04-16 20:19:12 -07001371 if (r.task == null) {
1372 r.task = intentActivity.task;
1373 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001374 targetStack = intentActivity.task.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001375 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001376 if (intentActivity.task.intent == null) {
1377 // This task was started because of movement of
1378 // the activity based on affinity... now that we
1379 // are actually launching it, we can assign the
1380 // base intent.
1381 intentActivity.task.setIntent(intent, r.info);
1382 }
1383 // If the target task is not in the front, then we need
1384 // to bring it to the front... except... well, with
1385 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
1386 // to have the same behavior as if a new instance was
1387 // being started, which means not bringing it to the front
1388 // if the caller is not itself in the front.
Craig Mautner165640b2013-04-20 10:34:33 -07001389 final ActivityStack lastStack = getLastStack();
1390 ActivityRecord curTop = lastStack == null?
1391 null : lastStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001392 if (curTop != null && curTop.task != intentActivity.task) {
1393 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001394 if (sourceRecord == null || sourceStack.topActivity() == sourceRecord) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001395 // We really do want to push this one into the
1396 // user's face, right now.
1397 movedHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001398 if ((launchFlags &
Craig Mautner29219d92013-04-16 20:19:12 -07001399 (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1400 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001401 // Caller wants to appear on home activity, so before starting
1402 // their own activity we will bring home to the front.
1403 r.mLaunchHomeTaskNext = true;
1404 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001405 targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1406 options = null;
1407 }
1408 }
1409 // If the caller has requested that the target task be
1410 // reset, then do so.
1411 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1412 intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1413 }
1414 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1415 // We don't need to start a new activity, and
1416 // the client said not to do anything if that
1417 // is the case, so this is it! And for paranoia, make
1418 // sure we have correctly resumed the top activity.
1419 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001420 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001421 resumeTopActivitiesLocked(targetStack, null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001422 } else {
1423 ActivityOptions.abort(options);
1424 }
Craig Mautner29219d92013-04-16 20:19:12 -07001425 if (r.task == null) Slog.v(TAG,
1426 "startActivityUncheckedLocked: task left null",
1427 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001428 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1429 }
1430 if ((launchFlags &
1431 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1432 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1433 // The caller has requested to completely replace any
1434 // existing task with its new activity. Well that should
1435 // not be too hard...
1436 reuseTask = intentActivity.task;
1437 reuseTask.performClearTaskLocked();
1438 reuseTask.setIntent(r.intent, r.info);
1439 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1440 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1441 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1442 // In this situation we want to remove all activities
1443 // from the task up to the one being started. In most
1444 // cases this means we are resetting the task to its
1445 // initial state.
1446 ActivityRecord top =
1447 intentActivity.task.performClearTaskLocked(r, launchFlags);
1448 if (top != null) {
1449 if (top.frontOfTask) {
1450 // Activity aliases may mean we use different
1451 // intents for the top activity, so make sure
1452 // the task now has the identity of the new
1453 // intent.
1454 top.task.setIntent(r.intent, r.info);
1455 }
1456 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1457 r, top.task);
1458 top.deliverNewIntentLocked(callingUid, r.intent);
1459 } else {
1460 // A special case: we need to
1461 // start the activity because it is not currently
1462 // running, and the caller has asked to clear the
1463 // current task to have this activity at the top.
1464 addingToTask = true;
1465 // Now pretend like this activity is being started
1466 // by the top of its task, so it is put in the
1467 // right place.
1468 sourceRecord = intentActivity;
1469 }
1470 } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1471 // In this case the top activity on the task is the
1472 // same as the one being launched, so we take that
1473 // as a request to bring the task to the foreground.
1474 // If the top activity in the task is the root
1475 // activity, deliver this new intent to it if it
1476 // desires.
1477 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1478 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1479 && intentActivity.realActivity.equals(r.realActivity)) {
1480 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1481 intentActivity.task);
1482 if (intentActivity.frontOfTask) {
1483 intentActivity.task.setIntent(r.intent, r.info);
1484 }
1485 intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1486 } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1487 // In this case we are launching the root activity
1488 // of the task, but with a different intent. We
1489 // should start a new instance on top.
1490 addingToTask = true;
1491 sourceRecord = intentActivity;
1492 }
1493 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1494 // In this case an activity is being launched in to an
1495 // existing task, without resetting that task. This
1496 // is typically the situation of launching an activity
1497 // from a notification or shortcut. We want to place
1498 // the new activity on top of the current task.
1499 addingToTask = true;
1500 sourceRecord = intentActivity;
1501 } else if (!intentActivity.task.rootWasReset) {
1502 // In this case we are launching in to an existing task
1503 // that has not yet been started from its front door.
1504 // The current task has been brought to the front.
1505 // Ideally, we'd probably like to place this new task
1506 // at the bottom of its stack, but that's a little hard
1507 // to do with the current organization of the code so
1508 // for now we'll just drop it.
1509 intentActivity.task.setIntent(r.intent, r.info);
1510 }
1511 if (!addingToTask && reuseTask == null) {
1512 // We didn't do anything... but it was needed (a.k.a., client
1513 // don't use that intent!) And for paranoia, make
1514 // sure we have correctly resumed the top activity.
1515 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001516 setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1517 targetStack.resumeTopActivityLocked(null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001518 } else {
1519 ActivityOptions.abort(options);
1520 }
Craig Mautner29219d92013-04-16 20:19:12 -07001521 if (r.task == null) Slog.v(TAG,
1522 "startActivityUncheckedLocked: task left null",
1523 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001524 return ActivityManager.START_TASK_TO_FRONT;
1525 }
1526 }
1527 }
1528 }
1529
1530 //String uri = r.intent.toURI();
1531 //Intent intent2 = new Intent(uri);
1532 //Slog.i(TAG, "Given intent: " + r.intent);
1533 //Slog.i(TAG, "URI is: " + uri);
1534 //Slog.i(TAG, "To intent: " + intent2);
1535
1536 if (r.packageName != null) {
1537 // If the activity being launched is the same as the one currently
1538 // at the top, then we need to check if it should only be launched
1539 // once.
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001540 ActivityStack topStack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001541 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001542 if (top != null && r.resultTo == null) {
1543 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1544 if (top.app != null && top.app.thread != null) {
1545 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1546 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1547 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1548 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1549 top.task);
1550 // For paranoia, make sure we have correctly
1551 // resumed the top activity.
1552 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001553 setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001554 resumeTopActivitiesLocked();
Craig Mautner8849a5e2013-04-02 16:41:03 -07001555 }
1556 ActivityOptions.abort(options);
1557 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1558 // We don't need to start a new activity, and
1559 // the client said not to do anything if that
1560 // is the case, so this is it!
Craig Mautner29219d92013-04-16 20:19:12 -07001561 if (r.task == null) Slog.v(TAG,
1562 "startActivityUncheckedLocked: task left null",
1563 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001564 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1565 }
1566 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner29219d92013-04-16 20:19:12 -07001567 if (r.task == null) Slog.v(TAG,
1568 "startActivityUncheckedLocked: task left null",
1569 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001570 return ActivityManager.START_DELIVERED_TO_TOP;
1571 }
1572 }
1573 }
1574 }
1575
1576 } else {
1577 if (r.resultTo != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001578 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1579 r.requestCode, Activity.RESULT_CANCELED, null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001580 }
1581 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001582 if (r.task == null) Slog.v(TAG,
1583 "startActivityUncheckedLocked: task left null",
1584 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001585 return ActivityManager.START_CLASS_NOT_FOUND;
1586 }
1587
1588 boolean newTask = false;
1589 boolean keepCurTransition = false;
1590
1591 // Should this be considered a new task?
1592 if (r.resultTo == null && !addingToTask
1593 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001594 targetStack = getCorrectStack(r);
1595 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001596 if (reuseTask == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001597 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1598 null, true);
1599 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1600 r.task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001601 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001602 r.setTask(reuseTask, reuseTask, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001603 }
1604 newTask = true;
1605 if (!movedHome) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001606 if ((launchFlags &
1607 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1608 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1609 // Caller wants to appear on home activity, so before starting
1610 // their own activity we will bring home to the front.
1611 r.mLaunchHomeTaskNext = true;
1612 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001613 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001614 } else if (sourceRecord != null) {
Craig Mautner525f3d92013-05-07 14:01:50 -07001615 sourceTask = sourceRecord.task;
1616 targetStack = sourceTask.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001617 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001618 if (!addingToTask &&
1619 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1620 // In this case, we are adding the activity to an existing
1621 // task, but the caller has asked to clear that task if the
1622 // activity is already running.
Craig Mautner525f3d92013-05-07 14:01:50 -07001623 ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001624 keepCurTransition = true;
1625 if (top != null) {
1626 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1627 top.deliverNewIntentLocked(callingUid, r.intent);
1628 // For paranoia, make sure we have correctly
1629 // resumed the top activity.
1630 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001631 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001632 targetStack.resumeTopActivityLocked(null);
1633 }
1634 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001635 if (r.task == null) Slog.v(TAG,
1636 "startActivityUncheckedLocked: task left null",
1637 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001638 return ActivityManager.START_DELIVERED_TO_TOP;
1639 }
1640 } else if (!addingToTask &&
1641 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1642 // In this case, we are launching an activity in our own task
1643 // that may already be running somewhere in the history, and
1644 // we want to shuffle it to the front of the stack if so.
Craig Mautner525f3d92013-05-07 14:01:50 -07001645 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001646 if (top != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001647 final TaskRecord task = top.task;
1648 task.moveActivityToFrontLocked(top);
1649 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001650 top.updateOptionsLocked(options);
1651 top.deliverNewIntentLocked(callingUid, r.intent);
1652 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001653 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001654 targetStack.resumeTopActivityLocked(null);
1655 }
Craig Mautner29219d92013-04-16 20:19:12 -07001656 if (r.task == null) Slog.v(TAG,
1657 "startActivityUncheckedLocked: task left null",
1658 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001659 return ActivityManager.START_DELIVERED_TO_TOP;
1660 }
1661 }
1662 // An existing activity is starting this new activity, so we want
1663 // to keep the new one in the same task as the one that is starting
1664 // it.
Craig Mautner525f3d92013-05-07 14:01:50 -07001665 r.setTask(sourceTask, sourceRecord.thumbHolder, false);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001666 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1667 + " in existing task " + r.task);
1668
1669 } else {
1670 // This not being started from an existing activity, and not part
1671 // of a new task... just put it in the top task, though these days
1672 // this case should never happen.
Craig Mautner1602ec22013-05-12 10:24:27 -07001673 targetStack = getCorrectStack(r);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001674 moveHomeStack(targetStack.isHomeStack());
Craig Mautner1602ec22013-05-12 10:24:27 -07001675 ActivityRecord prev = targetStack.topActivity();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001676 r.setTask(prev != null ? prev.task
1677 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1678 null, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001679 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1680 + " in new guessed " + r.task);
1681 }
1682
1683 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1684 intent, r.getUriPermissionsLocked());
1685
1686 if (newTask) {
1687 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1688 }
1689 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001690 setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001691 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
Craig Mautner1d001b62013-06-18 16:52:43 -07001692 mService.setFocusedActivityLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001693 return ActivityManager.START_SUCCESS;
1694 }
1695
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001696 void acquireLaunchWakelock() {
1697 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
1698 throw new IllegalStateException("Calling must be system uid");
1699 }
1700 mLaunchingActivity.acquire();
1701 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
1702 // To be safe, don't allow the wake lock to be held for too long.
1703 mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
1704 }
1705 }
1706
Craig Mautnerf3333272013-04-22 10:55:53 -07001707 // Checked.
1708 final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
1709 Configuration config) {
1710 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
1711
Craig Mautnerf3333272013-04-22 10:55:53 -07001712 ArrayList<ActivityRecord> stops = null;
1713 ArrayList<ActivityRecord> finishes = null;
1714 ArrayList<UserStartedState> startingUsers = null;
1715 int NS = 0;
1716 int NF = 0;
1717 IApplicationThread sendThumbnail = null;
1718 boolean booting = false;
1719 boolean enableScreen = false;
1720 boolean activityRemoved = false;
1721
1722 ActivityRecord r = ActivityRecord.forToken(token);
1723 if (r != null) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07001724 if (DEBUG_IDLE) Slog.d(TAG, "activityIdleInternalLocked: Callers=" +
1725 Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07001726 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
1727 r.finishLaunchTickingLocked();
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001728 if (fromTimeout) {
1729 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
Craig Mautnerf3333272013-04-22 10:55:53 -07001730 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001731
1732 // This is a hack to semi-deal with a race condition
1733 // in the client where it can be constructed with a
1734 // newer configuration from when we asked it to launch.
1735 // We'll update with whatever configuration it now says
1736 // it used to launch.
1737 if (config != null) {
1738 r.configuration = config;
1739 }
1740
1741 // We are now idle. If someone is waiting for a thumbnail from
1742 // us, we can now deliver.
1743 r.idle = true;
1744
1745 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
1746 sendThumbnail = r.app.thread;
1747 r.thumbnailNeeded = false;
1748 }
1749
1750 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
1751 if (!mService.mBooted && isFrontStack(r.task.stack)) {
1752 mService.mBooted = true;
1753 enableScreen = true;
1754 }
1755 }
1756
1757 if (allResumedActivitiesIdle()) {
1758 if (r != null) {
1759 mService.scheduleAppGcsLocked();
1760 mService.requestPssLocked(r.app, SystemClock.uptimeMillis(), false);
1761 }
1762
1763 if (mLaunchingActivity.isHeld()) {
1764 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
1765 if (VALIDATE_WAKE_LOCK_CALLER &&
1766 Binder.getCallingUid() != Process.myUid()) {
1767 throw new IllegalStateException("Calling must be system uid");
1768 }
1769 mLaunchingActivity.release();
1770 }
1771 ensureActivitiesVisibleLocked(null, 0);
Craig Mautnerf3333272013-04-22 10:55:53 -07001772 }
1773
1774 // Atomically retrieve all of the other things to do.
1775 stops = processStoppingActivitiesLocked(true);
1776 NS = stops != null ? stops.size() : 0;
1777 if ((NF=mFinishingActivities.size()) > 0) {
1778 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
1779 mFinishingActivities.clear();
1780 }
1781
1782 final ArrayList<ActivityRecord> thumbnails;
1783 final int NT = mCancelledThumbnails.size();
1784 if (NT > 0) {
1785 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
1786 mCancelledThumbnails.clear();
1787 } else {
1788 thumbnails = null;
1789 }
1790
1791 if (isFrontStack(mHomeStack)) {
1792 booting = mService.mBooting;
1793 mService.mBooting = false;
1794 }
1795
1796 if (mStartingUsers.size() > 0) {
1797 startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
1798 mStartingUsers.clear();
1799 }
1800
1801 // Perform the following actions from unsynchronized state.
1802 final IApplicationThread thumbnailThread = sendThumbnail;
1803 mHandler.post(new Runnable() {
1804 @Override
1805 public void run() {
1806 if (thumbnailThread != null) {
1807 try {
1808 thumbnailThread.requestThumbnail(token);
1809 } catch (Exception e) {
1810 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
1811 mService.sendPendingThumbnail(null, token, null, null, true);
1812 }
1813 }
1814
1815 // Report back to any thumbnail receivers.
1816 for (int i = 0; i < NT; i++) {
1817 ActivityRecord r = thumbnails.get(i);
1818 mService.sendPendingThumbnail(r, null, null, null, true);
1819 }
1820 }
1821 });
1822
1823 // Stop any activities that are scheduled to do so but have been
1824 // waiting for the next one to start.
1825 for (int i = 0; i < NS; i++) {
1826 r = stops.get(i);
1827 final ActivityStack stack = r.task.stack;
1828 if (r.finishing) {
1829 stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
1830 } else {
1831 stack.stopActivityLocked(r);
1832 }
1833 }
1834
1835 // Finish any activities that are scheduled to do so but have been
1836 // waiting for the next one to start.
1837 for (int i = 0; i < NF; i++) {
1838 r = finishes.get(i);
1839 activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle");
1840 }
1841
1842 if (booting) {
1843 mService.finishBooting();
1844 } else if (startingUsers != null) {
1845 for (int i = 0; i < startingUsers.size(); i++) {
1846 mService.finishUserSwitch(startingUsers.get(i));
1847 }
1848 }
1849
1850 mService.trimApplications();
1851 //dump();
1852 //mWindowManager.dump();
1853
1854 if (enableScreen) {
1855 mService.enableScreenAfterBoot();
1856 }
1857
1858 if (activityRemoved) {
Craig Mautner05d29032013-05-03 13:40:13 -07001859 resumeTopActivitiesLocked();
Craig Mautnerf3333272013-04-22 10:55:53 -07001860 }
1861
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001862 return r;
Craig Mautnerf3333272013-04-22 10:55:53 -07001863 }
1864
Craig Mautner8d341ef2013-03-26 09:03:27 -07001865 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
1866 // Just in case.
1867 final int numStacks = mStacks.size();
1868 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Craig Mautnere79d42682013-04-01 19:01:53 -07001869 mStacks.get(stackNdx).handleAppDiedLocked(app, restarting);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001870 }
1871 }
1872
1873 void closeSystemDialogsLocked() {
1874 final int numStacks = mStacks.size();
1875 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1876 final ActivityStack stack = mStacks.get(stackNdx);
1877 stack.closeSystemDialogsLocked();
1878 }
1879 }
1880
1881 /**
1882 * @return true if some activity was finished (or would have finished if doit were true).
1883 */
1884 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1885 boolean didSomething = false;
1886 final int numStacks = mStacks.size();
1887 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1888 final ActivityStack stack = mStacks.get(stackNdx);
1889 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1890 didSomething = true;
1891 }
1892 }
1893 return didSomething;
1894 }
1895
Craig Mautner05d29032013-05-03 13:40:13 -07001896 boolean resumeTopActivitiesLocked() {
1897 return resumeTopActivitiesLocked(null, null, null);
1898 }
1899
1900 boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
1901 Bundle targetOptions) {
1902 if (targetStack == null) {
1903 targetStack = getFocusedStack();
1904 }
1905 boolean result = false;
Craig Mautnerdbcb31f2013-04-02 12:32:53 -07001906 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001907 final ActivityStack stack = mStacks.get(stackNdx);
1908 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07001909 if (stack == targetStack) {
1910 result = stack.resumeTopActivityLocked(target, targetOptions);
1911 } else {
1912 stack.resumeTopActivityLocked(null);
1913 }
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001914 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001915 }
Craig Mautner05d29032013-05-03 13:40:13 -07001916 return result;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001917 }
1918
1919 void finishTopRunningActivityLocked(ProcessRecord app) {
1920 final int numStacks = mStacks.size();
1921 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1922 final ActivityStack stack = mStacks.get(stackNdx);
1923 stack.finishTopRunningActivityLocked(app);
1924 }
1925 }
1926
Craig Mautner8d341ef2013-03-26 09:03:27 -07001927 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
1928 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1929 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001930 if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack=" +
Craig Mautner1d001b62013-06-18 16:52:43 -07001931 mStacks.get(stackNdx));
Craig Mautner8d341ef2013-03-26 09:03:27 -07001932 return;
1933 }
1934 }
1935 }
1936
Craig Mautner967212c2013-04-13 21:10:58 -07001937 ActivityStack getStack(int stackId) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001938 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1939 final ActivityStack stack = mStacks.get(stackNdx);
1940 if (stack.getStackId() == stackId) {
1941 return stack;
1942 }
1943 }
1944 return null;
1945 }
1946
Craig Mautner967212c2013-04-13 21:10:58 -07001947 ArrayList<ActivityStack> getStacks() {
1948 return new ArrayList<ActivityStack>(mStacks);
1949 }
1950
1951 int createStack() {
Craig Mautner858d8a62013-04-23 17:08:34 -07001952 while (true) {
1953 if (++mLastStackId <= HOME_STACK_ID) {
1954 mLastStackId = HOME_STACK_ID + 1;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001955 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001956 if (getStack(mLastStackId) == null) {
1957 break;
1958 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001959 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001960 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
1961 return mLastStackId;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001962 }
1963
1964 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07001965 final TaskRecord task = anyTaskForIdLocked(taskId);
1966 if (task == null) {
1967 return;
1968 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001969 final ActivityStack stack = getStack(stackId);
1970 if (stack == null) {
1971 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
1972 return;
1973 }
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07001974 removeTask(task);
1975 stack.addTask(task, toTop);
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07001976 mWindowManager.addTask(taskId, stackId, toTop);
Craig Mautner05d29032013-05-03 13:40:13 -07001977 resumeTopActivitiesLocked();
Craig Mautner8d341ef2013-03-26 09:03:27 -07001978 }
1979
Craig Mautner8849a5e2013-04-02 16:41:03 -07001980 ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
1981 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1982 final ActivityRecord ar = mStacks.get(stackNdx).findTaskLocked(intent, info);
1983 if (ar != null) {
1984 return ar;
1985 }
1986 }
1987 return null;
1988 }
1989
1990 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
1991 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1992 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
1993 if (ar != null) {
1994 return ar;
1995 }
1996 }
1997 return null;
1998 }
1999
Craig Mautner8d341ef2013-03-26 09:03:27 -07002000 void goingToSleepLocked() {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002001 scheduleSleepTimeout();
2002 if (!mGoingToSleep.isHeld()) {
2003 mGoingToSleep.acquire();
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002004 if (mLaunchingActivity.isHeld()) {
2005 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
2006 throw new IllegalStateException("Calling must be system uid");
Craig Mautner0eea92c2013-05-16 13:35:39 -07002007 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002008 mLaunchingActivity.release();
2009 mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
Craig Mautner0eea92c2013-05-16 13:35:39 -07002010 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002011 }
2012 }
2013
2014 boolean shutdownLocked(int timeout) {
2015 boolean timedout = false;
Craig Mautner0eea92c2013-05-16 13:35:39 -07002016 goingToSleepLocked();
2017 checkReadyForSleepLocked();
2018
2019 final long endTime = System.currentTimeMillis() + timeout;
2020 while (true) {
2021 boolean cantShutdown = false;
2022 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2023 cantShutdown |= mStacks.get(stackNdx).checkReadyForSleepLocked();
2024 }
2025 if (cantShutdown) {
2026 long timeRemaining = endTime - System.currentTimeMillis();
2027 if (timeRemaining > 0) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002028 try {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002029 mService.wait(timeRemaining);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002030 } catch (InterruptedException e) {
2031 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002032 } else {
2033 Slog.w(TAG, "Activity manager shutdown timed out");
2034 timedout = true;
2035 break;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002036 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002037 } else {
2038 break;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002039 }
2040 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002041
2042 // Force checkReadyForSleep to complete.
2043 mSleepTimeout = true;
2044 checkReadyForSleepLocked();
2045
Craig Mautner8d341ef2013-03-26 09:03:27 -07002046 return timedout;
2047 }
2048
2049 void comeOutOfSleepIfNeededLocked() {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002050 removeSleepTimeouts();
2051 if (mGoingToSleep.isHeld()) {
2052 mGoingToSleep.release();
2053 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002054 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002055 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002056 stack.awakeFromSleepingLocked();
2057 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07002058 resumeTopActivitiesLocked();
Craig Mautnerde4ef022013-04-07 19:01:33 -07002059 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002060 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002061 mGoingToSleepActivities.clear();
2062 }
2063
2064 void activitySleptLocked(ActivityRecord r) {
2065 mGoingToSleepActivities.remove(r);
2066 checkReadyForSleepLocked();
2067 }
2068
2069 void checkReadyForSleepLocked() {
2070 if (!mService.isSleepingOrShuttingDown()) {
2071 // Do not care.
2072 return;
2073 }
2074
2075 if (!mSleepTimeout) {
2076 boolean dontSleep = false;
2077 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2078 dontSleep |= mStacks.get(stackNdx).checkReadyForSleepLocked();
2079 }
2080
2081 if (mStoppingActivities.size() > 0) {
2082 // Still need to tell some activities to stop; can't sleep yet.
2083 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
2084 + mStoppingActivities.size() + " activities");
2085 scheduleIdleLocked();
2086 dontSleep = true;
2087 }
2088
2089 if (mGoingToSleepActivities.size() > 0) {
2090 // Still need to tell some activities to sleep; can't sleep yet.
2091 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
2092 + mGoingToSleepActivities.size() + " activities");
2093 dontSleep = true;
2094 }
2095
2096 if (dontSleep) {
2097 return;
2098 }
2099 }
2100
2101 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2102 mStacks.get(stackNdx).goToSleep();
2103 }
2104
2105 removeSleepTimeouts();
2106
2107 if (mGoingToSleep.isHeld()) {
2108 mGoingToSleep.release();
2109 }
2110 if (mService.mShuttingDown) {
2111 mService.notifyAll();
2112 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002113 }
2114
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002115 boolean reportResumedActivityLocked(ActivityRecord r) {
2116 final ActivityStack stack = r.task.stack;
2117 if (isFrontStack(stack)) {
Jeff Sharkey5782da72013-04-25 14:32:30 -07002118 mService.updateUsageStats(r, true);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002119 }
2120 if (allResumedActivitiesComplete()) {
2121 ensureActivitiesVisibleLocked(null, 0);
2122 mWindowManager.executeAppTransition();
2123 return true;
2124 }
2125 return false;
2126 }
2127
Craig Mautner8d341ef2013-03-26 09:03:27 -07002128 void handleAppCrashLocked(ProcessRecord app) {
2129 final int numStacks = mStacks.size();
2130 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2131 final ActivityStack stack = mStacks.get(stackNdx);
2132 stack.handleAppCrashLocked(app);
2133 }
2134 }
2135
Craig Mautnerde4ef022013-04-07 19:01:33 -07002136 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
Craig Mautner580ea812013-04-25 12:58:38 -07002137 // First the front stacks. In case any are not fullscreen and are in front of home.
2138 boolean showHomeBehindStack = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07002139 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner580ea812013-04-25 12:58:38 -07002140 final ActivityStack stack = mStacks.get(stackNdx);
2141 if (isFrontStack(stack)) {
2142 showHomeBehindStack =
2143 stack.ensureActivitiesVisibleLocked(starting, configChanges);
2144 }
2145 }
2146 // Now do back stacks.
2147 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2148 final ActivityStack stack = mStacks.get(stackNdx);
2149 if (!isFrontStack(stack)) {
2150 stack.ensureActivitiesVisibleLocked(starting, configChanges, showHomeBehindStack);
2151 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002152 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002153 }
2154
2155 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
2156 final int numStacks = mStacks.size();
2157 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2158 final ActivityStack stack = mStacks.get(stackNdx);
2159 stack.scheduleDestroyActivities(app, false, reason);
2160 }
2161 }
2162
2163 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner858d8a62013-04-23 17:08:34 -07002164 mUserStates.put(mCurrentUser, new UserState());
Craig Mautner2420ead2013-04-01 17:13:20 -07002165 mCurrentUser = userId;
Craig Mautner858d8a62013-04-23 17:08:34 -07002166 UserState userState = mUserStates.get(userId);
2167 if (userState != null) {
2168 userState.restore();
2169 mUserStates.delete(userId);
2170 } else {
2171 mFocusedStack = null;
Craig Mautner76ea2242013-05-15 11:40:05 -07002172 if (DEBUG_STACK) Slog.d(TAG, "switchUserLocked: mStackState=" +
2173 stackStateToString(STACK_STATE_HOME_IN_FRONT));
Craig Mautner858d8a62013-04-23 17:08:34 -07002174 mStackState = STACK_STATE_HOME_IN_FRONT;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002175 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002176
2177 mStartingUsers.add(uss);
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002178 boolean haveActivities = mHomeStack.switchUserLocked(userId);
Craig Mautner858d8a62013-04-23 17:08:34 -07002179
2180 resumeTopActivitiesLocked();
2181
Craig Mautner8d341ef2013-03-26 09:03:27 -07002182 return haveActivities;
Craig Mautner2219a1b2013-03-25 09:44:30 -07002183 }
2184
Craig Mautnerde4ef022013-04-07 19:01:33 -07002185 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
2186 int N = mStoppingActivities.size();
2187 if (N <= 0) return null;
2188
2189 ArrayList<ActivityRecord> stops = null;
2190
2191 final boolean nowVisible = allResumedActivitiesVisible();
2192 for (int i=0; i<N; i++) {
2193 ActivityRecord s = mStoppingActivities.get(i);
2194 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
2195 + nowVisible + " waitingVisible=" + s.waitingVisible
2196 + " finishing=" + s.finishing);
2197 if (s.waitingVisible && nowVisible) {
2198 mWaitingVisibleActivities.remove(s);
2199 s.waitingVisible = false;
2200 if (s.finishing) {
2201 // If this activity is finishing, it is sitting on top of
2202 // everyone else but we now know it is no longer needed...
2203 // so get rid of it. Otherwise, we need to go through the
2204 // normal flow and hide it once we determine that it is
2205 // hidden by the activities in front of it.
2206 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002207 mWindowManager.setAppVisibility(s.appToken, false);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002208 }
2209 }
2210 if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
2211 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
2212 if (stops == null) {
2213 stops = new ArrayList<ActivityRecord>();
2214 }
2215 stops.add(s);
2216 mStoppingActivities.remove(i);
2217 N--;
2218 i--;
2219 }
2220 }
2221
2222 return stops;
2223 }
2224
Craig Mautnercf910b02013-04-23 11:23:27 -07002225 void validateTopActivitiesLocked() {
2226 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2227 final ActivityStack stack = mStacks.get(stackNdx);
2228 final ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002229 final ActivityState state = r == null ? ActivityState.DESTROYED : r.state;
Craig Mautnercf910b02013-04-23 11:23:27 -07002230 if (isFrontStack(stack)) {
2231 if (r == null) {
2232 Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
2233 } else {
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002234 final ActivityRecord pausing = stack.mPausingActivity;
2235 if (pausing != null && pausing == r) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002236 Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002237 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002238 }
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002239 if (state != ActivityState.INITIALIZING && state != ActivityState.RESUMED) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002240 Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002241 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002242 }
2243 }
2244 } else {
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002245 final ActivityRecord resumed = stack.mResumedActivity;
2246 if (resumed != null && resumed == r) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002247 Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002248 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002249 }
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002250 if (r != null && (state == ActivityState.INITIALIZING
2251 || state == ActivityState.RESUMED)) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002252 Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002253 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002254 }
2255 }
2256 }
2257 }
2258
Craig Mautner76ea2242013-05-15 11:40:05 -07002259 private static String stackStateToString(int stackState) {
2260 switch (stackState) {
2261 case STACK_STATE_HOME_IN_FRONT: return "STACK_STATE_HOME_IN_FRONT";
2262 case STACK_STATE_HOME_TO_BACK: return "STACK_STATE_HOME_TO_BACK";
2263 case STACK_STATE_HOME_IN_BACK: return "STACK_STATE_HOME_IN_BACK";
2264 case STACK_STATE_HOME_TO_FRONT: return "STACK_STATE_HOME_TO_FRONT";
2265 default: return "Unknown stackState=" + stackState;
2266 }
2267 }
2268
Craig Mautner27084302013-03-25 08:05:25 -07002269 public void dump(PrintWriter pw, String prefix) {
2270 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
2271 pw.println(mDismissKeyguardOnNextActivity);
Craig Mautner76ea2242013-05-15 11:40:05 -07002272 pw.print(prefix); pw.print("mStackState="); pw.println(stackStateToString(mStackState));
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002273 pw.print(prefix); pw.println("mSleepTimeout: " + mSleepTimeout);
2274 pw.print(prefix); pw.println("mCurTaskId: " + mCurTaskId);
Craig Mautner27084302013-03-25 08:05:25 -07002275 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002276
Craig Mautner20e72272013-04-01 13:45:53 -07002277 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002278 return getFocusedStack().getDumpActivitiesLocked(name);
Craig Mautner20e72272013-04-01 13:45:53 -07002279 }
2280
Dianne Hackborn390517b2013-05-30 15:03:32 -07002281 static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
2282 boolean needSep, String prefix) {
2283 if (activity != null) {
2284 if (dumpPackage == null || dumpPackage.equals(activity.packageName)) {
2285 if (needSep) {
2286 pw.println();
Dianne Hackborn390517b2013-05-30 15:03:32 -07002287 }
2288 pw.print(prefix);
2289 pw.println(activity);
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002290 return true;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002291 }
2292 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002293 return false;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002294 }
2295
Craig Mautner8d341ef2013-03-26 09:03:27 -07002296 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
2297 boolean dumpClient, String dumpPackage) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002298 boolean printed = false;
2299 boolean needSep = false;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002300 final int numStacks = mStacks.size();
2301 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2302 final ActivityStack stack = mStacks.get(stackNdx);
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002303 StringBuilder stackHeader = new StringBuilder(128);
2304 stackHeader.append(" Stack #");
2305 stackHeader.append(mStacks.indexOf(stack));
2306 stackHeader.append(":");
2307 printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, needSep,
2308 stackHeader.toString());
2309 printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll,
2310 false, dumpPackage, true, " Running activities (most recent first):", null);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002311
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002312 needSep = printed;
2313 boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002314 " mPausingActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002315 if (pr) {
2316 printed = true;
2317 needSep = false;
2318 }
2319 pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002320 " mResumedActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002321 if (pr) {
2322 printed = true;
2323 needSep = false;
2324 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002325 if (dumpAll) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002326 pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002327 " mLastPausedActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002328 if (pr) {
2329 printed = true;
2330 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002331 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002332 needSep = printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002333 }
2334
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002335 printed |= dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll,
2336 false, dumpPackage, true, " Activities waiting to finish:", null);
2337 printed |= dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll,
2338 false, dumpPackage, true, " Activities waiting to stop:", null);
2339 printed |= dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
2340 false, dumpPackage, true, " Activities waiting for another to become visible:",
2341 null);
2342 printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll,
2343 false, dumpPackage, true, " Activities waiting to sleep:", null);
2344 printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll,
2345 false, dumpPackage, true, " Activities waiting to sleep:", null);
Craig Mautnerf3333272013-04-22 10:55:53 -07002346
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002347 return printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002348 }
2349
Dianne Hackborn390517b2013-05-30 15:03:32 -07002350 static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
Craig Mautner8d341ef2013-03-26 09:03:27 -07002351 String prefix, String label, boolean complete, boolean brief, boolean client,
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002352 String dumpPackage, boolean needNL, String header1, String header2) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002353 TaskRecord lastTask = null;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002354 String innerPrefix = null;
2355 String[] args = null;
2356 boolean printed = false;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002357 for (int i=list.size()-1; i>=0; i--) {
2358 final ActivityRecord r = list.get(i);
2359 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
2360 continue;
2361 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07002362 if (innerPrefix == null) {
2363 innerPrefix = prefix + " ";
2364 args = new String[0];
2365 }
2366 printed = true;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002367 final boolean full = !brief && (complete || !r.isInHistory());
2368 if (needNL) {
Dianne Hackborn390517b2013-05-30 15:03:32 -07002369 pw.println("");
Craig Mautner8d341ef2013-03-26 09:03:27 -07002370 needNL = false;
2371 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002372 if (header1 != null) {
2373 pw.println(header1);
2374 header1 = null;
2375 }
2376 if (header2 != null) {
2377 pw.println(header2);
2378 header2 = null;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002379 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002380 if (lastTask != r.task) {
2381 lastTask = r.task;
2382 pw.print(prefix);
2383 pw.print(full ? "* " : " ");
2384 pw.println(lastTask);
2385 if (full) {
2386 lastTask.dump(pw, prefix + " ");
2387 } else if (complete) {
2388 // Complete + brief == give a summary. Isn't that obvious?!?
2389 if (lastTask.intent != null) {
2390 pw.print(prefix); pw.print(" ");
2391 pw.println(lastTask.intent.toInsecureStringWithClip());
2392 }
2393 }
2394 }
2395 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
2396 pw.print(" #"); pw.print(i); pw.print(": ");
2397 pw.println(r);
2398 if (full) {
2399 r.dump(pw, innerPrefix);
2400 } else if (complete) {
2401 // Complete + brief == give a summary. Isn't that obvious?!?
2402 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
2403 if (r.app != null) {
2404 pw.print(innerPrefix); pw.println(r.app);
2405 }
2406 }
2407 if (client && r.app != null && r.app.thread != null) {
2408 // flush anything that is already in the PrintWriter since the thread is going
2409 // to write to the file descriptor directly
2410 pw.flush();
2411 try {
2412 TransferPipe tp = new TransferPipe();
2413 try {
2414 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
2415 r.appToken, innerPrefix, args);
2416 // Short timeout, since blocking here can
2417 // deadlock with the application.
2418 tp.go(fd, 2000);
2419 } finally {
2420 tp.kill();
2421 }
2422 } catch (IOException e) {
2423 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
2424 } catch (RemoteException e) {
2425 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
2426 }
2427 needNL = true;
2428 }
2429 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07002430 return printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002431 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002432
Craig Mautnerf3333272013-04-22 10:55:53 -07002433 void scheduleIdleTimeoutLocked(ActivityRecord next) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002434 if (DEBUG_IDLE) Slog.d(TAG, "scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4));
Craig Mautnerc64f73e2013-04-24 16:44:56 -07002435 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
2436 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
Craig Mautnerf3333272013-04-22 10:55:53 -07002437 }
2438
2439 final void scheduleIdleLocked() {
Craig Mautner05d29032013-05-03 13:40:13 -07002440 mHandler.sendEmptyMessage(IDLE_NOW_MSG);
Craig Mautnerf3333272013-04-22 10:55:53 -07002441 }
2442
2443 void removeTimeoutsForActivityLocked(ActivityRecord r) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002444 if (DEBUG_IDLE) Slog.d(TAG, "removeTimeoutsForActivity: Callers=" + Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07002445 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
2446 }
2447
Craig Mautner05d29032013-05-03 13:40:13 -07002448 final void scheduleResumeTopActivities() {
2449 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2450 }
2451
Craig Mautner0eea92c2013-05-16 13:35:39 -07002452 void removeSleepTimeouts() {
2453 mSleepTimeout = false;
2454 mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
2455 }
2456
2457 final void scheduleSleepTimeout() {
2458 removeSleepTimeouts();
2459 mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT);
2460 }
2461
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002462 private final class ActivityStackSupervisorHandler extends Handler {
Craig Mautnerf3333272013-04-22 10:55:53 -07002463
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002464 public ActivityStackSupervisorHandler(Looper looper) {
2465 super(looper);
2466 }
2467
Craig Mautnerf3333272013-04-22 10:55:53 -07002468 void activityIdleInternal(ActivityRecord r) {
2469 synchronized (mService) {
2470 activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
2471 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002472 }
2473
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002474 @Override
2475 public void handleMessage(Message msg) {
2476 switch (msg.what) {
Craig Mautnerf3333272013-04-22 10:55:53 -07002477 case IDLE_TIMEOUT_MSG: {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002478 if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_TIMEOUT_MSG: Callers=" +
2479 Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07002480 if (mService.mDidDexOpt) {
2481 mService.mDidDexOpt = false;
2482 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2483 nmsg.obj = msg.obj;
2484 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
2485 return;
2486 }
2487 // We don't at this point know if the activity is fullscreen,
2488 // so we need to be conservative and assume it isn't.
2489 activityIdleInternal((ActivityRecord)msg.obj);
2490 } break;
2491 case IDLE_NOW_MSG: {
2492 activityIdleInternal((ActivityRecord)msg.obj);
2493 } break;
Craig Mautner05d29032013-05-03 13:40:13 -07002494 case RESUME_TOP_ACTIVITY_MSG: {
2495 synchronized (mService) {
2496 resumeTopActivitiesLocked();
2497 }
2498 } break;
Craig Mautner0eea92c2013-05-16 13:35:39 -07002499 case SLEEP_TIMEOUT_MSG: {
2500 synchronized (mService) {
2501 if (mService.isSleepingOrShuttingDown()) {
2502 Slog.w(TAG, "Sleep timeout! Sleeping now.");
2503 mSleepTimeout = true;
2504 checkReadyForSleepLocked();
2505 }
2506 }
2507 } break;
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002508 case LAUNCH_TIMEOUT_MSG: {
2509 if (mService.mDidDexOpt) {
2510 mService.mDidDexOpt = false;
2511 mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
2512 return;
2513 }
2514 synchronized (mService) {
2515 if (mLaunchingActivity.isHeld()) {
2516 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
2517 if (VALIDATE_WAKE_LOCK_CALLER
2518 && Binder.getCallingUid() != Process.myUid()) {
2519 throw new IllegalStateException("Calling must be system uid");
2520 }
2521 mLaunchingActivity.release();
2522 }
2523 }
2524 } break;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002525 }
2526 }
2527 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002528
2529 private final class UserState {
2530 final ActivityStack mSavedFocusedStack;
2531 final int mSavedStackState;
2532
2533 public UserState() {
2534 ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2535 mSavedFocusedStack = supervisor.mFocusedStack;
2536 mSavedStackState = supervisor.mStackState;
2537 }
2538
2539 void restore() {
2540 ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2541 supervisor.mFocusedStack = mSavedFocusedStack;
Craig Mautner76ea2242013-05-15 11:40:05 -07002542 if (DEBUG_STACK) Slog.d(TAG, "UserState.restore: mStackState old=" +
2543 stackStateToString(mSavedStackState));
Craig Mautner858d8a62013-04-23 17:08:34 -07002544 supervisor.mStackState = mSavedStackState;
2545 }
2546 }
Craig Mautner27084302013-03-25 08:05:25 -07002547}