blob: 136353ba2db9b54d490be6a8b4b76c2c0a30c351 [file] [log] [blame]
Craig Mautner27084302013-03-25 08:05:25 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Craig Mautner6170f732013-04-02 13:05:23 -070019import static android.Manifest.permission.START_ANY_ACTIVITY;
Craig Mautner29219d92013-04-16 20:19:12 -070020import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
21import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Craig Mautner6170f732013-04-02 13:05:23 -070022import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Craig Mautner2420ead2013-04-01 17:13:20 -070023import static com.android.server.am.ActivityManagerService.localLOGV;
Craig Mautner23ac33b2013-04-01 16:26:35 -070024import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION;
Craig Mautner0eea92c2013-05-16 13:35:39 -070025import static com.android.server.am.ActivityManagerService.DEBUG_PAUSE;
Craig Mautner6170f732013-04-02 13:05:23 -070026import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
Craig Mautner0eea92c2013-05-16 13:35:39 -070027import static com.android.server.am.ActivityManagerService.DEBUG_STACK;
Craig Mautner2420ead2013-04-01 17:13:20 -070028import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
Craig Mautner8849a5e2013-04-02 16:41:03 -070029import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
30import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
Craig Mautner05d29032013-05-03 13:40:13 -070031import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
Craig Mautner8d341ef2013-03-26 09:03:27 -070032import static com.android.server.am.ActivityManagerService.TAG;
33
Craig Mautner2420ead2013-04-01 17:13:20 -070034import android.app.Activity;
Craig Mautner23ac33b2013-04-01 16:26:35 -070035import android.app.ActivityManager;
36import android.app.ActivityOptions;
37import android.app.AppGlobals;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070038import android.app.IActivityManager;
Craig Mautner23ac33b2013-04-01 16:26:35 -070039import android.app.IApplicationThread;
Craig Mautner20e72272013-04-01 13:45:53 -070040import android.app.IThumbnailReceiver;
Craig Mautner23ac33b2013-04-01 16:26:35 -070041import android.app.PendingIntent;
Craig Mautner20e72272013-04-01 13:45:53 -070042import android.app.ActivityManager.RunningTaskInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070043import android.app.IActivityManager.WaitResult;
Craig Mautner2420ead2013-04-01 17:13:20 -070044import android.app.ResultInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070045import android.content.ComponentName;
Craig Mautner2219a1b2013-03-25 09:44:30 -070046import android.content.Context;
Craig Mautner23ac33b2013-04-01 16:26:35 -070047import android.content.IIntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070048import android.content.Intent;
Craig Mautner23ac33b2013-04-01 16:26:35 -070049import android.content.IntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070050import android.content.pm.ActivityInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070051import android.content.pm.ApplicationInfo;
52import android.content.pm.PackageManager;
53import android.content.pm.ResolveInfo;
54import android.content.res.Configuration;
55import android.os.Binder;
Craig Mautner8d341ef2013-03-26 09:03:27 -070056import android.os.Bundle;
Craig Mautnerb59dcfd2013-05-06 13:12:58 -070057import android.os.Debug;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070058import android.os.Handler;
Craig Mautner23ac33b2013-04-01 16:26:35 -070059import android.os.IBinder;
Craig Mautner2219a1b2013-03-25 09:44:30 -070060import android.os.Looper;
Craig Mautner2420ead2013-04-01 17:13:20 -070061import android.os.Message;
Craig Mautner23ac33b2013-04-01 16:26:35 -070062import android.os.ParcelFileDescriptor;
Craig Mautner0eea92c2013-05-16 13:35:39 -070063import android.os.PowerManager;
Craig Mautner8d341ef2013-03-26 09:03:27 -070064import android.os.RemoteException;
Craig Mautner23ac33b2013-04-01 16:26:35 -070065import android.os.SystemClock;
Craig Mautner6170f732013-04-02 13:05:23 -070066import android.os.UserHandle;
Craig Mautner2420ead2013-04-01 17:13:20 -070067import android.util.EventLog;
Craig Mautner8d341ef2013-03-26 09:03:27 -070068import android.util.Slog;
Craig Mautner858d8a62013-04-23 17:08:34 -070069import android.util.SparseArray;
Craig Mautner2219a1b2013-03-25 09:44:30 -070070
Craig Mautner23ac33b2013-04-01 16:26:35 -070071import com.android.internal.app.HeavyWeightSwitcherActivity;
Craig Mautner6170f732013-04-02 13:05:23 -070072import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
Craig Mautner2420ead2013-04-01 17:13:20 -070073import com.android.server.am.ActivityStack.ActivityState;
Craig Mautnerde4ef022013-04-07 19:01:33 -070074import com.android.server.wm.StackBox;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070075import com.android.server.wm.WindowManagerService;
Craig Mautner23ac33b2013-04-01 16:26:35 -070076
Craig Mautner8d341ef2013-03-26 09:03:27 -070077import java.io.FileDescriptor;
78import java.io.IOException;
Craig Mautner27084302013-03-25 08:05:25 -070079import java.io.PrintWriter;
Craig Mautner2219a1b2013-03-25 09:44:30 -070080import java.util.ArrayList;
Craig Mautner8d341ef2013-03-26 09:03:27 -070081import java.util.List;
Craig Mautner27084302013-03-25 08:05:25 -070082
83public class ActivityStackSupervisor {
Craig Mautnerde4ef022013-04-07 19:01:33 -070084 static final boolean DEBUG = ActivityManagerService.DEBUG || false;
85 static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
86 static final boolean DEBUG_APP = DEBUG || false;
87 static final boolean DEBUG_SAVED_STATE = DEBUG || false;
88 static final boolean DEBUG_STATES = DEBUG || false;
Craig Mautnerb59dcfd2013-05-06 13:12:58 -070089 static final boolean DEBUG_IDLE = DEBUG || false;
Craig Mautner2420ead2013-04-01 17:13:20 -070090
Craig Mautner2219a1b2013-03-25 09:44:30 -070091 public static final int HOME_STACK_ID = 0;
Craig Mautner27084302013-03-25 08:05:25 -070092
Craig Mautnerf3333272013-04-22 10:55:53 -070093 /** How long we wait until giving up on the last activity telling us it is idle. */
94 static final int IDLE_TIMEOUT = 10*1000;
95
Craig Mautner0eea92c2013-05-16 13:35:39 -070096 /** How long we can hold the sleep wake lock before giving up. */
97 static final int SLEEP_TIMEOUT = 5*1000;
98
Craig Mautner05d29032013-05-03 13:40:13 -070099 static final int IDLE_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG;
100 static final int IDLE_NOW_MSG = FIRST_SUPERVISOR_STACK_MSG + 1;
101 static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2;
Craig Mautner0eea92c2013-05-16 13:35:39 -0700102 static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3;
Craig Mautnerf3333272013-04-22 10:55:53 -0700103
Craig Mautner27084302013-03-25 08:05:25 -0700104 final ActivityManagerService mService;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700105 final Context mContext;
106 final Looper mLooper;
Craig Mautner27084302013-03-25 08:05:25 -0700107
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700108 final ActivityStackSupervisorHandler mHandler;
109
110 /** Short cut */
111 WindowManagerService mWindowManager;
112
Craig Mautner27084302013-03-25 08:05:25 -0700113 /** Dismiss the keyguard after the next activity is displayed? */
114 private boolean mDismissKeyguardOnNextActivity = false;
115
Craig Mautner8d341ef2013-03-26 09:03:27 -0700116 /** Identifier counter for all ActivityStacks */
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700117 private int mLastStackId = HOME_STACK_ID;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700118
119 /** Task identifier that activities are currently being started in. Incremented each time a
120 * new task is created. */
121 private int mCurTaskId = 0;
122
Craig Mautner2420ead2013-04-01 17:13:20 -0700123 /** The current user */
124 private int mCurrentUser;
125
Craig Mautner8d341ef2013-03-26 09:03:27 -0700126 /** The stack containing the launcher app */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700127 private ActivityStack mHomeStack;
Craig Mautner20e72272013-04-01 13:45:53 -0700128
Craig Mautnerde4ef022013-04-07 19:01:33 -0700129 /** The non-home stack currently receiving input or launching the next activity. If home is
Craig Mautner29219d92013-04-16 20:19:12 -0700130 * in front then mHomeStack overrides mFocusedStack. */
131 private ActivityStack mFocusedStack;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700132
133 /** All the non-launcher stacks */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700134 private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
135
Craig Mautnerde4ef022013-04-07 19:01:33 -0700136 private static final int STACK_STATE_HOME_IN_FRONT = 0;
137 private static final int STACK_STATE_HOME_TO_BACK = 1;
138 private static final int STACK_STATE_HOME_IN_BACK = 2;
139 private static final int STACK_STATE_HOME_TO_FRONT = 3;
140 private int mStackState = STACK_STATE_HOME_IN_FRONT;
141
142 /** List of activities that are waiting for a new activity to become visible before completing
143 * whatever operation they are supposed to do. */
144 final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();
145
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700146 /** List of processes waiting to find out about the next visible activity. */
147 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible =
148 new ArrayList<IActivityManager.WaitResult>();
149
150 /** List of processes waiting to find out about the next launched activity. */
151 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched =
152 new ArrayList<IActivityManager.WaitResult>();
153
Craig Mautnerde4ef022013-04-07 19:01:33 -0700154 /** List of activities that are ready to be stopped, but waiting for the next activity to
155 * settle down before doing so. */
156 final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();
157
Craig Mautnerf3333272013-04-22 10:55:53 -0700158 /** List of activities that are ready to be finished, but waiting for the previous activity to
159 * settle down before doing so. It contains ActivityRecord objects. */
160 final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<ActivityRecord>();
161
Craig Mautner0eea92c2013-05-16 13:35:39 -0700162 /** List of activities that are in the process of going to sleep. */
163 final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<ActivityRecord>();
164
Craig Mautnerf3333272013-04-22 10:55:53 -0700165 /** List of ActivityRecord objects that have been finished and must still report back to a
166 * pending thumbnail receiver. */
167 final ArrayList<ActivityRecord> mCancelledThumbnails = new ArrayList<ActivityRecord>();
168
169 /** Used on user changes */
170 final ArrayList<UserStartedState> mStartingUsers = new ArrayList<UserStartedState>();
171
Craig Mautnerde4ef022013-04-07 19:01:33 -0700172 /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity
173 * is being brought in front of us. */
174 boolean mUserLeaving = false;
175
Craig Mautner858d8a62013-04-23 17:08:34 -0700176 /** Stacks belonging to users other than mCurrentUser. Indexed by userId. */
177 final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
178
Craig Mautner0eea92c2013-05-16 13:35:39 -0700179 /** Set when we have taken too long waiting to go to sleep. */
180 boolean mSleepTimeout = false;
181
182 /**
183 * Set when the system is going to sleep, until we have
184 * successfully paused the current activity and released our wake lock.
185 * At that point the system is allowed to actually sleep.
186 */
187 final PowerManager.WakeLock mGoingToSleep;
188
Craig Mautner2219a1b2013-03-25 09:44:30 -0700189 public ActivityStackSupervisor(ActivityManagerService service, Context context,
190 Looper looper) {
Craig Mautner27084302013-03-25 08:05:25 -0700191 mService = service;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700192 mContext = context;
193 mLooper = looper;
Craig Mautner0eea92c2013-05-16 13:35:39 -0700194 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
195 mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700196 mHandler = new ActivityStackSupervisorHandler(looper);
Craig Mautner2219a1b2013-03-25 09:44:30 -0700197 }
198
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700199 void setWindowManager(WindowManagerService wm) {
200 mWindowManager = wm;
201 mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700202 mStacks.add(mHomeStack);
Craig Mautner27084302013-03-25 08:05:25 -0700203 }
204
205 void dismissKeyguard() {
206 if (mDismissKeyguardOnNextActivity) {
207 mDismissKeyguardOnNextActivity = false;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700208 mWindowManager.dismissKeyguard();
Craig Mautner27084302013-03-25 08:05:25 -0700209 }
210 }
211
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700212 ActivityStack getFocusedStack() {
Craig Mautnerf88c50f2013-04-18 19:25:12 -0700213 if (mFocusedStack == null) {
214 return mHomeStack;
215 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700216 switch (mStackState) {
217 case STACK_STATE_HOME_IN_FRONT:
218 case STACK_STATE_HOME_TO_FRONT:
219 return mHomeStack;
220 case STACK_STATE_HOME_IN_BACK:
221 case STACK_STATE_HOME_TO_BACK:
222 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700223 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700224 }
Craig Mautner20e72272013-04-01 13:45:53 -0700225 }
226
Craig Mautnerde4ef022013-04-07 19:01:33 -0700227 ActivityStack getLastStack() {
228 switch (mStackState) {
229 case STACK_STATE_HOME_IN_FRONT:
230 case STACK_STATE_HOME_TO_BACK:
231 return mHomeStack;
232 case STACK_STATE_HOME_TO_FRONT:
233 case STACK_STATE_HOME_IN_BACK:
234 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700235 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700236 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700237 }
238
Craig Mautnerde4ef022013-04-07 19:01:33 -0700239 boolean isFrontStack(ActivityStack stack) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700240 return (stack.mCurrentUser == mCurrentUser) &&
241 !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
Craig Mautner20e72272013-04-01 13:45:53 -0700242 }
243
Craig Mautnerde4ef022013-04-07 19:01:33 -0700244 void moveHomeStack(boolean toFront) {
245 final boolean homeInFront = isFrontStack(mHomeStack);
246 if (homeInFront ^ toFront) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700247 if (DEBUG_STACK) Slog.d(TAG, "moveHomeTask: mStackState old=" +
248 stackStateToString(mStackState) + " new=" + stackStateToString(homeInFront ?
249 STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700250 mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
251 }
252 }
253
Craig Mautner69ada552013-04-18 13:51:51 -0700254 boolean resumeHomeActivity(ActivityRecord prev) {
255 moveHomeStack(true);
256 if (prev != null) {
257 prev.mLaunchHomeTaskNext = false;
258 }
259 if (mHomeStack.topRunningActivityLocked(null) != null) {
Craig Mautner05d29032013-05-03 13:40:13 -0700260 return resumeTopActivitiesLocked(mHomeStack, prev, null);
Craig Mautner69ada552013-04-18 13:51:51 -0700261 }
262 return mService.startHomeActivityLocked(mCurrentUser);
263 }
264
Craig Mautnerde4ef022013-04-07 19:01:33 -0700265 final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r,
266 ActivityStack stack) {
267 if (stack == mHomeStack) {
268 return;
269 }
270 if ((sourceRecord == null && getLastStack() == mHomeStack) ||
Craig Mautner86d67a42013-05-14 10:34:38 -0700271 (sourceRecord != null && sourceRecord.isHomeActivity())) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700272 if (r == null) {
273 r = stack.topRunningActivityLocked(null);
274 }
Craig Mautner86d67a42013-05-14 10:34:38 -0700275 if (r != null && !r.isHomeActivity() && r.isRootActivity()) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700276 r.mLaunchHomeTaskNext = true;
277 }
278 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700279 }
280
Craig Mautner27084302013-03-25 08:05:25 -0700281 void setDismissKeyguard(boolean dismiss) {
282 mDismissKeyguardOnNextActivity = dismiss;
283 }
284
Craig Mautner8d341ef2013-03-26 09:03:27 -0700285 TaskRecord anyTaskForIdLocked(int id) {
286 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
287 ActivityStack stack = mStacks.get(stackNdx);
288 TaskRecord task = stack.taskForIdLocked(id);
289 if (task != null) {
290 return task;
291 }
292 }
293 return null;
294 }
295
Craig Mautner6170f732013-04-02 13:05:23 -0700296 ActivityRecord isInAnyStackLocked(IBinder token) {
297 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
298 final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
299 if (r != null) {
300 return r;
301 }
302 }
303 return null;
304 }
305
Craig Mautner8d341ef2013-03-26 09:03:27 -0700306 int getNextTaskId() {
307 do {
308 mCurTaskId++;
309 if (mCurTaskId <= 0) {
310 mCurTaskId = 1;
311 }
312 } while (anyTaskForIdLocked(mCurTaskId) != null);
313 return mCurTaskId;
314 }
315
Craig Mautnerde4ef022013-04-07 19:01:33 -0700316 void removeTask(TaskRecord task) {
317 final ActivityStack stack = task.stack;
318 if (stack.removeTask(task) && !stack.isHomeStack()) {
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700319 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700320 mStacks.remove(stack);
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700321 final int stackId = stack.mStackId;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700322 final int nextStackId = mWindowManager.removeStack(stackId);
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700323 // TODO: Perhaps we need to let the ActivityManager determine the next focus...
Guang Zhubefa8b52013-05-12 23:10:39 -0700324 if (mFocusedStack.mStackId == stackId) {
Craig Mautner1602ec22013-05-12 10:24:27 -0700325 // If this is the last app stack, set mFocusedStack to null.
Craig Mautner29219d92013-04-16 20:19:12 -0700326 mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700327 }
328 }
329 }
330
331 ActivityRecord resumedAppLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700332 ActivityStack stack = getFocusedStack();
333 if (stack == null) {
334 return null;
335 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700336 ActivityRecord resumedActivity = stack.mResumedActivity;
337 if (resumedActivity == null || resumedActivity.app == null) {
338 resumedActivity = stack.mPausingActivity;
339 if (resumedActivity == null || resumedActivity.app == null) {
340 resumedActivity = stack.topRunningActivityLocked(null);
341 }
342 }
343 return resumedActivity;
344 }
345
Craig Mautner20e72272013-04-01 13:45:53 -0700346 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
347 boolean didSomething = false;
348 final String processName = app.processName;
349 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
350 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner858d8a62013-04-23 17:08:34 -0700351 if (!isFrontStack(stack)) {
352 continue;
353 }
Craig Mautner20e72272013-04-01 13:45:53 -0700354 ActivityRecord hr = stack.topRunningActivityLocked(null);
355 if (hr != null) {
356 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
357 && processName.equals(hr.processName)) {
358 try {
359 if (headless) {
360 Slog.e(TAG, "Starting activities not supported on headless device: "
361 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700362 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700363 didSomething = true;
364 }
365 } catch (Exception e) {
366 Slog.w(TAG, "Exception in new application when starting activity "
367 + hr.intent.getComponent().flattenToShortString(), e);
368 throw e;
369 }
Craig Mautner20e72272013-04-01 13:45:53 -0700370 }
371 }
372 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -0700373 if (!didSomething) {
374 ensureActivitiesVisibleLocked(null, 0);
375 }
Craig Mautner20e72272013-04-01 13:45:53 -0700376 return didSomething;
377 }
378
379 boolean allResumedActivitiesIdle() {
380 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700381 final ActivityRecord resumedActivity = mStacks.get(stackNdx).mResumedActivity;
382 if (resumedActivity == null || !resumedActivity.idle) {
Craig Mautner20e72272013-04-01 13:45:53 -0700383 return false;
384 }
385 }
386 return true;
387 }
388
Craig Mautnerde4ef022013-04-07 19:01:33 -0700389 boolean allResumedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700390 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
391 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner967212c2013-04-13 21:10:58 -0700392 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700393 final ActivityRecord r = stack.mResumedActivity;
394 if (r != null && r.state != ActivityState.RESUMED) {
395 return false;
396 }
397 }
398 }
399 // TODO: Not sure if this should check if all Paused are complete too.
400 switch (mStackState) {
401 case STACK_STATE_HOME_TO_BACK:
Craig Mautner76ea2242013-05-15 11:40:05 -0700402 if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
403 stackStateToString(STACK_STATE_HOME_TO_BACK) + " new=" +
404 stackStateToString(STACK_STATE_HOME_IN_BACK));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700405 mStackState = STACK_STATE_HOME_IN_BACK;
406 break;
407 case STACK_STATE_HOME_TO_FRONT:
Craig Mautner76ea2242013-05-15 11:40:05 -0700408 if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
409 stackStateToString(STACK_STATE_HOME_TO_FRONT) + " new=" +
410 stackStateToString(STACK_STATE_HOME_IN_FRONT));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700411 mStackState = STACK_STATE_HOME_IN_FRONT;
412 break;
413 }
414 return true;
415 }
416
417 boolean allResumedActivitiesVisible() {
418 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
419 final ActivityStack stack = mStacks.get(stackNdx);
420 final ActivityRecord r = stack.mResumedActivity;
421 if (r != null && (!r.nowVisible || r.waitingVisible)) {
422 return false;
423 }
424 }
425 return true;
426 }
427
Craig Mautnercf910b02013-04-23 11:23:27 -0700428 boolean pauseBackStacks(boolean userLeaving) {
429 boolean someActivityPaused = false;
430 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
431 final ActivityStack stack = mStacks.get(stackNdx);
432 if (!isFrontStack(stack) && stack.mResumedActivity != null) {
433 stack.startPausingLocked(userLeaving, false);
434 someActivityPaused = true;
435 }
436 }
437 return someActivityPaused;
438 }
439
Craig Mautnerde4ef022013-04-07 19:01:33 -0700440 boolean allPausedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700441 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
442 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner69ada552013-04-18 13:51:51 -0700443 final ActivityRecord r = stack.mPausingActivity;
444 if (r != null && r.state != ActivityState.PAUSED
445 && r.state != ActivityState.STOPPED
446 && r.state != ActivityState.STOPPING) {
447 return false;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700448 }
449 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700450 return true;
451 }
452
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700453 void reportActivityVisibleLocked(ActivityRecord r) {
Craig Mautner858d8a62013-04-23 17:08:34 -0700454 for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700455 WaitResult w = mWaitingActivityVisible.get(i);
456 w.timeout = false;
457 if (r != null) {
458 w.who = new ComponentName(r.info.packageName, r.info.name);
459 }
460 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
461 w.thisTime = w.totalTime;
462 }
463 mService.notifyAll();
464 dismissKeyguard();
465 }
466
467 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
468 long thisTime, long totalTime) {
469 for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
Craig Mautnerc64f73e2013-04-24 16:44:56 -0700470 WaitResult w = mWaitingActivityLaunched.remove(i);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700471 w.timeout = timeout;
472 if (r != null) {
473 w.who = new ComponentName(r.info.packageName, r.info.name);
474 }
475 w.thisTime = thisTime;
476 w.totalTime = totalTime;
477 }
478 mService.notifyAll();
479 }
480
Craig Mautner29219d92013-04-16 20:19:12 -0700481 ActivityRecord topRunningActivityLocked() {
Craig Mautner1602ec22013-05-12 10:24:27 -0700482 final ActivityStack focusedStack = getFocusedStack();
483 ActivityRecord r = focusedStack.topRunningActivityLocked(null);
484 if (r != null) {
485 return r;
Craig Mautner29219d92013-04-16 20:19:12 -0700486 }
Craig Mautner1602ec22013-05-12 10:24:27 -0700487
Craig Mautner29219d92013-04-16 20:19:12 -0700488 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
489 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner1602ec22013-05-12 10:24:27 -0700490 if (stack.mCurrentUser == mCurrentUser && stack != focusedStack &&
491 isFrontStack(stack)) {
Craig Mautner29219d92013-04-16 20:19:12 -0700492 r = stack.topRunningActivityLocked(null);
493 if (r != null) {
494 return r;
495 }
496 }
497 }
498 return null;
499 }
500
Craig Mautner20e72272013-04-01 13:45:53 -0700501 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
502 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
503 ActivityRecord r = null;
Craig Mautner20e72272013-04-01 13:45:53 -0700504 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
505 final ActivityStack stack = mStacks.get(stackNdx);
506 final ActivityRecord ar =
507 stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700508 if (isFrontStack(stack)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700509 r = ar;
510 }
511 }
512 return r;
513 }
514
Craig Mautner23ac33b2013-04-01 16:26:35 -0700515 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
516 String profileFile, ParcelFileDescriptor profileFd, int userId) {
517 // Collect information about the target of the Intent.
518 ActivityInfo aInfo;
519 try {
520 ResolveInfo rInfo =
521 AppGlobals.getPackageManager().resolveIntent(
522 intent, resolvedType,
523 PackageManager.MATCH_DEFAULT_ONLY
524 | ActivityManagerService.STOCK_PM_FLAGS, userId);
525 aInfo = rInfo != null ? rInfo.activityInfo : null;
526 } catch (RemoteException e) {
527 aInfo = null;
528 }
529
530 if (aInfo != null) {
531 // Store the found target back into the intent, because now that
532 // we have it we never want to do this again. For example, if the
533 // user navigates back to this point in the history, we should
534 // always restart the exact same activity.
535 intent.setComponent(new ComponentName(
536 aInfo.applicationInfo.packageName, aInfo.name));
537
538 // Don't debug things in the system process
539 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
540 if (!aInfo.processName.equals("system")) {
541 mService.setDebugApp(aInfo.processName, true, false);
542 }
543 }
544
545 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
546 if (!aInfo.processName.equals("system")) {
547 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
548 }
549 }
550
551 if (profileFile != null) {
552 if (!aInfo.processName.equals("system")) {
553 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
554 profileFile, profileFd,
555 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
556 }
557 }
558 }
559 return aInfo;
560 }
561
Craig Mautner2219a1b2013-03-25 09:44:30 -0700562 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700563 moveHomeStack(true);
Craig Mautner6170f732013-04-02 13:05:23 -0700564 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
Craig Mautner2219a1b2013-03-25 09:44:30 -0700565 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700566 }
567
Craig Mautner23ac33b2013-04-01 16:26:35 -0700568 final int startActivityMayWait(IApplicationThread caller, int callingUid,
569 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
570 String resultWho, int requestCode, int startFlags, String profileFile,
571 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
572 Bundle options, int userId) {
573 // Refuse possible leaked file descriptors
574 if (intent != null && intent.hasFileDescriptors()) {
575 throw new IllegalArgumentException("File descriptors passed in Intent");
576 }
577 boolean componentSpecified = intent.getComponent() != null;
578
579 // Don't modify the client's object!
580 intent = new Intent(intent);
581
582 // Collect information about the target of the Intent.
583 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
584 profileFile, profileFd, userId);
585
586 synchronized (mService) {
587 int callingPid;
588 if (callingUid >= 0) {
589 callingPid = -1;
590 } else if (caller == null) {
591 callingPid = Binder.getCallingPid();
592 callingUid = Binder.getCallingUid();
593 } else {
594 callingPid = callingUid = -1;
595 }
596
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700597 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -0700598 stack.mConfigWillChange = config != null
Craig Mautner23ac33b2013-04-01 16:26:35 -0700599 && mService.mConfiguration.diff(config) != 0;
600 if (DEBUG_CONFIGURATION) Slog.v(TAG,
Craig Mautnerde4ef022013-04-07 19:01:33 -0700601 "Starting activity when config will change = " + stack.mConfigWillChange);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700602
603 final long origId = Binder.clearCallingIdentity();
604
605 if (aInfo != null &&
606 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
607 // This may be a heavy-weight process! Check to see if we already
608 // have another, different heavy-weight process running.
609 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
610 if (mService.mHeavyWeightProcess != null &&
611 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
612 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700613 int realCallingUid = callingUid;
614 if (caller != null) {
615 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
616 if (callerApp != null) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700617 realCallingUid = callerApp.info.uid;
618 } else {
619 Slog.w(TAG, "Unable to find app for caller " + caller
Craig Mautner76ea2242013-05-15 11:40:05 -0700620 + " (pid=" + callingPid + ") when starting: "
Craig Mautner23ac33b2013-04-01 16:26:35 -0700621 + intent.toString());
622 ActivityOptions.abort(options);
623 return ActivityManager.START_PERMISSION_DENIED;
624 }
625 }
626
627 IIntentSender target = mService.getIntentSenderLocked(
628 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
629 realCallingUid, userId, null, null, 0, new Intent[] { intent },
630 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
631 | PendingIntent.FLAG_ONE_SHOT, null);
632
633 Intent newIntent = new Intent();
634 if (requestCode >= 0) {
635 // Caller is requesting a result.
636 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
637 }
638 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
639 new IntentSender(target));
640 if (mService.mHeavyWeightProcess.activities.size() > 0) {
641 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
642 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
643 hist.packageName);
644 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
645 hist.task.taskId);
646 }
647 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
648 aInfo.packageName);
649 newIntent.setFlags(intent.getFlags());
650 newIntent.setClassName("android",
651 HeavyWeightSwitcherActivity.class.getName());
652 intent = newIntent;
653 resolvedType = null;
654 caller = null;
655 callingUid = Binder.getCallingUid();
656 callingPid = Binder.getCallingPid();
657 componentSpecified = true;
658 try {
659 ResolveInfo rInfo =
660 AppGlobals.getPackageManager().resolveIntent(
661 intent, null,
662 PackageManager.MATCH_DEFAULT_ONLY
663 | ActivityManagerService.STOCK_PM_FLAGS, userId);
664 aInfo = rInfo != null ? rInfo.activityInfo : null;
665 aInfo = mService.getActivityInfoForUser(aInfo, userId);
666 } catch (RemoteException e) {
667 aInfo = null;
668 }
669 }
670 }
671 }
672
Craig Mautner6170f732013-04-02 13:05:23 -0700673 int res = startActivityLocked(caller, intent, resolvedType,
Craig Mautner23ac33b2013-04-01 16:26:35 -0700674 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
675 callingPackage, startFlags, options, componentSpecified, null);
676
Craig Mautnerde4ef022013-04-07 19:01:33 -0700677 if (stack.mConfigWillChange) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700678 // If the caller also wants to switch to a new configuration,
679 // do so now. This allows a clean switch, as we are waiting
680 // for the current activity to pause (so we will not destroy
681 // it), and have not yet started the next activity.
682 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
683 "updateConfiguration()");
Craig Mautnerde4ef022013-04-07 19:01:33 -0700684 stack.mConfigWillChange = false;
Craig Mautner23ac33b2013-04-01 16:26:35 -0700685 if (DEBUG_CONFIGURATION) Slog.v(TAG,
686 "Updating to new configuration after starting activity.");
687 mService.updateConfigurationLocked(config, null, false, false);
688 }
689
690 Binder.restoreCallingIdentity(origId);
691
692 if (outResult != null) {
693 outResult.result = res;
694 if (res == ActivityManager.START_SUCCESS) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700695 mWaitingActivityLaunched.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700696 do {
697 try {
698 mService.wait();
699 } catch (InterruptedException e) {
700 }
701 } while (!outResult.timeout && outResult.who == null);
702 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700703 ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700704 if (r.nowVisible) {
705 outResult.timeout = false;
706 outResult.who = new ComponentName(r.info.packageName, r.info.name);
707 outResult.totalTime = 0;
708 outResult.thisTime = 0;
709 } else {
710 outResult.thisTime = SystemClock.uptimeMillis();
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700711 mWaitingActivityVisible.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700712 do {
713 try {
714 mService.wait();
715 } catch (InterruptedException e) {
716 }
717 } while (!outResult.timeout && outResult.who == null);
718 }
719 }
720 }
721
722 return res;
723 }
724 }
725
726 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
727 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
728 Bundle options, int userId) {
729 if (intents == null) {
730 throw new NullPointerException("intents is null");
731 }
732 if (resolvedTypes == null) {
733 throw new NullPointerException("resolvedTypes is null");
734 }
735 if (intents.length != resolvedTypes.length) {
736 throw new IllegalArgumentException("intents are length different than resolvedTypes");
737 }
738
Craig Mautner23ac33b2013-04-01 16:26:35 -0700739
740 int callingPid;
741 if (callingUid >= 0) {
742 callingPid = -1;
743 } else if (caller == null) {
744 callingPid = Binder.getCallingPid();
745 callingUid = Binder.getCallingUid();
746 } else {
747 callingPid = callingUid = -1;
748 }
749 final long origId = Binder.clearCallingIdentity();
750 try {
751 synchronized (mService) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700752 ActivityRecord[] outActivity = new ActivityRecord[1];
Craig Mautner23ac33b2013-04-01 16:26:35 -0700753 for (int i=0; i<intents.length; i++) {
754 Intent intent = intents[i];
755 if (intent == null) {
756 continue;
757 }
758
759 // Refuse possible leaked file descriptors
760 if (intent != null && intent.hasFileDescriptors()) {
761 throw new IllegalArgumentException("File descriptors passed in Intent");
762 }
763
764 boolean componentSpecified = intent.getComponent() != null;
765
766 // Don't modify the client's object!
767 intent = new Intent(intent);
768
769 // Collect information about the target of the Intent.
770 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
771 0, null, null, userId);
772 // TODO: New, check if this is correct
773 aInfo = mService.getActivityInfoForUser(aInfo, userId);
774
775 if (aInfo != null &&
776 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
777 != 0) {
778 throw new IllegalArgumentException(
779 "FLAG_CANT_SAVE_STATE not supported here");
780 }
781
782 Bundle theseOptions;
783 if (options != null && i == intents.length-1) {
784 theseOptions = options;
785 } else {
786 theseOptions = null;
787 }
Craig Mautner6170f732013-04-02 13:05:23 -0700788 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Craig Mautner23ac33b2013-04-01 16:26:35 -0700789 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
790 0, theseOptions, componentSpecified, outActivity);
791 if (res < 0) {
792 return res;
793 }
794
795 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
796 }
797 }
798 } finally {
799 Binder.restoreCallingIdentity(origId);
800 }
801
802 return ActivityManager.START_SUCCESS;
803 }
804
Craig Mautner2420ead2013-04-01 17:13:20 -0700805 final boolean realStartActivityLocked(ActivityRecord r,
806 ProcessRecord app, boolean andResume, boolean checkConfig)
807 throws RemoteException {
808
809 r.startFreezingScreenLocked(app, 0);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700810 mWindowManager.setAppVisibility(r.appToken, true);
Craig Mautner2420ead2013-04-01 17:13:20 -0700811
812 // schedule launch ticks to collect information about slow apps.
813 r.startLaunchTickingLocked();
814
815 // Have the window manager re-evaluate the orientation of
816 // the screen based on the new activity order. Note that
817 // as a result of this, it can call back into the activity
818 // manager with a new orientation. We don't care about that,
819 // because the activity is not currently running so we are
820 // just restarting it anyway.
821 if (checkConfig) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700822 Configuration config = mWindowManager.updateOrientationFromAppTokens(
Craig Mautner2420ead2013-04-01 17:13:20 -0700823 mService.mConfiguration,
824 r.mayFreezeScreenLocked(app) ? r.appToken : null);
825 mService.updateConfigurationLocked(config, r, false, false);
826 }
827
828 r.app = app;
829 app.waitingToKill = null;
830 r.launchCount++;
831 r.lastLaunchTime = SystemClock.uptimeMillis();
832
833 if (localLOGV) Slog.v(TAG, "Launching: " + r);
834
835 int idx = app.activities.indexOf(r);
836 if (idx < 0) {
837 app.activities.add(r);
838 }
839 mService.updateLruProcessLocked(app, true);
840
841 final ActivityStack stack = r.task.stack;
842 try {
843 if (app.thread == null) {
844 throw new RemoteException();
845 }
846 List<ResultInfo> results = null;
847 List<Intent> newIntents = null;
848 if (andResume) {
849 results = r.results;
850 newIntents = r.newIntents;
851 }
852 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
853 + " icicle=" + r.icicle
854 + " with results=" + results + " newIntents=" + newIntents
855 + " andResume=" + andResume);
856 if (andResume) {
857 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
858 r.userId, System.identityHashCode(r),
859 r.task.taskId, r.shortComponentName);
860 }
Craig Mautner86d67a42013-05-14 10:34:38 -0700861 if (r.isHomeActivity()) {
Craig Mautner2420ead2013-04-01 17:13:20 -0700862 mService.mHomeProcess = app;
863 }
864 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
865 r.sleeping = false;
866 r.forceNewConfig = false;
867 mService.showAskCompatModeDialogLocked(r);
868 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
869 String profileFile = null;
870 ParcelFileDescriptor profileFd = null;
871 boolean profileAutoStop = false;
872 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
873 if (mService.mProfileProc == null || mService.mProfileProc == app) {
874 mService.mProfileProc = app;
875 profileFile = mService.mProfileFile;
876 profileFd = mService.mProfileFd;
877 profileAutoStop = mService.mAutoStopProfiler;
878 }
879 }
880 app.hasShownUi = true;
881 app.pendingUiClean = true;
882 if (profileFd != null) {
883 try {
884 profileFd = profileFd.dup();
885 } catch (IOException e) {
886 if (profileFd != null) {
887 try {
888 profileFd.close();
889 } catch (IOException o) {
890 }
891 profileFd = null;
892 }
893 }
894 }
895 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
896 System.identityHashCode(r), r.info,
897 new Configuration(mService.mConfiguration),
898 r.compat, r.icicle, results, newIntents, !andResume,
899 mService.isNextTransitionForward(), profileFile, profileFd,
900 profileAutoStop);
901
902 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
903 // This may be a heavy-weight process! Note that the package
904 // manager will ensure that only activity can run in the main
905 // process of the .apk, which is the only thing that will be
906 // considered heavy-weight.
907 if (app.processName.equals(app.info.packageName)) {
908 if (mService.mHeavyWeightProcess != null
909 && mService.mHeavyWeightProcess != app) {
910 Slog.w(TAG, "Starting new heavy weight process " + app
911 + " when already running "
912 + mService.mHeavyWeightProcess);
913 }
914 mService.mHeavyWeightProcess = app;
915 Message msg = mService.mHandler.obtainMessage(
916 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
917 msg.obj = r;
918 mService.mHandler.sendMessage(msg);
919 }
920 }
921
922 } catch (RemoteException e) {
923 if (r.launchFailed) {
924 // This is the second time we failed -- finish activity
925 // and give up.
926 Slog.e(TAG, "Second failure launching "
927 + r.intent.getComponent().flattenToShortString()
928 + ", giving up", e);
929 mService.appDiedLocked(app, app.pid, app.thread);
930 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
931 "2nd-crash", false);
932 return false;
933 }
934
935 // This is the first time we failed -- restart process and
936 // retry.
937 app.activities.remove(r);
938 throw e;
939 }
940
941 r.launchFailed = false;
942 if (stack.updateLRUListLocked(r)) {
943 Slog.w(TAG, "Activity " + r
944 + " being launched, but already in LRU list");
945 }
946
947 if (andResume) {
948 // As part of the process of launching, ActivityThread also performs
949 // a resume.
950 stack.minimalResumeActivityLocked(r);
951 } else {
952 // This activity is not starting in the resumed state... which
953 // should look like we asked it to pause+stop (but remain visible),
954 // and it has done so and reported back the current icicle and
955 // other state.
956 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
957 + " (starting in stopped state)");
958 r.state = ActivityState.STOPPED;
959 r.stopped = true;
960 }
961
962 // Launch the new version setup screen if needed. We do this -after-
963 // launching the initial activity (that is, home), so that it can have
964 // a chance to initialize itself while in the background, making the
965 // switch back to it faster and look better.
Craig Mautnerde4ef022013-04-07 19:01:33 -0700966 if (isFrontStack(stack)) {
Craig Mautner2420ead2013-04-01 17:13:20 -0700967 mService.startSetupActivityLocked();
968 }
969
970 return true;
971 }
972
Craig Mautnere79d42682013-04-01 19:01:53 -0700973 void startSpecificActivityLocked(ActivityRecord r,
974 boolean andResume, boolean checkConfig) {
975 // Is this activity's application already running?
976 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
977 r.info.applicationInfo.uid);
978
979 r.task.stack.setLaunchTime(r);
980
981 if (app != null && app.thread != null) {
982 try {
983 app.addPackage(r.info.packageName);
984 realStartActivityLocked(r, app, andResume, checkConfig);
985 return;
986 } catch (RemoteException e) {
987 Slog.w(TAG, "Exception when starting activity "
988 + r.intent.getComponent().flattenToShortString(), e);
989 }
990
991 // If a dead object exception was thrown -- fall through to
992 // restart the application.
993 }
994
995 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
996 "activity", r.intent.getComponent(), false, false);
997 }
998
Craig Mautner6170f732013-04-02 13:05:23 -0700999 final int startActivityLocked(IApplicationThread caller,
1000 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
1001 String resultWho, int requestCode,
1002 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
1003 boolean componentSpecified, ActivityRecord[] outActivity) {
1004 int err = ActivityManager.START_SUCCESS;
1005
1006 ProcessRecord callerApp = null;
1007 if (caller != null) {
1008 callerApp = mService.getRecordForAppLocked(caller);
1009 if (callerApp != null) {
1010 callingPid = callerApp.pid;
1011 callingUid = callerApp.info.uid;
1012 } else {
1013 Slog.w(TAG, "Unable to find app for caller " + caller
1014 + " (pid=" + callingPid + ") when starting: "
1015 + intent.toString());
1016 err = ActivityManager.START_PERMISSION_DENIED;
1017 }
1018 }
1019
1020 if (err == ActivityManager.START_SUCCESS) {
1021 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
1022 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
1023 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
1024 }
1025
1026 ActivityRecord sourceRecord = null;
1027 ActivityRecord resultRecord = null;
1028 if (resultTo != null) {
1029 sourceRecord = isInAnyStackLocked(resultTo);
1030 if (DEBUG_RESULTS) Slog.v(
1031 TAG, "Will send result to " + resultTo + " " + sourceRecord);
1032 if (sourceRecord != null) {
1033 if (requestCode >= 0 && !sourceRecord.finishing) {
1034 resultRecord = sourceRecord;
1035 }
1036 }
1037 }
1038 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
1039
1040 int launchFlags = intent.getFlags();
1041
1042 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
1043 && sourceRecord != null) {
1044 // Transfer the result target from the source activity to the new
1045 // one being started, including any failures.
1046 if (requestCode >= 0) {
1047 ActivityOptions.abort(options);
1048 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
1049 }
1050 resultRecord = sourceRecord.resultTo;
1051 resultWho = sourceRecord.resultWho;
1052 requestCode = sourceRecord.requestCode;
1053 sourceRecord.resultTo = null;
1054 if (resultRecord != null) {
1055 resultRecord.removeResultsLocked(
1056 sourceRecord, resultWho, requestCode);
1057 }
1058 }
1059
1060 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
1061 // We couldn't find a class that can handle the given Intent.
1062 // That's the end of that!
1063 err = ActivityManager.START_INTENT_NOT_RESOLVED;
1064 }
1065
1066 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
1067 // We couldn't find the specific class specified in the Intent.
1068 // Also the end of the line.
1069 err = ActivityManager.START_CLASS_NOT_FOUND;
1070 }
1071
1072 if (err != ActivityManager.START_SUCCESS) {
1073 if (resultRecord != null) {
1074 resultStack.sendActivityResultLocked(-1,
1075 resultRecord, resultWho, requestCode,
1076 Activity.RESULT_CANCELED, null);
1077 }
1078 setDismissKeyguard(false);
1079 ActivityOptions.abort(options);
1080 return err;
1081 }
1082
1083 final int startAnyPerm = mService.checkPermission(
1084 START_ANY_ACTIVITY, callingPid, callingUid);
1085 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
1086 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
1087 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
1088 if (resultRecord != null) {
1089 resultStack.sendActivityResultLocked(-1,
1090 resultRecord, resultWho, requestCode,
1091 Activity.RESULT_CANCELED, null);
1092 }
1093 setDismissKeyguard(false);
1094 String msg;
1095 if (!aInfo.exported) {
1096 msg = "Permission Denial: starting " + intent.toString()
1097 + " from " + callerApp + " (pid=" + callingPid
1098 + ", uid=" + callingUid + ")"
1099 + " not exported from uid " + aInfo.applicationInfo.uid;
1100 } else {
1101 msg = "Permission Denial: starting " + intent.toString()
1102 + " from " + callerApp + " (pid=" + callingPid
1103 + ", uid=" + callingUid + ")"
1104 + " requires " + aInfo.permission;
1105 }
1106 Slog.w(TAG, msg);
1107 throw new SecurityException(msg);
1108 }
1109
Ben Gruver6617c3c2013-04-03 18:45:22 -07001110 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
Ben Gruver7b879f42013-04-08 14:56:55 -07001111 callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo);
Ben Gruver5e207332013-04-03 17:41:37 -07001112
Craig Mautner6170f732013-04-02 13:05:23 -07001113 if (mService.mController != null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001114 try {
1115 // The Intent we give to the watcher has the extra data
1116 // stripped off, since it can contain private information.
1117 Intent watchIntent = intent.cloneFilter();
Ben Gruver5e207332013-04-03 17:41:37 -07001118 abort |= !mService.mController.activityStarting(watchIntent,
Craig Mautner6170f732013-04-02 13:05:23 -07001119 aInfo.applicationInfo.packageName);
1120 } catch (RemoteException e) {
1121 mService.mController = null;
1122 }
Ben Gruver5e207332013-04-03 17:41:37 -07001123 }
Craig Mautner6170f732013-04-02 13:05:23 -07001124
Ben Gruver5e207332013-04-03 17:41:37 -07001125 if (abort) {
1126 if (resultRecord != null) {
1127 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Craig Mautner6170f732013-04-02 13:05:23 -07001128 Activity.RESULT_CANCELED, null);
Craig Mautner6170f732013-04-02 13:05:23 -07001129 }
Ben Gruver5e207332013-04-03 17:41:37 -07001130 // We pretend to the caller that it was really started, but
1131 // they will just get a cancel result.
1132 setDismissKeyguard(false);
1133 ActivityOptions.abort(options);
1134 return ActivityManager.START_SUCCESS;
Craig Mautner6170f732013-04-02 13:05:23 -07001135 }
1136
1137 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1138 intent, resolvedType, aInfo, mService.mConfiguration,
Craig Mautnerde4ef022013-04-07 19:01:33 -07001139 resultRecord, resultWho, requestCode, componentSpecified, this);
Craig Mautner6170f732013-04-02 13:05:23 -07001140 if (outActivity != null) {
1141 outActivity[0] = r;
1142 }
1143
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001144 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001145 if (stack.mResumedActivity == null
1146 || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
Craig Mautner6170f732013-04-02 13:05:23 -07001147 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1148 PendingActivityLaunch pal =
Craig Mautnerde4ef022013-04-07 19:01:33 -07001149 new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
Craig Mautner6170f732013-04-02 13:05:23 -07001150 mService.mPendingActivityLaunches.add(pal);
1151 setDismissKeyguard(false);
1152 ActivityOptions.abort(options);
1153 return ActivityManager.START_SWITCHES_CANCELED;
1154 }
1155 }
1156
1157 if (mService.mDidAppSwitch) {
1158 // This is the second allowed switch since we stopped switches,
1159 // so now just generally allow switches. Use case: user presses
1160 // home (switches disabled, switch to home, mDidAppSwitch now true);
1161 // user taps a home icon (coming from home so allowed, we hit here
1162 // and now allow anyone to switch again).
1163 mService.mAppSwitchesAllowedTime = 0;
1164 } else {
1165 mService.mDidAppSwitch = true;
1166 }
1167
1168 mService.doPendingActivityLaunchesLocked(false);
1169
Craig Mautner8849a5e2013-04-02 16:41:03 -07001170 err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001171 if (stack.mPausingActivity == null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001172 // Someone asked to have the keyguard dismissed on the next
1173 // activity start, but we are not actually doing an activity
1174 // switch... just dismiss the keyguard now, because we
1175 // probably want to see whatever is behind it.
1176 dismissKeyguard();
1177 }
1178 return err;
1179 }
1180
Craig Mautnerde4ef022013-04-07 19:01:33 -07001181 ActivityStack getCorrectStack(ActivityRecord r) {
Craig Mautner86d67a42013-05-14 10:34:38 -07001182 if (r.isApplicationActivity() || (r.task != null && r.task.isApplicationTask())) {
Craig Mautner858d8a62013-04-23 17:08:34 -07001183 int stackNdx;
1184 for (stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
1185 if (mStacks.get(stackNdx).mCurrentUser == mCurrentUser) {
1186 break;
1187 }
1188 }
1189 if (stackNdx == 0) {
1190 // Time to create the first app stack for this user.
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001191 int stackId = mService.createStack(-1, HOME_STACK_ID,
1192 StackBox.TASK_STACK_GOES_OVER, 1.0f);
Craig Mautner29219d92013-04-16 20:19:12 -07001193 mFocusedStack = getStack(stackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001194 }
Craig Mautner29219d92013-04-16 20:19:12 -07001195 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001196 }
1197 return mHomeStack;
1198 }
1199
Craig Mautner29219d92013-04-16 20:19:12 -07001200 void setFocusedStack(ActivityRecord r) {
1201 if (r == null) {
1202 return;
1203 }
Craig Mautner86d67a42013-05-14 10:34:38 -07001204 if (!r.isApplicationActivity() || (r.task != null && !r.task.isApplicationTask())) {
Craig Mautner29219d92013-04-16 20:19:12 -07001205 if (mStackState != STACK_STATE_HOME_IN_FRONT) {
Craig Mautner76ea2242013-05-15 11:40:05 -07001206 if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
1207 stackStateToString(mStackState) + " new=" +
1208 stackStateToString(STACK_STATE_HOME_TO_FRONT) +
1209 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001210 mStackState = STACK_STATE_HOME_TO_FRONT;
1211 }
1212 } else {
1213 mFocusedStack = r.task.stack;
1214 if (mStackState != STACK_STATE_HOME_IN_BACK) {
Craig Mautner76ea2242013-05-15 11:40:05 -07001215 if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
1216 stackStateToString(mStackState) + " new=" +
1217 stackStateToString(STACK_STATE_HOME_TO_BACK) +
1218 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001219 mStackState = STACK_STATE_HOME_TO_BACK;
1220 }
1221 }
1222 }
1223
Craig Mautner8849a5e2013-04-02 16:41:03 -07001224 final int startActivityUncheckedLocked(ActivityRecord r,
1225 ActivityRecord sourceRecord, int startFlags, boolean doResume,
1226 Bundle options) {
1227 final Intent intent = r.intent;
1228 final int callingUid = r.launchedFromUid;
1229
1230 int launchFlags = intent.getFlags();
1231
Craig Mautner8849a5e2013-04-02 16:41:03 -07001232 // We'll invoke onUserLeaving before onPause only if the launching
1233 // activity did not explicitly state that this is an automated launch.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001234 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1235 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001236
1237 // If the caller has asked not to resume at this point, we make note
1238 // of this in the record so that we can skip it when trying to find
1239 // the top running activity.
1240 if (!doResume) {
1241 r.delayedResume = true;
1242 }
1243
1244 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1245
1246 // If the onlyIfNeeded flag is set, then we can do this if the activity
1247 // being launched is the same as the one making the call... or, as
1248 // a special case, if we do not know the caller then we count the
1249 // current top activity as the caller.
1250 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1251 ActivityRecord checkedCaller = sourceRecord;
1252 if (checkedCaller == null) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001253 checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001254 }
1255 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1256 // Caller is not the same as launcher, so always needed.
1257 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1258 }
1259 }
1260
1261 if (sourceRecord == null) {
1262 // This activity is not being started from another... in this
1263 // case we -always- start a new task.
1264 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Craig Mautner29219d92013-04-16 20:19:12 -07001265 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1266 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001267 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1268 }
1269 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1270 // The original activity who is starting us is running as a single
1271 // instance... this new activity it is starting must go on its
1272 // own task.
1273 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1274 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1275 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1276 // The activity being started is a single instance... it always
1277 // gets launched into its own task.
1278 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1279 }
1280
Craig Mautnerde4ef022013-04-07 19:01:33 -07001281 final ActivityStack sourceStack;
Craig Mautner525f3d92013-05-07 14:01:50 -07001282 TaskRecord sourceTask;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001283 if (sourceRecord != null) {
1284 sourceTask = sourceRecord.task;
1285 sourceStack = sourceTask.stack;
1286 } else {
1287 sourceTask = null;
1288 sourceStack = null;
1289 }
1290
Craig Mautner8849a5e2013-04-02 16:41:03 -07001291 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1292 // For whatever reason this activity is being launched into a new
1293 // task... yet the caller has requested a result back. Well, that
1294 // is pretty messed up, so instead immediately send back a cancel
1295 // and let the new task continue launched as normal without a
1296 // dependency on its originator.
1297 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1298 r.resultTo.task.stack.sendActivityResultLocked(-1,
1299 r.resultTo, r.resultWho, r.requestCode,
1300 Activity.RESULT_CANCELED, null);
1301 r.resultTo = null;
1302 }
1303
1304 boolean addingToTask = false;
1305 boolean movedHome = false;
1306 TaskRecord reuseTask = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001307 ActivityStack targetStack;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001308 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1309 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1310 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1311 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1312 // If bring to front is requested, and no result is requested, and
1313 // we can find a task that was started with this same
1314 // component, then instead of launching bring that one to the front.
1315 if (r.resultTo == null) {
1316 // See if there is a task to bring to the front. If this is
1317 // a SINGLE_INSTANCE activity, there can be one and only one
1318 // instance of it in the history, and it is always in its own
1319 // unique task, so we do a special search.
1320 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
1321 ? findTaskLocked(intent, r.info)
1322 : findActivityLocked(intent, r.info);
1323 if (intentActivity != null) {
Craig Mautner29219d92013-04-16 20:19:12 -07001324 if (r.task == null) {
1325 r.task = intentActivity.task;
1326 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001327 targetStack = intentActivity.task.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001328 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001329 if (intentActivity.task.intent == null) {
1330 // This task was started because of movement of
1331 // the activity based on affinity... now that we
1332 // are actually launching it, we can assign the
1333 // base intent.
1334 intentActivity.task.setIntent(intent, r.info);
1335 }
1336 // If the target task is not in the front, then we need
1337 // to bring it to the front... except... well, with
1338 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
1339 // to have the same behavior as if a new instance was
1340 // being started, which means not bringing it to the front
1341 // if the caller is not itself in the front.
Craig Mautner165640b2013-04-20 10:34:33 -07001342 final ActivityStack lastStack = getLastStack();
1343 ActivityRecord curTop = lastStack == null?
1344 null : lastStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001345 if (curTop != null && curTop.task != intentActivity.task) {
1346 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001347 if (sourceRecord == null || sourceStack.topActivity() == sourceRecord) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001348 // We really do want to push this one into the
1349 // user's face, right now.
1350 movedHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001351 if ((launchFlags &
Craig Mautner29219d92013-04-16 20:19:12 -07001352 (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1353 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001354 // Caller wants to appear on home activity, so before starting
1355 // their own activity we will bring home to the front.
1356 r.mLaunchHomeTaskNext = true;
1357 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001358 targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1359 options = null;
1360 }
1361 }
1362 // If the caller has requested that the target task be
1363 // reset, then do so.
1364 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1365 intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1366 }
1367 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1368 // We don't need to start a new activity, and
1369 // the client said not to do anything if that
1370 // is the case, so this is it! And for paranoia, make
1371 // sure we have correctly resumed the top activity.
1372 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001373 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001374 resumeTopActivitiesLocked(targetStack, null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001375 } else {
1376 ActivityOptions.abort(options);
1377 }
Craig Mautner29219d92013-04-16 20:19:12 -07001378 if (r.task == null) Slog.v(TAG,
1379 "startActivityUncheckedLocked: task left null",
1380 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001381 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1382 }
1383 if ((launchFlags &
1384 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1385 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1386 // The caller has requested to completely replace any
1387 // existing task with its new activity. Well that should
1388 // not be too hard...
1389 reuseTask = intentActivity.task;
1390 reuseTask.performClearTaskLocked();
1391 reuseTask.setIntent(r.intent, r.info);
1392 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1393 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1394 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1395 // In this situation we want to remove all activities
1396 // from the task up to the one being started. In most
1397 // cases this means we are resetting the task to its
1398 // initial state.
1399 ActivityRecord top =
1400 intentActivity.task.performClearTaskLocked(r, launchFlags);
1401 if (top != null) {
1402 if (top.frontOfTask) {
1403 // Activity aliases may mean we use different
1404 // intents for the top activity, so make sure
1405 // the task now has the identity of the new
1406 // intent.
1407 top.task.setIntent(r.intent, r.info);
1408 }
1409 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1410 r, top.task);
1411 top.deliverNewIntentLocked(callingUid, r.intent);
1412 } else {
1413 // A special case: we need to
1414 // start the activity because it is not currently
1415 // running, and the caller has asked to clear the
1416 // current task to have this activity at the top.
1417 addingToTask = true;
1418 // Now pretend like this activity is being started
1419 // by the top of its task, so it is put in the
1420 // right place.
1421 sourceRecord = intentActivity;
1422 }
1423 } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1424 // In this case the top activity on the task is the
1425 // same as the one being launched, so we take that
1426 // as a request to bring the task to the foreground.
1427 // If the top activity in the task is the root
1428 // activity, deliver this new intent to it if it
1429 // desires.
1430 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1431 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1432 && intentActivity.realActivity.equals(r.realActivity)) {
1433 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1434 intentActivity.task);
1435 if (intentActivity.frontOfTask) {
1436 intentActivity.task.setIntent(r.intent, r.info);
1437 }
1438 intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1439 } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1440 // In this case we are launching the root activity
1441 // of the task, but with a different intent. We
1442 // should start a new instance on top.
1443 addingToTask = true;
1444 sourceRecord = intentActivity;
1445 }
1446 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1447 // In this case an activity is being launched in to an
1448 // existing task, without resetting that task. This
1449 // is typically the situation of launching an activity
1450 // from a notification or shortcut. We want to place
1451 // the new activity on top of the current task.
1452 addingToTask = true;
1453 sourceRecord = intentActivity;
1454 } else if (!intentActivity.task.rootWasReset) {
1455 // In this case we are launching in to an existing task
1456 // that has not yet been started from its front door.
1457 // The current task has been brought to the front.
1458 // Ideally, we'd probably like to place this new task
1459 // at the bottom of its stack, but that's a little hard
1460 // to do with the current organization of the code so
1461 // for now we'll just drop it.
1462 intentActivity.task.setIntent(r.intent, r.info);
1463 }
1464 if (!addingToTask && reuseTask == null) {
1465 // We didn't do anything... but it was needed (a.k.a., client
1466 // don't use that intent!) And for paranoia, make
1467 // sure we have correctly resumed the top activity.
1468 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001469 setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1470 targetStack.resumeTopActivityLocked(null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001471 } else {
1472 ActivityOptions.abort(options);
1473 }
Craig Mautner29219d92013-04-16 20:19:12 -07001474 if (r.task == null) Slog.v(TAG,
1475 "startActivityUncheckedLocked: task left null",
1476 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001477 return ActivityManager.START_TASK_TO_FRONT;
1478 }
1479 }
1480 }
1481 }
1482
1483 //String uri = r.intent.toURI();
1484 //Intent intent2 = new Intent(uri);
1485 //Slog.i(TAG, "Given intent: " + r.intent);
1486 //Slog.i(TAG, "URI is: " + uri);
1487 //Slog.i(TAG, "To intent: " + intent2);
1488
1489 if (r.packageName != null) {
1490 // If the activity being launched is the same as the one currently
1491 // at the top, then we need to check if it should only be launched
1492 // once.
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001493 ActivityStack topStack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001494 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001495 if (top != null && r.resultTo == null) {
1496 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1497 if (top.app != null && top.app.thread != null) {
1498 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1499 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1500 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1501 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1502 top.task);
1503 // For paranoia, make sure we have correctly
1504 // resumed the top activity.
1505 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001506 setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001507 resumeTopActivitiesLocked();
Craig Mautner8849a5e2013-04-02 16:41:03 -07001508 }
1509 ActivityOptions.abort(options);
1510 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1511 // We don't need to start a new activity, and
1512 // the client said not to do anything if that
1513 // is the case, so this is it!
Craig Mautner29219d92013-04-16 20:19:12 -07001514 if (r.task == null) Slog.v(TAG,
1515 "startActivityUncheckedLocked: task left null",
1516 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001517 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1518 }
1519 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner29219d92013-04-16 20:19:12 -07001520 if (r.task == null) Slog.v(TAG,
1521 "startActivityUncheckedLocked: task left null",
1522 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001523 return ActivityManager.START_DELIVERED_TO_TOP;
1524 }
1525 }
1526 }
1527 }
1528
1529 } else {
1530 if (r.resultTo != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001531 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1532 r.requestCode, Activity.RESULT_CANCELED, null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001533 }
1534 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001535 if (r.task == null) Slog.v(TAG,
1536 "startActivityUncheckedLocked: task left null",
1537 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001538 return ActivityManager.START_CLASS_NOT_FOUND;
1539 }
1540
1541 boolean newTask = false;
1542 boolean keepCurTransition = false;
1543
1544 // Should this be considered a new task?
1545 if (r.resultTo == null && !addingToTask
1546 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001547 targetStack = getCorrectStack(r);
1548 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001549 if (reuseTask == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001550 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1551 null, true);
1552 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1553 r.task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001554 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001555 r.setTask(reuseTask, reuseTask, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001556 }
1557 newTask = true;
1558 if (!movedHome) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001559 if ((launchFlags &
1560 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1561 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1562 // Caller wants to appear on home activity, so before starting
1563 // their own activity we will bring home to the front.
1564 r.mLaunchHomeTaskNext = true;
1565 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001566 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001567 } else if (sourceRecord != null) {
Craig Mautner525f3d92013-05-07 14:01:50 -07001568 sourceTask = sourceRecord.task;
1569 targetStack = sourceTask.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001570 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001571 if (!addingToTask &&
1572 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1573 // In this case, we are adding the activity to an existing
1574 // task, but the caller has asked to clear that task if the
1575 // activity is already running.
Craig Mautner525f3d92013-05-07 14:01:50 -07001576 ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001577 keepCurTransition = true;
1578 if (top != null) {
1579 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1580 top.deliverNewIntentLocked(callingUid, r.intent);
1581 // For paranoia, make sure we have correctly
1582 // resumed the top activity.
1583 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001584 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001585 targetStack.resumeTopActivityLocked(null);
1586 }
1587 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001588 if (r.task == null) Slog.v(TAG,
1589 "startActivityUncheckedLocked: task left null",
1590 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001591 return ActivityManager.START_DELIVERED_TO_TOP;
1592 }
1593 } else if (!addingToTask &&
1594 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1595 // In this case, we are launching an activity in our own task
1596 // that may already be running somewhere in the history, and
1597 // we want to shuffle it to the front of the stack if so.
Craig Mautner525f3d92013-05-07 14:01:50 -07001598 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001599 if (top != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001600 final TaskRecord task = top.task;
1601 task.moveActivityToFrontLocked(top);
1602 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001603 top.updateOptionsLocked(options);
1604 top.deliverNewIntentLocked(callingUid, r.intent);
1605 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001606 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001607 targetStack.resumeTopActivityLocked(null);
1608 }
Craig Mautner29219d92013-04-16 20:19:12 -07001609 if (r.task == null) Slog.v(TAG,
1610 "startActivityUncheckedLocked: task left null",
1611 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001612 return ActivityManager.START_DELIVERED_TO_TOP;
1613 }
1614 }
1615 // An existing activity is starting this new activity, so we want
1616 // to keep the new one in the same task as the one that is starting
1617 // it.
Craig Mautner525f3d92013-05-07 14:01:50 -07001618 r.setTask(sourceTask, sourceRecord.thumbHolder, false);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001619 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1620 + " in existing task " + r.task);
1621
1622 } else {
1623 // This not being started from an existing activity, and not part
1624 // of a new task... just put it in the top task, though these days
1625 // this case should never happen.
Craig Mautner1602ec22013-05-12 10:24:27 -07001626 targetStack = getCorrectStack(r);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001627 moveHomeStack(targetStack.isHomeStack());
Craig Mautner1602ec22013-05-12 10:24:27 -07001628 ActivityRecord prev = targetStack.topActivity();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001629 r.setTask(prev != null ? prev.task
1630 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1631 null, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001632 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1633 + " in new guessed " + r.task);
1634 }
1635
1636 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1637 intent, r.getUriPermissionsLocked());
1638
1639 if (newTask) {
1640 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1641 }
1642 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001643 setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001644 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
1645 return ActivityManager.START_SUCCESS;
1646 }
1647
Craig Mautnerf3333272013-04-22 10:55:53 -07001648 // Checked.
1649 final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
1650 Configuration config) {
1651 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
1652
1653 ActivityRecord res = null;
1654
1655 ArrayList<ActivityRecord> stops = null;
1656 ArrayList<ActivityRecord> finishes = null;
1657 ArrayList<UserStartedState> startingUsers = null;
1658 int NS = 0;
1659 int NF = 0;
1660 IApplicationThread sendThumbnail = null;
1661 boolean booting = false;
1662 boolean enableScreen = false;
1663 boolean activityRemoved = false;
1664
1665 ActivityRecord r = ActivityRecord.forToken(token);
1666 if (r != null) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07001667 if (DEBUG_IDLE) Slog.d(TAG, "activityIdleInternalLocked: Callers=" +
1668 Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07001669 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
1670 r.finishLaunchTickingLocked();
Craig Mautner525f3d92013-05-07 14:01:50 -07001671 res = r.task.stack.activityIdleInternalLocked(token);
Craig Mautnerf3333272013-04-22 10:55:53 -07001672 if (res != null) {
1673 if (fromTimeout) {
1674 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
1675 }
1676
1677 // This is a hack to semi-deal with a race condition
1678 // in the client where it can be constructed with a
1679 // newer configuration from when we asked it to launch.
1680 // We'll update with whatever configuration it now says
1681 // it used to launch.
1682 if (config != null) {
1683 r.configuration = config;
1684 }
1685
1686 // We are now idle. If someone is waiting for a thumbnail from
1687 // us, we can now deliver.
1688 r.idle = true;
1689 if (allResumedActivitiesIdle()) {
1690 mService.scheduleAppGcsLocked();
1691 }
1692 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
1693 sendThumbnail = r.app.thread;
1694 r.thumbnailNeeded = false;
1695 }
1696
1697 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
1698 if (!mService.mBooted && isFrontStack(r.task.stack)) {
1699 mService.mBooted = true;
1700 enableScreen = true;
1701 }
1702 } else if (fromTimeout) {
1703 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
1704 }
1705 }
1706
1707 // Atomically retrieve all of the other things to do.
1708 stops = processStoppingActivitiesLocked(true);
1709 NS = stops != null ? stops.size() : 0;
1710 if ((NF=mFinishingActivities.size()) > 0) {
1711 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
1712 mFinishingActivities.clear();
1713 }
1714
1715 final ArrayList<ActivityRecord> thumbnails;
1716 final int NT = mCancelledThumbnails.size();
1717 if (NT > 0) {
1718 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
1719 mCancelledThumbnails.clear();
1720 } else {
1721 thumbnails = null;
1722 }
1723
1724 if (isFrontStack(mHomeStack)) {
1725 booting = mService.mBooting;
1726 mService.mBooting = false;
1727 }
1728
1729 if (mStartingUsers.size() > 0) {
1730 startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
1731 mStartingUsers.clear();
1732 }
1733
1734 // Perform the following actions from unsynchronized state.
1735 final IApplicationThread thumbnailThread = sendThumbnail;
1736 mHandler.post(new Runnable() {
1737 @Override
1738 public void run() {
1739 if (thumbnailThread != null) {
1740 try {
1741 thumbnailThread.requestThumbnail(token);
1742 } catch (Exception e) {
1743 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
1744 mService.sendPendingThumbnail(null, token, null, null, true);
1745 }
1746 }
1747
1748 // Report back to any thumbnail receivers.
1749 for (int i = 0; i < NT; i++) {
1750 ActivityRecord r = thumbnails.get(i);
1751 mService.sendPendingThumbnail(r, null, null, null, true);
1752 }
1753 }
1754 });
1755
1756 // Stop any activities that are scheduled to do so but have been
1757 // waiting for the next one to start.
1758 for (int i = 0; i < NS; i++) {
1759 r = stops.get(i);
1760 final ActivityStack stack = r.task.stack;
1761 if (r.finishing) {
1762 stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
1763 } else {
1764 stack.stopActivityLocked(r);
1765 }
1766 }
1767
1768 // Finish any activities that are scheduled to do so but have been
1769 // waiting for the next one to start.
1770 for (int i = 0; i < NF; i++) {
1771 r = finishes.get(i);
1772 activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle");
1773 }
1774
1775 if (booting) {
1776 mService.finishBooting();
1777 } else if (startingUsers != null) {
1778 for (int i = 0; i < startingUsers.size(); i++) {
1779 mService.finishUserSwitch(startingUsers.get(i));
1780 }
1781 }
1782
1783 mService.trimApplications();
1784 //dump();
1785 //mWindowManager.dump();
1786
1787 if (enableScreen) {
1788 mService.enableScreenAfterBoot();
1789 }
1790
1791 if (activityRemoved) {
Craig Mautner05d29032013-05-03 13:40:13 -07001792 resumeTopActivitiesLocked();
Craig Mautnerf3333272013-04-22 10:55:53 -07001793 }
1794
1795 return res;
1796 }
1797
Craig Mautner8d341ef2013-03-26 09:03:27 -07001798 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
1799 // Just in case.
1800 final int numStacks = mStacks.size();
1801 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Craig Mautnere79d42682013-04-01 19:01:53 -07001802 mStacks.get(stackNdx).handleAppDiedLocked(app, restarting);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001803 }
1804 }
1805
1806 void closeSystemDialogsLocked() {
1807 final int numStacks = mStacks.size();
1808 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1809 final ActivityStack stack = mStacks.get(stackNdx);
1810 stack.closeSystemDialogsLocked();
1811 }
1812 }
1813
1814 /**
1815 * @return true if some activity was finished (or would have finished if doit were true).
1816 */
1817 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1818 boolean didSomething = false;
1819 final int numStacks = mStacks.size();
1820 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1821 final ActivityStack stack = mStacks.get(stackNdx);
1822 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1823 didSomething = true;
1824 }
1825 }
1826 return didSomething;
1827 }
1828
Craig Mautner05d29032013-05-03 13:40:13 -07001829 boolean resumeTopActivitiesLocked() {
1830 return resumeTopActivitiesLocked(null, null, null);
1831 }
1832
1833 boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
1834 Bundle targetOptions) {
1835 if (targetStack == null) {
1836 targetStack = getFocusedStack();
1837 }
1838 boolean result = false;
Craig Mautnerdbcb31f2013-04-02 12:32:53 -07001839 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001840 final ActivityStack stack = mStacks.get(stackNdx);
1841 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07001842 if (stack == targetStack) {
1843 result = stack.resumeTopActivityLocked(target, targetOptions);
1844 } else {
1845 stack.resumeTopActivityLocked(null);
1846 }
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001847 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001848 }
Craig Mautner05d29032013-05-03 13:40:13 -07001849 return result;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001850 }
1851
1852 void finishTopRunningActivityLocked(ProcessRecord app) {
1853 final int numStacks = mStacks.size();
1854 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1855 final ActivityStack stack = mStacks.get(stackNdx);
1856 stack.finishTopRunningActivityLocked(app);
1857 }
1858 }
1859
Craig Mautner8d341ef2013-03-26 09:03:27 -07001860 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
1861 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1862 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
1863 return;
1864 }
1865 }
1866 }
1867
Craig Mautner967212c2013-04-13 21:10:58 -07001868 ActivityStack getStack(int stackId) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001869 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1870 final ActivityStack stack = mStacks.get(stackNdx);
1871 if (stack.getStackId() == stackId) {
1872 return stack;
1873 }
1874 }
1875 return null;
1876 }
1877
Craig Mautner967212c2013-04-13 21:10:58 -07001878 ArrayList<ActivityStack> getStacks() {
1879 return new ArrayList<ActivityStack>(mStacks);
1880 }
1881
1882 int createStack() {
Craig Mautner858d8a62013-04-23 17:08:34 -07001883 while (true) {
1884 if (++mLastStackId <= HOME_STACK_ID) {
1885 mLastStackId = HOME_STACK_ID + 1;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001886 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001887 if (getStack(mLastStackId) == null) {
1888 break;
1889 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001890 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001891 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
1892 return mLastStackId;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001893 }
1894
1895 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
1896 final ActivityStack stack = getStack(stackId);
1897 if (stack == null) {
1898 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
1899 return;
1900 }
1901 stack.moveTask(taskId, toTop);
Craig Mautner05d29032013-05-03 13:40:13 -07001902 resumeTopActivitiesLocked();
Craig Mautner8d341ef2013-03-26 09:03:27 -07001903 }
1904
Craig Mautner8849a5e2013-04-02 16:41:03 -07001905 ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
1906 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1907 final ActivityRecord ar = mStacks.get(stackNdx).findTaskLocked(intent, info);
1908 if (ar != null) {
1909 return ar;
1910 }
1911 }
1912 return null;
1913 }
1914
1915 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
1916 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1917 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
1918 if (ar != null) {
1919 return ar;
1920 }
1921 }
1922 return null;
1923 }
1924
Craig Mautner8d341ef2013-03-26 09:03:27 -07001925 void goingToSleepLocked() {
Craig Mautner0eea92c2013-05-16 13:35:39 -07001926 scheduleSleepTimeout();
1927 if (!mGoingToSleep.isHeld()) {
1928 mGoingToSleep.acquire();
1929 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1930 final ActivityStack stack = mStacks.get(stackNdx);
1931 if (stack.mResumedActivity != null) {
1932 stack.stopIfSleepingLocked();
1933 }
1934 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001935 }
1936 }
1937
1938 boolean shutdownLocked(int timeout) {
1939 boolean timedout = false;
Craig Mautner0eea92c2013-05-16 13:35:39 -07001940 goingToSleepLocked();
1941 checkReadyForSleepLocked();
1942
1943 final long endTime = System.currentTimeMillis() + timeout;
1944 while (true) {
1945 boolean cantShutdown = false;
1946 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1947 cantShutdown |= mStacks.get(stackNdx).checkReadyForSleepLocked();
1948 }
1949 if (cantShutdown) {
1950 long timeRemaining = endTime - System.currentTimeMillis();
1951 if (timeRemaining > 0) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001952 try {
Craig Mautner0eea92c2013-05-16 13:35:39 -07001953 mService.wait(timeRemaining);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001954 } catch (InterruptedException e) {
1955 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07001956 } else {
1957 Slog.w(TAG, "Activity manager shutdown timed out");
1958 timedout = true;
1959 break;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001960 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07001961 } else {
1962 break;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001963 }
1964 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07001965
1966 // Force checkReadyForSleep to complete.
1967 mSleepTimeout = true;
1968 checkReadyForSleepLocked();
1969
Craig Mautner8d341ef2013-03-26 09:03:27 -07001970 return timedout;
1971 }
1972
1973 void comeOutOfSleepIfNeededLocked() {
Craig Mautner0eea92c2013-05-16 13:35:39 -07001974 removeSleepTimeouts();
1975 if (mGoingToSleep.isHeld()) {
1976 mGoingToSleep.release();
1977 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001978 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001979 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001980 stack.awakeFromSleepingLocked();
1981 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07001982 resumeTopActivitiesLocked();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001983 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001984 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07001985 mGoingToSleepActivities.clear();
1986 }
1987
1988 void activitySleptLocked(ActivityRecord r) {
1989 mGoingToSleepActivities.remove(r);
1990 checkReadyForSleepLocked();
1991 }
1992
1993 void checkReadyForSleepLocked() {
1994 if (!mService.isSleepingOrShuttingDown()) {
1995 // Do not care.
1996 return;
1997 }
1998
1999 if (!mSleepTimeout) {
2000 boolean dontSleep = false;
2001 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2002 dontSleep |= mStacks.get(stackNdx).checkReadyForSleepLocked();
2003 }
2004
2005 if (mStoppingActivities.size() > 0) {
2006 // Still need to tell some activities to stop; can't sleep yet.
2007 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
2008 + mStoppingActivities.size() + " activities");
2009 scheduleIdleLocked();
2010 dontSleep = true;
2011 }
2012
2013 if (mGoingToSleepActivities.size() > 0) {
2014 // Still need to tell some activities to sleep; can't sleep yet.
2015 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
2016 + mGoingToSleepActivities.size() + " activities");
2017 dontSleep = true;
2018 }
2019
2020 if (dontSleep) {
2021 return;
2022 }
2023 }
2024
2025 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2026 mStacks.get(stackNdx).goToSleep();
2027 }
2028
2029 removeSleepTimeouts();
2030
2031 if (mGoingToSleep.isHeld()) {
2032 mGoingToSleep.release();
2033 }
2034 if (mService.mShuttingDown) {
2035 mService.notifyAll();
2036 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002037 }
2038
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002039 boolean reportResumedActivityLocked(ActivityRecord r) {
2040 final ActivityStack stack = r.task.stack;
2041 if (isFrontStack(stack)) {
Jeff Sharkey5782da72013-04-25 14:32:30 -07002042 mService.updateUsageStats(r, true);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002043 mService.setFocusedActivityLocked(r);
2044 }
2045 if (allResumedActivitiesComplete()) {
2046 ensureActivitiesVisibleLocked(null, 0);
2047 mWindowManager.executeAppTransition();
2048 return true;
2049 }
2050 return false;
2051 }
2052
Craig Mautner8d341ef2013-03-26 09:03:27 -07002053 void handleAppCrashLocked(ProcessRecord app) {
2054 final int numStacks = mStacks.size();
2055 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2056 final ActivityStack stack = mStacks.get(stackNdx);
2057 stack.handleAppCrashLocked(app);
2058 }
2059 }
2060
Craig Mautnerde4ef022013-04-07 19:01:33 -07002061 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
Craig Mautner580ea812013-04-25 12:58:38 -07002062 // First the front stacks. In case any are not fullscreen and are in front of home.
2063 boolean showHomeBehindStack = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07002064 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner580ea812013-04-25 12:58:38 -07002065 final ActivityStack stack = mStacks.get(stackNdx);
2066 if (isFrontStack(stack)) {
2067 showHomeBehindStack =
2068 stack.ensureActivitiesVisibleLocked(starting, configChanges);
2069 }
2070 }
2071 // Now do back stacks.
2072 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2073 final ActivityStack stack = mStacks.get(stackNdx);
2074 if (!isFrontStack(stack)) {
2075 stack.ensureActivitiesVisibleLocked(starting, configChanges, showHomeBehindStack);
2076 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002077 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002078 }
2079
2080 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
2081 final int numStacks = mStacks.size();
2082 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2083 final ActivityStack stack = mStacks.get(stackNdx);
2084 stack.scheduleDestroyActivities(app, false, reason);
2085 }
2086 }
2087
2088 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner858d8a62013-04-23 17:08:34 -07002089 mUserStates.put(mCurrentUser, new UserState());
Craig Mautner2420ead2013-04-01 17:13:20 -07002090 mCurrentUser = userId;
Craig Mautner858d8a62013-04-23 17:08:34 -07002091 UserState userState = mUserStates.get(userId);
2092 if (userState != null) {
2093 userState.restore();
2094 mUserStates.delete(userId);
2095 } else {
2096 mFocusedStack = null;
Craig Mautner76ea2242013-05-15 11:40:05 -07002097 if (DEBUG_STACK) Slog.d(TAG, "switchUserLocked: mStackState=" +
2098 stackStateToString(STACK_STATE_HOME_IN_FRONT));
Craig Mautner858d8a62013-04-23 17:08:34 -07002099 mStackState = STACK_STATE_HOME_IN_FRONT;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002100 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002101
2102 mStartingUsers.add(uss);
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002103 boolean haveActivities = mHomeStack.switchUserLocked(userId);
Craig Mautner858d8a62013-04-23 17:08:34 -07002104
2105 resumeTopActivitiesLocked();
2106
Craig Mautner8d341ef2013-03-26 09:03:27 -07002107 return haveActivities;
Craig Mautner2219a1b2013-03-25 09:44:30 -07002108 }
2109
Craig Mautnerde4ef022013-04-07 19:01:33 -07002110 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
2111 int N = mStoppingActivities.size();
2112 if (N <= 0) return null;
2113
2114 ArrayList<ActivityRecord> stops = null;
2115
2116 final boolean nowVisible = allResumedActivitiesVisible();
2117 for (int i=0; i<N; i++) {
2118 ActivityRecord s = mStoppingActivities.get(i);
2119 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
2120 + nowVisible + " waitingVisible=" + s.waitingVisible
2121 + " finishing=" + s.finishing);
2122 if (s.waitingVisible && nowVisible) {
2123 mWaitingVisibleActivities.remove(s);
2124 s.waitingVisible = false;
2125 if (s.finishing) {
2126 // If this activity is finishing, it is sitting on top of
2127 // everyone else but we now know it is no longer needed...
2128 // so get rid of it. Otherwise, we need to go through the
2129 // normal flow and hide it once we determine that it is
2130 // hidden by the activities in front of it.
2131 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002132 mWindowManager.setAppVisibility(s.appToken, false);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002133 }
2134 }
2135 if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
2136 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
2137 if (stops == null) {
2138 stops = new ArrayList<ActivityRecord>();
2139 }
2140 stops.add(s);
2141 mStoppingActivities.remove(i);
2142 N--;
2143 i--;
2144 }
2145 }
2146
2147 return stops;
2148 }
2149
Craig Mautnercf910b02013-04-23 11:23:27 -07002150 void validateTopActivitiesLocked() {
2151 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2152 final ActivityStack stack = mStacks.get(stackNdx);
2153 final ActivityRecord r = stack.topRunningActivityLocked(null);
2154 if (isFrontStack(stack)) {
2155 if (r == null) {
2156 Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
2157 } else {
2158 if (stack.mPausingActivity != null) {
2159 Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
2160 " state=" + r.state);
2161 }
2162 if (r.state != ActivityState.INITIALIZING &&
2163 r.state != ActivityState.RESUMED) {
2164 Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
2165 " state=" + r.state);
2166 }
2167 }
2168 } else {
2169 if (stack.mResumedActivity != null) {
2170 Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
2171 " state=" + r.state);
2172 }
2173 if (r != null && (r.state == ActivityState.INITIALIZING
2174 || r.state == ActivityState.RESUMED)) {
2175 Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
2176 " state=" + r.state);
2177 }
2178 }
2179 }
2180 }
2181
Craig Mautner76ea2242013-05-15 11:40:05 -07002182 private static String stackStateToString(int stackState) {
2183 switch (stackState) {
2184 case STACK_STATE_HOME_IN_FRONT: return "STACK_STATE_HOME_IN_FRONT";
2185 case STACK_STATE_HOME_TO_BACK: return "STACK_STATE_HOME_TO_BACK";
2186 case STACK_STATE_HOME_IN_BACK: return "STACK_STATE_HOME_IN_BACK";
2187 case STACK_STATE_HOME_TO_FRONT: return "STACK_STATE_HOME_TO_FRONT";
2188 default: return "Unknown stackState=" + stackState;
2189 }
2190 }
2191
Craig Mautner27084302013-03-25 08:05:25 -07002192 public void dump(PrintWriter pw, String prefix) {
2193 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
2194 pw.println(mDismissKeyguardOnNextActivity);
Craig Mautner76ea2242013-05-15 11:40:05 -07002195 pw.print(prefix); pw.print("mStackState="); pw.println(stackStateToString(mStackState));
Craig Mautner27084302013-03-25 08:05:25 -07002196 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002197
Craig Mautner20e72272013-04-01 13:45:53 -07002198 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002199 return getFocusedStack().getDumpActivitiesLocked(name);
Craig Mautner20e72272013-04-01 13:45:53 -07002200 }
2201
Craig Mautner8d341ef2013-03-26 09:03:27 -07002202 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
2203 boolean dumpClient, String dumpPackage) {
Craig Mautner76ea2242013-05-15 11:40:05 -07002204 pw.print(" mStackState="); pw.println(stackStateToString(mStackState));
Craig Mautner0eea92c2013-05-16 13:35:39 -07002205 if (mGoingToSleepActivities.size() > 0) {
2206 pw.println(" Activities waiting to sleep:");
2207 dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll, false,
2208 dumpPackage);
2209 }
2210 if (dumpAll) {
2211 pw.println(" mSleepTimeout: " + mSleepTimeout);
2212 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002213 final int numStacks = mStacks.size();
2214 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2215 final ActivityStack stack = mStacks.get(stackNdx);
2216 pw.print(" Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
2217 stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
2218 pw.println(" ");
2219 pw.println(" Running activities (most recent first):");
2220 dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false,
2221 dumpPackage);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002222
Craig Mautner8d341ef2013-03-26 09:03:27 -07002223 pw.print(" Stack #"); pw.println(mStacks.indexOf(stack));
2224 if (stack.mPausingActivity != null) {
2225 pw.println(" mPausingActivity: " + stack.mPausingActivity);
2226 }
2227 pw.println(" mResumedActivity: " + stack.mResumedActivity);
2228 if (dumpAll) {
2229 pw.println(" mLastPausedActivity: " + stack.mLastPausedActivity);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002230 }
2231 }
2232
Craig Mautnerf3333272013-04-22 10:55:53 -07002233 if (mFinishingActivities.size() > 0) {
2234 pw.println(" ");
2235 pw.println(" Activities waiting to finish:");
2236 dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll, false,
2237 dumpPackage);
2238 }
2239
Craig Mautnerde4ef022013-04-07 19:01:33 -07002240 if (mStoppingActivities.size() > 0) {
2241 pw.println(" ");
2242 pw.println(" Activities waiting to stop:");
2243 dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, false,
2244 dumpPackage);
2245 }
2246
2247 if (mWaitingVisibleActivities.size() > 0) {
2248 pw.println(" ");
2249 pw.println(" Activities waiting for another to become visible:");
2250 dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
2251 false, dumpPackage);
2252 }
2253
Craig Mautner8d341ef2013-03-26 09:03:27 -07002254 if (dumpAll) {
2255 pw.println(" ");
2256 pw.println(" mCurTaskId: " + mCurTaskId);
2257 }
2258 return true;
2259 }
2260
Craig Mautner76ea2242013-05-15 11:40:05 -07002261 static void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
Craig Mautner8d341ef2013-03-26 09:03:27 -07002262 String prefix, String label, boolean complete, boolean brief, boolean client,
2263 String dumpPackage) {
2264 TaskRecord lastTask = null;
2265 boolean needNL = false;
2266 final String innerPrefix = prefix + " ";
2267 final String[] args = new String[0];
2268 for (int i=list.size()-1; i>=0; i--) {
2269 final ActivityRecord r = list.get(i);
2270 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
2271 continue;
2272 }
2273 final boolean full = !brief && (complete || !r.isInHistory());
2274 if (needNL) {
2275 pw.println(" ");
2276 needNL = false;
2277 }
2278 if (lastTask != r.task) {
2279 lastTask = r.task;
2280 pw.print(prefix);
2281 pw.print(full ? "* " : " ");
2282 pw.println(lastTask);
2283 if (full) {
2284 lastTask.dump(pw, prefix + " ");
2285 } else if (complete) {
2286 // Complete + brief == give a summary. Isn't that obvious?!?
2287 if (lastTask.intent != null) {
2288 pw.print(prefix); pw.print(" ");
2289 pw.println(lastTask.intent.toInsecureStringWithClip());
2290 }
2291 }
2292 }
2293 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
2294 pw.print(" #"); pw.print(i); pw.print(": ");
2295 pw.println(r);
2296 if (full) {
2297 r.dump(pw, innerPrefix);
2298 } else if (complete) {
2299 // Complete + brief == give a summary. Isn't that obvious?!?
2300 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
2301 if (r.app != null) {
2302 pw.print(innerPrefix); pw.println(r.app);
2303 }
2304 }
2305 if (client && r.app != null && r.app.thread != null) {
2306 // flush anything that is already in the PrintWriter since the thread is going
2307 // to write to the file descriptor directly
2308 pw.flush();
2309 try {
2310 TransferPipe tp = new TransferPipe();
2311 try {
2312 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
2313 r.appToken, innerPrefix, args);
2314 // Short timeout, since blocking here can
2315 // deadlock with the application.
2316 tp.go(fd, 2000);
2317 } finally {
2318 tp.kill();
2319 }
2320 } catch (IOException e) {
2321 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
2322 } catch (RemoteException e) {
2323 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
2324 }
2325 needNL = true;
2326 }
2327 }
2328 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002329
Craig Mautnerf3333272013-04-22 10:55:53 -07002330 void scheduleIdleTimeoutLocked(ActivityRecord next) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002331 if (DEBUG_IDLE) Slog.d(TAG, "scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4));
Craig Mautnerc64f73e2013-04-24 16:44:56 -07002332 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
2333 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
Craig Mautnerf3333272013-04-22 10:55:53 -07002334 }
2335
2336 final void scheduleIdleLocked() {
Craig Mautner05d29032013-05-03 13:40:13 -07002337 mHandler.sendEmptyMessage(IDLE_NOW_MSG);
Craig Mautnerf3333272013-04-22 10:55:53 -07002338 }
2339
2340 void removeTimeoutsForActivityLocked(ActivityRecord r) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002341 if (DEBUG_IDLE) Slog.d(TAG, "removeTimeoutsForActivity: Callers=" + Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07002342 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
2343 }
2344
Craig Mautner05d29032013-05-03 13:40:13 -07002345 final void scheduleResumeTopActivities() {
2346 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2347 }
2348
Craig Mautner0eea92c2013-05-16 13:35:39 -07002349 void removeSleepTimeouts() {
2350 mSleepTimeout = false;
2351 mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
2352 }
2353
2354 final void scheduleSleepTimeout() {
2355 removeSleepTimeouts();
2356 mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT);
2357 }
2358
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002359 private final class ActivityStackSupervisorHandler extends Handler {
Craig Mautnerf3333272013-04-22 10:55:53 -07002360
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002361 public ActivityStackSupervisorHandler(Looper looper) {
2362 super(looper);
2363 }
2364
Craig Mautnerf3333272013-04-22 10:55:53 -07002365 void activityIdleInternal(ActivityRecord r) {
2366 synchronized (mService) {
2367 activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
2368 }
2369 }
2370
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002371 @Override
2372 public void handleMessage(Message msg) {
2373 switch (msg.what) {
Craig Mautnerf3333272013-04-22 10:55:53 -07002374 case IDLE_TIMEOUT_MSG: {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002375 if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_TIMEOUT_MSG: Callers=" +
2376 Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07002377 if (mService.mDidDexOpt) {
2378 mService.mDidDexOpt = false;
2379 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2380 nmsg.obj = msg.obj;
2381 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
2382 return;
2383 }
2384 // We don't at this point know if the activity is fullscreen,
2385 // so we need to be conservative and assume it isn't.
2386 activityIdleInternal((ActivityRecord)msg.obj);
2387 } break;
2388 case IDLE_NOW_MSG: {
2389 activityIdleInternal((ActivityRecord)msg.obj);
2390 } break;
Craig Mautner05d29032013-05-03 13:40:13 -07002391 case RESUME_TOP_ACTIVITY_MSG: {
2392 synchronized (mService) {
2393 resumeTopActivitiesLocked();
2394 }
2395 } break;
Craig Mautner0eea92c2013-05-16 13:35:39 -07002396 case SLEEP_TIMEOUT_MSG: {
2397 synchronized (mService) {
2398 if (mService.isSleepingOrShuttingDown()) {
2399 Slog.w(TAG, "Sleep timeout! Sleeping now.");
2400 mSleepTimeout = true;
2401 checkReadyForSleepLocked();
2402 }
2403 }
2404 } break;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002405 }
2406 }
2407 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002408
2409 private final class UserState {
2410 final ActivityStack mSavedFocusedStack;
2411 final int mSavedStackState;
2412
2413 public UserState() {
2414 ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2415 mSavedFocusedStack = supervisor.mFocusedStack;
2416 mSavedStackState = supervisor.mStackState;
2417 }
2418
2419 void restore() {
2420 ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2421 supervisor.mFocusedStack = mSavedFocusedStack;
Craig Mautner76ea2242013-05-15 11:40:05 -07002422 if (DEBUG_STACK) Slog.d(TAG, "UserState.restore: mStackState old=" +
2423 stackStateToString(mSavedStackState));
Craig Mautner858d8a62013-04-23 17:08:34 -07002424 supervisor.mStackState = mSavedStackState;
2425 }
2426 }
Craig Mautner27084302013-03-25 08:05:25 -07002427}