blob: 7d7fe438fba745d079ef75c467db062a27dd22a8 [file] [log] [blame]
Craig Mautner27084302013-03-25 08:05:25 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Craig Mautner6170f732013-04-02 13:05:23 -070019import static android.Manifest.permission.START_ANY_ACTIVITY;
Craig Mautner29219d92013-04-16 20:19:12 -070020import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
21import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Craig Mautner6170f732013-04-02 13:05:23 -070022import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Craig Mautner2420ead2013-04-01 17:13:20 -070023import static com.android.server.am.ActivityManagerService.localLOGV;
Craig Mautner23ac33b2013-04-01 16:26:35 -070024import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION;
Craig Mautnere7c58b62013-06-12 20:19:00 -070025import static com.android.server.am.ActivityManagerService.DEBUG_FOCUS;
Craig Mautner0eea92c2013-05-16 13:35:39 -070026import static com.android.server.am.ActivityManagerService.DEBUG_PAUSE;
Craig Mautner6170f732013-04-02 13:05:23 -070027import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
Craig Mautner0eea92c2013-05-16 13:35:39 -070028import static com.android.server.am.ActivityManagerService.DEBUG_STACK;
Craig Mautner2420ead2013-04-01 17:13:20 -070029import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
Craig Mautner8849a5e2013-04-02 16:41:03 -070030import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
31import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
Craig Mautner05d29032013-05-03 13:40:13 -070032import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
Craig Mautner8d341ef2013-03-26 09:03:27 -070033import static com.android.server.am.ActivityManagerService.TAG;
34
Craig Mautner2420ead2013-04-01 17:13:20 -070035import android.app.Activity;
Craig Mautner23ac33b2013-04-01 16:26:35 -070036import android.app.ActivityManager;
37import android.app.ActivityOptions;
38import android.app.AppGlobals;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070039import android.app.IActivityManager;
Craig Mautner23ac33b2013-04-01 16:26:35 -070040import android.app.IApplicationThread;
Craig Mautner20e72272013-04-01 13:45:53 -070041import android.app.IThumbnailReceiver;
Craig Mautner23ac33b2013-04-01 16:26:35 -070042import android.app.PendingIntent;
Craig Mautner20e72272013-04-01 13:45:53 -070043import android.app.ActivityManager.RunningTaskInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070044import android.app.IActivityManager.WaitResult;
Craig Mautner2420ead2013-04-01 17:13:20 -070045import android.app.ResultInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070046import android.content.ComponentName;
Craig Mautner2219a1b2013-03-25 09:44:30 -070047import android.content.Context;
Craig Mautner23ac33b2013-04-01 16:26:35 -070048import android.content.IIntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070049import android.content.Intent;
Craig Mautner23ac33b2013-04-01 16:26:35 -070050import android.content.IntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070051import android.content.pm.ActivityInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070052import android.content.pm.ApplicationInfo;
53import android.content.pm.PackageManager;
54import android.content.pm.ResolveInfo;
55import android.content.res.Configuration;
56import android.os.Binder;
Craig Mautner8d341ef2013-03-26 09:03:27 -070057import android.os.Bundle;
Craig Mautnerb59dcfd2013-05-06 13:12:58 -070058import android.os.Debug;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070059import android.os.Handler;
Craig Mautner23ac33b2013-04-01 16:26:35 -070060import android.os.IBinder;
Craig Mautner2219a1b2013-03-25 09:44:30 -070061import android.os.Looper;
Craig Mautner2420ead2013-04-01 17:13:20 -070062import android.os.Message;
Craig Mautner23ac33b2013-04-01 16:26:35 -070063import android.os.ParcelFileDescriptor;
Craig Mautner0eea92c2013-05-16 13:35:39 -070064import android.os.PowerManager;
Craig Mautner7ea5bd42013-07-05 15:27:08 -070065import android.os.Process;
Craig Mautner8d341ef2013-03-26 09:03:27 -070066import android.os.RemoteException;
Craig Mautner23ac33b2013-04-01 16:26:35 -070067import android.os.SystemClock;
Craig Mautner6170f732013-04-02 13:05:23 -070068import android.os.UserHandle;
Craig Mautner2420ead2013-04-01 17:13:20 -070069import android.util.EventLog;
Craig Mautner8d341ef2013-03-26 09:03:27 -070070import android.util.Slog;
Craig Mautner858d8a62013-04-23 17:08:34 -070071import android.util.SparseArray;
Craig Mautner2219a1b2013-03-25 09:44:30 -070072
Craig Mautner93529a42013-10-04 15:03:13 -070073import android.util.SparseBooleanArray;
Craig Mautner23ac33b2013-04-01 16:26:35 -070074import com.android.internal.app.HeavyWeightSwitcherActivity;
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070075import com.android.internal.os.TransferPipe;
Craig Mautner6170f732013-04-02 13:05:23 -070076import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
Craig Mautner2420ead2013-04-01 17:13:20 -070077import com.android.server.am.ActivityStack.ActivityState;
Craig Mautnerde4ef022013-04-07 19:01:33 -070078import com.android.server.wm.StackBox;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070079import com.android.server.wm.WindowManagerService;
Craig Mautner23ac33b2013-04-01 16:26:35 -070080
Craig Mautner8d341ef2013-03-26 09:03:27 -070081import java.io.FileDescriptor;
82import java.io.IOException;
Craig Mautner27084302013-03-25 08:05:25 -070083import java.io.PrintWriter;
Craig Mautner2219a1b2013-03-25 09:44:30 -070084import java.util.ArrayList;
Craig Mautner8d341ef2013-03-26 09:03:27 -070085import java.util.List;
Craig Mautner27084302013-03-25 08:05:25 -070086
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070087public final class ActivityStackSupervisor {
Craig Mautnerde4ef022013-04-07 19:01:33 -070088 static final boolean DEBUG = ActivityManagerService.DEBUG || false;
89 static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
90 static final boolean DEBUG_APP = DEBUG || false;
91 static final boolean DEBUG_SAVED_STATE = DEBUG || false;
Craig Mautnerb3370ce2013-09-19 12:02:09 -070092 static final boolean DEBUG_STATES = DEBUG || true;
Craig Mautnerb59dcfd2013-05-06 13:12:58 -070093 static final boolean DEBUG_IDLE = DEBUG || false;
Craig Mautner2420ead2013-04-01 17:13:20 -070094
Craig Mautner2219a1b2013-03-25 09:44:30 -070095 public static final int HOME_STACK_ID = 0;
Craig Mautner27084302013-03-25 08:05:25 -070096
Craig Mautnerf3333272013-04-22 10:55:53 -070097 /** How long we wait until giving up on the last activity telling us it is idle. */
98 static final int IDLE_TIMEOUT = 10*1000;
99
Craig Mautner0eea92c2013-05-16 13:35:39 -0700100 /** How long we can hold the sleep wake lock before giving up. */
101 static final int SLEEP_TIMEOUT = 5*1000;
102
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700103 // How long we can hold the launch wake lock before giving up.
104 static final int LAUNCH_TIMEOUT = 10*1000;
105
Craig Mautner05d29032013-05-03 13:40:13 -0700106 static final int IDLE_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG;
107 static final int IDLE_NOW_MSG = FIRST_SUPERVISOR_STACK_MSG + 1;
108 static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2;
Craig Mautner0eea92c2013-05-16 13:35:39 -0700109 static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3;
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700110 static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 4;
111
112 // For debugging to make sure the caller when acquiring/releasing our
113 // wake lock is the system process.
114 static final boolean VALIDATE_WAKE_LOCK_CALLER = false;
Craig Mautnerf3333272013-04-22 10:55:53 -0700115
Craig Mautner27084302013-03-25 08:05:25 -0700116 final ActivityManagerService mService;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700117 final Context mContext;
118 final Looper mLooper;
Craig Mautner27084302013-03-25 08:05:25 -0700119
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700120 final ActivityStackSupervisorHandler mHandler;
121
122 /** Short cut */
123 WindowManagerService mWindowManager;
124
Craig Mautner27084302013-03-25 08:05:25 -0700125 /** Dismiss the keyguard after the next activity is displayed? */
Craig Mautner5314a402013-09-26 12:40:16 -0700126 boolean mDismissKeyguardOnNextActivity = false;
Craig Mautner27084302013-03-25 08:05:25 -0700127
Craig Mautner8d341ef2013-03-26 09:03:27 -0700128 /** Identifier counter for all ActivityStacks */
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700129 private int mLastStackId = HOME_STACK_ID;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700130
131 /** Task identifier that activities are currently being started in. Incremented each time a
132 * new task is created. */
133 private int mCurTaskId = 0;
134
Craig Mautner2420ead2013-04-01 17:13:20 -0700135 /** The current user */
136 private int mCurrentUser;
137
Craig Mautner8d341ef2013-03-26 09:03:27 -0700138 /** The stack containing the launcher app */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700139 private ActivityStack mHomeStack;
Craig Mautner20e72272013-04-01 13:45:53 -0700140
Craig Mautnerde4ef022013-04-07 19:01:33 -0700141 /** The non-home stack currently receiving input or launching the next activity. If home is
Craig Mautner41c0f352013-05-28 08:39:25 -0700142 * in front then mHomeStack overrides mFocusedStack.
143 * DO NOT ACCESS DIRECTLY - It may be null, use getFocusedStack() */
Craig Mautner29219d92013-04-16 20:19:12 -0700144 private ActivityStack mFocusedStack;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700145
146 /** All the non-launcher stacks */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700147 private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
148
Craig Mautnerde4ef022013-04-07 19:01:33 -0700149 private static final int STACK_STATE_HOME_IN_FRONT = 0;
150 private static final int STACK_STATE_HOME_TO_BACK = 1;
151 private static final int STACK_STATE_HOME_IN_BACK = 2;
152 private static final int STACK_STATE_HOME_TO_FRONT = 3;
153 private int mStackState = STACK_STATE_HOME_IN_FRONT;
154
155 /** List of activities that are waiting for a new activity to become visible before completing
156 * whatever operation they are supposed to do. */
157 final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();
158
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700159 /** List of processes waiting to find out about the next visible activity. */
160 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible =
161 new ArrayList<IActivityManager.WaitResult>();
162
163 /** List of processes waiting to find out about the next launched activity. */
164 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched =
165 new ArrayList<IActivityManager.WaitResult>();
166
Craig Mautnerde4ef022013-04-07 19:01:33 -0700167 /** List of activities that are ready to be stopped, but waiting for the next activity to
168 * settle down before doing so. */
169 final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();
170
Craig Mautnerf3333272013-04-22 10:55:53 -0700171 /** List of activities that are ready to be finished, but waiting for the previous activity to
172 * settle down before doing so. It contains ActivityRecord objects. */
173 final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<ActivityRecord>();
174
Craig Mautner0eea92c2013-05-16 13:35:39 -0700175 /** List of activities that are in the process of going to sleep. */
176 final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<ActivityRecord>();
177
Craig Mautnerf3333272013-04-22 10:55:53 -0700178 /** List of ActivityRecord objects that have been finished and must still report back to a
179 * pending thumbnail receiver. */
180 final ArrayList<ActivityRecord> mCancelledThumbnails = new ArrayList<ActivityRecord>();
181
182 /** Used on user changes */
183 final ArrayList<UserStartedState> mStartingUsers = new ArrayList<UserStartedState>();
184
Craig Mautnerde4ef022013-04-07 19:01:33 -0700185 /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity
186 * is being brought in front of us. */
187 boolean mUserLeaving = false;
188
Craig Mautner0eea92c2013-05-16 13:35:39 -0700189 /** Set when we have taken too long waiting to go to sleep. */
190 boolean mSleepTimeout = false;
191
192 /**
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700193 * We don't want to allow the device to go to sleep while in the process
194 * of launching an activity. This is primarily to allow alarm intent
195 * receivers to launch an activity and get that to run before the device
196 * goes back to sleep.
197 */
198 final PowerManager.WakeLock mLaunchingActivity;
199
200 /**
Craig Mautner0eea92c2013-05-16 13:35:39 -0700201 * Set when the system is going to sleep, until we have
202 * successfully paused the current activity and released our wake lock.
203 * At that point the system is allowed to actually sleep.
204 */
205 final PowerManager.WakeLock mGoingToSleep;
206
Craig Mautner93529a42013-10-04 15:03:13 -0700207 /** State of the stacks when user switched, indexed by userId. */
208 SparseBooleanArray mUserHomeInFront = new SparseBooleanArray(2);
209
Craig Mautner2219a1b2013-03-25 09:44:30 -0700210 public ActivityStackSupervisor(ActivityManagerService service, Context context,
211 Looper looper) {
Craig Mautner27084302013-03-25 08:05:25 -0700212 mService = service;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700213 mContext = context;
214 mLooper = looper;
Craig Mautner0eea92c2013-05-16 13:35:39 -0700215 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
216 mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700217 mHandler = new ActivityStackSupervisorHandler(looper);
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700218 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
219 throw new IllegalStateException("Calling must be system uid");
220 }
221 mLaunchingActivity =
222 pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
223 mLaunchingActivity.setReferenceCounted(false);
Craig Mautner2219a1b2013-03-25 09:44:30 -0700224 }
225
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700226 void setWindowManager(WindowManagerService wm) {
227 mWindowManager = wm;
228 mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700229 mStacks.add(mHomeStack);
Craig Mautner27084302013-03-25 08:05:25 -0700230 }
231
232 void dismissKeyguard() {
Craig Mautner5314a402013-09-26 12:40:16 -0700233 if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
Craig Mautner27084302013-03-25 08:05:25 -0700234 if (mDismissKeyguardOnNextActivity) {
235 mDismissKeyguardOnNextActivity = false;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700236 mWindowManager.dismissKeyguard();
Craig Mautner27084302013-03-25 08:05:25 -0700237 }
238 }
239
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700240 ActivityStack getFocusedStack() {
Craig Mautnerf88c50f2013-04-18 19:25:12 -0700241 if (mFocusedStack == null) {
242 return mHomeStack;
243 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700244 switch (mStackState) {
245 case STACK_STATE_HOME_IN_FRONT:
246 case STACK_STATE_HOME_TO_FRONT:
247 return mHomeStack;
248 case STACK_STATE_HOME_IN_BACK:
249 case STACK_STATE_HOME_TO_BACK:
250 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700251 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700252 }
Craig Mautner20e72272013-04-01 13:45:53 -0700253 }
254
Craig Mautnerde4ef022013-04-07 19:01:33 -0700255 ActivityStack getLastStack() {
256 switch (mStackState) {
257 case STACK_STATE_HOME_IN_FRONT:
258 case STACK_STATE_HOME_TO_BACK:
259 return mHomeStack;
260 case STACK_STATE_HOME_TO_FRONT:
261 case STACK_STATE_HOME_IN_BACK:
262 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700263 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700264 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700265 }
266
Craig Mautnerde4ef022013-04-07 19:01:33 -0700267 boolean isFrontStack(ActivityStack stack) {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700268 return !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
Craig Mautner20e72272013-04-01 13:45:53 -0700269 }
270
Craig Mautnerde4ef022013-04-07 19:01:33 -0700271 void moveHomeStack(boolean toFront) {
272 final boolean homeInFront = isFrontStack(mHomeStack);
273 if (homeInFront ^ toFront) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700274 if (DEBUG_STACK) Slog.d(TAG, "moveHomeTask: mStackState old=" +
275 stackStateToString(mStackState) + " new=" + stackStateToString(homeInFront ?
276 STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700277 mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
278 }
279 }
280
Craig Mautner69ada552013-04-18 13:51:51 -0700281 boolean resumeHomeActivity(ActivityRecord prev) {
282 moveHomeStack(true);
283 if (prev != null) {
Craig Mautnerae7ecab2013-09-18 11:48:14 -0700284 prev.task.mOnTopOfHome = false;
Craig Mautner69ada552013-04-18 13:51:51 -0700285 }
Craig Mautnera82aa092013-09-13 15:34:08 -0700286 mHomeStack.moveHomeTaskToTop();
Craig Mautnera8a90e02013-06-28 15:24:50 -0700287 ActivityRecord r = mHomeStack.topRunningActivityLocked(null);
288 if (r != null) {
289 mService.setFocusedActivityLocked(r);
Craig Mautner05d29032013-05-03 13:40:13 -0700290 return resumeTopActivitiesLocked(mHomeStack, prev, null);
Craig Mautner69ada552013-04-18 13:51:51 -0700291 }
292 return mService.startHomeActivityLocked(mCurrentUser);
293 }
294
Craig Mautnerde4ef022013-04-07 19:01:33 -0700295 final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r,
296 ActivityStack stack) {
297 if (stack == mHomeStack) {
298 return;
299 }
300 if ((sourceRecord == null && getLastStack() == mHomeStack) ||
Craig Mautner86d67a42013-05-14 10:34:38 -0700301 (sourceRecord != null && sourceRecord.isHomeActivity())) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700302 if (r == null) {
303 r = stack.topRunningActivityLocked(null);
304 }
Craig Mautner86d67a42013-05-14 10:34:38 -0700305 if (r != null && !r.isHomeActivity() && r.isRootActivity()) {
Craig Mautnerae7ecab2013-09-18 11:48:14 -0700306 r.task.mOnTopOfHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700307 }
308 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700309 }
310
Craig Mautner27084302013-03-25 08:05:25 -0700311 void setDismissKeyguard(boolean dismiss) {
Craig Mautner5314a402013-09-26 12:40:16 -0700312 if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen(" dismiss=" + dismiss);
Craig Mautner27084302013-03-25 08:05:25 -0700313 mDismissKeyguardOnNextActivity = dismiss;
314 }
315
Craig Mautner8d341ef2013-03-26 09:03:27 -0700316 TaskRecord anyTaskForIdLocked(int id) {
317 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
318 ActivityStack stack = mStacks.get(stackNdx);
319 TaskRecord task = stack.taskForIdLocked(id);
320 if (task != null) {
321 return task;
322 }
323 }
324 return null;
325 }
326
Craig Mautner6170f732013-04-02 13:05:23 -0700327 ActivityRecord isInAnyStackLocked(IBinder token) {
328 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
329 final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
330 if (r != null) {
331 return r;
332 }
333 }
334 return null;
335 }
336
Craig Mautner8d341ef2013-03-26 09:03:27 -0700337 int getNextTaskId() {
338 do {
339 mCurTaskId++;
340 if (mCurTaskId <= 0) {
341 mCurTaskId = 1;
342 }
343 } while (anyTaskForIdLocked(mCurTaskId) != null);
344 return mCurTaskId;
345 }
346
Craig Mautnerde4ef022013-04-07 19:01:33 -0700347 void removeTask(TaskRecord task) {
Craig Mautnerb3b36ba2013-05-20 13:21:10 -0700348 mWindowManager.removeTask(task.taskId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700349 final ActivityStack stack = task.stack;
Craig Mautnerb3b36ba2013-05-20 13:21:10 -0700350 final ActivityRecord r = stack.mResumedActivity;
351 if (r != null && r.task == task) {
352 stack.mResumedActivity = null;
353 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700354 if (stack.removeTask(task) && !stack.isHomeStack()) {
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700355 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700356 mStacks.remove(stack);
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700357 final int stackId = stack.mStackId;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700358 final int nextStackId = mWindowManager.removeStack(stackId);
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700359 // TODO: Perhaps we need to let the ActivityManager determine the next focus...
Craig Mautnerac6f8432013-07-17 13:24:59 -0700360 if (mFocusedStack == null || mFocusedStack.mStackId == stackId) {
Craig Mautner1602ec22013-05-12 10:24:27 -0700361 // If this is the last app stack, set mFocusedStack to null.
Craig Mautner29219d92013-04-16 20:19:12 -0700362 mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700363 }
364 }
365 }
366
367 ActivityRecord resumedAppLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700368 ActivityStack stack = getFocusedStack();
369 if (stack == null) {
370 return null;
371 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700372 ActivityRecord resumedActivity = stack.mResumedActivity;
373 if (resumedActivity == null || resumedActivity.app == null) {
374 resumedActivity = stack.mPausingActivity;
375 if (resumedActivity == null || resumedActivity.app == null) {
376 resumedActivity = stack.topRunningActivityLocked(null);
377 }
378 }
379 return resumedActivity;
380 }
381
Craig Mautner20e72272013-04-01 13:45:53 -0700382 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
383 boolean didSomething = false;
384 final String processName = app.processName;
385 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
386 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner858d8a62013-04-23 17:08:34 -0700387 if (!isFrontStack(stack)) {
388 continue;
389 }
Craig Mautner20e72272013-04-01 13:45:53 -0700390 ActivityRecord hr = stack.topRunningActivityLocked(null);
391 if (hr != null) {
392 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
393 && processName.equals(hr.processName)) {
394 try {
395 if (headless) {
396 Slog.e(TAG, "Starting activities not supported on headless device: "
397 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700398 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700399 didSomething = true;
400 }
401 } catch (Exception e) {
402 Slog.w(TAG, "Exception in new application when starting activity "
403 + hr.intent.getComponent().flattenToShortString(), e);
404 throw e;
405 }
Craig Mautner20e72272013-04-01 13:45:53 -0700406 }
407 }
408 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -0700409 if (!didSomething) {
410 ensureActivitiesVisibleLocked(null, 0);
411 }
Craig Mautner20e72272013-04-01 13:45:53 -0700412 return didSomething;
413 }
414
415 boolean allResumedActivitiesIdle() {
416 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700417 final ActivityStack stack = mStacks.get(stackNdx);
418 if (!isFrontStack(stack)) {
419 continue;
420 }
421 final ActivityRecord resumedActivity = stack.mResumedActivity;
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700422 if (resumedActivity == null || !resumedActivity.idle) {
Craig Mautner20e72272013-04-01 13:45:53 -0700423 return false;
424 }
425 }
426 return true;
427 }
428
Craig Mautnerde4ef022013-04-07 19:01:33 -0700429 boolean allResumedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700430 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
431 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner967212c2013-04-13 21:10:58 -0700432 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700433 final ActivityRecord r = stack.mResumedActivity;
434 if (r != null && r.state != ActivityState.RESUMED) {
435 return false;
436 }
437 }
438 }
439 // TODO: Not sure if this should check if all Paused are complete too.
440 switch (mStackState) {
441 case STACK_STATE_HOME_TO_BACK:
Craig Mautner76ea2242013-05-15 11:40:05 -0700442 if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
443 stackStateToString(STACK_STATE_HOME_TO_BACK) + " new=" +
444 stackStateToString(STACK_STATE_HOME_IN_BACK));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700445 mStackState = STACK_STATE_HOME_IN_BACK;
446 break;
447 case STACK_STATE_HOME_TO_FRONT:
Craig Mautner76ea2242013-05-15 11:40:05 -0700448 if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
449 stackStateToString(STACK_STATE_HOME_TO_FRONT) + " new=" +
450 stackStateToString(STACK_STATE_HOME_IN_FRONT));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700451 mStackState = STACK_STATE_HOME_IN_FRONT;
452 break;
453 }
454 return true;
455 }
456
457 boolean allResumedActivitiesVisible() {
458 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
459 final ActivityStack stack = mStacks.get(stackNdx);
460 final ActivityRecord r = stack.mResumedActivity;
461 if (r != null && (!r.nowVisible || r.waitingVisible)) {
462 return false;
463 }
464 }
465 return true;
466 }
467
Craig Mautner2acc3892013-09-23 10:28:14 -0700468 /**
469 * Pause all activities in either all of the stacks or just the back stacks.
470 * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
Craig Mautner2acc3892013-09-23 10:28:14 -0700471 * @return true if any activity was paused as a result of this call.
472 */
Craig Mautner5314a402013-09-26 12:40:16 -0700473 boolean pauseBackStacks(boolean userLeaving) {
Craig Mautnercf910b02013-04-23 11:23:27 -0700474 boolean someActivityPaused = false;
475 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
476 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner5314a402013-09-26 12:40:16 -0700477 if (!isFrontStack(stack) && stack.mResumedActivity != null) {
478 if (DEBUG_STATES) Slog.d(TAG, "pauseBackStacks: stack=" + stack +
Craig Mautnerac6f8432013-07-17 13:24:59 -0700479 " mResumedActivity=" + stack.mResumedActivity);
Craig Mautnercf910b02013-04-23 11:23:27 -0700480 stack.startPausingLocked(userLeaving, false);
481 someActivityPaused = true;
482 }
483 }
484 return someActivityPaused;
485 }
486
Craig Mautnerde4ef022013-04-07 19:01:33 -0700487 boolean allPausedActivitiesComplete() {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700488 boolean pausing = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700489 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
490 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner69ada552013-04-18 13:51:51 -0700491 final ActivityRecord r = stack.mPausingActivity;
492 if (r != null && r.state != ActivityState.PAUSED
493 && r.state != ActivityState.STOPPED
494 && r.state != ActivityState.STOPPING) {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700495 if (DEBUG_STATES) {
496 Slog.d(TAG, "allPausedActivitiesComplete: r=" + r + " state=" + r.state);
497 pausing = false;
498 } else {
499 return false;
500 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700501 }
502 }
Craig Mautnerac6f8432013-07-17 13:24:59 -0700503 return pausing;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700504 }
505
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700506 void reportActivityVisibleLocked(ActivityRecord r) {
Craig Mautner858d8a62013-04-23 17:08:34 -0700507 for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700508 WaitResult w = mWaitingActivityVisible.get(i);
509 w.timeout = false;
510 if (r != null) {
511 w.who = new ComponentName(r.info.packageName, r.info.name);
512 }
513 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
514 w.thisTime = w.totalTime;
515 }
516 mService.notifyAll();
517 dismissKeyguard();
518 }
519
520 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
521 long thisTime, long totalTime) {
522 for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
Craig Mautnerc64f73e2013-04-24 16:44:56 -0700523 WaitResult w = mWaitingActivityLaunched.remove(i);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700524 w.timeout = timeout;
525 if (r != null) {
526 w.who = new ComponentName(r.info.packageName, r.info.name);
527 }
528 w.thisTime = thisTime;
529 w.totalTime = totalTime;
530 }
531 mService.notifyAll();
532 }
533
Craig Mautner29219d92013-04-16 20:19:12 -0700534 ActivityRecord topRunningActivityLocked() {
Craig Mautner1602ec22013-05-12 10:24:27 -0700535 final ActivityStack focusedStack = getFocusedStack();
536 ActivityRecord r = focusedStack.topRunningActivityLocked(null);
537 if (r != null) {
538 return r;
Craig Mautner29219d92013-04-16 20:19:12 -0700539 }
Craig Mautner1602ec22013-05-12 10:24:27 -0700540
Craig Mautner29219d92013-04-16 20:19:12 -0700541 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
542 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700543 if (stack != focusedStack && isFrontStack(stack)) {
Craig Mautner29219d92013-04-16 20:19:12 -0700544 r = stack.topRunningActivityLocked(null);
545 if (r != null) {
546 return r;
547 }
548 }
549 }
550 return null;
551 }
552
Craig Mautner20e72272013-04-01 13:45:53 -0700553 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
554 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
555 ActivityRecord r = null;
Craig Mautnerc0fd8052013-09-19 11:20:17 -0700556
557 // Gather all of the running tasks for each stack into runningTaskLists.
558 final int numStacks = mStacks.size();
559 ArrayList<RunningTaskInfo>[] runningTaskLists = new ArrayList[numStacks];
560 for (int stackNdx = numStacks - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner20e72272013-04-01 13:45:53 -0700561 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerc0fd8052013-09-19 11:20:17 -0700562 ArrayList<RunningTaskInfo> stackTaskList = new ArrayList<RunningTaskInfo>();
563 runningTaskLists[stackNdx] = stackTaskList;
564 final ActivityRecord ar = stack.getTasksLocked(receiver, pending, stackTaskList);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700565 if (isFrontStack(stack)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700566 r = ar;
567 }
568 }
Craig Mautnerc0fd8052013-09-19 11:20:17 -0700569
570 // The lists are already sorted from most recent to oldest. Just pull the most recent off
571 // each list and add it to list. Stop when all lists are empty or maxNum reached.
572 while (maxNum > 0) {
573 long mostRecentActiveTime = Long.MIN_VALUE;
574 ArrayList<RunningTaskInfo> selectedStackList = null;
575 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
576 ArrayList<RunningTaskInfo> stackTaskList = runningTaskLists[stackNdx];
577 if (!stackTaskList.isEmpty()) {
578 final long lastActiveTime = stackTaskList.get(0).lastActiveTime;
579 if (lastActiveTime > mostRecentActiveTime) {
580 mostRecentActiveTime = lastActiveTime;
581 selectedStackList = stackTaskList;
582 }
583 }
584 }
585 if (selectedStackList != null) {
586 list.add(selectedStackList.remove(0));
587 --maxNum;
588 } else {
589 break;
590 }
591 }
592
Craig Mautner20e72272013-04-01 13:45:53 -0700593 return r;
594 }
595
Craig Mautner23ac33b2013-04-01 16:26:35 -0700596 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
597 String profileFile, ParcelFileDescriptor profileFd, int userId) {
598 // Collect information about the target of the Intent.
599 ActivityInfo aInfo;
600 try {
601 ResolveInfo rInfo =
602 AppGlobals.getPackageManager().resolveIntent(
603 intent, resolvedType,
604 PackageManager.MATCH_DEFAULT_ONLY
605 | ActivityManagerService.STOCK_PM_FLAGS, userId);
606 aInfo = rInfo != null ? rInfo.activityInfo : null;
607 } catch (RemoteException e) {
608 aInfo = null;
609 }
610
611 if (aInfo != null) {
612 // Store the found target back into the intent, because now that
613 // we have it we never want to do this again. For example, if the
614 // user navigates back to this point in the history, we should
615 // always restart the exact same activity.
616 intent.setComponent(new ComponentName(
617 aInfo.applicationInfo.packageName, aInfo.name));
618
619 // Don't debug things in the system process
620 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
621 if (!aInfo.processName.equals("system")) {
622 mService.setDebugApp(aInfo.processName, true, false);
623 }
624 }
625
626 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
627 if (!aInfo.processName.equals("system")) {
628 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
629 }
630 }
631
632 if (profileFile != null) {
633 if (!aInfo.processName.equals("system")) {
634 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
635 profileFile, profileFd,
636 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
637 }
638 }
639 }
640 return aInfo;
641 }
642
Craig Mautner2219a1b2013-03-25 09:44:30 -0700643 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700644 moveHomeStack(true);
Craig Mautner6170f732013-04-02 13:05:23 -0700645 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
Craig Mautner2219a1b2013-03-25 09:44:30 -0700646 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700647 }
648
Craig Mautner23ac33b2013-04-01 16:26:35 -0700649 final int startActivityMayWait(IApplicationThread caller, int callingUid,
650 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
651 String resultWho, int requestCode, int startFlags, String profileFile,
652 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
653 Bundle options, int userId) {
654 // Refuse possible leaked file descriptors
655 if (intent != null && intent.hasFileDescriptors()) {
656 throw new IllegalArgumentException("File descriptors passed in Intent");
657 }
658 boolean componentSpecified = intent.getComponent() != null;
659
660 // Don't modify the client's object!
661 intent = new Intent(intent);
662
663 // Collect information about the target of the Intent.
664 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
665 profileFile, profileFd, userId);
666
667 synchronized (mService) {
668 int callingPid;
669 if (callingUid >= 0) {
670 callingPid = -1;
671 } else if (caller == null) {
672 callingPid = Binder.getCallingPid();
673 callingUid = Binder.getCallingUid();
674 } else {
675 callingPid = callingUid = -1;
676 }
677
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700678 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -0700679 stack.mConfigWillChange = config != null
Craig Mautner23ac33b2013-04-01 16:26:35 -0700680 && mService.mConfiguration.diff(config) != 0;
681 if (DEBUG_CONFIGURATION) Slog.v(TAG,
Craig Mautnerde4ef022013-04-07 19:01:33 -0700682 "Starting activity when config will change = " + stack.mConfigWillChange);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700683
684 final long origId = Binder.clearCallingIdentity();
685
686 if (aInfo != null &&
687 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
688 // This may be a heavy-weight process! Check to see if we already
689 // have another, different heavy-weight process running.
690 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
691 if (mService.mHeavyWeightProcess != null &&
692 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
693 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700694 int realCallingUid = callingUid;
695 if (caller != null) {
696 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
697 if (callerApp != null) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700698 realCallingUid = callerApp.info.uid;
699 } else {
700 Slog.w(TAG, "Unable to find app for caller " + caller
Craig Mautner76ea2242013-05-15 11:40:05 -0700701 + " (pid=" + callingPid + ") when starting: "
Craig Mautner23ac33b2013-04-01 16:26:35 -0700702 + intent.toString());
703 ActivityOptions.abort(options);
704 return ActivityManager.START_PERMISSION_DENIED;
705 }
706 }
707
708 IIntentSender target = mService.getIntentSenderLocked(
709 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
710 realCallingUid, userId, null, null, 0, new Intent[] { intent },
711 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
712 | PendingIntent.FLAG_ONE_SHOT, null);
713
714 Intent newIntent = new Intent();
715 if (requestCode >= 0) {
716 // Caller is requesting a result.
717 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
718 }
719 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
720 new IntentSender(target));
721 if (mService.mHeavyWeightProcess.activities.size() > 0) {
722 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
723 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
724 hist.packageName);
725 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
726 hist.task.taskId);
727 }
728 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
729 aInfo.packageName);
730 newIntent.setFlags(intent.getFlags());
731 newIntent.setClassName("android",
732 HeavyWeightSwitcherActivity.class.getName());
733 intent = newIntent;
734 resolvedType = null;
735 caller = null;
736 callingUid = Binder.getCallingUid();
737 callingPid = Binder.getCallingPid();
738 componentSpecified = true;
739 try {
740 ResolveInfo rInfo =
741 AppGlobals.getPackageManager().resolveIntent(
742 intent, null,
743 PackageManager.MATCH_DEFAULT_ONLY
744 | ActivityManagerService.STOCK_PM_FLAGS, userId);
745 aInfo = rInfo != null ? rInfo.activityInfo : null;
746 aInfo = mService.getActivityInfoForUser(aInfo, userId);
747 } catch (RemoteException e) {
748 aInfo = null;
749 }
750 }
751 }
752 }
753
Craig Mautner6170f732013-04-02 13:05:23 -0700754 int res = startActivityLocked(caller, intent, resolvedType,
Craig Mautner23ac33b2013-04-01 16:26:35 -0700755 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
756 callingPackage, startFlags, options, componentSpecified, null);
757
Craig Mautnerde4ef022013-04-07 19:01:33 -0700758 if (stack.mConfigWillChange) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700759 // If the caller also wants to switch to a new configuration,
760 // do so now. This allows a clean switch, as we are waiting
761 // for the current activity to pause (so we will not destroy
762 // it), and have not yet started the next activity.
763 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
764 "updateConfiguration()");
Craig Mautnerde4ef022013-04-07 19:01:33 -0700765 stack.mConfigWillChange = false;
Craig Mautner23ac33b2013-04-01 16:26:35 -0700766 if (DEBUG_CONFIGURATION) Slog.v(TAG,
767 "Updating to new configuration after starting activity.");
768 mService.updateConfigurationLocked(config, null, false, false);
769 }
770
771 Binder.restoreCallingIdentity(origId);
772
773 if (outResult != null) {
774 outResult.result = res;
775 if (res == ActivityManager.START_SUCCESS) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700776 mWaitingActivityLaunched.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700777 do {
778 try {
779 mService.wait();
780 } catch (InterruptedException e) {
781 }
782 } while (!outResult.timeout && outResult.who == null);
783 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700784 ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700785 if (r.nowVisible) {
786 outResult.timeout = false;
787 outResult.who = new ComponentName(r.info.packageName, r.info.name);
788 outResult.totalTime = 0;
789 outResult.thisTime = 0;
790 } else {
791 outResult.thisTime = SystemClock.uptimeMillis();
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700792 mWaitingActivityVisible.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700793 do {
794 try {
795 mService.wait();
796 } catch (InterruptedException e) {
797 }
798 } while (!outResult.timeout && outResult.who == null);
799 }
800 }
801 }
802
803 return res;
804 }
805 }
806
807 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
808 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
809 Bundle options, int userId) {
810 if (intents == null) {
811 throw new NullPointerException("intents is null");
812 }
813 if (resolvedTypes == null) {
814 throw new NullPointerException("resolvedTypes is null");
815 }
816 if (intents.length != resolvedTypes.length) {
817 throw new IllegalArgumentException("intents are length different than resolvedTypes");
818 }
819
Craig Mautner23ac33b2013-04-01 16:26:35 -0700820
821 int callingPid;
822 if (callingUid >= 0) {
823 callingPid = -1;
824 } else if (caller == null) {
825 callingPid = Binder.getCallingPid();
826 callingUid = Binder.getCallingUid();
827 } else {
828 callingPid = callingUid = -1;
829 }
830 final long origId = Binder.clearCallingIdentity();
831 try {
832 synchronized (mService) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700833 ActivityRecord[] outActivity = new ActivityRecord[1];
Craig Mautner23ac33b2013-04-01 16:26:35 -0700834 for (int i=0; i<intents.length; i++) {
835 Intent intent = intents[i];
836 if (intent == null) {
837 continue;
838 }
839
840 // Refuse possible leaked file descriptors
841 if (intent != null && intent.hasFileDescriptors()) {
842 throw new IllegalArgumentException("File descriptors passed in Intent");
843 }
844
845 boolean componentSpecified = intent.getComponent() != null;
846
847 // Don't modify the client's object!
848 intent = new Intent(intent);
849
850 // Collect information about the target of the Intent.
851 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
852 0, null, null, userId);
853 // TODO: New, check if this is correct
854 aInfo = mService.getActivityInfoForUser(aInfo, userId);
855
856 if (aInfo != null &&
857 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
858 != 0) {
859 throw new IllegalArgumentException(
860 "FLAG_CANT_SAVE_STATE not supported here");
861 }
862
863 Bundle theseOptions;
864 if (options != null && i == intents.length-1) {
865 theseOptions = options;
866 } else {
867 theseOptions = null;
868 }
Craig Mautner6170f732013-04-02 13:05:23 -0700869 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Craig Mautner23ac33b2013-04-01 16:26:35 -0700870 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
871 0, theseOptions, componentSpecified, outActivity);
872 if (res < 0) {
873 return res;
874 }
875
876 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
877 }
878 }
879 } finally {
880 Binder.restoreCallingIdentity(origId);
881 }
882
883 return ActivityManager.START_SUCCESS;
884 }
885
Craig Mautner2420ead2013-04-01 17:13:20 -0700886 final boolean realStartActivityLocked(ActivityRecord r,
887 ProcessRecord app, boolean andResume, boolean checkConfig)
888 throws RemoteException {
889
890 r.startFreezingScreenLocked(app, 0);
Craig Mautner323f7802013-10-01 21:16:22 -0700891 if (true) Slog.d(TAG, "realStartActivity: setting app visibility true");
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700892 mWindowManager.setAppVisibility(r.appToken, true);
Craig Mautner2420ead2013-04-01 17:13:20 -0700893
894 // schedule launch ticks to collect information about slow apps.
895 r.startLaunchTickingLocked();
896
897 // Have the window manager re-evaluate the orientation of
898 // the screen based on the new activity order. Note that
899 // as a result of this, it can call back into the activity
900 // manager with a new orientation. We don't care about that,
901 // because the activity is not currently running so we are
902 // just restarting it anyway.
903 if (checkConfig) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700904 Configuration config = mWindowManager.updateOrientationFromAppTokens(
Craig Mautner2420ead2013-04-01 17:13:20 -0700905 mService.mConfiguration,
906 r.mayFreezeScreenLocked(app) ? r.appToken : null);
907 mService.updateConfigurationLocked(config, r, false, false);
908 }
909
910 r.app = app;
911 app.waitingToKill = null;
912 r.launchCount++;
913 r.lastLaunchTime = SystemClock.uptimeMillis();
914
915 if (localLOGV) Slog.v(TAG, "Launching: " + r);
916
917 int idx = app.activities.indexOf(r);
918 if (idx < 0) {
919 app.activities.add(r);
920 }
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -0700921 mService.updateLruProcessLocked(app, true, true);
Craig Mautner2420ead2013-04-01 17:13:20 -0700922
923 final ActivityStack stack = r.task.stack;
924 try {
925 if (app.thread == null) {
926 throw new RemoteException();
927 }
928 List<ResultInfo> results = null;
929 List<Intent> newIntents = null;
930 if (andResume) {
931 results = r.results;
932 newIntents = r.newIntents;
933 }
934 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
935 + " icicle=" + r.icicle
936 + " with results=" + results + " newIntents=" + newIntents
937 + " andResume=" + andResume);
938 if (andResume) {
939 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
940 r.userId, System.identityHashCode(r),
941 r.task.taskId, r.shortComponentName);
942 }
Craig Mautnerac6f8432013-07-17 13:24:59 -0700943 if (r.isHomeActivity() && r.isNotResolverActivity()) {
Craig Mautner4ef26932013-09-18 15:15:52 -0700944 // Home process is the root process of the task.
945 mService.mHomeProcess = r.task.mActivities.get(0).app;
Craig Mautner2420ead2013-04-01 17:13:20 -0700946 }
947 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
948 r.sleeping = false;
949 r.forceNewConfig = false;
950 mService.showAskCompatModeDialogLocked(r);
951 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
952 String profileFile = null;
953 ParcelFileDescriptor profileFd = null;
954 boolean profileAutoStop = false;
955 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
956 if (mService.mProfileProc == null || mService.mProfileProc == app) {
957 mService.mProfileProc = app;
958 profileFile = mService.mProfileFile;
959 profileFd = mService.mProfileFd;
960 profileAutoStop = mService.mAutoStopProfiler;
961 }
962 }
963 app.hasShownUi = true;
964 app.pendingUiClean = true;
965 if (profileFd != null) {
966 try {
967 profileFd = profileFd.dup();
968 } catch (IOException e) {
969 if (profileFd != null) {
970 try {
971 profileFd.close();
972 } catch (IOException o) {
973 }
974 profileFd = null;
975 }
976 }
977 }
Dianne Hackborna413dc02013-07-12 12:02:55 -0700978 app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
Craig Mautner2420ead2013-04-01 17:13:20 -0700979 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
980 System.identityHashCode(r), r.info,
Dianne Hackborna413dc02013-07-12 12:02:55 -0700981 new Configuration(mService.mConfiguration), r.compat,
982 app.repProcState, r.icicle, results, newIntents, !andResume,
Craig Mautner2420ead2013-04-01 17:13:20 -0700983 mService.isNextTransitionForward(), profileFile, profileFd,
984 profileAutoStop);
985
986 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
987 // This may be a heavy-weight process! Note that the package
988 // manager will ensure that only activity can run in the main
989 // process of the .apk, which is the only thing that will be
990 // considered heavy-weight.
991 if (app.processName.equals(app.info.packageName)) {
992 if (mService.mHeavyWeightProcess != null
993 && mService.mHeavyWeightProcess != app) {
994 Slog.w(TAG, "Starting new heavy weight process " + app
995 + " when already running "
996 + mService.mHeavyWeightProcess);
997 }
998 mService.mHeavyWeightProcess = app;
999 Message msg = mService.mHandler.obtainMessage(
1000 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
1001 msg.obj = r;
1002 mService.mHandler.sendMessage(msg);
1003 }
1004 }
1005
1006 } catch (RemoteException e) {
1007 if (r.launchFailed) {
1008 // This is the second time we failed -- finish activity
1009 // and give up.
1010 Slog.e(TAG, "Second failure launching "
1011 + r.intent.getComponent().flattenToShortString()
1012 + ", giving up", e);
1013 mService.appDiedLocked(app, app.pid, app.thread);
1014 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
1015 "2nd-crash", false);
1016 return false;
1017 }
1018
1019 // This is the first time we failed -- restart process and
1020 // retry.
1021 app.activities.remove(r);
1022 throw e;
1023 }
1024
1025 r.launchFailed = false;
1026 if (stack.updateLRUListLocked(r)) {
1027 Slog.w(TAG, "Activity " + r
1028 + " being launched, but already in LRU list");
1029 }
1030
1031 if (andResume) {
1032 // As part of the process of launching, ActivityThread also performs
1033 // a resume.
1034 stack.minimalResumeActivityLocked(r);
1035 } else {
1036 // This activity is not starting in the resumed state... which
1037 // should look like we asked it to pause+stop (but remain visible),
1038 // and it has done so and reported back the current icicle and
1039 // other state.
1040 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
1041 + " (starting in stopped state)");
1042 r.state = ActivityState.STOPPED;
1043 r.stopped = true;
1044 }
1045
1046 // Launch the new version setup screen if needed. We do this -after-
1047 // launching the initial activity (that is, home), so that it can have
1048 // a chance to initialize itself while in the background, making the
1049 // switch back to it faster and look better.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001050 if (isFrontStack(stack)) {
Craig Mautner2420ead2013-04-01 17:13:20 -07001051 mService.startSetupActivityLocked();
1052 }
1053
1054 return true;
1055 }
1056
Craig Mautnere79d42682013-04-01 19:01:53 -07001057 void startSpecificActivityLocked(ActivityRecord r,
1058 boolean andResume, boolean checkConfig) {
1059 // Is this activity's application already running?
1060 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07001061 r.info.applicationInfo.uid, true);
Craig Mautnere79d42682013-04-01 19:01:53 -07001062
1063 r.task.stack.setLaunchTime(r);
1064
1065 if (app != null && app.thread != null) {
1066 try {
Dianne Hackbornd2932242013-08-05 18:18:42 -07001067 app.addPackage(r.info.packageName, mService.mProcessStats);
Craig Mautnere79d42682013-04-01 19:01:53 -07001068 realStartActivityLocked(r, app, andResume, checkConfig);
1069 return;
1070 } catch (RemoteException e) {
1071 Slog.w(TAG, "Exception when starting activity "
1072 + r.intent.getComponent().flattenToShortString(), e);
1073 }
1074
1075 // If a dead object exception was thrown -- fall through to
1076 // restart the application.
1077 }
1078
1079 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07001080 "activity", r.intent.getComponent(), false, false, true);
Craig Mautnere79d42682013-04-01 19:01:53 -07001081 }
1082
Craig Mautner6170f732013-04-02 13:05:23 -07001083 final int startActivityLocked(IApplicationThread caller,
1084 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
1085 String resultWho, int requestCode,
1086 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
1087 boolean componentSpecified, ActivityRecord[] outActivity) {
1088 int err = ActivityManager.START_SUCCESS;
1089
1090 ProcessRecord callerApp = null;
1091 if (caller != null) {
1092 callerApp = mService.getRecordForAppLocked(caller);
1093 if (callerApp != null) {
1094 callingPid = callerApp.pid;
1095 callingUid = callerApp.info.uid;
1096 } else {
1097 Slog.w(TAG, "Unable to find app for caller " + caller
1098 + " (pid=" + callingPid + ") when starting: "
1099 + intent.toString());
1100 err = ActivityManager.START_PERMISSION_DENIED;
1101 }
1102 }
1103
1104 if (err == ActivityManager.START_SUCCESS) {
1105 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
1106 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
1107 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
1108 }
1109
1110 ActivityRecord sourceRecord = null;
1111 ActivityRecord resultRecord = null;
1112 if (resultTo != null) {
1113 sourceRecord = isInAnyStackLocked(resultTo);
1114 if (DEBUG_RESULTS) Slog.v(
1115 TAG, "Will send result to " + resultTo + " " + sourceRecord);
1116 if (sourceRecord != null) {
1117 if (requestCode >= 0 && !sourceRecord.finishing) {
1118 resultRecord = sourceRecord;
1119 }
1120 }
1121 }
1122 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
1123
1124 int launchFlags = intent.getFlags();
1125
1126 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
1127 && sourceRecord != null) {
1128 // Transfer the result target from the source activity to the new
1129 // one being started, including any failures.
1130 if (requestCode >= 0) {
1131 ActivityOptions.abort(options);
1132 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
1133 }
1134 resultRecord = sourceRecord.resultTo;
1135 resultWho = sourceRecord.resultWho;
1136 requestCode = sourceRecord.requestCode;
1137 sourceRecord.resultTo = null;
1138 if (resultRecord != null) {
1139 resultRecord.removeResultsLocked(
1140 sourceRecord, resultWho, requestCode);
1141 }
1142 }
1143
1144 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
1145 // We couldn't find a class that can handle the given Intent.
1146 // That's the end of that!
1147 err = ActivityManager.START_INTENT_NOT_RESOLVED;
1148 }
1149
1150 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
1151 // We couldn't find the specific class specified in the Intent.
1152 // Also the end of the line.
1153 err = ActivityManager.START_CLASS_NOT_FOUND;
1154 }
1155
1156 if (err != ActivityManager.START_SUCCESS) {
1157 if (resultRecord != null) {
1158 resultStack.sendActivityResultLocked(-1,
1159 resultRecord, resultWho, requestCode,
1160 Activity.RESULT_CANCELED, null);
1161 }
1162 setDismissKeyguard(false);
1163 ActivityOptions.abort(options);
1164 return err;
1165 }
1166
1167 final int startAnyPerm = mService.checkPermission(
1168 START_ANY_ACTIVITY, callingPid, callingUid);
1169 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
1170 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
1171 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
1172 if (resultRecord != null) {
1173 resultStack.sendActivityResultLocked(-1,
1174 resultRecord, resultWho, requestCode,
1175 Activity.RESULT_CANCELED, null);
1176 }
1177 setDismissKeyguard(false);
1178 String msg;
1179 if (!aInfo.exported) {
1180 msg = "Permission Denial: starting " + intent.toString()
1181 + " from " + callerApp + " (pid=" + callingPid
1182 + ", uid=" + callingUid + ")"
1183 + " not exported from uid " + aInfo.applicationInfo.uid;
1184 } else {
1185 msg = "Permission Denial: starting " + intent.toString()
1186 + " from " + callerApp + " (pid=" + callingPid
1187 + ", uid=" + callingUid + ")"
1188 + " requires " + aInfo.permission;
1189 }
1190 Slog.w(TAG, msg);
1191 throw new SecurityException(msg);
1192 }
1193
Ben Gruverdd72c9e2013-08-06 12:34:17 -07001194 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
Ben Gruverb6223792013-07-29 16:35:40 -07001195 callingPid, resolvedType, aInfo.applicationInfo);
Ben Gruver5e207332013-04-03 17:41:37 -07001196
Craig Mautner6170f732013-04-02 13:05:23 -07001197 if (mService.mController != null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001198 try {
1199 // The Intent we give to the watcher has the extra data
1200 // stripped off, since it can contain private information.
1201 Intent watchIntent = intent.cloneFilter();
Ben Gruver5e207332013-04-03 17:41:37 -07001202 abort |= !mService.mController.activityStarting(watchIntent,
Craig Mautner6170f732013-04-02 13:05:23 -07001203 aInfo.applicationInfo.packageName);
1204 } catch (RemoteException e) {
1205 mService.mController = null;
1206 }
Ben Gruver5e207332013-04-03 17:41:37 -07001207 }
Craig Mautner6170f732013-04-02 13:05:23 -07001208
Ben Gruver5e207332013-04-03 17:41:37 -07001209 if (abort) {
1210 if (resultRecord != null) {
1211 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Craig Mautner6170f732013-04-02 13:05:23 -07001212 Activity.RESULT_CANCELED, null);
Craig Mautner6170f732013-04-02 13:05:23 -07001213 }
Ben Gruver5e207332013-04-03 17:41:37 -07001214 // We pretend to the caller that it was really started, but
1215 // they will just get a cancel result.
1216 setDismissKeyguard(false);
1217 ActivityOptions.abort(options);
1218 return ActivityManager.START_SUCCESS;
Craig Mautner6170f732013-04-02 13:05:23 -07001219 }
1220
1221 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1222 intent, resolvedType, aInfo, mService.mConfiguration,
Craig Mautnerde4ef022013-04-07 19:01:33 -07001223 resultRecord, resultWho, requestCode, componentSpecified, this);
Craig Mautner6170f732013-04-02 13:05:23 -07001224 if (outActivity != null) {
1225 outActivity[0] = r;
1226 }
1227
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001228 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001229 if (stack.mResumedActivity == null
1230 || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
Craig Mautner6170f732013-04-02 13:05:23 -07001231 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1232 PendingActivityLaunch pal =
Craig Mautnerde4ef022013-04-07 19:01:33 -07001233 new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
Craig Mautner6170f732013-04-02 13:05:23 -07001234 mService.mPendingActivityLaunches.add(pal);
1235 setDismissKeyguard(false);
1236 ActivityOptions.abort(options);
1237 return ActivityManager.START_SWITCHES_CANCELED;
1238 }
1239 }
1240
1241 if (mService.mDidAppSwitch) {
1242 // This is the second allowed switch since we stopped switches,
1243 // so now just generally allow switches. Use case: user presses
1244 // home (switches disabled, switch to home, mDidAppSwitch now true);
1245 // user taps a home icon (coming from home so allowed, we hit here
1246 // and now allow anyone to switch again).
1247 mService.mAppSwitchesAllowedTime = 0;
1248 } else {
1249 mService.mDidAppSwitch = true;
1250 }
1251
1252 mService.doPendingActivityLaunchesLocked(false);
1253
Craig Mautner8849a5e2013-04-02 16:41:03 -07001254 err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
Craig Mautner10385a12013-09-22 21:08:32 -07001255
1256 if (allPausedActivitiesComplete()) {
1257 // If someone asked to have the keyguard dismissed on the next
Craig Mautner6170f732013-04-02 13:05:23 -07001258 // activity start, but we are not actually doing an activity
1259 // switch... just dismiss the keyguard now, because we
1260 // probably want to see whatever is behind it.
1261 dismissKeyguard();
1262 }
1263 return err;
1264 }
1265
Craig Mautnerac6f8432013-07-17 13:24:59 -07001266 ActivityStack adjustStackFocus(ActivityRecord r) {
Craig Mautner1d001b62013-06-18 16:52:43 -07001267 final TaskRecord task = r.task;
1268 if (r.isApplicationActivity() || (task != null && task.isApplicationTask())) {
Craig Mautnerac6f8432013-07-17 13:24:59 -07001269 if (task != null) {
1270 if (mFocusedStack != task.stack) {
1271 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1272 "adjustStackFocus: Setting focused stack to r=" + r + " task=" + task);
1273 mFocusedStack = task.stack;
1274 } else {
1275 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1276 "adjustStackFocus: Focused stack already=" + mFocusedStack);
1277 }
1278 return mFocusedStack;
1279 }
1280
1281 if (mFocusedStack != null) {
1282 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1283 "adjustStackFocus: Have a focused stack=" + mFocusedStack);
1284 return mFocusedStack;
1285 }
1286
1287 for (int stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
1288 ActivityStack stack = mStacks.get(stackNdx);
1289 if (!stack.isHomeStack()) {
1290 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1291 "adjustStackFocus: Setting focused stack=" + stack);
1292 mFocusedStack = stack;
1293 return mFocusedStack;
Craig Mautner858d8a62013-04-23 17:08:34 -07001294 }
1295 }
Craig Mautnerac6f8432013-07-17 13:24:59 -07001296
1297 // Time to create the first app stack for this user.
1298 int stackId = mService.createStack(-1, HOME_STACK_ID,
1299 StackBox.TASK_STACK_GOES_OVER, 1.0f);
1300 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack r=" + r +
1301 " stackId=" + stackId);
1302 mFocusedStack = getStack(stackId);
Craig Mautner29219d92013-04-16 20:19:12 -07001303 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001304 }
1305 return mHomeStack;
1306 }
1307
Craig Mautner29219d92013-04-16 20:19:12 -07001308 void setFocusedStack(ActivityRecord r) {
1309 if (r == null) {
1310 return;
1311 }
Craig Mautner86d67a42013-05-14 10:34:38 -07001312 if (!r.isApplicationActivity() || (r.task != null && !r.task.isApplicationTask())) {
Craig Mautner29219d92013-04-16 20:19:12 -07001313 if (mStackState != STACK_STATE_HOME_IN_FRONT) {
Craig Mautnere7c58b62013-06-12 20:19:00 -07001314 if (DEBUG_STACK || DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: mStackState old=" +
Craig Mautner76ea2242013-05-15 11:40:05 -07001315 stackStateToString(mStackState) + " new=" +
1316 stackStateToString(STACK_STATE_HOME_TO_FRONT) +
1317 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001318 mStackState = STACK_STATE_HOME_TO_FRONT;
1319 }
1320 } else {
Craig Mautnerac6f8432013-07-17 13:24:59 -07001321 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1322 "setFocusedStack: Setting focused stack to r=" + r + " task=" + r.task +
1323 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001324 mFocusedStack = r.task.stack;
1325 if (mStackState != STACK_STATE_HOME_IN_BACK) {
Craig Mautner76ea2242013-05-15 11:40:05 -07001326 if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
1327 stackStateToString(mStackState) + " new=" +
1328 stackStateToString(STACK_STATE_HOME_TO_BACK) +
1329 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001330 mStackState = STACK_STATE_HOME_TO_BACK;
1331 }
1332 }
1333 }
1334
Craig Mautner8849a5e2013-04-02 16:41:03 -07001335 final int startActivityUncheckedLocked(ActivityRecord r,
1336 ActivityRecord sourceRecord, int startFlags, boolean doResume,
1337 Bundle options) {
1338 final Intent intent = r.intent;
1339 final int callingUid = r.launchedFromUid;
1340
1341 int launchFlags = intent.getFlags();
1342
Craig Mautner8849a5e2013-04-02 16:41:03 -07001343 // We'll invoke onUserLeaving before onPause only if the launching
1344 // activity did not explicitly state that this is an automated launch.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001345 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1346 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001347
1348 // If the caller has asked not to resume at this point, we make note
1349 // of this in the record so that we can skip it when trying to find
1350 // the top running activity.
1351 if (!doResume) {
1352 r.delayedResume = true;
1353 }
1354
1355 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1356
1357 // If the onlyIfNeeded flag is set, then we can do this if the activity
1358 // being launched is the same as the one making the call... or, as
1359 // a special case, if we do not know the caller then we count the
1360 // current top activity as the caller.
1361 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1362 ActivityRecord checkedCaller = sourceRecord;
1363 if (checkedCaller == null) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001364 checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001365 }
1366 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1367 // Caller is not the same as launcher, so always needed.
1368 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1369 }
1370 }
1371
1372 if (sourceRecord == null) {
1373 // This activity is not being started from another... in this
1374 // case we -always- start a new task.
1375 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Craig Mautner29219d92013-04-16 20:19:12 -07001376 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1377 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001378 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1379 }
1380 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1381 // The original activity who is starting us is running as a single
1382 // instance... this new activity it is starting must go on its
1383 // own task.
1384 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1385 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1386 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1387 // The activity being started is a single instance... it always
1388 // gets launched into its own task.
1389 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1390 }
1391
Craig Mautnerde4ef022013-04-07 19:01:33 -07001392 final ActivityStack sourceStack;
Craig Mautner525f3d92013-05-07 14:01:50 -07001393 TaskRecord sourceTask;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001394 if (sourceRecord != null) {
1395 sourceTask = sourceRecord.task;
1396 sourceStack = sourceTask.stack;
1397 } else {
1398 sourceTask = null;
1399 sourceStack = null;
1400 }
1401
Craig Mautner8849a5e2013-04-02 16:41:03 -07001402 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1403 // For whatever reason this activity is being launched into a new
1404 // task... yet the caller has requested a result back. Well, that
1405 // is pretty messed up, so instead immediately send back a cancel
1406 // and let the new task continue launched as normal without a
1407 // dependency on its originator.
1408 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1409 r.resultTo.task.stack.sendActivityResultLocked(-1,
1410 r.resultTo, r.resultWho, r.requestCode,
1411 Activity.RESULT_CANCELED, null);
1412 r.resultTo = null;
1413 }
1414
1415 boolean addingToTask = false;
1416 boolean movedHome = false;
1417 TaskRecord reuseTask = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001418 ActivityStack targetStack;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001419 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1420 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1421 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1422 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1423 // If bring to front is requested, and no result is requested, and
1424 // we can find a task that was started with this same
1425 // component, then instead of launching bring that one to the front.
1426 if (r.resultTo == null) {
1427 // See if there is a task to bring to the front. If this is
1428 // a SINGLE_INSTANCE activity, there can be one and only one
1429 // instance of it in the history, and it is always in its own
1430 // unique task, so we do a special search.
1431 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
Craig Mautnerac6f8432013-07-17 13:24:59 -07001432 ? findTaskLocked(r)
Craig Mautner8849a5e2013-04-02 16:41:03 -07001433 : findActivityLocked(intent, r.info);
1434 if (intentActivity != null) {
Craig Mautner29219d92013-04-16 20:19:12 -07001435 if (r.task == null) {
1436 r.task = intentActivity.task;
1437 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001438 targetStack = intentActivity.task.stack;
Craig Mautner0f922742013-08-06 08:44:42 -07001439 targetStack.mLastPausedActivity = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001440 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001441 if (intentActivity.task.intent == null) {
1442 // This task was started because of movement of
1443 // the activity based on affinity... now that we
1444 // are actually launching it, we can assign the
1445 // base intent.
1446 intentActivity.task.setIntent(intent, r.info);
1447 }
1448 // If the target task is not in the front, then we need
1449 // to bring it to the front... except... well, with
1450 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
1451 // to have the same behavior as if a new instance was
1452 // being started, which means not bringing it to the front
1453 // if the caller is not itself in the front.
Craig Mautner165640b2013-04-20 10:34:33 -07001454 final ActivityStack lastStack = getLastStack();
1455 ActivityRecord curTop = lastStack == null?
1456 null : lastStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner7504d7b2013-09-17 10:50:53 -07001457 if (curTop != null && (curTop.task != intentActivity.task ||
1458 curTop.task != lastStack.topTask())) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001459 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Craig Mautnerd0f964f2013-08-07 11:16:33 -07001460 if (sourceRecord == null || (sourceStack.topActivity() != null &&
1461 sourceStack.topActivity().task == sourceRecord.task)) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001462 // We really do want to push this one into the
1463 // user's face, right now.
1464 movedHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001465 if ((launchFlags &
Craig Mautner29219d92013-04-16 20:19:12 -07001466 (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1467 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
Craig Mautnere12a4a62013-08-29 12:24:56 -07001468 // Caller wants to appear on home activity.
Craig Mautnerae7ecab2013-09-18 11:48:14 -07001469 intentActivity.task.mOnTopOfHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001470 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001471 targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1472 options = null;
1473 }
1474 }
1475 // If the caller has requested that the target task be
1476 // reset, then do so.
1477 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1478 intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1479 }
1480 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1481 // We don't need to start a new activity, and
1482 // the client said not to do anything if that
1483 // is the case, so this is it! And for paranoia, make
1484 // sure we have correctly resumed the top activity.
1485 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001486 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001487 resumeTopActivitiesLocked(targetStack, null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001488 } else {
1489 ActivityOptions.abort(options);
1490 }
Craig Mautner29219d92013-04-16 20:19:12 -07001491 if (r.task == null) Slog.v(TAG,
1492 "startActivityUncheckedLocked: task left null",
1493 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001494 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1495 }
1496 if ((launchFlags &
1497 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1498 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1499 // The caller has requested to completely replace any
1500 // existing task with its new activity. Well that should
1501 // not be too hard...
1502 reuseTask = intentActivity.task;
1503 reuseTask.performClearTaskLocked();
1504 reuseTask.setIntent(r.intent, r.info);
1505 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1506 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1507 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1508 // In this situation we want to remove all activities
1509 // from the task up to the one being started. In most
1510 // cases this means we are resetting the task to its
1511 // initial state.
1512 ActivityRecord top =
1513 intentActivity.task.performClearTaskLocked(r, launchFlags);
1514 if (top != null) {
1515 if (top.frontOfTask) {
1516 // Activity aliases may mean we use different
1517 // intents for the top activity, so make sure
1518 // the task now has the identity of the new
1519 // intent.
1520 top.task.setIntent(r.intent, r.info);
1521 }
1522 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1523 r, top.task);
1524 top.deliverNewIntentLocked(callingUid, r.intent);
1525 } else {
1526 // A special case: we need to
1527 // start the activity because it is not currently
1528 // running, and the caller has asked to clear the
1529 // current task to have this activity at the top.
1530 addingToTask = true;
1531 // Now pretend like this activity is being started
1532 // by the top of its task, so it is put in the
1533 // right place.
1534 sourceRecord = intentActivity;
1535 }
1536 } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1537 // In this case the top activity on the task is the
1538 // same as the one being launched, so we take that
1539 // as a request to bring the task to the foreground.
1540 // If the top activity in the task is the root
1541 // activity, deliver this new intent to it if it
1542 // desires.
1543 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1544 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1545 && intentActivity.realActivity.equals(r.realActivity)) {
1546 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1547 intentActivity.task);
1548 if (intentActivity.frontOfTask) {
1549 intentActivity.task.setIntent(r.intent, r.info);
1550 }
1551 intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1552 } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1553 // In this case we are launching the root activity
1554 // of the task, but with a different intent. We
1555 // should start a new instance on top.
1556 addingToTask = true;
1557 sourceRecord = intentActivity;
1558 }
1559 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1560 // In this case an activity is being launched in to an
1561 // existing task, without resetting that task. This
1562 // is typically the situation of launching an activity
1563 // from a notification or shortcut. We want to place
1564 // the new activity on top of the current task.
1565 addingToTask = true;
1566 sourceRecord = intentActivity;
1567 } else if (!intentActivity.task.rootWasReset) {
1568 // In this case we are launching in to an existing task
1569 // that has not yet been started from its front door.
1570 // The current task has been brought to the front.
1571 // Ideally, we'd probably like to place this new task
1572 // at the bottom of its stack, but that's a little hard
1573 // to do with the current organization of the code so
1574 // for now we'll just drop it.
1575 intentActivity.task.setIntent(r.intent, r.info);
1576 }
1577 if (!addingToTask && reuseTask == null) {
1578 // We didn't do anything... but it was needed (a.k.a., client
1579 // don't use that intent!) And for paranoia, make
1580 // sure we have correctly resumed the top activity.
1581 if (doResume) {
Craig Mautnere12a4a62013-08-29 12:24:56 -07001582 // Reset flag so it gets correctly reevaluated.
Craig Mautnerae7ecab2013-09-18 11:48:14 -07001583 intentActivity.task.mOnTopOfHome = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001584 setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1585 targetStack.resumeTopActivityLocked(null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001586 } else {
1587 ActivityOptions.abort(options);
1588 }
Craig Mautner29219d92013-04-16 20:19:12 -07001589 if (r.task == null) Slog.v(TAG,
1590 "startActivityUncheckedLocked: task left null",
1591 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001592 return ActivityManager.START_TASK_TO_FRONT;
1593 }
1594 }
1595 }
1596 }
1597
1598 //String uri = r.intent.toURI();
1599 //Intent intent2 = new Intent(uri);
1600 //Slog.i(TAG, "Given intent: " + r.intent);
1601 //Slog.i(TAG, "URI is: " + uri);
1602 //Slog.i(TAG, "To intent: " + intent2);
1603
1604 if (r.packageName != null) {
1605 // If the activity being launched is the same as the one currently
1606 // at the top, then we need to check if it should only be launched
1607 // once.
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001608 ActivityStack topStack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001609 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001610 if (top != null && r.resultTo == null) {
1611 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1612 if (top.app != null && top.app.thread != null) {
1613 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1614 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1615 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1616 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1617 top.task);
1618 // For paranoia, make sure we have correctly
1619 // resumed the top activity.
Craig Mautner0f922742013-08-06 08:44:42 -07001620 topStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001621 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001622 setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001623 resumeTopActivitiesLocked();
Craig Mautner8849a5e2013-04-02 16:41:03 -07001624 }
1625 ActivityOptions.abort(options);
1626 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1627 // We don't need to start a new activity, and
1628 // the client said not to do anything if that
1629 // is the case, so this is it!
Craig Mautner29219d92013-04-16 20:19:12 -07001630 if (r.task == null) Slog.v(TAG,
1631 "startActivityUncheckedLocked: task left null",
1632 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001633 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1634 }
1635 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner29219d92013-04-16 20:19:12 -07001636 if (r.task == null) Slog.v(TAG,
1637 "startActivityUncheckedLocked: task left null",
1638 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001639 return ActivityManager.START_DELIVERED_TO_TOP;
1640 }
1641 }
1642 }
1643 }
1644
1645 } else {
1646 if (r.resultTo != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001647 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1648 r.requestCode, Activity.RESULT_CANCELED, null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001649 }
1650 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001651 if (r.task == null) Slog.v(TAG,
1652 "startActivityUncheckedLocked: task left null",
1653 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001654 return ActivityManager.START_CLASS_NOT_FOUND;
1655 }
1656
1657 boolean newTask = false;
1658 boolean keepCurTransition = false;
1659
1660 // Should this be considered a new task?
1661 if (r.resultTo == null && !addingToTask
1662 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Craig Mautnerac6f8432013-07-17 13:24:59 -07001663 targetStack = adjustStackFocus(r);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001664 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001665 if (reuseTask == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001666 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1667 null, true);
1668 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1669 r.task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001670 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001671 r.setTask(reuseTask, reuseTask, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001672 }
1673 newTask = true;
1674 if (!movedHome) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001675 if ((launchFlags &
1676 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1677 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1678 // Caller wants to appear on home activity, so before starting
1679 // their own activity we will bring home to the front.
Craig Mautnerae7ecab2013-09-18 11:48:14 -07001680 r.task.mOnTopOfHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001681 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001682 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001683 } else if (sourceRecord != null) {
Craig Mautner525f3d92013-05-07 14:01:50 -07001684 sourceTask = sourceRecord.task;
1685 targetStack = sourceTask.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001686 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001687 if (!addingToTask &&
1688 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1689 // In this case, we are adding the activity to an existing
1690 // task, but the caller has asked to clear that task if the
1691 // activity is already running.
Craig Mautner525f3d92013-05-07 14:01:50 -07001692 ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001693 keepCurTransition = true;
1694 if (top != null) {
1695 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1696 top.deliverNewIntentLocked(callingUid, r.intent);
1697 // For paranoia, make sure we have correctly
1698 // resumed the top activity.
Craig Mautner0f922742013-08-06 08:44:42 -07001699 targetStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001700 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001701 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001702 targetStack.resumeTopActivityLocked(null);
1703 }
1704 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001705 if (r.task == null) Slog.v(TAG,
1706 "startActivityUncheckedLocked: task left null",
1707 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001708 return ActivityManager.START_DELIVERED_TO_TOP;
1709 }
1710 } else if (!addingToTask &&
1711 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1712 // In this case, we are launching an activity in our own task
1713 // that may already be running somewhere in the history, and
1714 // we want to shuffle it to the front of the stack if so.
Craig Mautner525f3d92013-05-07 14:01:50 -07001715 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001716 if (top != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001717 final TaskRecord task = top.task;
1718 task.moveActivityToFrontLocked(top);
1719 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001720 top.updateOptionsLocked(options);
1721 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner0f922742013-08-06 08:44:42 -07001722 targetStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001723 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001724 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001725 targetStack.resumeTopActivityLocked(null);
1726 }
1727 return ActivityManager.START_DELIVERED_TO_TOP;
1728 }
1729 }
1730 // An existing activity is starting this new activity, so we want
1731 // to keep the new one in the same task as the one that is starting
1732 // it.
Craig Mautner525f3d92013-05-07 14:01:50 -07001733 r.setTask(sourceTask, sourceRecord.thumbHolder, false);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001734 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1735 + " in existing task " + r.task);
1736
1737 } else {
1738 // This not being started from an existing activity, and not part
1739 // of a new task... just put it in the top task, though these days
1740 // this case should never happen.
Craig Mautnerac6f8432013-07-17 13:24:59 -07001741 targetStack = adjustStackFocus(r);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001742 moveHomeStack(targetStack.isHomeStack());
Craig Mautner1602ec22013-05-12 10:24:27 -07001743 ActivityRecord prev = targetStack.topActivity();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001744 r.setTask(prev != null ? prev.task
1745 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1746 null, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001747 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1748 + " in new guessed " + r.task);
1749 }
1750
1751 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1752 intent, r.getUriPermissionsLocked());
1753
1754 if (newTask) {
1755 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1756 }
1757 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001758 setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
Craig Mautner0f922742013-08-06 08:44:42 -07001759 targetStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001760 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
Craig Mautner1d001b62013-06-18 16:52:43 -07001761 mService.setFocusedActivityLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001762 return ActivityManager.START_SUCCESS;
1763 }
1764
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001765 void acquireLaunchWakelock() {
1766 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
1767 throw new IllegalStateException("Calling must be system uid");
1768 }
1769 mLaunchingActivity.acquire();
1770 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
1771 // To be safe, don't allow the wake lock to be held for too long.
1772 mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
1773 }
1774 }
1775
Craig Mautnerf3333272013-04-22 10:55:53 -07001776 // Checked.
1777 final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
1778 Configuration config) {
1779 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
1780
Craig Mautnerf3333272013-04-22 10:55:53 -07001781 ArrayList<ActivityRecord> stops = null;
1782 ArrayList<ActivityRecord> finishes = null;
1783 ArrayList<UserStartedState> startingUsers = null;
1784 int NS = 0;
1785 int NF = 0;
1786 IApplicationThread sendThumbnail = null;
1787 boolean booting = false;
1788 boolean enableScreen = false;
1789 boolean activityRemoved = false;
1790
1791 ActivityRecord r = ActivityRecord.forToken(token);
1792 if (r != null) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07001793 if (DEBUG_IDLE) Slog.d(TAG, "activityIdleInternalLocked: Callers=" +
1794 Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07001795 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
1796 r.finishLaunchTickingLocked();
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001797 if (fromTimeout) {
1798 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
Craig Mautnerf3333272013-04-22 10:55:53 -07001799 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001800
1801 // This is a hack to semi-deal with a race condition
1802 // in the client where it can be constructed with a
1803 // newer configuration from when we asked it to launch.
1804 // We'll update with whatever configuration it now says
1805 // it used to launch.
1806 if (config != null) {
1807 r.configuration = config;
1808 }
1809
1810 // We are now idle. If someone is waiting for a thumbnail from
1811 // us, we can now deliver.
1812 r.idle = true;
1813
1814 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
1815 sendThumbnail = r.app.thread;
1816 r.thumbnailNeeded = false;
1817 }
1818
1819 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
1820 if (!mService.mBooted && isFrontStack(r.task.stack)) {
1821 mService.mBooted = true;
1822 enableScreen = true;
1823 }
1824 }
1825
1826 if (allResumedActivitiesIdle()) {
1827 if (r != null) {
1828 mService.scheduleAppGcsLocked();
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001829 }
1830
1831 if (mLaunchingActivity.isHeld()) {
1832 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
1833 if (VALIDATE_WAKE_LOCK_CALLER &&
1834 Binder.getCallingUid() != Process.myUid()) {
1835 throw new IllegalStateException("Calling must be system uid");
1836 }
1837 mLaunchingActivity.release();
1838 }
1839 ensureActivitiesVisibleLocked(null, 0);
Craig Mautnerf3333272013-04-22 10:55:53 -07001840 }
1841
1842 // Atomically retrieve all of the other things to do.
1843 stops = processStoppingActivitiesLocked(true);
1844 NS = stops != null ? stops.size() : 0;
1845 if ((NF=mFinishingActivities.size()) > 0) {
1846 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
1847 mFinishingActivities.clear();
1848 }
1849
1850 final ArrayList<ActivityRecord> thumbnails;
1851 final int NT = mCancelledThumbnails.size();
1852 if (NT > 0) {
1853 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
1854 mCancelledThumbnails.clear();
1855 } else {
1856 thumbnails = null;
1857 }
1858
1859 if (isFrontStack(mHomeStack)) {
1860 booting = mService.mBooting;
1861 mService.mBooting = false;
1862 }
1863
1864 if (mStartingUsers.size() > 0) {
1865 startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
1866 mStartingUsers.clear();
1867 }
1868
1869 // Perform the following actions from unsynchronized state.
1870 final IApplicationThread thumbnailThread = sendThumbnail;
1871 mHandler.post(new Runnable() {
1872 @Override
1873 public void run() {
1874 if (thumbnailThread != null) {
1875 try {
1876 thumbnailThread.requestThumbnail(token);
1877 } catch (Exception e) {
1878 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
1879 mService.sendPendingThumbnail(null, token, null, null, true);
1880 }
1881 }
1882
1883 // Report back to any thumbnail receivers.
1884 for (int i = 0; i < NT; i++) {
1885 ActivityRecord r = thumbnails.get(i);
1886 mService.sendPendingThumbnail(r, null, null, null, true);
1887 }
1888 }
1889 });
1890
1891 // Stop any activities that are scheduled to do so but have been
1892 // waiting for the next one to start.
1893 for (int i = 0; i < NS; i++) {
1894 r = stops.get(i);
1895 final ActivityStack stack = r.task.stack;
1896 if (r.finishing) {
1897 stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
1898 } else {
1899 stack.stopActivityLocked(r);
1900 }
1901 }
1902
1903 // Finish any activities that are scheduled to do so but have been
1904 // waiting for the next one to start.
1905 for (int i = 0; i < NF; i++) {
1906 r = finishes.get(i);
1907 activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle");
1908 }
1909
1910 if (booting) {
1911 mService.finishBooting();
1912 } else if (startingUsers != null) {
1913 for (int i = 0; i < startingUsers.size(); i++) {
1914 mService.finishUserSwitch(startingUsers.get(i));
1915 }
1916 }
1917
1918 mService.trimApplications();
1919 //dump();
1920 //mWindowManager.dump();
1921
1922 if (enableScreen) {
1923 mService.enableScreenAfterBoot();
1924 }
1925
1926 if (activityRemoved) {
Craig Mautner05d29032013-05-03 13:40:13 -07001927 resumeTopActivitiesLocked();
Craig Mautnerf3333272013-04-22 10:55:53 -07001928 }
1929
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001930 return r;
Craig Mautnerf3333272013-04-22 10:55:53 -07001931 }
1932
Craig Mautner8d341ef2013-03-26 09:03:27 -07001933 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
Craig Mautner6b74cb52013-09-27 17:02:21 -07001934 boolean launchHomeTaskNext = false;
1935 final ActivityStack focusedStack = getFocusedStack();
Craig Mautner8d341ef2013-03-26 09:03:27 -07001936 final int numStacks = mStacks.size();
1937 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Craig Mautner6b74cb52013-09-27 17:02:21 -07001938 final ActivityStack stack = mStacks.get(stackNdx);
1939 // Only update launchHomeTaskNext for the focused stack.
Craig Mautner51277a82013-10-01 14:28:23 -07001940 launchHomeTaskNext |= (stack.handleAppDiedLocked(app) && stack == focusedStack);
Craig Mautner6b74cb52013-09-27 17:02:21 -07001941 }
1942
1943 if (!restarting) {
1944 if (launchHomeTaskNext) {
1945 resumeHomeActivity(null);
1946 } else {
1947 if (!resumeTopActivitiesLocked(focusedStack, null, null)) {
1948 // If there was nothing to resume, and we are not already
1949 // restarting this process, but there is a visible activity that
1950 // is hosted by the process... then make sure all visible
1951 // activities are running, taking care of restarting this
1952 // process.
1953 ensureActivitiesVisibleLocked(null, 0);
1954 }
1955 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001956 }
1957 }
1958
1959 void closeSystemDialogsLocked() {
1960 final int numStacks = mStacks.size();
1961 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1962 final ActivityStack stack = mStacks.get(stackNdx);
1963 stack.closeSystemDialogsLocked();
1964 }
1965 }
1966
Craig Mautner93529a42013-10-04 15:03:13 -07001967 void removeUserLocked(int userId) {
1968 mUserHomeInFront.delete(userId);
1969 }
1970
Craig Mautner8d341ef2013-03-26 09:03:27 -07001971 /**
1972 * @return true if some activity was finished (or would have finished if doit were true).
1973 */
1974 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1975 boolean didSomething = false;
1976 final int numStacks = mStacks.size();
1977 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1978 final ActivityStack stack = mStacks.get(stackNdx);
1979 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1980 didSomething = true;
1981 }
1982 }
1983 return didSomething;
1984 }
1985
Dianne Hackborna413dc02013-07-12 12:02:55 -07001986 void updatePreviousProcessLocked(ActivityRecord r) {
1987 // Now that this process has stopped, we may want to consider
1988 // it to be the previous app to try to keep around in case
1989 // the user wants to return to it.
1990
1991 // First, found out what is currently the foreground app, so that
1992 // we don't blow away the previous app if this activity is being
1993 // hosted by the process that is actually still the foreground.
1994 ProcessRecord fgApp = null;
1995 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1996 final ActivityStack stack = mStacks.get(stackNdx);
1997 if (isFrontStack(stack)) {
1998 if (stack.mResumedActivity != null) {
1999 fgApp = stack.mResumedActivity.app;
2000 } else if (stack.mPausingActivity != null) {
2001 fgApp = stack.mPausingActivity.app;
2002 }
2003 break;
2004 }
2005 }
2006
2007 // Now set this one as the previous process, only if that really
2008 // makes sense to.
2009 if (r.app != null && fgApp != null && r.app != fgApp
2010 && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
Craig Mautner4ef26932013-09-18 15:15:52 -07002011 && r.app != mService.mHomeProcess) {
Dianne Hackborna413dc02013-07-12 12:02:55 -07002012 mService.mPreviousProcess = r.app;
2013 mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
2014 }
2015 }
2016
Craig Mautner05d29032013-05-03 13:40:13 -07002017 boolean resumeTopActivitiesLocked() {
2018 return resumeTopActivitiesLocked(null, null, null);
2019 }
2020
2021 boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
2022 Bundle targetOptions) {
2023 if (targetStack == null) {
2024 targetStack = getFocusedStack();
2025 }
2026 boolean result = false;
Craig Mautnerdbcb31f2013-04-02 12:32:53 -07002027 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerf88c50f2013-04-18 19:25:12 -07002028 final ActivityStack stack = mStacks.get(stackNdx);
2029 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07002030 if (stack == targetStack) {
2031 result = stack.resumeTopActivityLocked(target, targetOptions);
2032 } else {
2033 stack.resumeTopActivityLocked(null);
2034 }
Craig Mautnerf88c50f2013-04-18 19:25:12 -07002035 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002036 }
Craig Mautner05d29032013-05-03 13:40:13 -07002037 return result;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002038 }
2039
2040 void finishTopRunningActivityLocked(ProcessRecord app) {
2041 final int numStacks = mStacks.size();
2042 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2043 final ActivityStack stack = mStacks.get(stackNdx);
2044 stack.finishTopRunningActivityLocked(app);
2045 }
2046 }
2047
Craig Mautner8d341ef2013-03-26 09:03:27 -07002048 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
2049 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2050 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002051 if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack=" +
Craig Mautner1d001b62013-06-18 16:52:43 -07002052 mStacks.get(stackNdx));
Craig Mautner8d341ef2013-03-26 09:03:27 -07002053 return;
2054 }
2055 }
2056 }
2057
Craig Mautner967212c2013-04-13 21:10:58 -07002058 ActivityStack getStack(int stackId) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002059 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2060 final ActivityStack stack = mStacks.get(stackNdx);
2061 if (stack.getStackId() == stackId) {
2062 return stack;
2063 }
2064 }
2065 return null;
2066 }
2067
Craig Mautner967212c2013-04-13 21:10:58 -07002068 ArrayList<ActivityStack> getStacks() {
2069 return new ArrayList<ActivityStack>(mStacks);
2070 }
2071
2072 int createStack() {
Craig Mautner858d8a62013-04-23 17:08:34 -07002073 while (true) {
2074 if (++mLastStackId <= HOME_STACK_ID) {
2075 mLastStackId = HOME_STACK_ID + 1;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002076 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002077 if (getStack(mLastStackId) == null) {
2078 break;
2079 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002080 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002081 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
2082 return mLastStackId;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002083 }
2084
2085 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07002086 final TaskRecord task = anyTaskForIdLocked(taskId);
2087 if (task == null) {
2088 return;
2089 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002090 final ActivityStack stack = getStack(stackId);
2091 if (stack == null) {
2092 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
2093 return;
2094 }
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07002095 removeTask(task);
2096 stack.addTask(task, toTop);
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07002097 mWindowManager.addTask(taskId, stackId, toTop);
Craig Mautner05d29032013-05-03 13:40:13 -07002098 resumeTopActivitiesLocked();
Craig Mautner8d341ef2013-03-26 09:03:27 -07002099 }
2100
Craig Mautnerac6f8432013-07-17 13:24:59 -07002101 ActivityRecord findTaskLocked(ActivityRecord r) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07002102 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerac6f8432013-07-17 13:24:59 -07002103 final ActivityStack stack = mStacks.get(stackNdx);
2104 if (!r.isApplicationActivity() && !stack.isHomeStack()) {
2105 continue;
2106 }
2107 final ActivityRecord ar = stack.findTaskLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07002108 if (ar != null) {
2109 return ar;
2110 }
2111 }
2112 return null;
2113 }
2114
2115 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
2116 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2117 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
2118 if (ar != null) {
2119 return ar;
2120 }
2121 }
2122 return null;
2123 }
2124
Craig Mautner8d341ef2013-03-26 09:03:27 -07002125 void goingToSleepLocked() {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002126 scheduleSleepTimeout();
2127 if (!mGoingToSleep.isHeld()) {
2128 mGoingToSleep.acquire();
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002129 if (mLaunchingActivity.isHeld()) {
2130 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
2131 throw new IllegalStateException("Calling must be system uid");
Craig Mautner0eea92c2013-05-16 13:35:39 -07002132 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002133 mLaunchingActivity.release();
2134 mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
Craig Mautner0eea92c2013-05-16 13:35:39 -07002135 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002136 }
Amith Yamasanice15e152013-09-19 12:30:32 -07002137 checkReadyForSleepLocked();
Craig Mautner8d341ef2013-03-26 09:03:27 -07002138 }
2139
2140 boolean shutdownLocked(int timeout) {
2141 boolean timedout = false;
Craig Mautner0eea92c2013-05-16 13:35:39 -07002142 goingToSleepLocked();
Craig Mautner0eea92c2013-05-16 13:35:39 -07002143
2144 final long endTime = System.currentTimeMillis() + timeout;
2145 while (true) {
2146 boolean cantShutdown = false;
2147 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2148 cantShutdown |= mStacks.get(stackNdx).checkReadyForSleepLocked();
2149 }
2150 if (cantShutdown) {
2151 long timeRemaining = endTime - System.currentTimeMillis();
2152 if (timeRemaining > 0) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002153 try {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002154 mService.wait(timeRemaining);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002155 } catch (InterruptedException e) {
2156 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002157 } else {
2158 Slog.w(TAG, "Activity manager shutdown timed out");
2159 timedout = true;
2160 break;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002161 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002162 } else {
2163 break;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002164 }
2165 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002166
2167 // Force checkReadyForSleep to complete.
2168 mSleepTimeout = true;
2169 checkReadyForSleepLocked();
2170
Craig Mautner8d341ef2013-03-26 09:03:27 -07002171 return timedout;
2172 }
2173
2174 void comeOutOfSleepIfNeededLocked() {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002175 removeSleepTimeouts();
2176 if (mGoingToSleep.isHeld()) {
2177 mGoingToSleep.release();
2178 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002179 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002180 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002181 stack.awakeFromSleepingLocked();
Craig Mautner5314a402013-09-26 12:40:16 -07002182 if (isFrontStack(stack)) {
2183 resumeTopActivitiesLocked();
2184 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002185 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002186 mGoingToSleepActivities.clear();
2187 }
2188
2189 void activitySleptLocked(ActivityRecord r) {
2190 mGoingToSleepActivities.remove(r);
2191 checkReadyForSleepLocked();
2192 }
2193
2194 void checkReadyForSleepLocked() {
2195 if (!mService.isSleepingOrShuttingDown()) {
2196 // Do not care.
2197 return;
2198 }
2199
2200 if (!mSleepTimeout) {
2201 boolean dontSleep = false;
2202 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2203 dontSleep |= mStacks.get(stackNdx).checkReadyForSleepLocked();
2204 }
2205
2206 if (mStoppingActivities.size() > 0) {
2207 // Still need to tell some activities to stop; can't sleep yet.
2208 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
2209 + mStoppingActivities.size() + " activities");
2210 scheduleIdleLocked();
2211 dontSleep = true;
2212 }
2213
2214 if (mGoingToSleepActivities.size() > 0) {
2215 // Still need to tell some activities to sleep; can't sleep yet.
2216 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
2217 + mGoingToSleepActivities.size() + " activities");
2218 dontSleep = true;
2219 }
2220
2221 if (dontSleep) {
2222 return;
2223 }
2224 }
2225
2226 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2227 mStacks.get(stackNdx).goToSleep();
2228 }
2229
2230 removeSleepTimeouts();
2231
2232 if (mGoingToSleep.isHeld()) {
2233 mGoingToSleep.release();
2234 }
2235 if (mService.mShuttingDown) {
2236 mService.notifyAll();
2237 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002238 }
2239
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002240 boolean reportResumedActivityLocked(ActivityRecord r) {
2241 final ActivityStack stack = r.task.stack;
2242 if (isFrontStack(stack)) {
Jeff Sharkey5782da72013-04-25 14:32:30 -07002243 mService.updateUsageStats(r, true);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002244 }
2245 if (allResumedActivitiesComplete()) {
2246 ensureActivitiesVisibleLocked(null, 0);
2247 mWindowManager.executeAppTransition();
2248 return true;
2249 }
2250 return false;
2251 }
2252
Craig Mautner8d341ef2013-03-26 09:03:27 -07002253 void handleAppCrashLocked(ProcessRecord app) {
2254 final int numStacks = mStacks.size();
2255 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2256 final ActivityStack stack = mStacks.get(stackNdx);
2257 stack.handleAppCrashLocked(app);
2258 }
2259 }
2260
Craig Mautnerde4ef022013-04-07 19:01:33 -07002261 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
Craig Mautner580ea812013-04-25 12:58:38 -07002262 // First the front stacks. In case any are not fullscreen and are in front of home.
2263 boolean showHomeBehindStack = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07002264 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner580ea812013-04-25 12:58:38 -07002265 final ActivityStack stack = mStacks.get(stackNdx);
2266 if (isFrontStack(stack)) {
2267 showHomeBehindStack =
2268 stack.ensureActivitiesVisibleLocked(starting, configChanges);
2269 }
2270 }
2271 // Now do back stacks.
2272 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2273 final ActivityStack stack = mStacks.get(stackNdx);
2274 if (!isFrontStack(stack)) {
2275 stack.ensureActivitiesVisibleLocked(starting, configChanges, showHomeBehindStack);
2276 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002277 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002278 }
2279
2280 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
2281 final int numStacks = mStacks.size();
2282 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2283 final ActivityStack stack = mStacks.get(stackNdx);
2284 stack.scheduleDestroyActivities(app, false, reason);
2285 }
2286 }
2287
2288 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner93529a42013-10-04 15:03:13 -07002289 mUserHomeInFront.put(mCurrentUser, isFrontStack(mHomeStack));
2290 final boolean homeInFront = mUserHomeInFront.get(userId, true);
Craig Mautner2420ead2013-04-01 17:13:20 -07002291 mCurrentUser = userId;
Craig Mautnerac6f8432013-07-17 13:24:59 -07002292
Craig Mautner858d8a62013-04-23 17:08:34 -07002293 mStartingUsers.add(uss);
Craig Mautnerac6f8432013-07-17 13:24:59 -07002294 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner93529a42013-10-04 15:03:13 -07002295 mStacks.get(stackNdx).switchUserLocked(userId);
Craig Mautnerac6f8432013-07-17 13:24:59 -07002296 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002297
Craig Mautner93529a42013-10-04 15:03:13 -07002298 moveHomeStack(homeInFront);
2299 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 Mautner323f7802013-10-01 21:16:22 -07002311 if (true || 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) {
2387 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
2388 pw.println(mDismissKeyguardOnNextActivity);
Craig Mautner76ea2242013-05-15 11:40:05 -07002389 pw.print(prefix); pw.print("mStackState="); pw.println(stackStateToString(mStackState));
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002390 pw.print(prefix); pw.println("mSleepTimeout: " + mSleepTimeout);
2391 pw.print(prefix); pw.println("mCurTaskId: " + mCurTaskId);
Craig Mautner93529a42013-10-04 15:03:13 -07002392 pw.print(prefix); pw.println("mUserHomeInFront: " + mUserHomeInFront);
Craig Mautner27084302013-03-25 08:05:25 -07002393 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002394
Craig Mautner20e72272013-04-01 13:45:53 -07002395 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002396 return getFocusedStack().getDumpActivitiesLocked(name);
Craig Mautner20e72272013-04-01 13:45:53 -07002397 }
2398
Dianne Hackborn390517b2013-05-30 15:03:32 -07002399 static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
2400 boolean needSep, String prefix) {
2401 if (activity != null) {
2402 if (dumpPackage == null || dumpPackage.equals(activity.packageName)) {
2403 if (needSep) {
2404 pw.println();
Dianne Hackborn390517b2013-05-30 15:03:32 -07002405 }
2406 pw.print(prefix);
2407 pw.println(activity);
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002408 return true;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002409 }
2410 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002411 return false;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002412 }
2413
Craig Mautner8d341ef2013-03-26 09:03:27 -07002414 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
2415 boolean dumpClient, String dumpPackage) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002416 boolean printed = false;
2417 boolean needSep = false;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002418 final int numStacks = mStacks.size();
2419 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2420 final ActivityStack stack = mStacks.get(stackNdx);
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002421 StringBuilder stackHeader = new StringBuilder(128);
2422 stackHeader.append(" Stack #");
2423 stackHeader.append(mStacks.indexOf(stack));
2424 stackHeader.append(":");
2425 printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, needSep,
2426 stackHeader.toString());
2427 printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll,
2428 false, dumpPackage, true, " Running activities (most recent first):", null);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002429
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002430 needSep = printed;
2431 boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002432 " mPausingActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002433 if (pr) {
2434 printed = true;
2435 needSep = false;
2436 }
2437 pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002438 " mResumedActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002439 if (pr) {
2440 printed = true;
2441 needSep = false;
2442 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002443 if (dumpAll) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002444 pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002445 " mLastPausedActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002446 if (pr) {
2447 printed = true;
Craig Mautner0f922742013-08-06 08:44:42 -07002448 needSep = true;
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002449 }
Craig Mautner0f922742013-08-06 08:44:42 -07002450 printed |= printThisActivity(pw, stack.mLastNoHistoryActivity, dumpPackage,
2451 needSep, " mLastNoHistoryActivity: ");
Craig Mautner8d341ef2013-03-26 09:03:27 -07002452 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002453 needSep = printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002454 }
2455
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002456 printed |= dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll,
2457 false, dumpPackage, true, " Activities waiting to finish:", null);
2458 printed |= dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll,
2459 false, dumpPackage, true, " Activities waiting to stop:", null);
2460 printed |= dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
2461 false, dumpPackage, true, " Activities waiting for another to become visible:",
2462 null);
2463 printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll,
2464 false, dumpPackage, true, " Activities waiting to sleep:", null);
2465 printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll,
2466 false, dumpPackage, true, " Activities waiting to sleep:", null);
Craig Mautnerf3333272013-04-22 10:55:53 -07002467
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002468 return printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002469 }
2470
Dianne Hackborn390517b2013-05-30 15:03:32 -07002471 static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
Craig Mautner8d341ef2013-03-26 09:03:27 -07002472 String prefix, String label, boolean complete, boolean brief, boolean client,
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002473 String dumpPackage, boolean needNL, String header1, String header2) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002474 TaskRecord lastTask = null;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002475 String innerPrefix = null;
2476 String[] args = null;
2477 boolean printed = false;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002478 for (int i=list.size()-1; i>=0; i--) {
2479 final ActivityRecord r = list.get(i);
2480 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
2481 continue;
2482 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07002483 if (innerPrefix == null) {
2484 innerPrefix = prefix + " ";
2485 args = new String[0];
2486 }
2487 printed = true;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002488 final boolean full = !brief && (complete || !r.isInHistory());
2489 if (needNL) {
Dianne Hackborn390517b2013-05-30 15:03:32 -07002490 pw.println("");
Craig Mautner8d341ef2013-03-26 09:03:27 -07002491 needNL = false;
2492 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002493 if (header1 != null) {
2494 pw.println(header1);
2495 header1 = null;
2496 }
2497 if (header2 != null) {
2498 pw.println(header2);
2499 header2 = null;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002500 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002501 if (lastTask != r.task) {
2502 lastTask = r.task;
2503 pw.print(prefix);
2504 pw.print(full ? "* " : " ");
2505 pw.println(lastTask);
2506 if (full) {
2507 lastTask.dump(pw, prefix + " ");
2508 } else if (complete) {
2509 // Complete + brief == give a summary. Isn't that obvious?!?
2510 if (lastTask.intent != null) {
2511 pw.print(prefix); pw.print(" ");
2512 pw.println(lastTask.intent.toInsecureStringWithClip());
2513 }
2514 }
2515 }
2516 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
2517 pw.print(" #"); pw.print(i); pw.print(": ");
2518 pw.println(r);
2519 if (full) {
2520 r.dump(pw, innerPrefix);
2521 } else if (complete) {
2522 // Complete + brief == give a summary. Isn't that obvious?!?
2523 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
2524 if (r.app != null) {
2525 pw.print(innerPrefix); pw.println(r.app);
2526 }
2527 }
2528 if (client && r.app != null && r.app.thread != null) {
2529 // flush anything that is already in the PrintWriter since the thread is going
2530 // to write to the file descriptor directly
2531 pw.flush();
2532 try {
2533 TransferPipe tp = new TransferPipe();
2534 try {
2535 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
2536 r.appToken, innerPrefix, args);
2537 // Short timeout, since blocking here can
2538 // deadlock with the application.
2539 tp.go(fd, 2000);
2540 } finally {
2541 tp.kill();
2542 }
2543 } catch (IOException e) {
2544 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
2545 } catch (RemoteException e) {
2546 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
2547 }
2548 needNL = true;
2549 }
2550 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07002551 return printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002552 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002553
Craig Mautnerf3333272013-04-22 10:55:53 -07002554 void scheduleIdleTimeoutLocked(ActivityRecord next) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002555 if (DEBUG_IDLE) Slog.d(TAG, "scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4));
Craig Mautnerc64f73e2013-04-24 16:44:56 -07002556 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
2557 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
Craig Mautnerf3333272013-04-22 10:55:53 -07002558 }
2559
2560 final void scheduleIdleLocked() {
Craig Mautner05d29032013-05-03 13:40:13 -07002561 mHandler.sendEmptyMessage(IDLE_NOW_MSG);
Craig Mautnerf3333272013-04-22 10:55:53 -07002562 }
2563
2564 void removeTimeoutsForActivityLocked(ActivityRecord r) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002565 if (DEBUG_IDLE) Slog.d(TAG, "removeTimeoutsForActivity: Callers=" + Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07002566 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
2567 }
2568
Craig Mautner05d29032013-05-03 13:40:13 -07002569 final void scheduleResumeTopActivities() {
2570 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2571 }
2572
Craig Mautner0eea92c2013-05-16 13:35:39 -07002573 void removeSleepTimeouts() {
2574 mSleepTimeout = false;
2575 mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
2576 }
2577
2578 final void scheduleSleepTimeout() {
2579 removeSleepTimeouts();
2580 mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT);
2581 }
2582
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002583 private final class ActivityStackSupervisorHandler extends Handler {
Craig Mautnerf3333272013-04-22 10:55:53 -07002584
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002585 public ActivityStackSupervisorHandler(Looper looper) {
2586 super(looper);
2587 }
2588
Craig Mautnerf3333272013-04-22 10:55:53 -07002589 void activityIdleInternal(ActivityRecord r) {
2590 synchronized (mService) {
2591 activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
2592 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002593 }
2594
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002595 @Override
2596 public void handleMessage(Message msg) {
2597 switch (msg.what) {
Craig Mautnerf3333272013-04-22 10:55:53 -07002598 case IDLE_TIMEOUT_MSG: {
Craig Mautner5eda9b32013-07-02 11:58:16 -07002599 if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_TIMEOUT_MSG: r=" + msg.obj);
Craig Mautnerf3333272013-04-22 10:55:53 -07002600 if (mService.mDidDexOpt) {
2601 mService.mDidDexOpt = false;
2602 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2603 nmsg.obj = msg.obj;
2604 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
2605 return;
2606 }
2607 // We don't at this point know if the activity is fullscreen,
2608 // so we need to be conservative and assume it isn't.
2609 activityIdleInternal((ActivityRecord)msg.obj);
2610 } break;
2611 case IDLE_NOW_MSG: {
Craig Mautner5eda9b32013-07-02 11:58:16 -07002612 if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_NOW_MSG: r=" + msg.obj);
Craig Mautnerf3333272013-04-22 10:55:53 -07002613 activityIdleInternal((ActivityRecord)msg.obj);
2614 } break;
Craig Mautner05d29032013-05-03 13:40:13 -07002615 case RESUME_TOP_ACTIVITY_MSG: {
2616 synchronized (mService) {
2617 resumeTopActivitiesLocked();
2618 }
2619 } break;
Craig Mautner0eea92c2013-05-16 13:35:39 -07002620 case SLEEP_TIMEOUT_MSG: {
2621 synchronized (mService) {
2622 if (mService.isSleepingOrShuttingDown()) {
2623 Slog.w(TAG, "Sleep timeout! Sleeping now.");
2624 mSleepTimeout = true;
2625 checkReadyForSleepLocked();
2626 }
2627 }
2628 } break;
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002629 case LAUNCH_TIMEOUT_MSG: {
2630 if (mService.mDidDexOpt) {
2631 mService.mDidDexOpt = false;
2632 mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
2633 return;
2634 }
2635 synchronized (mService) {
2636 if (mLaunchingActivity.isHeld()) {
2637 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
2638 if (VALIDATE_WAKE_LOCK_CALLER
2639 && Binder.getCallingUid() != Process.myUid()) {
2640 throw new IllegalStateException("Calling must be system uid");
2641 }
2642 mLaunchingActivity.release();
2643 }
2644 }
2645 } break;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002646 }
2647 }
2648 }
Craig Mautner27084302013-03-25 08:05:25 -07002649}