blob: 483b4a04390e086630510360ea29bb3f18e0c57e [file] [log] [blame]
Craig Mautner27084302013-03-25 08:05:25 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Craig Mautner6170f732013-04-02 13:05:23 -070019import static android.Manifest.permission.START_ANY_ACTIVITY;
Craig Mautner29219d92013-04-16 20:19:12 -070020import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
21import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Craig Mautner6170f732013-04-02 13:05:23 -070022import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Craig Mautner2420ead2013-04-01 17:13:20 -070023import static com.android.server.am.ActivityManagerService.localLOGV;
Craig Mautner23ac33b2013-04-01 16:26:35 -070024import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION;
Craig Mautnere7c58b62013-06-12 20:19:00 -070025import static com.android.server.am.ActivityManagerService.DEBUG_FOCUS;
Craig Mautner0eea92c2013-05-16 13:35:39 -070026import static com.android.server.am.ActivityManagerService.DEBUG_PAUSE;
Craig Mautner6170f732013-04-02 13:05:23 -070027import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
Craig Mautner0eea92c2013-05-16 13:35:39 -070028import static com.android.server.am.ActivityManagerService.DEBUG_STACK;
Craig Mautner2420ead2013-04-01 17:13:20 -070029import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
Craig Mautner8849a5e2013-04-02 16:41:03 -070030import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
31import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
Craig Mautner05d29032013-05-03 13:40:13 -070032import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
Craig Mautner8d341ef2013-03-26 09:03:27 -070033import static com.android.server.am.ActivityManagerService.TAG;
34
Craig Mautner2420ead2013-04-01 17:13:20 -070035import android.app.Activity;
Craig Mautner23ac33b2013-04-01 16:26:35 -070036import android.app.ActivityManager;
37import android.app.ActivityOptions;
38import android.app.AppGlobals;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070039import android.app.IActivityManager;
Craig Mautner23ac33b2013-04-01 16:26:35 -070040import android.app.IApplicationThread;
Craig Mautner20e72272013-04-01 13:45:53 -070041import android.app.IThumbnailReceiver;
Craig Mautner23ac33b2013-04-01 16:26:35 -070042import android.app.PendingIntent;
Craig Mautner20e72272013-04-01 13:45:53 -070043import android.app.ActivityManager.RunningTaskInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070044import android.app.IActivityManager.WaitResult;
Craig Mautner2420ead2013-04-01 17:13:20 -070045import android.app.ResultInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070046import android.content.ComponentName;
Craig Mautner2219a1b2013-03-25 09:44:30 -070047import android.content.Context;
Craig Mautner23ac33b2013-04-01 16:26:35 -070048import android.content.IIntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070049import android.content.Intent;
Craig Mautner23ac33b2013-04-01 16:26:35 -070050import android.content.IntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070051import android.content.pm.ActivityInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070052import android.content.pm.ApplicationInfo;
53import android.content.pm.PackageManager;
54import android.content.pm.ResolveInfo;
55import android.content.res.Configuration;
56import android.os.Binder;
Craig Mautner8d341ef2013-03-26 09:03:27 -070057import android.os.Bundle;
Craig Mautnerb59dcfd2013-05-06 13:12:58 -070058import android.os.Debug;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070059import android.os.Handler;
Craig Mautner23ac33b2013-04-01 16:26:35 -070060import android.os.IBinder;
Craig Mautner2219a1b2013-03-25 09:44:30 -070061import android.os.Looper;
Craig Mautner2420ead2013-04-01 17:13:20 -070062import android.os.Message;
Craig Mautner23ac33b2013-04-01 16:26:35 -070063import android.os.ParcelFileDescriptor;
Craig Mautner0eea92c2013-05-16 13:35:39 -070064import android.os.PowerManager;
Craig Mautner7ea5bd42013-07-05 15:27:08 -070065import android.os.Process;
Craig Mautner8d341ef2013-03-26 09:03:27 -070066import android.os.RemoteException;
Craig Mautner23ac33b2013-04-01 16:26:35 -070067import android.os.SystemClock;
Craig Mautner6170f732013-04-02 13:05:23 -070068import android.os.UserHandle;
Craig Mautner2420ead2013-04-01 17:13:20 -070069import android.util.EventLog;
Craig Mautner8d341ef2013-03-26 09:03:27 -070070import android.util.Slog;
Craig Mautner4f1df4f2013-10-15 15:44:14 -070071import android.util.SparseIntArray;
Craig Mautner2219a1b2013-03-25 09:44:30 -070072
Craig Mautner23ac33b2013-04-01 16:26:35 -070073import com.android.internal.app.HeavyWeightSwitcherActivity;
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070074import com.android.internal.os.TransferPipe;
Craig Mautner6170f732013-04-02 13:05:23 -070075import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
Craig Mautner2420ead2013-04-01 17:13:20 -070076import com.android.server.am.ActivityStack.ActivityState;
Craig Mautnerde4ef022013-04-07 19:01:33 -070077import com.android.server.wm.StackBox;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070078import com.android.server.wm.WindowManagerService;
Craig Mautner23ac33b2013-04-01 16:26:35 -070079
Craig Mautner8d341ef2013-03-26 09:03:27 -070080import java.io.FileDescriptor;
81import java.io.IOException;
Craig Mautner27084302013-03-25 08:05:25 -070082import java.io.PrintWriter;
Craig Mautner2219a1b2013-03-25 09:44:30 -070083import java.util.ArrayList;
Craig Mautner8d341ef2013-03-26 09:03:27 -070084import java.util.List;
Craig Mautner27084302013-03-25 08:05:25 -070085
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070086public final class ActivityStackSupervisor {
Craig Mautnerde4ef022013-04-07 19:01:33 -070087 static final boolean DEBUG = ActivityManagerService.DEBUG || false;
88 static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
89 static final boolean DEBUG_APP = DEBUG || false;
90 static final boolean DEBUG_SAVED_STATE = DEBUG || false;
Craig Mautnera7f2bd42013-10-15 16:13:50 -070091 static final boolean DEBUG_STATES = DEBUG || false;
Craig Mautnerb59dcfd2013-05-06 13:12:58 -070092 static final boolean DEBUG_IDLE = DEBUG || false;
Craig Mautner2420ead2013-04-01 17:13:20 -070093
Craig Mautner2219a1b2013-03-25 09:44:30 -070094 public static final int HOME_STACK_ID = 0;
Craig Mautner27084302013-03-25 08:05:25 -070095
Craig Mautnerf3333272013-04-22 10:55:53 -070096 /** How long we wait until giving up on the last activity telling us it is idle. */
97 static final int IDLE_TIMEOUT = 10*1000;
98
Craig Mautner0eea92c2013-05-16 13:35:39 -070099 /** How long we can hold the sleep wake lock before giving up. */
100 static final int SLEEP_TIMEOUT = 5*1000;
101
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700102 // How long we can hold the launch wake lock before giving up.
103 static final int LAUNCH_TIMEOUT = 10*1000;
104
Craig Mautner05d29032013-05-03 13:40:13 -0700105 static final int IDLE_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG;
106 static final int IDLE_NOW_MSG = FIRST_SUPERVISOR_STACK_MSG + 1;
107 static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2;
Craig Mautner0eea92c2013-05-16 13:35:39 -0700108 static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3;
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700109 static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 4;
110
111 // For debugging to make sure the caller when acquiring/releasing our
112 // wake lock is the system process.
113 static final boolean VALIDATE_WAKE_LOCK_CALLER = false;
Craig Mautnerf3333272013-04-22 10:55:53 -0700114
Craig Mautner27084302013-03-25 08:05:25 -0700115 final ActivityManagerService mService;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700116 final Context mContext;
117 final Looper mLooper;
Craig Mautner27084302013-03-25 08:05:25 -0700118
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700119 final ActivityStackSupervisorHandler mHandler;
120
121 /** Short cut */
122 WindowManagerService mWindowManager;
123
Craig Mautner27084302013-03-25 08:05:25 -0700124 /** Dismiss the keyguard after the next activity is displayed? */
Craig Mautner5314a402013-09-26 12:40:16 -0700125 boolean mDismissKeyguardOnNextActivity = false;
Craig Mautner27084302013-03-25 08:05:25 -0700126
Craig Mautner8d341ef2013-03-26 09:03:27 -0700127 /** Identifier counter for all ActivityStacks */
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700128 private int mLastStackId = HOME_STACK_ID;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700129
130 /** Task identifier that activities are currently being started in. Incremented each time a
131 * new task is created. */
132 private int mCurTaskId = 0;
133
Craig Mautner2420ead2013-04-01 17:13:20 -0700134 /** The current user */
135 private int mCurrentUser;
136
Craig Mautner8d341ef2013-03-26 09:03:27 -0700137 /** The stack containing the launcher app */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700138 private ActivityStack mHomeStack;
Craig Mautner20e72272013-04-01 13:45:53 -0700139
Craig Mautnerde4ef022013-04-07 19:01:33 -0700140 /** The non-home stack currently receiving input or launching the next activity. If home is
Craig Mautner41c0f352013-05-28 08:39:25 -0700141 * in front then mHomeStack overrides mFocusedStack.
142 * DO NOT ACCESS DIRECTLY - It may be null, use getFocusedStack() */
Craig Mautner29219d92013-04-16 20:19:12 -0700143 private ActivityStack mFocusedStack;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700144
145 /** All the non-launcher stacks */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700146 private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
147
Craig Mautnerde4ef022013-04-07 19:01:33 -0700148 private static final int STACK_STATE_HOME_IN_FRONT = 0;
149 private static final int STACK_STATE_HOME_TO_BACK = 1;
150 private static final int STACK_STATE_HOME_IN_BACK = 2;
151 private static final int STACK_STATE_HOME_TO_FRONT = 3;
152 private int mStackState = STACK_STATE_HOME_IN_FRONT;
153
154 /** List of activities that are waiting for a new activity to become visible before completing
155 * whatever operation they are supposed to do. */
156 final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();
157
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700158 /** List of processes waiting to find out about the next visible activity. */
159 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible =
160 new ArrayList<IActivityManager.WaitResult>();
161
162 /** List of processes waiting to find out about the next launched activity. */
163 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched =
164 new ArrayList<IActivityManager.WaitResult>();
165
Craig Mautnerde4ef022013-04-07 19:01:33 -0700166 /** List of activities that are ready to be stopped, but waiting for the next activity to
167 * settle down before doing so. */
168 final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();
169
Craig Mautnerf3333272013-04-22 10:55:53 -0700170 /** List of activities that are ready to be finished, but waiting for the previous activity to
171 * settle down before doing so. It contains ActivityRecord objects. */
172 final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<ActivityRecord>();
173
Craig Mautner0eea92c2013-05-16 13:35:39 -0700174 /** List of activities that are in the process of going to sleep. */
175 final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<ActivityRecord>();
176
Craig Mautnerf3333272013-04-22 10:55:53 -0700177 /** List of ActivityRecord objects that have been finished and must still report back to a
178 * pending thumbnail receiver. */
179 final ArrayList<ActivityRecord> mCancelledThumbnails = new ArrayList<ActivityRecord>();
180
181 /** Used on user changes */
182 final ArrayList<UserStartedState> mStartingUsers = new ArrayList<UserStartedState>();
183
Craig Mautnerde4ef022013-04-07 19:01:33 -0700184 /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity
185 * is being brought in front of us. */
186 boolean mUserLeaving = false;
187
Craig Mautner0eea92c2013-05-16 13:35:39 -0700188 /** Set when we have taken too long waiting to go to sleep. */
189 boolean mSleepTimeout = false;
190
191 /**
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700192 * We don't want to allow the device to go to sleep while in the process
193 * of launching an activity. This is primarily to allow alarm intent
194 * receivers to launch an activity and get that to run before the device
195 * goes back to sleep.
196 */
197 final PowerManager.WakeLock mLaunchingActivity;
198
199 /**
Craig Mautner0eea92c2013-05-16 13:35:39 -0700200 * Set when the system is going to sleep, until we have
201 * successfully paused the current activity and released our wake lock.
202 * At that point the system is allowed to actually sleep.
203 */
204 final PowerManager.WakeLock mGoingToSleep;
205
Craig Mautner4f1df4f2013-10-15 15:44:14 -0700206 /** Stack id of the front stack when user switched, indexed by userId. */
207 SparseIntArray mUserStackInFront = new SparseIntArray(2);
Craig Mautner93529a42013-10-04 15:03:13 -0700208
Craig Mautner2219a1b2013-03-25 09:44:30 -0700209 public ActivityStackSupervisor(ActivityManagerService service, Context context,
210 Looper looper) {
Craig Mautner27084302013-03-25 08:05:25 -0700211 mService = service;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700212 mContext = context;
213 mLooper = looper;
Craig Mautner0eea92c2013-05-16 13:35:39 -0700214 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
215 mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700216 mHandler = new ActivityStackSupervisorHandler(looper);
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700217 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
218 throw new IllegalStateException("Calling must be system uid");
219 }
220 mLaunchingActivity =
221 pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
222 mLaunchingActivity.setReferenceCounted(false);
Craig Mautner2219a1b2013-03-25 09:44:30 -0700223 }
224
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700225 void setWindowManager(WindowManagerService wm) {
226 mWindowManager = wm;
227 mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700228 mStacks.add(mHomeStack);
Craig Mautner27084302013-03-25 08:05:25 -0700229 }
230
231 void dismissKeyguard() {
Craig Mautner5314a402013-09-26 12:40:16 -0700232 if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
Craig Mautner27084302013-03-25 08:05:25 -0700233 if (mDismissKeyguardOnNextActivity) {
234 mDismissKeyguardOnNextActivity = false;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700235 mWindowManager.dismissKeyguard();
Craig Mautner27084302013-03-25 08:05:25 -0700236 }
237 }
238
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700239 ActivityStack getFocusedStack() {
Craig Mautnerf88c50f2013-04-18 19:25:12 -0700240 if (mFocusedStack == null) {
241 return mHomeStack;
242 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700243 switch (mStackState) {
244 case STACK_STATE_HOME_IN_FRONT:
245 case STACK_STATE_HOME_TO_FRONT:
246 return mHomeStack;
247 case STACK_STATE_HOME_IN_BACK:
248 case STACK_STATE_HOME_TO_BACK:
249 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700250 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700251 }
Craig Mautner20e72272013-04-01 13:45:53 -0700252 }
253
Craig Mautnerde4ef022013-04-07 19:01:33 -0700254 ActivityStack getLastStack() {
255 switch (mStackState) {
256 case STACK_STATE_HOME_IN_FRONT:
257 case STACK_STATE_HOME_TO_BACK:
258 return mHomeStack;
259 case STACK_STATE_HOME_TO_FRONT:
260 case STACK_STATE_HOME_IN_BACK:
261 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700262 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700263 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700264 }
265
Craig Mautnerde4ef022013-04-07 19:01:33 -0700266 boolean isFrontStack(ActivityStack stack) {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700267 return !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
Craig Mautner20e72272013-04-01 13:45:53 -0700268 }
269
Craig Mautnerde4ef022013-04-07 19:01:33 -0700270 void moveHomeStack(boolean toFront) {
271 final boolean homeInFront = isFrontStack(mHomeStack);
272 if (homeInFront ^ toFront) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700273 if (DEBUG_STACK) Slog.d(TAG, "moveHomeTask: mStackState old=" +
274 stackStateToString(mStackState) + " new=" + stackStateToString(homeInFront ?
275 STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700276 mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
277 }
278 }
279
Craig Mautner8e569572013-10-11 17:36:59 -0700280 void moveHomeToTop() {
Craig Mautner69ada552013-04-18 13:51:51 -0700281 moveHomeStack(true);
Craig Mautner8e569572013-10-11 17:36:59 -0700282 mHomeStack.moveHomeTaskToTop();
283 }
284
285 boolean resumeHomeActivity(ActivityRecord prev) {
286 moveHomeToTop();
Craig Mautner69ada552013-04-18 13:51:51 -0700287 if (prev != null) {
Craig Mautnerae7ecab2013-09-18 11:48:14 -0700288 prev.task.mOnTopOfHome = false;
Craig Mautner69ada552013-04-18 13:51:51 -0700289 }
Craig Mautnera8a90e02013-06-28 15:24:50 -0700290 ActivityRecord r = mHomeStack.topRunningActivityLocked(null);
Craig Mautner760b2312013-10-11 11:57:07 -0700291 if (r != null && r.isHomeActivity()) {
Craig Mautnera8a90e02013-06-28 15:24:50 -0700292 mService.setFocusedActivityLocked(r);
Craig Mautner05d29032013-05-03 13:40:13 -0700293 return resumeTopActivitiesLocked(mHomeStack, prev, null);
Craig Mautner69ada552013-04-18 13:51:51 -0700294 }
295 return mService.startHomeActivityLocked(mCurrentUser);
296 }
297
Craig Mautner27084302013-03-25 08:05:25 -0700298 void setDismissKeyguard(boolean dismiss) {
Craig Mautner5314a402013-09-26 12:40:16 -0700299 if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen(" dismiss=" + dismiss);
Craig Mautner27084302013-03-25 08:05:25 -0700300 mDismissKeyguardOnNextActivity = dismiss;
301 }
302
Craig Mautner8d341ef2013-03-26 09:03:27 -0700303 TaskRecord anyTaskForIdLocked(int id) {
304 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
305 ActivityStack stack = mStacks.get(stackNdx);
306 TaskRecord task = stack.taskForIdLocked(id);
307 if (task != null) {
308 return task;
309 }
310 }
311 return null;
312 }
313
Craig Mautner6170f732013-04-02 13:05:23 -0700314 ActivityRecord isInAnyStackLocked(IBinder token) {
315 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
316 final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
317 if (r != null) {
318 return r;
319 }
320 }
321 return null;
322 }
323
Craig Mautner8d341ef2013-03-26 09:03:27 -0700324 int getNextTaskId() {
325 do {
326 mCurTaskId++;
327 if (mCurTaskId <= 0) {
328 mCurTaskId = 1;
329 }
330 } while (anyTaskForIdLocked(mCurTaskId) != null);
331 return mCurTaskId;
332 }
333
Craig Mautnerde4ef022013-04-07 19:01:33 -0700334 void removeTask(TaskRecord task) {
Craig Mautnerb3b36ba2013-05-20 13:21:10 -0700335 mWindowManager.removeTask(task.taskId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700336 final ActivityStack stack = task.stack;
Craig Mautnerb3b36ba2013-05-20 13:21:10 -0700337 final ActivityRecord r = stack.mResumedActivity;
338 if (r != null && r.task == task) {
339 stack.mResumedActivity = null;
340 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700341 if (stack.removeTask(task) && !stack.isHomeStack()) {
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700342 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700343 mStacks.remove(stack);
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700344 final int stackId = stack.mStackId;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700345 final int nextStackId = mWindowManager.removeStack(stackId);
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700346 // TODO: Perhaps we need to let the ActivityManager determine the next focus...
Craig Mautnerac6f8432013-07-17 13:24:59 -0700347 if (mFocusedStack == null || mFocusedStack.mStackId == stackId) {
Craig Mautner1602ec22013-05-12 10:24:27 -0700348 // If this is the last app stack, set mFocusedStack to null.
Craig Mautner29219d92013-04-16 20:19:12 -0700349 mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700350 }
351 }
352 }
353
354 ActivityRecord resumedAppLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700355 ActivityStack stack = getFocusedStack();
356 if (stack == null) {
357 return null;
358 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700359 ActivityRecord resumedActivity = stack.mResumedActivity;
360 if (resumedActivity == null || resumedActivity.app == null) {
361 resumedActivity = stack.mPausingActivity;
362 if (resumedActivity == null || resumedActivity.app == null) {
363 resumedActivity = stack.topRunningActivityLocked(null);
364 }
365 }
366 return resumedActivity;
367 }
368
Craig Mautner20e72272013-04-01 13:45:53 -0700369 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
370 boolean didSomething = false;
371 final String processName = app.processName;
372 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
373 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner858d8a62013-04-23 17:08:34 -0700374 if (!isFrontStack(stack)) {
375 continue;
376 }
Craig Mautner20e72272013-04-01 13:45:53 -0700377 ActivityRecord hr = stack.topRunningActivityLocked(null);
378 if (hr != null) {
379 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
380 && processName.equals(hr.processName)) {
381 try {
382 if (headless) {
383 Slog.e(TAG, "Starting activities not supported on headless device: "
384 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700385 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700386 didSomething = true;
387 }
388 } catch (Exception e) {
389 Slog.w(TAG, "Exception in new application when starting activity "
390 + hr.intent.getComponent().flattenToShortString(), e);
391 throw e;
392 }
Craig Mautner20e72272013-04-01 13:45:53 -0700393 }
394 }
395 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -0700396 if (!didSomething) {
397 ensureActivitiesVisibleLocked(null, 0);
398 }
Craig Mautner20e72272013-04-01 13:45:53 -0700399 return didSomething;
400 }
401
402 boolean allResumedActivitiesIdle() {
403 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700404 final ActivityStack stack = mStacks.get(stackNdx);
405 if (!isFrontStack(stack)) {
406 continue;
407 }
408 final ActivityRecord resumedActivity = stack.mResumedActivity;
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700409 if (resumedActivity == null || !resumedActivity.idle) {
Craig Mautner20e72272013-04-01 13:45:53 -0700410 return false;
411 }
412 }
413 return true;
414 }
415
Craig Mautnerde4ef022013-04-07 19:01:33 -0700416 boolean allResumedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700417 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
418 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner967212c2013-04-13 21:10:58 -0700419 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700420 final ActivityRecord r = stack.mResumedActivity;
421 if (r != null && r.state != ActivityState.RESUMED) {
422 return false;
423 }
424 }
425 }
426 // TODO: Not sure if this should check if all Paused are complete too.
427 switch (mStackState) {
428 case STACK_STATE_HOME_TO_BACK:
Craig Mautner76ea2242013-05-15 11:40:05 -0700429 if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
430 stackStateToString(STACK_STATE_HOME_TO_BACK) + " new=" +
431 stackStateToString(STACK_STATE_HOME_IN_BACK));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700432 mStackState = STACK_STATE_HOME_IN_BACK;
433 break;
434 case STACK_STATE_HOME_TO_FRONT:
Craig Mautner76ea2242013-05-15 11:40:05 -0700435 if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
436 stackStateToString(STACK_STATE_HOME_TO_FRONT) + " new=" +
437 stackStateToString(STACK_STATE_HOME_IN_FRONT));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700438 mStackState = STACK_STATE_HOME_IN_FRONT;
439 break;
440 }
441 return true;
442 }
443
444 boolean allResumedActivitiesVisible() {
445 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
446 final ActivityStack stack = mStacks.get(stackNdx);
447 final ActivityRecord r = stack.mResumedActivity;
448 if (r != null && (!r.nowVisible || r.waitingVisible)) {
449 return false;
450 }
451 }
452 return true;
453 }
454
Craig Mautner2acc3892013-09-23 10:28:14 -0700455 /**
456 * Pause all activities in either all of the stacks or just the back stacks.
457 * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
Craig Mautner2acc3892013-09-23 10:28:14 -0700458 * @return true if any activity was paused as a result of this call.
459 */
Craig Mautner5314a402013-09-26 12:40:16 -0700460 boolean pauseBackStacks(boolean userLeaving) {
Craig Mautnercf910b02013-04-23 11:23:27 -0700461 boolean someActivityPaused = false;
462 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
463 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner5314a402013-09-26 12:40:16 -0700464 if (!isFrontStack(stack) && stack.mResumedActivity != null) {
465 if (DEBUG_STATES) Slog.d(TAG, "pauseBackStacks: stack=" + stack +
Craig Mautnerac6f8432013-07-17 13:24:59 -0700466 " mResumedActivity=" + stack.mResumedActivity);
Craig Mautnercf910b02013-04-23 11:23:27 -0700467 stack.startPausingLocked(userLeaving, false);
468 someActivityPaused = true;
469 }
470 }
471 return someActivityPaused;
472 }
473
Craig Mautnerde4ef022013-04-07 19:01:33 -0700474 boolean allPausedActivitiesComplete() {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700475 boolean pausing = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700476 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
477 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner69ada552013-04-18 13:51:51 -0700478 final ActivityRecord r = stack.mPausingActivity;
479 if (r != null && r.state != ActivityState.PAUSED
480 && r.state != ActivityState.STOPPED
481 && r.state != ActivityState.STOPPING) {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700482 if (DEBUG_STATES) {
483 Slog.d(TAG, "allPausedActivitiesComplete: r=" + r + " state=" + r.state);
484 pausing = false;
485 } else {
486 return false;
487 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700488 }
489 }
Craig Mautnerac6f8432013-07-17 13:24:59 -0700490 return pausing;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700491 }
492
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700493 void reportActivityVisibleLocked(ActivityRecord r) {
Craig Mautner858d8a62013-04-23 17:08:34 -0700494 for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700495 WaitResult w = mWaitingActivityVisible.get(i);
496 w.timeout = false;
497 if (r != null) {
498 w.who = new ComponentName(r.info.packageName, r.info.name);
499 }
500 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
501 w.thisTime = w.totalTime;
502 }
503 mService.notifyAll();
504 dismissKeyguard();
505 }
506
507 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
508 long thisTime, long totalTime) {
509 for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
Craig Mautnerc64f73e2013-04-24 16:44:56 -0700510 WaitResult w = mWaitingActivityLaunched.remove(i);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700511 w.timeout = timeout;
512 if (r != null) {
513 w.who = new ComponentName(r.info.packageName, r.info.name);
514 }
515 w.thisTime = thisTime;
516 w.totalTime = totalTime;
517 }
518 mService.notifyAll();
519 }
520
Craig Mautner29219d92013-04-16 20:19:12 -0700521 ActivityRecord topRunningActivityLocked() {
Craig Mautner1602ec22013-05-12 10:24:27 -0700522 final ActivityStack focusedStack = getFocusedStack();
523 ActivityRecord r = focusedStack.topRunningActivityLocked(null);
524 if (r != null) {
525 return r;
Craig Mautner29219d92013-04-16 20:19:12 -0700526 }
Craig Mautner1602ec22013-05-12 10:24:27 -0700527
Craig Mautner29219d92013-04-16 20:19:12 -0700528 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
529 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700530 if (stack != focusedStack && isFrontStack(stack)) {
Craig Mautner29219d92013-04-16 20:19:12 -0700531 r = stack.topRunningActivityLocked(null);
532 if (r != null) {
533 return r;
534 }
535 }
536 }
537 return null;
538 }
539
Craig Mautner20e72272013-04-01 13:45:53 -0700540 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
541 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
542 ActivityRecord r = null;
Craig Mautnerc0fd8052013-09-19 11:20:17 -0700543
544 // Gather all of the running tasks for each stack into runningTaskLists.
545 final int numStacks = mStacks.size();
546 ArrayList<RunningTaskInfo>[] runningTaskLists = new ArrayList[numStacks];
547 for (int stackNdx = numStacks - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner20e72272013-04-01 13:45:53 -0700548 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerc0fd8052013-09-19 11:20:17 -0700549 ArrayList<RunningTaskInfo> stackTaskList = new ArrayList<RunningTaskInfo>();
550 runningTaskLists[stackNdx] = stackTaskList;
551 final ActivityRecord ar = stack.getTasksLocked(receiver, pending, stackTaskList);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700552 if (isFrontStack(stack)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700553 r = ar;
554 }
555 }
Craig Mautnerc0fd8052013-09-19 11:20:17 -0700556
557 // The lists are already sorted from most recent to oldest. Just pull the most recent off
558 // each list and add it to list. Stop when all lists are empty or maxNum reached.
559 while (maxNum > 0) {
560 long mostRecentActiveTime = Long.MIN_VALUE;
561 ArrayList<RunningTaskInfo> selectedStackList = null;
562 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
563 ArrayList<RunningTaskInfo> stackTaskList = runningTaskLists[stackNdx];
564 if (!stackTaskList.isEmpty()) {
565 final long lastActiveTime = stackTaskList.get(0).lastActiveTime;
566 if (lastActiveTime > mostRecentActiveTime) {
567 mostRecentActiveTime = lastActiveTime;
568 selectedStackList = stackTaskList;
569 }
570 }
571 }
572 if (selectedStackList != null) {
573 list.add(selectedStackList.remove(0));
574 --maxNum;
575 } else {
576 break;
577 }
578 }
579
Craig Mautner20e72272013-04-01 13:45:53 -0700580 return r;
581 }
582
Craig Mautner23ac33b2013-04-01 16:26:35 -0700583 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
584 String profileFile, ParcelFileDescriptor profileFd, int userId) {
585 // Collect information about the target of the Intent.
586 ActivityInfo aInfo;
587 try {
588 ResolveInfo rInfo =
589 AppGlobals.getPackageManager().resolveIntent(
590 intent, resolvedType,
591 PackageManager.MATCH_DEFAULT_ONLY
592 | ActivityManagerService.STOCK_PM_FLAGS, userId);
593 aInfo = rInfo != null ? rInfo.activityInfo : null;
594 } catch (RemoteException e) {
595 aInfo = null;
596 }
597
598 if (aInfo != null) {
599 // Store the found target back into the intent, because now that
600 // we have it we never want to do this again. For example, if the
601 // user navigates back to this point in the history, we should
602 // always restart the exact same activity.
603 intent.setComponent(new ComponentName(
604 aInfo.applicationInfo.packageName, aInfo.name));
605
606 // Don't debug things in the system process
607 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
608 if (!aInfo.processName.equals("system")) {
609 mService.setDebugApp(aInfo.processName, true, false);
610 }
611 }
612
613 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
614 if (!aInfo.processName.equals("system")) {
615 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
616 }
617 }
618
619 if (profileFile != null) {
620 if (!aInfo.processName.equals("system")) {
621 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
622 profileFile, profileFd,
623 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
624 }
625 }
626 }
627 return aInfo;
628 }
629
Craig Mautner2219a1b2013-03-25 09:44:30 -0700630 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
Craig Mautner8e569572013-10-11 17:36:59 -0700631 moveHomeToTop();
Craig Mautner6170f732013-04-02 13:05:23 -0700632 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
Craig Mautner2219a1b2013-03-25 09:44:30 -0700633 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700634 }
635
Craig Mautner23ac33b2013-04-01 16:26:35 -0700636 final int startActivityMayWait(IApplicationThread caller, int callingUid,
637 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
638 String resultWho, int requestCode, int startFlags, String profileFile,
639 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
640 Bundle options, int userId) {
641 // Refuse possible leaked file descriptors
642 if (intent != null && intent.hasFileDescriptors()) {
643 throw new IllegalArgumentException("File descriptors passed in Intent");
644 }
645 boolean componentSpecified = intent.getComponent() != null;
646
647 // Don't modify the client's object!
648 intent = new Intent(intent);
649
650 // Collect information about the target of the Intent.
651 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
652 profileFile, profileFd, userId);
653
654 synchronized (mService) {
655 int callingPid;
656 if (callingUid >= 0) {
657 callingPid = -1;
658 } else if (caller == null) {
659 callingPid = Binder.getCallingPid();
660 callingUid = Binder.getCallingUid();
661 } else {
662 callingPid = callingUid = -1;
663 }
664
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700665 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -0700666 stack.mConfigWillChange = config != null
Craig Mautner23ac33b2013-04-01 16:26:35 -0700667 && mService.mConfiguration.diff(config) != 0;
668 if (DEBUG_CONFIGURATION) Slog.v(TAG,
Craig Mautnerde4ef022013-04-07 19:01:33 -0700669 "Starting activity when config will change = " + stack.mConfigWillChange);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700670
671 final long origId = Binder.clearCallingIdentity();
672
673 if (aInfo != null &&
674 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
675 // This may be a heavy-weight process! Check to see if we already
676 // have another, different heavy-weight process running.
677 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
678 if (mService.mHeavyWeightProcess != null &&
679 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
680 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700681 int realCallingUid = callingUid;
682 if (caller != null) {
683 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
684 if (callerApp != null) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700685 realCallingUid = callerApp.info.uid;
686 } else {
687 Slog.w(TAG, "Unable to find app for caller " + caller
Craig Mautner76ea2242013-05-15 11:40:05 -0700688 + " (pid=" + callingPid + ") when starting: "
Craig Mautner23ac33b2013-04-01 16:26:35 -0700689 + intent.toString());
690 ActivityOptions.abort(options);
691 return ActivityManager.START_PERMISSION_DENIED;
692 }
693 }
694
695 IIntentSender target = mService.getIntentSenderLocked(
696 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
697 realCallingUid, userId, null, null, 0, new Intent[] { intent },
698 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
699 | PendingIntent.FLAG_ONE_SHOT, null);
700
701 Intent newIntent = new Intent();
702 if (requestCode >= 0) {
703 // Caller is requesting a result.
704 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
705 }
706 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
707 new IntentSender(target));
708 if (mService.mHeavyWeightProcess.activities.size() > 0) {
709 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
710 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
711 hist.packageName);
712 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
713 hist.task.taskId);
714 }
715 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
716 aInfo.packageName);
717 newIntent.setFlags(intent.getFlags());
718 newIntent.setClassName("android",
719 HeavyWeightSwitcherActivity.class.getName());
720 intent = newIntent;
721 resolvedType = null;
722 caller = null;
723 callingUid = Binder.getCallingUid();
724 callingPid = Binder.getCallingPid();
725 componentSpecified = true;
726 try {
727 ResolveInfo rInfo =
728 AppGlobals.getPackageManager().resolveIntent(
729 intent, null,
730 PackageManager.MATCH_DEFAULT_ONLY
731 | ActivityManagerService.STOCK_PM_FLAGS, userId);
732 aInfo = rInfo != null ? rInfo.activityInfo : null;
733 aInfo = mService.getActivityInfoForUser(aInfo, userId);
734 } catch (RemoteException e) {
735 aInfo = null;
736 }
737 }
738 }
739 }
740
Craig Mautner6170f732013-04-02 13:05:23 -0700741 int res = startActivityLocked(caller, intent, resolvedType,
Craig Mautner23ac33b2013-04-01 16:26:35 -0700742 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
743 callingPackage, startFlags, options, componentSpecified, null);
744
Craig Mautnerde4ef022013-04-07 19:01:33 -0700745 if (stack.mConfigWillChange) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700746 // If the caller also wants to switch to a new configuration,
747 // do so now. This allows a clean switch, as we are waiting
748 // for the current activity to pause (so we will not destroy
749 // it), and have not yet started the next activity.
750 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
751 "updateConfiguration()");
Craig Mautnerde4ef022013-04-07 19:01:33 -0700752 stack.mConfigWillChange = false;
Craig Mautner23ac33b2013-04-01 16:26:35 -0700753 if (DEBUG_CONFIGURATION) Slog.v(TAG,
754 "Updating to new configuration after starting activity.");
755 mService.updateConfigurationLocked(config, null, false, false);
756 }
757
758 Binder.restoreCallingIdentity(origId);
759
760 if (outResult != null) {
761 outResult.result = res;
762 if (res == ActivityManager.START_SUCCESS) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700763 mWaitingActivityLaunched.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700764 do {
765 try {
766 mService.wait();
767 } catch (InterruptedException e) {
768 }
769 } while (!outResult.timeout && outResult.who == null);
770 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700771 ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700772 if (r.nowVisible) {
773 outResult.timeout = false;
774 outResult.who = new ComponentName(r.info.packageName, r.info.name);
775 outResult.totalTime = 0;
776 outResult.thisTime = 0;
777 } else {
778 outResult.thisTime = SystemClock.uptimeMillis();
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700779 mWaitingActivityVisible.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700780 do {
781 try {
782 mService.wait();
783 } catch (InterruptedException e) {
784 }
785 } while (!outResult.timeout && outResult.who == null);
786 }
787 }
788 }
789
790 return res;
791 }
792 }
793
794 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
795 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
796 Bundle options, int userId) {
797 if (intents == null) {
798 throw new NullPointerException("intents is null");
799 }
800 if (resolvedTypes == null) {
801 throw new NullPointerException("resolvedTypes is null");
802 }
803 if (intents.length != resolvedTypes.length) {
804 throw new IllegalArgumentException("intents are length different than resolvedTypes");
805 }
806
Craig Mautner23ac33b2013-04-01 16:26:35 -0700807
808 int callingPid;
809 if (callingUid >= 0) {
810 callingPid = -1;
811 } else if (caller == null) {
812 callingPid = Binder.getCallingPid();
813 callingUid = Binder.getCallingUid();
814 } else {
815 callingPid = callingUid = -1;
816 }
817 final long origId = Binder.clearCallingIdentity();
818 try {
819 synchronized (mService) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700820 ActivityRecord[] outActivity = new ActivityRecord[1];
Craig Mautner23ac33b2013-04-01 16:26:35 -0700821 for (int i=0; i<intents.length; i++) {
822 Intent intent = intents[i];
823 if (intent == null) {
824 continue;
825 }
826
827 // Refuse possible leaked file descriptors
828 if (intent != null && intent.hasFileDescriptors()) {
829 throw new IllegalArgumentException("File descriptors passed in Intent");
830 }
831
832 boolean componentSpecified = intent.getComponent() != null;
833
834 // Don't modify the client's object!
835 intent = new Intent(intent);
836
837 // Collect information about the target of the Intent.
838 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
839 0, null, null, userId);
840 // TODO: New, check if this is correct
841 aInfo = mService.getActivityInfoForUser(aInfo, userId);
842
843 if (aInfo != null &&
844 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
845 != 0) {
846 throw new IllegalArgumentException(
847 "FLAG_CANT_SAVE_STATE not supported here");
848 }
849
850 Bundle theseOptions;
851 if (options != null && i == intents.length-1) {
852 theseOptions = options;
853 } else {
854 theseOptions = null;
855 }
Craig Mautner6170f732013-04-02 13:05:23 -0700856 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Craig Mautner23ac33b2013-04-01 16:26:35 -0700857 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
858 0, theseOptions, componentSpecified, outActivity);
859 if (res < 0) {
860 return res;
861 }
862
863 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
864 }
865 }
866 } finally {
867 Binder.restoreCallingIdentity(origId);
868 }
869
870 return ActivityManager.START_SUCCESS;
871 }
872
Craig Mautner2420ead2013-04-01 17:13:20 -0700873 final boolean realStartActivityLocked(ActivityRecord r,
874 ProcessRecord app, boolean andResume, boolean checkConfig)
875 throws RemoteException {
876
877 r.startFreezingScreenLocked(app, 0);
Craig Mautnera7f2bd42013-10-15 16:13:50 -0700878 if (false) Slog.d(TAG, "realStartActivity: setting app visibility true");
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700879 mWindowManager.setAppVisibility(r.appToken, true);
Craig Mautner2420ead2013-04-01 17:13:20 -0700880
881 // schedule launch ticks to collect information about slow apps.
882 r.startLaunchTickingLocked();
883
884 // Have the window manager re-evaluate the orientation of
885 // the screen based on the new activity order. Note that
886 // as a result of this, it can call back into the activity
887 // manager with a new orientation. We don't care about that,
888 // because the activity is not currently running so we are
889 // just restarting it anyway.
890 if (checkConfig) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700891 Configuration config = mWindowManager.updateOrientationFromAppTokens(
Craig Mautner2420ead2013-04-01 17:13:20 -0700892 mService.mConfiguration,
893 r.mayFreezeScreenLocked(app) ? r.appToken : null);
894 mService.updateConfigurationLocked(config, r, false, false);
895 }
896
897 r.app = app;
898 app.waitingToKill = null;
899 r.launchCount++;
900 r.lastLaunchTime = SystemClock.uptimeMillis();
901
902 if (localLOGV) Slog.v(TAG, "Launching: " + r);
903
904 int idx = app.activities.indexOf(r);
905 if (idx < 0) {
906 app.activities.add(r);
907 }
Dianne Hackborndb926082013-10-31 16:32:44 -0700908 mService.updateLruProcessLocked(app, true, null);
909 mService.updateOomAdjLocked();
Craig Mautner2420ead2013-04-01 17:13:20 -0700910
911 final ActivityStack stack = r.task.stack;
912 try {
913 if (app.thread == null) {
914 throw new RemoteException();
915 }
916 List<ResultInfo> results = null;
917 List<Intent> newIntents = null;
918 if (andResume) {
919 results = r.results;
920 newIntents = r.newIntents;
921 }
922 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
923 + " icicle=" + r.icicle
924 + " with results=" + results + " newIntents=" + newIntents
925 + " andResume=" + andResume);
926 if (andResume) {
927 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
928 r.userId, System.identityHashCode(r),
929 r.task.taskId, r.shortComponentName);
930 }
Craig Mautnerac6f8432013-07-17 13:24:59 -0700931 if (r.isHomeActivity() && r.isNotResolverActivity()) {
Craig Mautner4ef26932013-09-18 15:15:52 -0700932 // Home process is the root process of the task.
933 mService.mHomeProcess = r.task.mActivities.get(0).app;
Craig Mautner2420ead2013-04-01 17:13:20 -0700934 }
935 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
936 r.sleeping = false;
937 r.forceNewConfig = false;
938 mService.showAskCompatModeDialogLocked(r);
939 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
940 String profileFile = null;
941 ParcelFileDescriptor profileFd = null;
942 boolean profileAutoStop = false;
943 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
944 if (mService.mProfileProc == null || mService.mProfileProc == app) {
945 mService.mProfileProc = app;
946 profileFile = mService.mProfileFile;
947 profileFd = mService.mProfileFd;
948 profileAutoStop = mService.mAutoStopProfiler;
949 }
950 }
951 app.hasShownUi = true;
952 app.pendingUiClean = true;
953 if (profileFd != null) {
954 try {
955 profileFd = profileFd.dup();
956 } catch (IOException e) {
957 if (profileFd != null) {
958 try {
959 profileFd.close();
960 } catch (IOException o) {
961 }
962 profileFd = null;
963 }
964 }
965 }
Dianne Hackborna413dc02013-07-12 12:02:55 -0700966 app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
Craig Mautner2420ead2013-04-01 17:13:20 -0700967 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
968 System.identityHashCode(r), r.info,
Dianne Hackborna413dc02013-07-12 12:02:55 -0700969 new Configuration(mService.mConfiguration), r.compat,
970 app.repProcState, r.icicle, results, newIntents, !andResume,
Craig Mautner2420ead2013-04-01 17:13:20 -0700971 mService.isNextTransitionForward(), profileFile, profileFd,
972 profileAutoStop);
973
974 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
975 // This may be a heavy-weight process! Note that the package
976 // manager will ensure that only activity can run in the main
977 // process of the .apk, which is the only thing that will be
978 // considered heavy-weight.
979 if (app.processName.equals(app.info.packageName)) {
980 if (mService.mHeavyWeightProcess != null
981 && mService.mHeavyWeightProcess != app) {
982 Slog.w(TAG, "Starting new heavy weight process " + app
983 + " when already running "
984 + mService.mHeavyWeightProcess);
985 }
986 mService.mHeavyWeightProcess = app;
987 Message msg = mService.mHandler.obtainMessage(
988 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
989 msg.obj = r;
990 mService.mHandler.sendMessage(msg);
991 }
992 }
993
994 } catch (RemoteException e) {
995 if (r.launchFailed) {
996 // This is the second time we failed -- finish activity
997 // and give up.
998 Slog.e(TAG, "Second failure launching "
999 + r.intent.getComponent().flattenToShortString()
1000 + ", giving up", e);
1001 mService.appDiedLocked(app, app.pid, app.thread);
1002 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
1003 "2nd-crash", false);
1004 return false;
1005 }
1006
1007 // This is the first time we failed -- restart process and
1008 // retry.
1009 app.activities.remove(r);
1010 throw e;
1011 }
1012
1013 r.launchFailed = false;
1014 if (stack.updateLRUListLocked(r)) {
1015 Slog.w(TAG, "Activity " + r
1016 + " being launched, but already in LRU list");
1017 }
1018
1019 if (andResume) {
1020 // As part of the process of launching, ActivityThread also performs
1021 // a resume.
1022 stack.minimalResumeActivityLocked(r);
1023 } else {
1024 // This activity is not starting in the resumed state... which
1025 // should look like we asked it to pause+stop (but remain visible),
1026 // and it has done so and reported back the current icicle and
1027 // other state.
1028 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
1029 + " (starting in stopped state)");
1030 r.state = ActivityState.STOPPED;
1031 r.stopped = true;
1032 }
1033
1034 // Launch the new version setup screen if needed. We do this -after-
1035 // launching the initial activity (that is, home), so that it can have
1036 // a chance to initialize itself while in the background, making the
1037 // switch back to it faster and look better.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001038 if (isFrontStack(stack)) {
Craig Mautner2420ead2013-04-01 17:13:20 -07001039 mService.startSetupActivityLocked();
1040 }
1041
1042 return true;
1043 }
1044
Craig Mautnere79d42682013-04-01 19:01:53 -07001045 void startSpecificActivityLocked(ActivityRecord r,
1046 boolean andResume, boolean checkConfig) {
1047 // Is this activity's application already running?
1048 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07001049 r.info.applicationInfo.uid, true);
Craig Mautnere79d42682013-04-01 19:01:53 -07001050
1051 r.task.stack.setLaunchTime(r);
1052
1053 if (app != null && app.thread != null) {
1054 try {
Dianne Hackborn237cefb2013-10-22 18:45:27 -07001055 if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
1056 || !"android".equals(r.info.packageName)) {
1057 // Don't add this if it is a platform component that is marked
1058 // to run in multiple processes, because this is actually
1059 // part of the framework so doesn't make sense to track as a
1060 // separate apk in the process.
1061 app.addPackage(r.info.packageName, mService.mProcessStats);
1062 }
Craig Mautnere79d42682013-04-01 19:01:53 -07001063 realStartActivityLocked(r, app, andResume, checkConfig);
1064 return;
1065 } catch (RemoteException e) {
1066 Slog.w(TAG, "Exception when starting activity "
1067 + r.intent.getComponent().flattenToShortString(), e);
1068 }
1069
1070 // If a dead object exception was thrown -- fall through to
1071 // restart the application.
1072 }
1073
1074 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07001075 "activity", r.intent.getComponent(), false, false, true);
Craig Mautnere79d42682013-04-01 19:01:53 -07001076 }
1077
Craig Mautner6170f732013-04-02 13:05:23 -07001078 final int startActivityLocked(IApplicationThread caller,
1079 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
1080 String resultWho, int requestCode,
1081 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
1082 boolean componentSpecified, ActivityRecord[] outActivity) {
1083 int err = ActivityManager.START_SUCCESS;
1084
1085 ProcessRecord callerApp = null;
1086 if (caller != null) {
1087 callerApp = mService.getRecordForAppLocked(caller);
1088 if (callerApp != null) {
1089 callingPid = callerApp.pid;
1090 callingUid = callerApp.info.uid;
1091 } else {
1092 Slog.w(TAG, "Unable to find app for caller " + caller
1093 + " (pid=" + callingPid + ") when starting: "
1094 + intent.toString());
1095 err = ActivityManager.START_PERMISSION_DENIED;
1096 }
1097 }
1098
1099 if (err == ActivityManager.START_SUCCESS) {
1100 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
1101 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
1102 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
1103 }
1104
1105 ActivityRecord sourceRecord = null;
1106 ActivityRecord resultRecord = null;
1107 if (resultTo != null) {
1108 sourceRecord = isInAnyStackLocked(resultTo);
1109 if (DEBUG_RESULTS) Slog.v(
1110 TAG, "Will send result to " + resultTo + " " + sourceRecord);
1111 if (sourceRecord != null) {
1112 if (requestCode >= 0 && !sourceRecord.finishing) {
1113 resultRecord = sourceRecord;
1114 }
1115 }
1116 }
1117 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
1118
1119 int launchFlags = intent.getFlags();
1120
1121 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
1122 && sourceRecord != null) {
1123 // Transfer the result target from the source activity to the new
1124 // one being started, including any failures.
1125 if (requestCode >= 0) {
1126 ActivityOptions.abort(options);
1127 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
1128 }
1129 resultRecord = sourceRecord.resultTo;
1130 resultWho = sourceRecord.resultWho;
1131 requestCode = sourceRecord.requestCode;
1132 sourceRecord.resultTo = null;
1133 if (resultRecord != null) {
1134 resultRecord.removeResultsLocked(
1135 sourceRecord, resultWho, requestCode);
1136 }
1137 }
1138
1139 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
1140 // We couldn't find a class that can handle the given Intent.
1141 // That's the end of that!
1142 err = ActivityManager.START_INTENT_NOT_RESOLVED;
1143 }
1144
1145 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
1146 // We couldn't find the specific class specified in the Intent.
1147 // Also the end of the line.
1148 err = ActivityManager.START_CLASS_NOT_FOUND;
1149 }
1150
1151 if (err != ActivityManager.START_SUCCESS) {
1152 if (resultRecord != null) {
1153 resultStack.sendActivityResultLocked(-1,
1154 resultRecord, resultWho, requestCode,
1155 Activity.RESULT_CANCELED, null);
1156 }
1157 setDismissKeyguard(false);
1158 ActivityOptions.abort(options);
1159 return err;
1160 }
1161
1162 final int startAnyPerm = mService.checkPermission(
1163 START_ANY_ACTIVITY, callingPid, callingUid);
1164 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
1165 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
1166 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
1167 if (resultRecord != null) {
1168 resultStack.sendActivityResultLocked(-1,
1169 resultRecord, resultWho, requestCode,
1170 Activity.RESULT_CANCELED, null);
1171 }
1172 setDismissKeyguard(false);
1173 String msg;
1174 if (!aInfo.exported) {
1175 msg = "Permission Denial: starting " + intent.toString()
1176 + " from " + callerApp + " (pid=" + callingPid
1177 + ", uid=" + callingUid + ")"
1178 + " not exported from uid " + aInfo.applicationInfo.uid;
1179 } else {
1180 msg = "Permission Denial: starting " + intent.toString()
1181 + " from " + callerApp + " (pid=" + callingPid
1182 + ", uid=" + callingUid + ")"
1183 + " requires " + aInfo.permission;
1184 }
1185 Slog.w(TAG, msg);
1186 throw new SecurityException(msg);
1187 }
1188
Ben Gruverdd72c9e2013-08-06 12:34:17 -07001189 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
Ben Gruverb6223792013-07-29 16:35:40 -07001190 callingPid, resolvedType, aInfo.applicationInfo);
Ben Gruver5e207332013-04-03 17:41:37 -07001191
Craig Mautner6170f732013-04-02 13:05:23 -07001192 if (mService.mController != null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001193 try {
1194 // The Intent we give to the watcher has the extra data
1195 // stripped off, since it can contain private information.
1196 Intent watchIntent = intent.cloneFilter();
Ben Gruver5e207332013-04-03 17:41:37 -07001197 abort |= !mService.mController.activityStarting(watchIntent,
Craig Mautner6170f732013-04-02 13:05:23 -07001198 aInfo.applicationInfo.packageName);
1199 } catch (RemoteException e) {
1200 mService.mController = null;
1201 }
Ben Gruver5e207332013-04-03 17:41:37 -07001202 }
Craig Mautner6170f732013-04-02 13:05:23 -07001203
Ben Gruver5e207332013-04-03 17:41:37 -07001204 if (abort) {
1205 if (resultRecord != null) {
1206 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Craig Mautner6170f732013-04-02 13:05:23 -07001207 Activity.RESULT_CANCELED, null);
Craig Mautner6170f732013-04-02 13:05:23 -07001208 }
Ben Gruver5e207332013-04-03 17:41:37 -07001209 // We pretend to the caller that it was really started, but
1210 // they will just get a cancel result.
1211 setDismissKeyguard(false);
1212 ActivityOptions.abort(options);
1213 return ActivityManager.START_SUCCESS;
Craig Mautner6170f732013-04-02 13:05:23 -07001214 }
1215
1216 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1217 intent, resolvedType, aInfo, mService.mConfiguration,
Craig Mautnerde4ef022013-04-07 19:01:33 -07001218 resultRecord, resultWho, requestCode, componentSpecified, this);
Craig Mautner6170f732013-04-02 13:05:23 -07001219 if (outActivity != null) {
1220 outActivity[0] = r;
1221 }
1222
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001223 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001224 if (stack.mResumedActivity == null
1225 || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
Craig Mautner6170f732013-04-02 13:05:23 -07001226 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1227 PendingActivityLaunch pal =
Craig Mautnerde4ef022013-04-07 19:01:33 -07001228 new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
Craig Mautner6170f732013-04-02 13:05:23 -07001229 mService.mPendingActivityLaunches.add(pal);
1230 setDismissKeyguard(false);
1231 ActivityOptions.abort(options);
1232 return ActivityManager.START_SWITCHES_CANCELED;
1233 }
1234 }
1235
1236 if (mService.mDidAppSwitch) {
1237 // This is the second allowed switch since we stopped switches,
1238 // so now just generally allow switches. Use case: user presses
1239 // home (switches disabled, switch to home, mDidAppSwitch now true);
1240 // user taps a home icon (coming from home so allowed, we hit here
1241 // and now allow anyone to switch again).
1242 mService.mAppSwitchesAllowedTime = 0;
1243 } else {
1244 mService.mDidAppSwitch = true;
1245 }
1246
1247 mService.doPendingActivityLaunchesLocked(false);
1248
Craig Mautner8849a5e2013-04-02 16:41:03 -07001249 err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
Craig Mautner10385a12013-09-22 21:08:32 -07001250
1251 if (allPausedActivitiesComplete()) {
1252 // If someone asked to have the keyguard dismissed on the next
Craig Mautner6170f732013-04-02 13:05:23 -07001253 // activity start, but we are not actually doing an activity
1254 // switch... just dismiss the keyguard now, because we
1255 // probably want to see whatever is behind it.
1256 dismissKeyguard();
1257 }
1258 return err;
1259 }
1260
Craig Mautnerac6f8432013-07-17 13:24:59 -07001261 ActivityStack adjustStackFocus(ActivityRecord r) {
Craig Mautner1d001b62013-06-18 16:52:43 -07001262 final TaskRecord task = r.task;
1263 if (r.isApplicationActivity() || (task != null && task.isApplicationTask())) {
Craig Mautnerac6f8432013-07-17 13:24:59 -07001264 if (task != null) {
Craig Mautnerd1bbdb4622013-10-22 09:53:20 -07001265 final ActivityStack taskStack = task.stack;
1266 if (mFocusedStack != taskStack) {
Craig Mautnerac6f8432013-07-17 13:24:59 -07001267 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1268 "adjustStackFocus: Setting focused stack to r=" + r + " task=" + task);
Craig Mautnerd1bbdb4622013-10-22 09:53:20 -07001269 mFocusedStack = taskStack.isHomeStack() ? null : taskStack;
Craig Mautnerac6f8432013-07-17 13:24:59 -07001270 } else {
1271 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1272 "adjustStackFocus: Focused stack already=" + mFocusedStack);
1273 }
Craig Mautnerd1bbdb4622013-10-22 09:53:20 -07001274 return taskStack;
Craig Mautnerac6f8432013-07-17 13:24:59 -07001275 }
1276
1277 if (mFocusedStack != null) {
1278 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1279 "adjustStackFocus: Have a focused stack=" + mFocusedStack);
1280 return mFocusedStack;
1281 }
1282
1283 for (int stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
1284 ActivityStack stack = mStacks.get(stackNdx);
1285 if (!stack.isHomeStack()) {
1286 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1287 "adjustStackFocus: Setting focused stack=" + stack);
1288 mFocusedStack = stack;
1289 return mFocusedStack;
Craig Mautner858d8a62013-04-23 17:08:34 -07001290 }
1291 }
Craig Mautnerac6f8432013-07-17 13:24:59 -07001292
1293 // Time to create the first app stack for this user.
Craig Mautnerd1bbdb4622013-10-22 09:53:20 -07001294 int stackId =
1295 mService.createStack(-1, HOME_STACK_ID, StackBox.TASK_STACK_GOES_OVER, 1.0f);
Craig Mautnerac6f8432013-07-17 13:24:59 -07001296 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack r=" + r +
1297 " stackId=" + stackId);
1298 mFocusedStack = getStack(stackId);
Craig Mautner29219d92013-04-16 20:19:12 -07001299 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001300 }
1301 return mHomeStack;
1302 }
1303
Craig Mautner29219d92013-04-16 20:19:12 -07001304 void setFocusedStack(ActivityRecord r) {
1305 if (r == null) {
1306 return;
1307 }
Craig Mautner86d67a42013-05-14 10:34:38 -07001308 if (!r.isApplicationActivity() || (r.task != null && !r.task.isApplicationTask())) {
Craig Mautner29219d92013-04-16 20:19:12 -07001309 if (mStackState != STACK_STATE_HOME_IN_FRONT) {
Craig Mautnere7c58b62013-06-12 20:19:00 -07001310 if (DEBUG_STACK || DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: mStackState old=" +
Craig Mautner76ea2242013-05-15 11:40:05 -07001311 stackStateToString(mStackState) + " new=" +
1312 stackStateToString(STACK_STATE_HOME_TO_FRONT) +
1313 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001314 mStackState = STACK_STATE_HOME_TO_FRONT;
1315 }
1316 } else {
Craig Mautnerac6f8432013-07-17 13:24:59 -07001317 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1318 "setFocusedStack: Setting focused stack to r=" + r + " task=" + r.task +
1319 " Callers=" + Debug.getCallers(3));
Craig Mautnerd1bbdb4622013-10-22 09:53:20 -07001320 final ActivityStack taskStack = r.task.stack;
1321 mFocusedStack = taskStack.isHomeStack() ? null : taskStack;
Craig Mautner29219d92013-04-16 20:19:12 -07001322 if (mStackState != STACK_STATE_HOME_IN_BACK) {
Craig Mautner76ea2242013-05-15 11:40:05 -07001323 if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
1324 stackStateToString(mStackState) + " new=" +
1325 stackStateToString(STACK_STATE_HOME_TO_BACK) +
1326 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001327 mStackState = STACK_STATE_HOME_TO_BACK;
1328 }
1329 }
1330 }
1331
Craig Mautner8849a5e2013-04-02 16:41:03 -07001332 final int startActivityUncheckedLocked(ActivityRecord r,
1333 ActivityRecord sourceRecord, int startFlags, boolean doResume,
1334 Bundle options) {
1335 final Intent intent = r.intent;
1336 final int callingUid = r.launchedFromUid;
1337
1338 int launchFlags = intent.getFlags();
1339
Craig Mautner8849a5e2013-04-02 16:41:03 -07001340 // We'll invoke onUserLeaving before onPause only if the launching
1341 // activity did not explicitly state that this is an automated launch.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001342 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1343 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001344
1345 // If the caller has asked not to resume at this point, we make note
1346 // of this in the record so that we can skip it when trying to find
1347 // the top running activity.
1348 if (!doResume) {
1349 r.delayedResume = true;
1350 }
1351
1352 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1353
1354 // If the onlyIfNeeded flag is set, then we can do this if the activity
1355 // being launched is the same as the one making the call... or, as
1356 // a special case, if we do not know the caller then we count the
1357 // current top activity as the caller.
1358 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1359 ActivityRecord checkedCaller = sourceRecord;
1360 if (checkedCaller == null) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001361 checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001362 }
1363 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1364 // Caller is not the same as launcher, so always needed.
1365 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1366 }
1367 }
1368
1369 if (sourceRecord == null) {
1370 // This activity is not being started from another... in this
1371 // case we -always- start a new task.
1372 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Craig Mautner29219d92013-04-16 20:19:12 -07001373 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1374 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001375 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1376 }
1377 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1378 // The original activity who is starting us is running as a single
1379 // instance... this new activity it is starting must go on its
1380 // own task.
1381 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1382 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1383 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1384 // The activity being started is a single instance... it always
1385 // gets launched into its own task.
1386 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1387 }
1388
Craig Mautner88629292013-11-10 20:39:05 -08001389 ActivityInfo newTaskInfo = null;
1390 Intent newTaskIntent = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001391 final ActivityStack sourceStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001392 if (sourceRecord != null) {
Dianne Hackborn2a272d42013-10-16 13:34:33 -07001393 if (sourceRecord.finishing) {
1394 // If the source is finishing, we can't further count it as our source. This
1395 // is because the task it is associated with may now be empty and on its way out,
1396 // so we don't want to blindly throw it in to that task. Instead we will take
Craig Mautner88629292013-11-10 20:39:05 -08001397 // the NEW_TASK flow and try to find a task for it. But save the task information
1398 // so it can be used when creating the new task.
Dianne Hackborn2a272d42013-10-16 13:34:33 -07001399 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
1400 Slog.w(TAG, "startActivity called from finishing " + sourceRecord
1401 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
1402 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
Craig Mautner88629292013-11-10 20:39:05 -08001403 newTaskInfo = sourceRecord.info;
1404 newTaskIntent = sourceRecord.task.intent;
Dianne Hackborn2a272d42013-10-16 13:34:33 -07001405 }
1406 sourceRecord = null;
1407 sourceStack = null;
1408 } else {
1409 sourceStack = sourceRecord.task.stack;
1410 }
Craig Mautnerde4ef022013-04-07 19:01:33 -07001411 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001412 sourceStack = null;
1413 }
1414
Craig Mautner8849a5e2013-04-02 16:41:03 -07001415 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1416 // For whatever reason this activity is being launched into a new
1417 // task... yet the caller has requested a result back. Well, that
1418 // is pretty messed up, so instead immediately send back a cancel
1419 // and let the new task continue launched as normal without a
1420 // dependency on its originator.
1421 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1422 r.resultTo.task.stack.sendActivityResultLocked(-1,
1423 r.resultTo, r.resultWho, r.requestCode,
1424 Activity.RESULT_CANCELED, null);
1425 r.resultTo = null;
1426 }
1427
1428 boolean addingToTask = false;
1429 boolean movedHome = false;
1430 TaskRecord reuseTask = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001431 ActivityStack targetStack;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001432 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1433 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1434 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1435 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1436 // If bring to front is requested, and no result is requested, and
1437 // we can find a task that was started with this same
1438 // component, then instead of launching bring that one to the front.
1439 if (r.resultTo == null) {
1440 // See if there is a task to bring to the front. If this is
1441 // a SINGLE_INSTANCE activity, there can be one and only one
1442 // instance of it in the history, and it is always in its own
1443 // unique task, so we do a special search.
1444 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
Craig Mautnerac6f8432013-07-17 13:24:59 -07001445 ? findTaskLocked(r)
Craig Mautner8849a5e2013-04-02 16:41:03 -07001446 : findActivityLocked(intent, r.info);
1447 if (intentActivity != null) {
Craig Mautner29219d92013-04-16 20:19:12 -07001448 if (r.task == null) {
1449 r.task = intentActivity.task;
1450 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001451 targetStack = intentActivity.task.stack;
Craig Mautner0f922742013-08-06 08:44:42 -07001452 targetStack.mLastPausedActivity = null;
Dianne Hackborn2a272d42013-10-16 13:34:33 -07001453 if (DEBUG_TASKS) Slog.d(TAG, "Bring to front target: " + targetStack
1454 + " from " + intentActivity);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001455 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001456 if (intentActivity.task.intent == null) {
1457 // This task was started because of movement of
1458 // the activity based on affinity... now that we
1459 // are actually launching it, we can assign the
1460 // base intent.
1461 intentActivity.task.setIntent(intent, r.info);
1462 }
1463 // If the target task is not in the front, then we need
1464 // to bring it to the front... except... well, with
1465 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
1466 // to have the same behavior as if a new instance was
1467 // being started, which means not bringing it to the front
1468 // if the caller is not itself in the front.
Craig Mautner165640b2013-04-20 10:34:33 -07001469 final ActivityStack lastStack = getLastStack();
1470 ActivityRecord curTop = lastStack == null?
1471 null : lastStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner7504d7b2013-09-17 10:50:53 -07001472 if (curTop != null && (curTop.task != intentActivity.task ||
1473 curTop.task != lastStack.topTask())) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001474 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Craig Mautnerd0f964f2013-08-07 11:16:33 -07001475 if (sourceRecord == null || (sourceStack.topActivity() != null &&
1476 sourceStack.topActivity().task == sourceRecord.task)) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001477 // We really do want to push this one into the
1478 // user's face, right now.
1479 movedHome = true;
Craig Mautnerb53d97c2013-10-25 11:54:37 -07001480 targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001481 if ((launchFlags &
Craig Mautner29219d92013-04-16 20:19:12 -07001482 (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1483 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
Craig Mautnere12a4a62013-08-29 12:24:56 -07001484 // Caller wants to appear on home activity.
Craig Mautnerae7ecab2013-09-18 11:48:14 -07001485 intentActivity.task.mOnTopOfHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001486 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001487 options = null;
1488 }
1489 }
1490 // If the caller has requested that the target task be
1491 // reset, then do so.
1492 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1493 intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1494 }
1495 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1496 // We don't need to start a new activity, and
1497 // the client said not to do anything if that
1498 // is the case, so this is it! And for paranoia, make
1499 // sure we have correctly resumed the top activity.
1500 if (doResume) {
Craig Mautner05d29032013-05-03 13:40:13 -07001501 resumeTopActivitiesLocked(targetStack, null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001502 } else {
1503 ActivityOptions.abort(options);
1504 }
Craig Mautner29219d92013-04-16 20:19:12 -07001505 if (r.task == null) Slog.v(TAG,
1506 "startActivityUncheckedLocked: task left null",
1507 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001508 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1509 }
1510 if ((launchFlags &
1511 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1512 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1513 // The caller has requested to completely replace any
1514 // existing task with its new activity. Well that should
1515 // not be too hard...
1516 reuseTask = intentActivity.task;
1517 reuseTask.performClearTaskLocked();
1518 reuseTask.setIntent(r.intent, r.info);
1519 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1520 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1521 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1522 // In this situation we want to remove all activities
1523 // from the task up to the one being started. In most
1524 // cases this means we are resetting the task to its
1525 // initial state.
1526 ActivityRecord top =
1527 intentActivity.task.performClearTaskLocked(r, launchFlags);
1528 if (top != null) {
1529 if (top.frontOfTask) {
1530 // Activity aliases may mean we use different
1531 // intents for the top activity, so make sure
1532 // the task now has the identity of the new
1533 // intent.
1534 top.task.setIntent(r.intent, r.info);
1535 }
1536 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1537 r, top.task);
1538 top.deliverNewIntentLocked(callingUid, r.intent);
1539 } else {
1540 // A special case: we need to
1541 // start the activity because it is not currently
1542 // running, and the caller has asked to clear the
1543 // current task to have this activity at the top.
1544 addingToTask = true;
1545 // Now pretend like this activity is being started
1546 // by the top of its task, so it is put in the
1547 // right place.
1548 sourceRecord = intentActivity;
1549 }
1550 } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1551 // In this case the top activity on the task is the
1552 // same as the one being launched, so we take that
1553 // as a request to bring the task to the foreground.
1554 // If the top activity in the task is the root
1555 // activity, deliver this new intent to it if it
1556 // desires.
1557 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1558 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1559 && intentActivity.realActivity.equals(r.realActivity)) {
1560 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1561 intentActivity.task);
1562 if (intentActivity.frontOfTask) {
1563 intentActivity.task.setIntent(r.intent, r.info);
1564 }
1565 intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1566 } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1567 // In this case we are launching the root activity
1568 // of the task, but with a different intent. We
1569 // should start a new instance on top.
1570 addingToTask = true;
1571 sourceRecord = intentActivity;
1572 }
1573 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1574 // In this case an activity is being launched in to an
1575 // existing task, without resetting that task. This
1576 // is typically the situation of launching an activity
1577 // from a notification or shortcut. We want to place
1578 // the new activity on top of the current task.
1579 addingToTask = true;
1580 sourceRecord = intentActivity;
1581 } else if (!intentActivity.task.rootWasReset) {
1582 // In this case we are launching in to an existing task
1583 // that has not yet been started from its front door.
1584 // The current task has been brought to the front.
1585 // Ideally, we'd probably like to place this new task
1586 // at the bottom of its stack, but that's a little hard
1587 // to do with the current organization of the code so
1588 // for now we'll just drop it.
1589 intentActivity.task.setIntent(r.intent, r.info);
1590 }
1591 if (!addingToTask && reuseTask == null) {
1592 // We didn't do anything... but it was needed (a.k.a., client
1593 // don't use that intent!) And for paranoia, make
1594 // sure we have correctly resumed the top activity.
1595 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001596 targetStack.resumeTopActivityLocked(null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001597 } else {
1598 ActivityOptions.abort(options);
1599 }
Craig Mautner29219d92013-04-16 20:19:12 -07001600 if (r.task == null) Slog.v(TAG,
1601 "startActivityUncheckedLocked: task left null",
1602 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001603 return ActivityManager.START_TASK_TO_FRONT;
1604 }
1605 }
1606 }
1607 }
1608
1609 //String uri = r.intent.toURI();
1610 //Intent intent2 = new Intent(uri);
1611 //Slog.i(TAG, "Given intent: " + r.intent);
1612 //Slog.i(TAG, "URI is: " + uri);
1613 //Slog.i(TAG, "To intent: " + intent2);
1614
1615 if (r.packageName != null) {
1616 // If the activity being launched is the same as the one currently
1617 // at the top, then we need to check if it should only be launched
1618 // once.
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001619 ActivityStack topStack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001620 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001621 if (top != null && r.resultTo == null) {
1622 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1623 if (top.app != null && top.app.thread != null) {
1624 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1625 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1626 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1627 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1628 top.task);
1629 // For paranoia, make sure we have correctly
1630 // resumed the top activity.
Craig Mautner0f922742013-08-06 08:44:42 -07001631 topStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001632 if (doResume) {
Craig Mautner05d29032013-05-03 13:40:13 -07001633 resumeTopActivitiesLocked();
Craig Mautner8849a5e2013-04-02 16:41:03 -07001634 }
1635 ActivityOptions.abort(options);
1636 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1637 // We don't need to start a new activity, and
1638 // the client said not to do anything if that
1639 // is the case, so this is it!
Craig Mautner29219d92013-04-16 20:19:12 -07001640 if (r.task == null) Slog.v(TAG,
1641 "startActivityUncheckedLocked: task left null",
1642 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001643 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1644 }
1645 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner29219d92013-04-16 20:19:12 -07001646 if (r.task == null) Slog.v(TAG,
1647 "startActivityUncheckedLocked: task left null",
1648 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001649 return ActivityManager.START_DELIVERED_TO_TOP;
1650 }
1651 }
1652 }
1653 }
1654
1655 } else {
1656 if (r.resultTo != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001657 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1658 r.requestCode, Activity.RESULT_CANCELED, null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001659 }
1660 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001661 if (r.task == null) Slog.v(TAG,
1662 "startActivityUncheckedLocked: task left null",
1663 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001664 return ActivityManager.START_CLASS_NOT_FOUND;
1665 }
1666
1667 boolean newTask = false;
1668 boolean keepCurTransition = false;
1669
1670 // Should this be considered a new task?
1671 if (r.resultTo == null && !addingToTask
1672 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Craig Mautnerac6f8432013-07-17 13:24:59 -07001673 targetStack = adjustStackFocus(r);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001674 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001675 if (reuseTask == null) {
Craig Mautner88629292013-11-10 20:39:05 -08001676 r.setTask(targetStack.createTaskRecord(getNextTaskId(),
1677 newTaskInfo != null ? newTaskInfo : r.info,
1678 newTaskIntent != null ? newTaskIntent : intent,
1679 true), null, true);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001680 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1681 r.task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001682 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001683 r.setTask(reuseTask, reuseTask, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001684 }
1685 newTask = true;
1686 if (!movedHome) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001687 if ((launchFlags &
1688 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1689 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1690 // Caller wants to appear on home activity, so before starting
1691 // their own activity we will bring home to the front.
Craig Mautnerae7ecab2013-09-18 11:48:14 -07001692 r.task.mOnTopOfHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001693 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001694 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001695 } else if (sourceRecord != null) {
Dianne Hackborn2a272d42013-10-16 13:34:33 -07001696 TaskRecord sourceTask = sourceRecord.task;
Craig Mautner525f3d92013-05-07 14:01:50 -07001697 targetStack = sourceTask.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001698 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001699 if (!addingToTask &&
1700 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1701 // In this case, we are adding the activity to an existing
1702 // task, but the caller has asked to clear that task if the
1703 // activity is already running.
Craig Mautner525f3d92013-05-07 14:01:50 -07001704 ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001705 keepCurTransition = true;
1706 if (top != null) {
1707 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1708 top.deliverNewIntentLocked(callingUid, r.intent);
1709 // For paranoia, make sure we have correctly
1710 // resumed the top activity.
Craig Mautner0f922742013-08-06 08:44:42 -07001711 targetStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001712 if (doResume) {
1713 targetStack.resumeTopActivityLocked(null);
1714 }
1715 ActivityOptions.abort(options);
Dianne Hackborn2a272d42013-10-16 13:34:33 -07001716 if (r.task == null) Slog.w(TAG,
Craig Mautner29219d92013-04-16 20:19:12 -07001717 "startActivityUncheckedLocked: task left null",
1718 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001719 return ActivityManager.START_DELIVERED_TO_TOP;
1720 }
1721 } else if (!addingToTask &&
1722 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1723 // In this case, we are launching an activity in our own task
1724 // that may already be running somewhere in the history, and
1725 // we want to shuffle it to the front of the stack if so.
Craig Mautner525f3d92013-05-07 14:01:50 -07001726 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001727 if (top != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001728 final TaskRecord task = top.task;
1729 task.moveActivityToFrontLocked(top);
1730 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001731 top.updateOptionsLocked(options);
1732 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner0f922742013-08-06 08:44:42 -07001733 targetStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001734 if (doResume) {
1735 targetStack.resumeTopActivityLocked(null);
1736 }
1737 return ActivityManager.START_DELIVERED_TO_TOP;
1738 }
1739 }
1740 // An existing activity is starting this new activity, so we want
1741 // to keep the new one in the same task as the one that is starting
1742 // it.
Craig Mautner525f3d92013-05-07 14:01:50 -07001743 r.setTask(sourceTask, sourceRecord.thumbHolder, false);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001744 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
Dianne Hackborn2a272d42013-10-16 13:34:33 -07001745 + " in existing task " + r.task + " from source " + sourceRecord);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001746
1747 } else {
1748 // This not being started from an existing activity, and not part
1749 // of a new task... just put it in the top task, though these days
1750 // this case should never happen.
Craig Mautnerac6f8432013-07-17 13:24:59 -07001751 targetStack = adjustStackFocus(r);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001752 moveHomeStack(targetStack.isHomeStack());
Craig Mautner1602ec22013-05-12 10:24:27 -07001753 ActivityRecord prev = targetStack.topActivity();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001754 r.setTask(prev != null ? prev.task
1755 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1756 null, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001757 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1758 + " in new guessed " + r.task);
1759 }
1760
1761 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1762 intent, r.getUriPermissionsLocked());
1763
1764 if (newTask) {
1765 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1766 }
1767 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Craig Mautner0f922742013-08-06 08:44:42 -07001768 targetStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001769 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
Craig Mautner1d001b62013-06-18 16:52:43 -07001770 mService.setFocusedActivityLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001771 return ActivityManager.START_SUCCESS;
1772 }
1773
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001774 void acquireLaunchWakelock() {
1775 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
1776 throw new IllegalStateException("Calling must be system uid");
1777 }
1778 mLaunchingActivity.acquire();
1779 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
1780 // To be safe, don't allow the wake lock to be held for too long.
1781 mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
1782 }
1783 }
1784
Craig Mautnerf3333272013-04-22 10:55:53 -07001785 // Checked.
1786 final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
1787 Configuration config) {
1788 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
1789
Craig Mautnerf3333272013-04-22 10:55:53 -07001790 ArrayList<ActivityRecord> stops = null;
1791 ArrayList<ActivityRecord> finishes = null;
1792 ArrayList<UserStartedState> startingUsers = null;
1793 int NS = 0;
1794 int NF = 0;
1795 IApplicationThread sendThumbnail = null;
1796 boolean booting = false;
1797 boolean enableScreen = false;
1798 boolean activityRemoved = false;
1799
1800 ActivityRecord r = ActivityRecord.forToken(token);
1801 if (r != null) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07001802 if (DEBUG_IDLE) Slog.d(TAG, "activityIdleInternalLocked: Callers=" +
1803 Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07001804 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
1805 r.finishLaunchTickingLocked();
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001806 if (fromTimeout) {
1807 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
Craig Mautnerf3333272013-04-22 10:55:53 -07001808 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001809
1810 // This is a hack to semi-deal with a race condition
1811 // in the client where it can be constructed with a
1812 // newer configuration from when we asked it to launch.
1813 // We'll update with whatever configuration it now says
1814 // it used to launch.
1815 if (config != null) {
1816 r.configuration = config;
1817 }
1818
1819 // We are now idle. If someone is waiting for a thumbnail from
1820 // us, we can now deliver.
1821 r.idle = true;
1822
1823 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
1824 sendThumbnail = r.app.thread;
1825 r.thumbnailNeeded = false;
1826 }
1827
1828 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
1829 if (!mService.mBooted && isFrontStack(r.task.stack)) {
1830 mService.mBooted = true;
1831 enableScreen = true;
1832 }
1833 }
1834
1835 if (allResumedActivitiesIdle()) {
1836 if (r != null) {
1837 mService.scheduleAppGcsLocked();
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001838 }
1839
1840 if (mLaunchingActivity.isHeld()) {
1841 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
1842 if (VALIDATE_WAKE_LOCK_CALLER &&
1843 Binder.getCallingUid() != Process.myUid()) {
1844 throw new IllegalStateException("Calling must be system uid");
1845 }
1846 mLaunchingActivity.release();
1847 }
1848 ensureActivitiesVisibleLocked(null, 0);
Craig Mautnerf3333272013-04-22 10:55:53 -07001849 }
1850
1851 // Atomically retrieve all of the other things to do.
1852 stops = processStoppingActivitiesLocked(true);
1853 NS = stops != null ? stops.size() : 0;
1854 if ((NF=mFinishingActivities.size()) > 0) {
1855 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
1856 mFinishingActivities.clear();
1857 }
1858
1859 final ArrayList<ActivityRecord> thumbnails;
1860 final int NT = mCancelledThumbnails.size();
1861 if (NT > 0) {
1862 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
1863 mCancelledThumbnails.clear();
1864 } else {
1865 thumbnails = null;
1866 }
1867
1868 if (isFrontStack(mHomeStack)) {
1869 booting = mService.mBooting;
1870 mService.mBooting = false;
1871 }
1872
1873 if (mStartingUsers.size() > 0) {
1874 startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
1875 mStartingUsers.clear();
1876 }
1877
1878 // Perform the following actions from unsynchronized state.
1879 final IApplicationThread thumbnailThread = sendThumbnail;
1880 mHandler.post(new Runnable() {
1881 @Override
1882 public void run() {
1883 if (thumbnailThread != null) {
1884 try {
1885 thumbnailThread.requestThumbnail(token);
1886 } catch (Exception e) {
1887 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
1888 mService.sendPendingThumbnail(null, token, null, null, true);
1889 }
1890 }
1891
1892 // Report back to any thumbnail receivers.
1893 for (int i = 0; i < NT; i++) {
1894 ActivityRecord r = thumbnails.get(i);
1895 mService.sendPendingThumbnail(r, null, null, null, true);
1896 }
1897 }
1898 });
1899
1900 // Stop any activities that are scheduled to do so but have been
1901 // waiting for the next one to start.
1902 for (int i = 0; i < NS; i++) {
1903 r = stops.get(i);
1904 final ActivityStack stack = r.task.stack;
1905 if (r.finishing) {
1906 stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
1907 } else {
1908 stack.stopActivityLocked(r);
1909 }
1910 }
1911
1912 // Finish any activities that are scheduled to do so but have been
1913 // waiting for the next one to start.
1914 for (int i = 0; i < NF; i++) {
1915 r = finishes.get(i);
1916 activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle");
1917 }
1918
1919 if (booting) {
1920 mService.finishBooting();
1921 } else if (startingUsers != null) {
1922 for (int i = 0; i < startingUsers.size(); i++) {
1923 mService.finishUserSwitch(startingUsers.get(i));
1924 }
1925 }
1926
1927 mService.trimApplications();
1928 //dump();
1929 //mWindowManager.dump();
1930
1931 if (enableScreen) {
1932 mService.enableScreenAfterBoot();
1933 }
1934
1935 if (activityRemoved) {
Craig Mautner05d29032013-05-03 13:40:13 -07001936 resumeTopActivitiesLocked();
Craig Mautnerf3333272013-04-22 10:55:53 -07001937 }
1938
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001939 return r;
Craig Mautnerf3333272013-04-22 10:55:53 -07001940 }
1941
Craig Mautner8e569572013-10-11 17:36:59 -07001942 boolean handleAppDiedLocked(ProcessRecord app) {
Craig Mautner19091252013-10-05 00:03:53 -07001943 boolean hasVisibleActivities = false;
1944 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1945 hasVisibleActivities |= mStacks.get(stackNdx).handleAppDiedLocked(app);
Craig Mautner6b74cb52013-09-27 17:02:21 -07001946 }
Craig Mautner19091252013-10-05 00:03:53 -07001947 return hasVisibleActivities;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001948 }
1949
1950 void closeSystemDialogsLocked() {
1951 final int numStacks = mStacks.size();
1952 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1953 final ActivityStack stack = mStacks.get(stackNdx);
1954 stack.closeSystemDialogsLocked();
1955 }
1956 }
1957
Craig Mautner93529a42013-10-04 15:03:13 -07001958 void removeUserLocked(int userId) {
Craig Mautner4f1df4f2013-10-15 15:44:14 -07001959 mUserStackInFront.delete(userId);
Craig Mautner93529a42013-10-04 15:03:13 -07001960 }
1961
Craig Mautner8d341ef2013-03-26 09:03:27 -07001962 /**
1963 * @return true if some activity was finished (or would have finished if doit were true).
1964 */
1965 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1966 boolean didSomething = false;
1967 final int numStacks = mStacks.size();
1968 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1969 final ActivityStack stack = mStacks.get(stackNdx);
1970 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1971 didSomething = true;
1972 }
1973 }
1974 return didSomething;
1975 }
1976
Dianne Hackborna413dc02013-07-12 12:02:55 -07001977 void updatePreviousProcessLocked(ActivityRecord r) {
1978 // Now that this process has stopped, we may want to consider
1979 // it to be the previous app to try to keep around in case
1980 // the user wants to return to it.
1981
1982 // First, found out what is currently the foreground app, so that
1983 // we don't blow away the previous app if this activity is being
1984 // hosted by the process that is actually still the foreground.
1985 ProcessRecord fgApp = null;
1986 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1987 final ActivityStack stack = mStacks.get(stackNdx);
1988 if (isFrontStack(stack)) {
1989 if (stack.mResumedActivity != null) {
1990 fgApp = stack.mResumedActivity.app;
1991 } else if (stack.mPausingActivity != null) {
1992 fgApp = stack.mPausingActivity.app;
1993 }
1994 break;
1995 }
1996 }
1997
1998 // Now set this one as the previous process, only if that really
1999 // makes sense to.
2000 if (r.app != null && fgApp != null && r.app != fgApp
2001 && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
Craig Mautner4ef26932013-09-18 15:15:52 -07002002 && r.app != mService.mHomeProcess) {
Dianne Hackborna413dc02013-07-12 12:02:55 -07002003 mService.mPreviousProcess = r.app;
2004 mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
2005 }
2006 }
2007
Craig Mautner05d29032013-05-03 13:40:13 -07002008 boolean resumeTopActivitiesLocked() {
2009 return resumeTopActivitiesLocked(null, null, null);
2010 }
2011
2012 boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
2013 Bundle targetOptions) {
2014 if (targetStack == null) {
2015 targetStack = getFocusedStack();
2016 }
2017 boolean result = false;
Craig Mautnerdbcb31f2013-04-02 12:32:53 -07002018 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerf88c50f2013-04-18 19:25:12 -07002019 final ActivityStack stack = mStacks.get(stackNdx);
2020 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07002021 if (stack == targetStack) {
2022 result = stack.resumeTopActivityLocked(target, targetOptions);
2023 } else {
2024 stack.resumeTopActivityLocked(null);
2025 }
Craig Mautnerf88c50f2013-04-18 19:25:12 -07002026 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002027 }
Craig Mautner05d29032013-05-03 13:40:13 -07002028 return result;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002029 }
2030
2031 void finishTopRunningActivityLocked(ProcessRecord app) {
2032 final int numStacks = mStacks.size();
2033 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2034 final ActivityStack stack = mStacks.get(stackNdx);
2035 stack.finishTopRunningActivityLocked(app);
2036 }
2037 }
2038
Craig Mautner8d341ef2013-03-26 09:03:27 -07002039 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
2040 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2041 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002042 if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack=" +
Craig Mautner1d001b62013-06-18 16:52:43 -07002043 mStacks.get(stackNdx));
Craig Mautner8d341ef2013-03-26 09:03:27 -07002044 return;
2045 }
2046 }
2047 }
2048
Craig Mautner967212c2013-04-13 21:10:58 -07002049 ActivityStack getStack(int stackId) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002050 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2051 final ActivityStack stack = mStacks.get(stackNdx);
2052 if (stack.getStackId() == stackId) {
2053 return stack;
2054 }
2055 }
2056 return null;
2057 }
2058
Craig Mautner967212c2013-04-13 21:10:58 -07002059 ArrayList<ActivityStack> getStacks() {
2060 return new ArrayList<ActivityStack>(mStacks);
2061 }
2062
2063 int createStack() {
Craig Mautner858d8a62013-04-23 17:08:34 -07002064 while (true) {
2065 if (++mLastStackId <= HOME_STACK_ID) {
2066 mLastStackId = HOME_STACK_ID + 1;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002067 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002068 if (getStack(mLastStackId) == null) {
2069 break;
2070 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002071 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002072 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
2073 return mLastStackId;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002074 }
2075
2076 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07002077 final TaskRecord task = anyTaskForIdLocked(taskId);
2078 if (task == null) {
2079 return;
2080 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002081 final ActivityStack stack = getStack(stackId);
2082 if (stack == null) {
2083 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
2084 return;
2085 }
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07002086 removeTask(task);
2087 stack.addTask(task, toTop);
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07002088 mWindowManager.addTask(taskId, stackId, toTop);
Craig Mautner05d29032013-05-03 13:40:13 -07002089 resumeTopActivitiesLocked();
Craig Mautner8d341ef2013-03-26 09:03:27 -07002090 }
2091
Craig Mautnerac6f8432013-07-17 13:24:59 -07002092 ActivityRecord findTaskLocked(ActivityRecord r) {
Dianne Hackborn2a272d42013-10-16 13:34:33 -07002093 if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07002094 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerac6f8432013-07-17 13:24:59 -07002095 final ActivityStack stack = mStacks.get(stackNdx);
2096 if (!r.isApplicationActivity() && !stack.isHomeStack()) {
Dianne Hackborn2a272d42013-10-16 13:34:33 -07002097 if (DEBUG_TASKS) Slog.d(TAG, "Skipping stack: " + stack);
Craig Mautnerac6f8432013-07-17 13:24:59 -07002098 continue;
2099 }
2100 final ActivityRecord ar = stack.findTaskLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07002101 if (ar != null) {
2102 return ar;
2103 }
2104 }
Dianne Hackborn2a272d42013-10-16 13:34:33 -07002105 if (DEBUG_TASKS) Slog.d(TAG, "No task found");
Craig Mautner8849a5e2013-04-02 16:41:03 -07002106 return null;
2107 }
2108
2109 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
2110 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2111 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
2112 if (ar != null) {
2113 return ar;
2114 }
2115 }
2116 return null;
2117 }
2118
Craig Mautner8d341ef2013-03-26 09:03:27 -07002119 void goingToSleepLocked() {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002120 scheduleSleepTimeout();
2121 if (!mGoingToSleep.isHeld()) {
2122 mGoingToSleep.acquire();
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002123 if (mLaunchingActivity.isHeld()) {
2124 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
2125 throw new IllegalStateException("Calling must be system uid");
Craig Mautner0eea92c2013-05-16 13:35:39 -07002126 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002127 mLaunchingActivity.release();
2128 mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
Craig Mautner0eea92c2013-05-16 13:35:39 -07002129 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002130 }
Amith Yamasanice15e152013-09-19 12:30:32 -07002131 checkReadyForSleepLocked();
Craig Mautner8d341ef2013-03-26 09:03:27 -07002132 }
2133
2134 boolean shutdownLocked(int timeout) {
2135 boolean timedout = false;
Craig Mautner0eea92c2013-05-16 13:35:39 -07002136 goingToSleepLocked();
Craig Mautner0eea92c2013-05-16 13:35:39 -07002137
2138 final long endTime = System.currentTimeMillis() + timeout;
2139 while (true) {
2140 boolean cantShutdown = false;
2141 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2142 cantShutdown |= mStacks.get(stackNdx).checkReadyForSleepLocked();
2143 }
2144 if (cantShutdown) {
2145 long timeRemaining = endTime - System.currentTimeMillis();
2146 if (timeRemaining > 0) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002147 try {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002148 mService.wait(timeRemaining);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002149 } catch (InterruptedException e) {
2150 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002151 } else {
2152 Slog.w(TAG, "Activity manager shutdown timed out");
2153 timedout = true;
2154 break;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002155 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002156 } else {
2157 break;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002158 }
2159 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002160
2161 // Force checkReadyForSleep to complete.
2162 mSleepTimeout = true;
2163 checkReadyForSleepLocked();
2164
Craig Mautner8d341ef2013-03-26 09:03:27 -07002165 return timedout;
2166 }
2167
2168 void comeOutOfSleepIfNeededLocked() {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002169 removeSleepTimeouts();
2170 if (mGoingToSleep.isHeld()) {
2171 mGoingToSleep.release();
2172 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002173 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002174 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002175 stack.awakeFromSleepingLocked();
Craig Mautner5314a402013-09-26 12:40:16 -07002176 if (isFrontStack(stack)) {
2177 resumeTopActivitiesLocked();
2178 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002179 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002180 mGoingToSleepActivities.clear();
2181 }
2182
2183 void activitySleptLocked(ActivityRecord r) {
2184 mGoingToSleepActivities.remove(r);
2185 checkReadyForSleepLocked();
2186 }
2187
2188 void checkReadyForSleepLocked() {
2189 if (!mService.isSleepingOrShuttingDown()) {
2190 // Do not care.
2191 return;
2192 }
2193
2194 if (!mSleepTimeout) {
2195 boolean dontSleep = false;
2196 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2197 dontSleep |= mStacks.get(stackNdx).checkReadyForSleepLocked();
2198 }
2199
2200 if (mStoppingActivities.size() > 0) {
2201 // Still need to tell some activities to stop; can't sleep yet.
2202 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
2203 + mStoppingActivities.size() + " activities");
2204 scheduleIdleLocked();
2205 dontSleep = true;
2206 }
2207
2208 if (mGoingToSleepActivities.size() > 0) {
2209 // Still need to tell some activities to sleep; can't sleep yet.
2210 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
2211 + mGoingToSleepActivities.size() + " activities");
2212 dontSleep = true;
2213 }
2214
2215 if (dontSleep) {
2216 return;
2217 }
2218 }
2219
2220 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2221 mStacks.get(stackNdx).goToSleep();
2222 }
2223
2224 removeSleepTimeouts();
2225
2226 if (mGoingToSleep.isHeld()) {
2227 mGoingToSleep.release();
2228 }
2229 if (mService.mShuttingDown) {
2230 mService.notifyAll();
2231 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002232 }
2233
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002234 boolean reportResumedActivityLocked(ActivityRecord r) {
2235 final ActivityStack stack = r.task.stack;
2236 if (isFrontStack(stack)) {
Jeff Sharkey5782da72013-04-25 14:32:30 -07002237 mService.updateUsageStats(r, true);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002238 }
2239 if (allResumedActivitiesComplete()) {
2240 ensureActivitiesVisibleLocked(null, 0);
2241 mWindowManager.executeAppTransition();
2242 return true;
2243 }
2244 return false;
2245 }
2246
Craig Mautner8d341ef2013-03-26 09:03:27 -07002247 void handleAppCrashLocked(ProcessRecord app) {
2248 final int numStacks = mStacks.size();
2249 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2250 final ActivityStack stack = mStacks.get(stackNdx);
2251 stack.handleAppCrashLocked(app);
2252 }
2253 }
2254
Craig Mautnerde4ef022013-04-07 19:01:33 -07002255 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
Craig Mautner580ea812013-04-25 12:58:38 -07002256 // First the front stacks. In case any are not fullscreen and are in front of home.
2257 boolean showHomeBehindStack = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07002258 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner580ea812013-04-25 12:58:38 -07002259 final ActivityStack stack = mStacks.get(stackNdx);
2260 if (isFrontStack(stack)) {
2261 showHomeBehindStack =
2262 stack.ensureActivitiesVisibleLocked(starting, configChanges);
2263 }
2264 }
2265 // Now do back stacks.
2266 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2267 final ActivityStack stack = mStacks.get(stackNdx);
2268 if (!isFrontStack(stack)) {
2269 stack.ensureActivitiesVisibleLocked(starting, configChanges, showHomeBehindStack);
2270 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002271 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002272 }
2273
2274 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
2275 final int numStacks = mStacks.size();
2276 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2277 final ActivityStack stack = mStacks.get(stackNdx);
2278 stack.scheduleDestroyActivities(app, false, reason);
2279 }
2280 }
2281
2282 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner4f1df4f2013-10-15 15:44:14 -07002283 mUserStackInFront.put(mCurrentUser, getFocusedStack().getStackId());
2284 final int restoreStackId = mUserStackInFront.get(userId, HOME_STACK_ID);
Craig Mautner2420ead2013-04-01 17:13:20 -07002285 mCurrentUser = userId;
Craig Mautnerac6f8432013-07-17 13:24:59 -07002286
Craig Mautner858d8a62013-04-23 17:08:34 -07002287 mStartingUsers.add(uss);
Craig Mautnerac6f8432013-07-17 13:24:59 -07002288 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner93529a42013-10-04 15:03:13 -07002289 mStacks.get(stackNdx).switchUserLocked(userId);
Craig Mautnerac6f8432013-07-17 13:24:59 -07002290 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002291
Craig Mautner4f1df4f2013-10-15 15:44:14 -07002292 ActivityStack stack = getStack(restoreStackId);
2293 if (stack == null) {
2294 stack = mHomeStack;
2295 }
2296 final boolean homeInFront = stack.isHomeStack();
Craig Mautner93529a42013-10-04 15:03:13 -07002297 moveHomeStack(homeInFront);
Craig Mautner4f1df4f2013-10-15 15:44:14 -07002298 mWindowManager.moveTaskToTop(stack.topTask().taskId);
Craig Mautner93529a42013-10-04 15:03:13 -07002299 return homeInFront;
Craig Mautner2219a1b2013-03-25 09:44:30 -07002300 }
2301
Craig Mautnerde4ef022013-04-07 19:01:33 -07002302 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
2303 int N = mStoppingActivities.size();
2304 if (N <= 0) return null;
2305
2306 ArrayList<ActivityRecord> stops = null;
2307
2308 final boolean nowVisible = allResumedActivitiesVisible();
2309 for (int i=0; i<N; i++) {
2310 ActivityRecord s = mStoppingActivities.get(i);
Craig Mautnera7f2bd42013-10-15 16:13:50 -07002311 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
Craig Mautnerde4ef022013-04-07 19:01:33 -07002312 + nowVisible + " waitingVisible=" + s.waitingVisible
2313 + " finishing=" + s.finishing);
2314 if (s.waitingVisible && nowVisible) {
2315 mWaitingVisibleActivities.remove(s);
2316 s.waitingVisible = false;
2317 if (s.finishing) {
2318 // If this activity is finishing, it is sitting on top of
2319 // everyone else but we now know it is no longer needed...
2320 // so get rid of it. Otherwise, we need to go through the
2321 // normal flow and hide it once we determine that it is
2322 // hidden by the activities in front of it.
2323 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002324 mWindowManager.setAppVisibility(s.appToken, false);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002325 }
2326 }
2327 if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
2328 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
2329 if (stops == null) {
2330 stops = new ArrayList<ActivityRecord>();
2331 }
2332 stops.add(s);
2333 mStoppingActivities.remove(i);
2334 N--;
2335 i--;
2336 }
2337 }
2338
2339 return stops;
2340 }
2341
Craig Mautnercf910b02013-04-23 11:23:27 -07002342 void validateTopActivitiesLocked() {
2343 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2344 final ActivityStack stack = mStacks.get(stackNdx);
2345 final ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002346 final ActivityState state = r == null ? ActivityState.DESTROYED : r.state;
Craig Mautnercf910b02013-04-23 11:23:27 -07002347 if (isFrontStack(stack)) {
2348 if (r == null) {
2349 Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
2350 } else {
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002351 final ActivityRecord pausing = stack.mPausingActivity;
2352 if (pausing != null && pausing == r) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002353 Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002354 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002355 }
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002356 if (state != ActivityState.INITIALIZING && state != ActivityState.RESUMED) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002357 Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002358 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002359 }
2360 }
2361 } else {
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002362 final ActivityRecord resumed = stack.mResumedActivity;
2363 if (resumed != null && resumed == r) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002364 Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002365 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002366 }
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002367 if (r != null && (state == ActivityState.INITIALIZING
2368 || state == ActivityState.RESUMED)) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002369 Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002370 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002371 }
2372 }
2373 }
2374 }
2375
Craig Mautner76ea2242013-05-15 11:40:05 -07002376 private static String stackStateToString(int stackState) {
2377 switch (stackState) {
2378 case STACK_STATE_HOME_IN_FRONT: return "STACK_STATE_HOME_IN_FRONT";
2379 case STACK_STATE_HOME_TO_BACK: return "STACK_STATE_HOME_TO_BACK";
2380 case STACK_STATE_HOME_IN_BACK: return "STACK_STATE_HOME_IN_BACK";
2381 case STACK_STATE_HOME_TO_FRONT: return "STACK_STATE_HOME_TO_FRONT";
2382 default: return "Unknown stackState=" + stackState;
2383 }
2384 }
2385
Craig Mautner27084302013-03-25 08:05:25 -07002386 public void dump(PrintWriter pw, String prefix) {
Craig Mautnerd1bbdb4622013-10-22 09:53:20 -07002387 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity=");
Craig Mautner27084302013-03-25 08:05:25 -07002388 pw.println(mDismissKeyguardOnNextActivity);
Craig Mautnerd1bbdb4622013-10-22 09:53:20 -07002389 pw.print(prefix); pw.print("mFocusedStack=" + mFocusedStack);
2390 pw.print(" mStackState="); pw.println(stackStateToString(mStackState));
2391 pw.print(prefix); pw.println("mSleepTimeout=" + mSleepTimeout);
2392 pw.print(prefix); pw.println("mCurTaskId=" + mCurTaskId);
2393 pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront);
Craig Mautner27084302013-03-25 08:05:25 -07002394 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002395
Craig Mautner20e72272013-04-01 13:45:53 -07002396 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002397 return getFocusedStack().getDumpActivitiesLocked(name);
Craig Mautner20e72272013-04-01 13:45:53 -07002398 }
2399
Dianne Hackborn390517b2013-05-30 15:03:32 -07002400 static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
2401 boolean needSep, String prefix) {
2402 if (activity != null) {
2403 if (dumpPackage == null || dumpPackage.equals(activity.packageName)) {
2404 if (needSep) {
2405 pw.println();
Dianne Hackborn390517b2013-05-30 15:03:32 -07002406 }
2407 pw.print(prefix);
2408 pw.println(activity);
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002409 return true;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002410 }
2411 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002412 return false;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002413 }
2414
Craig Mautner8d341ef2013-03-26 09:03:27 -07002415 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
2416 boolean dumpClient, String dumpPackage) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002417 boolean printed = false;
2418 boolean needSep = false;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002419 final int numStacks = mStacks.size();
2420 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2421 final ActivityStack stack = mStacks.get(stackNdx);
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002422 StringBuilder stackHeader = new StringBuilder(128);
2423 stackHeader.append(" Stack #");
2424 stackHeader.append(mStacks.indexOf(stack));
2425 stackHeader.append(":");
2426 printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, needSep,
2427 stackHeader.toString());
2428 printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll,
2429 false, dumpPackage, true, " Running activities (most recent first):", null);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002430
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002431 needSep = printed;
2432 boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002433 " mPausingActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002434 if (pr) {
2435 printed = true;
2436 needSep = false;
2437 }
2438 pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002439 " mResumedActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002440 if (pr) {
2441 printed = true;
2442 needSep = false;
2443 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002444 if (dumpAll) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002445 pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002446 " mLastPausedActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002447 if (pr) {
2448 printed = true;
Craig Mautner0f922742013-08-06 08:44:42 -07002449 needSep = true;
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002450 }
Craig Mautner0f922742013-08-06 08:44:42 -07002451 printed |= printThisActivity(pw, stack.mLastNoHistoryActivity, dumpPackage,
2452 needSep, " mLastNoHistoryActivity: ");
Craig Mautner8d341ef2013-03-26 09:03:27 -07002453 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002454 needSep = printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002455 }
2456
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002457 printed |= dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll,
2458 false, dumpPackage, true, " Activities waiting to finish:", null);
2459 printed |= dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll,
2460 false, dumpPackage, true, " Activities waiting to stop:", null);
2461 printed |= dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
2462 false, dumpPackage, true, " Activities waiting for another to become visible:",
2463 null);
2464 printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll,
2465 false, dumpPackage, true, " Activities waiting to sleep:", null);
2466 printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll,
2467 false, dumpPackage, true, " Activities waiting to sleep:", null);
Craig Mautnerf3333272013-04-22 10:55:53 -07002468
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002469 return printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002470 }
2471
Dianne Hackborn390517b2013-05-30 15:03:32 -07002472 static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
Craig Mautner8d341ef2013-03-26 09:03:27 -07002473 String prefix, String label, boolean complete, boolean brief, boolean client,
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002474 String dumpPackage, boolean needNL, String header1, String header2) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002475 TaskRecord lastTask = null;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002476 String innerPrefix = null;
2477 String[] args = null;
2478 boolean printed = false;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002479 for (int i=list.size()-1; i>=0; i--) {
2480 final ActivityRecord r = list.get(i);
2481 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
2482 continue;
2483 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07002484 if (innerPrefix == null) {
2485 innerPrefix = prefix + " ";
2486 args = new String[0];
2487 }
2488 printed = true;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002489 final boolean full = !brief && (complete || !r.isInHistory());
2490 if (needNL) {
Dianne Hackborn390517b2013-05-30 15:03:32 -07002491 pw.println("");
Craig Mautner8d341ef2013-03-26 09:03:27 -07002492 needNL = false;
2493 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002494 if (header1 != null) {
2495 pw.println(header1);
2496 header1 = null;
2497 }
2498 if (header2 != null) {
2499 pw.println(header2);
2500 header2 = null;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002501 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002502 if (lastTask != r.task) {
2503 lastTask = r.task;
2504 pw.print(prefix);
2505 pw.print(full ? "* " : " ");
2506 pw.println(lastTask);
2507 if (full) {
2508 lastTask.dump(pw, prefix + " ");
2509 } else if (complete) {
2510 // Complete + brief == give a summary. Isn't that obvious?!?
2511 if (lastTask.intent != null) {
2512 pw.print(prefix); pw.print(" ");
2513 pw.println(lastTask.intent.toInsecureStringWithClip());
2514 }
2515 }
2516 }
2517 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
2518 pw.print(" #"); pw.print(i); pw.print(": ");
2519 pw.println(r);
2520 if (full) {
2521 r.dump(pw, innerPrefix);
2522 } else if (complete) {
2523 // Complete + brief == give a summary. Isn't that obvious?!?
2524 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
2525 if (r.app != null) {
2526 pw.print(innerPrefix); pw.println(r.app);
2527 }
2528 }
2529 if (client && r.app != null && r.app.thread != null) {
2530 // flush anything that is already in the PrintWriter since the thread is going
2531 // to write to the file descriptor directly
2532 pw.flush();
2533 try {
2534 TransferPipe tp = new TransferPipe();
2535 try {
2536 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
2537 r.appToken, innerPrefix, args);
2538 // Short timeout, since blocking here can
2539 // deadlock with the application.
2540 tp.go(fd, 2000);
2541 } finally {
2542 tp.kill();
2543 }
2544 } catch (IOException e) {
2545 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
2546 } catch (RemoteException e) {
2547 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
2548 }
2549 needNL = true;
2550 }
2551 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07002552 return printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002553 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002554
Craig Mautnerf3333272013-04-22 10:55:53 -07002555 void scheduleIdleTimeoutLocked(ActivityRecord next) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002556 if (DEBUG_IDLE) Slog.d(TAG, "scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4));
Craig Mautnerc64f73e2013-04-24 16:44:56 -07002557 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
2558 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
Craig Mautnerf3333272013-04-22 10:55:53 -07002559 }
2560
2561 final void scheduleIdleLocked() {
Craig Mautner05d29032013-05-03 13:40:13 -07002562 mHandler.sendEmptyMessage(IDLE_NOW_MSG);
Craig Mautnerf3333272013-04-22 10:55:53 -07002563 }
2564
2565 void removeTimeoutsForActivityLocked(ActivityRecord r) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002566 if (DEBUG_IDLE) Slog.d(TAG, "removeTimeoutsForActivity: Callers=" + Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07002567 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
2568 }
2569
Craig Mautner05d29032013-05-03 13:40:13 -07002570 final void scheduleResumeTopActivities() {
2571 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2572 }
2573
Craig Mautner0eea92c2013-05-16 13:35:39 -07002574 void removeSleepTimeouts() {
2575 mSleepTimeout = false;
2576 mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
2577 }
2578
2579 final void scheduleSleepTimeout() {
2580 removeSleepTimeouts();
2581 mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT);
2582 }
2583
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002584 private final class ActivityStackSupervisorHandler extends Handler {
Craig Mautnerf3333272013-04-22 10:55:53 -07002585
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002586 public ActivityStackSupervisorHandler(Looper looper) {
2587 super(looper);
2588 }
2589
Craig Mautnerf3333272013-04-22 10:55:53 -07002590 void activityIdleInternal(ActivityRecord r) {
2591 synchronized (mService) {
2592 activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
2593 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002594 }
2595
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002596 @Override
2597 public void handleMessage(Message msg) {
2598 switch (msg.what) {
Craig Mautnerf3333272013-04-22 10:55:53 -07002599 case IDLE_TIMEOUT_MSG: {
Craig Mautner5eda9b32013-07-02 11:58:16 -07002600 if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_TIMEOUT_MSG: r=" + msg.obj);
Craig Mautnerf3333272013-04-22 10:55:53 -07002601 if (mService.mDidDexOpt) {
2602 mService.mDidDexOpt = false;
2603 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2604 nmsg.obj = msg.obj;
2605 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
2606 return;
2607 }
2608 // We don't at this point know if the activity is fullscreen,
2609 // so we need to be conservative and assume it isn't.
2610 activityIdleInternal((ActivityRecord)msg.obj);
2611 } break;
2612 case IDLE_NOW_MSG: {
Craig Mautner5eda9b32013-07-02 11:58:16 -07002613 if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_NOW_MSG: r=" + msg.obj);
Craig Mautnerf3333272013-04-22 10:55:53 -07002614 activityIdleInternal((ActivityRecord)msg.obj);
2615 } break;
Craig Mautner05d29032013-05-03 13:40:13 -07002616 case RESUME_TOP_ACTIVITY_MSG: {
2617 synchronized (mService) {
2618 resumeTopActivitiesLocked();
2619 }
2620 } break;
Craig Mautner0eea92c2013-05-16 13:35:39 -07002621 case SLEEP_TIMEOUT_MSG: {
2622 synchronized (mService) {
2623 if (mService.isSleepingOrShuttingDown()) {
2624 Slog.w(TAG, "Sleep timeout! Sleeping now.");
2625 mSleepTimeout = true;
2626 checkReadyForSleepLocked();
2627 }
2628 }
2629 } break;
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002630 case LAUNCH_TIMEOUT_MSG: {
2631 if (mService.mDidDexOpt) {
2632 mService.mDidDexOpt = false;
2633 mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
2634 return;
2635 }
2636 synchronized (mService) {
2637 if (mLaunchingActivity.isHeld()) {
2638 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
2639 if (VALIDATE_WAKE_LOCK_CALLER
2640 && Binder.getCallingUid() != Process.myUid()) {
2641 throw new IllegalStateException("Calling must be system uid");
2642 }
2643 mLaunchingActivity.release();
2644 }
2645 }
2646 } break;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002647 }
2648 }
2649 }
Craig Mautner27084302013-03-25 08:05:25 -07002650}