blob: bf9190435d2b89b29129b6aa666d8bc08c6c66d7 [file] [log] [blame]
Craig Mautner27084302013-03-25 08:05:25 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Craig Mautner6170f732013-04-02 13:05:23 -070019import static android.Manifest.permission.START_ANY_ACTIVITY;
Craig Mautner29219d92013-04-16 20:19:12 -070020import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
21import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Craig Mautner6170f732013-04-02 13:05:23 -070022import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Craig Mautner2420ead2013-04-01 17:13:20 -070023import static com.android.server.am.ActivityManagerService.localLOGV;
Craig Mautner23ac33b2013-04-01 16:26:35 -070024import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION;
Craig Mautnere7c58b62013-06-12 20:19:00 -070025import static com.android.server.am.ActivityManagerService.DEBUG_FOCUS;
Craig Mautner0eea92c2013-05-16 13:35:39 -070026import static com.android.server.am.ActivityManagerService.DEBUG_PAUSE;
Craig Mautner6170f732013-04-02 13:05:23 -070027import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
Craig Mautner0eea92c2013-05-16 13:35:39 -070028import static com.android.server.am.ActivityManagerService.DEBUG_STACK;
Craig Mautner2420ead2013-04-01 17:13:20 -070029import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
Craig Mautner8849a5e2013-04-02 16:41:03 -070030import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
31import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
Craig Mautner05d29032013-05-03 13:40:13 -070032import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
Craig Mautner8d341ef2013-03-26 09:03:27 -070033import static com.android.server.am.ActivityManagerService.TAG;
34
Craig Mautner2420ead2013-04-01 17:13:20 -070035import android.app.Activity;
Craig Mautner23ac33b2013-04-01 16:26:35 -070036import android.app.ActivityManager;
37import android.app.ActivityOptions;
38import android.app.AppGlobals;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070039import android.app.IActivityManager;
Craig Mautner23ac33b2013-04-01 16:26:35 -070040import android.app.IApplicationThread;
Craig Mautner20e72272013-04-01 13:45:53 -070041import android.app.IThumbnailReceiver;
Craig Mautner23ac33b2013-04-01 16:26:35 -070042import android.app.PendingIntent;
Craig Mautner20e72272013-04-01 13:45:53 -070043import android.app.ActivityManager.RunningTaskInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070044import android.app.IActivityManager.WaitResult;
Craig Mautner2420ead2013-04-01 17:13:20 -070045import android.app.ResultInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070046import android.content.ComponentName;
Craig Mautner2219a1b2013-03-25 09:44:30 -070047import android.content.Context;
Craig Mautner23ac33b2013-04-01 16:26:35 -070048import android.content.IIntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070049import android.content.Intent;
Craig Mautner23ac33b2013-04-01 16:26:35 -070050import android.content.IntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070051import android.content.pm.ActivityInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070052import android.content.pm.ApplicationInfo;
53import android.content.pm.PackageManager;
54import android.content.pm.ResolveInfo;
55import android.content.res.Configuration;
56import android.os.Binder;
Craig Mautner8d341ef2013-03-26 09:03:27 -070057import android.os.Bundle;
Craig Mautnerb59dcfd2013-05-06 13:12:58 -070058import android.os.Debug;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070059import android.os.Handler;
Craig Mautner23ac33b2013-04-01 16:26:35 -070060import android.os.IBinder;
Craig Mautner2219a1b2013-03-25 09:44:30 -070061import android.os.Looper;
Craig Mautner2420ead2013-04-01 17:13:20 -070062import android.os.Message;
Craig Mautner23ac33b2013-04-01 16:26:35 -070063import android.os.ParcelFileDescriptor;
Craig Mautner0eea92c2013-05-16 13:35:39 -070064import android.os.PowerManager;
Craig Mautner7ea5bd42013-07-05 15:27:08 -070065import android.os.Process;
Craig Mautner8d341ef2013-03-26 09:03:27 -070066import android.os.RemoteException;
Craig Mautner23ac33b2013-04-01 16:26:35 -070067import android.os.SystemClock;
Craig Mautner6170f732013-04-02 13:05:23 -070068import android.os.UserHandle;
Craig Mautner2420ead2013-04-01 17:13:20 -070069import android.util.EventLog;
Craig Mautner8d341ef2013-03-26 09:03:27 -070070import android.util.Slog;
Craig Mautner858d8a62013-04-23 17:08:34 -070071import android.util.SparseArray;
Craig Mautner2219a1b2013-03-25 09:44:30 -070072
Craig Mautner23ac33b2013-04-01 16:26:35 -070073import com.android.internal.app.HeavyWeightSwitcherActivity;
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070074import com.android.internal.os.TransferPipe;
Craig Mautner6170f732013-04-02 13:05:23 -070075import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
Craig Mautner2420ead2013-04-01 17:13:20 -070076import com.android.server.am.ActivityStack.ActivityState;
Craig Mautnerde4ef022013-04-07 19:01:33 -070077import com.android.server.wm.StackBox;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070078import com.android.server.wm.WindowManagerService;
Craig Mautner23ac33b2013-04-01 16:26:35 -070079
Craig Mautner8d341ef2013-03-26 09:03:27 -070080import java.io.FileDescriptor;
81import java.io.IOException;
Craig Mautner27084302013-03-25 08:05:25 -070082import java.io.PrintWriter;
Craig Mautner2219a1b2013-03-25 09:44:30 -070083import java.util.ArrayList;
Craig Mautner8d341ef2013-03-26 09:03:27 -070084import java.util.List;
Craig Mautner27084302013-03-25 08:05:25 -070085
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070086public final class ActivityStackSupervisor {
Craig Mautnerde4ef022013-04-07 19:01:33 -070087 static final boolean DEBUG = ActivityManagerService.DEBUG || false;
88 static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
89 static final boolean DEBUG_APP = DEBUG || false;
90 static final boolean DEBUG_SAVED_STATE = DEBUG || false;
Craig Mautnerb3370ce2013-09-19 12:02:09 -070091 static final boolean DEBUG_STATES = DEBUG || true;
Craig Mautnerb59dcfd2013-05-06 13:12:58 -070092 static final boolean DEBUG_IDLE = DEBUG || false;
Craig Mautner2420ead2013-04-01 17:13:20 -070093
Craig Mautner2219a1b2013-03-25 09:44:30 -070094 public static final int HOME_STACK_ID = 0;
Craig Mautner27084302013-03-25 08:05:25 -070095
Craig Mautnerf3333272013-04-22 10:55:53 -070096 /** How long we wait until giving up on the last activity telling us it is idle. */
97 static final int IDLE_TIMEOUT = 10*1000;
98
Craig Mautner0eea92c2013-05-16 13:35:39 -070099 /** How long we can hold the sleep wake lock before giving up. */
100 static final int SLEEP_TIMEOUT = 5*1000;
101
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700102 // How long we can hold the launch wake lock before giving up.
103 static final int LAUNCH_TIMEOUT = 10*1000;
104
Craig Mautner05d29032013-05-03 13:40:13 -0700105 static final int IDLE_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG;
106 static final int IDLE_NOW_MSG = FIRST_SUPERVISOR_STACK_MSG + 1;
107 static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2;
Craig Mautner0eea92c2013-05-16 13:35:39 -0700108 static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3;
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700109 static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 4;
110
111 // For debugging to make sure the caller when acquiring/releasing our
112 // wake lock is the system process.
113 static final boolean VALIDATE_WAKE_LOCK_CALLER = false;
Craig Mautnerf3333272013-04-22 10:55:53 -0700114
Craig Mautner27084302013-03-25 08:05:25 -0700115 final ActivityManagerService mService;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700116 final Context mContext;
117 final Looper mLooper;
Craig Mautner27084302013-03-25 08:05:25 -0700118
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700119 final ActivityStackSupervisorHandler mHandler;
120
121 /** Short cut */
122 WindowManagerService mWindowManager;
123
Craig Mautner27084302013-03-25 08:05:25 -0700124 /** Dismiss the keyguard after the next activity is displayed? */
Craig Mautner5314a402013-09-26 12:40:16 -0700125 boolean mDismissKeyguardOnNextActivity = false;
Craig Mautner27084302013-03-25 08:05:25 -0700126
Craig Mautner8d341ef2013-03-26 09:03:27 -0700127 /** Identifier counter for all ActivityStacks */
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700128 private int mLastStackId = HOME_STACK_ID;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700129
130 /** Task identifier that activities are currently being started in. Incremented each time a
131 * new task is created. */
132 private int mCurTaskId = 0;
133
Craig Mautner2420ead2013-04-01 17:13:20 -0700134 /** The current user */
135 private int mCurrentUser;
136
Craig Mautner8d341ef2013-03-26 09:03:27 -0700137 /** The stack containing the launcher app */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700138 private ActivityStack mHomeStack;
Craig Mautner20e72272013-04-01 13:45:53 -0700139
Craig Mautnerde4ef022013-04-07 19:01:33 -0700140 /** The non-home stack currently receiving input or launching the next activity. If home is
Craig Mautner41c0f352013-05-28 08:39:25 -0700141 * in front then mHomeStack overrides mFocusedStack.
142 * DO NOT ACCESS DIRECTLY - It may be null, use getFocusedStack() */
Craig Mautner29219d92013-04-16 20:19:12 -0700143 private ActivityStack mFocusedStack;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700144
145 /** All the non-launcher stacks */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700146 private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
147
Craig Mautnerde4ef022013-04-07 19:01:33 -0700148 private static final int STACK_STATE_HOME_IN_FRONT = 0;
149 private static final int STACK_STATE_HOME_TO_BACK = 1;
150 private static final int STACK_STATE_HOME_IN_BACK = 2;
151 private static final int STACK_STATE_HOME_TO_FRONT = 3;
152 private int mStackState = STACK_STATE_HOME_IN_FRONT;
153
154 /** List of activities that are waiting for a new activity to become visible before completing
155 * whatever operation they are supposed to do. */
156 final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();
157
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700158 /** List of processes waiting to find out about the next visible activity. */
159 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible =
160 new ArrayList<IActivityManager.WaitResult>();
161
162 /** List of processes waiting to find out about the next launched activity. */
163 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched =
164 new ArrayList<IActivityManager.WaitResult>();
165
Craig Mautnerde4ef022013-04-07 19:01:33 -0700166 /** List of activities that are ready to be stopped, but waiting for the next activity to
167 * settle down before doing so. */
168 final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();
169
Craig Mautnerf3333272013-04-22 10:55:53 -0700170 /** List of activities that are ready to be finished, but waiting for the previous activity to
171 * settle down before doing so. It contains ActivityRecord objects. */
172 final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<ActivityRecord>();
173
Craig Mautner0eea92c2013-05-16 13:35:39 -0700174 /** List of activities that are in the process of going to sleep. */
175 final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<ActivityRecord>();
176
Craig Mautnerf3333272013-04-22 10:55:53 -0700177 /** List of ActivityRecord objects that have been finished and must still report back to a
178 * pending thumbnail receiver. */
179 final ArrayList<ActivityRecord> mCancelledThumbnails = new ArrayList<ActivityRecord>();
180
181 /** Used on user changes */
182 final ArrayList<UserStartedState> mStartingUsers = new ArrayList<UserStartedState>();
183
Craig Mautnerde4ef022013-04-07 19:01:33 -0700184 /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity
185 * is being brought in front of us. */
186 boolean mUserLeaving = false;
187
Craig Mautner0eea92c2013-05-16 13:35:39 -0700188 /** Set when we have taken too long waiting to go to sleep. */
189 boolean mSleepTimeout = false;
190
191 /**
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700192 * We don't want to allow the device to go to sleep while in the process
193 * of launching an activity. This is primarily to allow alarm intent
194 * receivers to launch an activity and get that to run before the device
195 * goes back to sleep.
196 */
197 final PowerManager.WakeLock mLaunchingActivity;
198
199 /**
Craig Mautner0eea92c2013-05-16 13:35:39 -0700200 * Set when the system is going to sleep, until we have
201 * successfully paused the current activity and released our wake lock.
202 * At that point the system is allowed to actually sleep.
203 */
204 final PowerManager.WakeLock mGoingToSleep;
205
Craig Mautnerac6f8432013-07-17 13:24:59 -0700206 /**
207 * The name of the current home activity for each user.
208 * TODO: Remove entries when user is deleted.
209 */
210 final SparseArray<String> mHomePackageNames = new SparseArray<String>();
211
Craig Mautner2219a1b2013-03-25 09:44:30 -0700212 public ActivityStackSupervisor(ActivityManagerService service, Context context,
213 Looper looper) {
Craig Mautner27084302013-03-25 08:05:25 -0700214 mService = service;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700215 mContext = context;
216 mLooper = looper;
Craig Mautner0eea92c2013-05-16 13:35:39 -0700217 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
218 mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700219 mHandler = new ActivityStackSupervisorHandler(looper);
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700220 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
221 throw new IllegalStateException("Calling must be system uid");
222 }
223 mLaunchingActivity =
224 pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
225 mLaunchingActivity.setReferenceCounted(false);
Craig Mautner2219a1b2013-03-25 09:44:30 -0700226 }
227
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700228 void setWindowManager(WindowManagerService wm) {
229 mWindowManager = wm;
230 mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700231 mStacks.add(mHomeStack);
Craig Mautner27084302013-03-25 08:05:25 -0700232 }
233
234 void dismissKeyguard() {
Craig Mautner5314a402013-09-26 12:40:16 -0700235 if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
Craig Mautner27084302013-03-25 08:05:25 -0700236 if (mDismissKeyguardOnNextActivity) {
237 mDismissKeyguardOnNextActivity = false;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700238 mWindowManager.dismissKeyguard();
Craig Mautner27084302013-03-25 08:05:25 -0700239 }
240 }
241
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700242 ActivityStack getFocusedStack() {
Craig Mautnerf88c50f2013-04-18 19:25:12 -0700243 if (mFocusedStack == null) {
244 return mHomeStack;
245 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700246 switch (mStackState) {
247 case STACK_STATE_HOME_IN_FRONT:
248 case STACK_STATE_HOME_TO_FRONT:
249 return mHomeStack;
250 case STACK_STATE_HOME_IN_BACK:
251 case STACK_STATE_HOME_TO_BACK:
252 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700253 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700254 }
Craig Mautner20e72272013-04-01 13:45:53 -0700255 }
256
Craig Mautnerde4ef022013-04-07 19:01:33 -0700257 ActivityStack getLastStack() {
258 switch (mStackState) {
259 case STACK_STATE_HOME_IN_FRONT:
260 case STACK_STATE_HOME_TO_BACK:
261 return mHomeStack;
262 case STACK_STATE_HOME_TO_FRONT:
263 case STACK_STATE_HOME_IN_BACK:
264 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700265 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700266 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700267 }
268
Craig Mautnerde4ef022013-04-07 19:01:33 -0700269 boolean isFrontStack(ActivityStack stack) {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700270 return !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
Craig Mautner20e72272013-04-01 13:45:53 -0700271 }
272
Craig Mautnerde4ef022013-04-07 19:01:33 -0700273 void moveHomeStack(boolean toFront) {
274 final boolean homeInFront = isFrontStack(mHomeStack);
275 if (homeInFront ^ toFront) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700276 if (DEBUG_STACK) Slog.d(TAG, "moveHomeTask: mStackState old=" +
277 stackStateToString(mStackState) + " new=" + stackStateToString(homeInFront ?
278 STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700279 mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
280 }
281 }
282
Craig Mautner69ada552013-04-18 13:51:51 -0700283 boolean resumeHomeActivity(ActivityRecord prev) {
284 moveHomeStack(true);
285 if (prev != null) {
Craig Mautnerae7ecab2013-09-18 11:48:14 -0700286 prev.task.mOnTopOfHome = false;
Craig Mautner69ada552013-04-18 13:51:51 -0700287 }
Craig Mautnera82aa092013-09-13 15:34:08 -0700288 mHomeStack.moveHomeTaskToTop();
Craig Mautnera8a90e02013-06-28 15:24:50 -0700289 ActivityRecord r = mHomeStack.topRunningActivityLocked(null);
290 if (r != null) {
291 mService.setFocusedActivityLocked(r);
Craig Mautner05d29032013-05-03 13:40:13 -0700292 return resumeTopActivitiesLocked(mHomeStack, prev, null);
Craig Mautner69ada552013-04-18 13:51:51 -0700293 }
294 return mService.startHomeActivityLocked(mCurrentUser);
295 }
296
Craig Mautnerde4ef022013-04-07 19:01:33 -0700297 final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r,
298 ActivityStack stack) {
299 if (stack == mHomeStack) {
300 return;
301 }
302 if ((sourceRecord == null && getLastStack() == mHomeStack) ||
Craig Mautner86d67a42013-05-14 10:34:38 -0700303 (sourceRecord != null && sourceRecord.isHomeActivity())) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700304 if (r == null) {
305 r = stack.topRunningActivityLocked(null);
306 }
Craig Mautner86d67a42013-05-14 10:34:38 -0700307 if (r != null && !r.isHomeActivity() && r.isRootActivity()) {
Craig Mautnerae7ecab2013-09-18 11:48:14 -0700308 r.task.mOnTopOfHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700309 }
310 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700311 }
312
Craig Mautner27084302013-03-25 08:05:25 -0700313 void setDismissKeyguard(boolean dismiss) {
Craig Mautner5314a402013-09-26 12:40:16 -0700314 if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen(" dismiss=" + dismiss);
Craig Mautner27084302013-03-25 08:05:25 -0700315 mDismissKeyguardOnNextActivity = dismiss;
316 }
317
Craig Mautner8d341ef2013-03-26 09:03:27 -0700318 TaskRecord anyTaskForIdLocked(int id) {
319 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
320 ActivityStack stack = mStacks.get(stackNdx);
321 TaskRecord task = stack.taskForIdLocked(id);
322 if (task != null) {
323 return task;
324 }
325 }
326 return null;
327 }
328
Craig Mautner6170f732013-04-02 13:05:23 -0700329 ActivityRecord isInAnyStackLocked(IBinder token) {
330 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
331 final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
332 if (r != null) {
333 return r;
334 }
335 }
336 return null;
337 }
338
Craig Mautner8d341ef2013-03-26 09:03:27 -0700339 int getNextTaskId() {
340 do {
341 mCurTaskId++;
342 if (mCurTaskId <= 0) {
343 mCurTaskId = 1;
344 }
345 } while (anyTaskForIdLocked(mCurTaskId) != null);
346 return mCurTaskId;
347 }
348
Craig Mautnerde4ef022013-04-07 19:01:33 -0700349 void removeTask(TaskRecord task) {
Craig Mautnerb3b36ba2013-05-20 13:21:10 -0700350 mWindowManager.removeTask(task.taskId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700351 final ActivityStack stack = task.stack;
Craig Mautnerb3b36ba2013-05-20 13:21:10 -0700352 final ActivityRecord r = stack.mResumedActivity;
353 if (r != null && r.task == task) {
354 stack.mResumedActivity = null;
355 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700356 if (stack.removeTask(task) && !stack.isHomeStack()) {
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700357 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700358 mStacks.remove(stack);
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700359 final int stackId = stack.mStackId;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700360 final int nextStackId = mWindowManager.removeStack(stackId);
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700361 // TODO: Perhaps we need to let the ActivityManager determine the next focus...
Craig Mautnerac6f8432013-07-17 13:24:59 -0700362 if (mFocusedStack == null || mFocusedStack.mStackId == stackId) {
Craig Mautner1602ec22013-05-12 10:24:27 -0700363 // If this is the last app stack, set mFocusedStack to null.
Craig Mautner29219d92013-04-16 20:19:12 -0700364 mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700365 }
366 }
367 }
368
369 ActivityRecord resumedAppLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700370 ActivityStack stack = getFocusedStack();
371 if (stack == null) {
372 return null;
373 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700374 ActivityRecord resumedActivity = stack.mResumedActivity;
375 if (resumedActivity == null || resumedActivity.app == null) {
376 resumedActivity = stack.mPausingActivity;
377 if (resumedActivity == null || resumedActivity.app == null) {
378 resumedActivity = stack.topRunningActivityLocked(null);
379 }
380 }
381 return resumedActivity;
382 }
383
Craig Mautner20e72272013-04-01 13:45:53 -0700384 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
385 boolean didSomething = false;
386 final String processName = app.processName;
387 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
388 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner858d8a62013-04-23 17:08:34 -0700389 if (!isFrontStack(stack)) {
390 continue;
391 }
Craig Mautner20e72272013-04-01 13:45:53 -0700392 ActivityRecord hr = stack.topRunningActivityLocked(null);
393 if (hr != null) {
394 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
395 && processName.equals(hr.processName)) {
396 try {
397 if (headless) {
398 Slog.e(TAG, "Starting activities not supported on headless device: "
399 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700400 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700401 didSomething = true;
402 }
403 } catch (Exception e) {
404 Slog.w(TAG, "Exception in new application when starting activity "
405 + hr.intent.getComponent().flattenToShortString(), e);
406 throw e;
407 }
Craig Mautner20e72272013-04-01 13:45:53 -0700408 }
409 }
410 }
Craig Mautnerb59dcfd2013-05-06 13:12:58 -0700411 if (!didSomething) {
412 ensureActivitiesVisibleLocked(null, 0);
413 }
Craig Mautner20e72272013-04-01 13:45:53 -0700414 return didSomething;
415 }
416
417 boolean allResumedActivitiesIdle() {
418 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner7ea5bd42013-07-05 15:27:08 -0700419 final ActivityStack stack = mStacks.get(stackNdx);
420 if (!isFrontStack(stack)) {
421 continue;
422 }
423 final ActivityRecord resumedActivity = stack.mResumedActivity;
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700424 if (resumedActivity == null || !resumedActivity.idle) {
Craig Mautner20e72272013-04-01 13:45:53 -0700425 return false;
426 }
427 }
428 return true;
429 }
430
Craig Mautnerde4ef022013-04-07 19:01:33 -0700431 boolean allResumedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700432 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
433 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner967212c2013-04-13 21:10:58 -0700434 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700435 final ActivityRecord r = stack.mResumedActivity;
436 if (r != null && r.state != ActivityState.RESUMED) {
437 return false;
438 }
439 }
440 }
441 // TODO: Not sure if this should check if all Paused are complete too.
442 switch (mStackState) {
443 case STACK_STATE_HOME_TO_BACK:
Craig Mautner76ea2242013-05-15 11:40:05 -0700444 if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
445 stackStateToString(STACK_STATE_HOME_TO_BACK) + " new=" +
446 stackStateToString(STACK_STATE_HOME_IN_BACK));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700447 mStackState = STACK_STATE_HOME_IN_BACK;
448 break;
449 case STACK_STATE_HOME_TO_FRONT:
Craig Mautner76ea2242013-05-15 11:40:05 -0700450 if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
451 stackStateToString(STACK_STATE_HOME_TO_FRONT) + " new=" +
452 stackStateToString(STACK_STATE_HOME_IN_FRONT));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700453 mStackState = STACK_STATE_HOME_IN_FRONT;
454 break;
455 }
456 return true;
457 }
458
459 boolean allResumedActivitiesVisible() {
460 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
461 final ActivityStack stack = mStacks.get(stackNdx);
462 final ActivityRecord r = stack.mResumedActivity;
463 if (r != null && (!r.nowVisible || r.waitingVisible)) {
464 return false;
465 }
466 }
467 return true;
468 }
469
Craig Mautner2acc3892013-09-23 10:28:14 -0700470 /**
471 * Pause all activities in either all of the stacks or just the back stacks.
472 * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
Craig Mautner2acc3892013-09-23 10:28:14 -0700473 * @return true if any activity was paused as a result of this call.
474 */
Craig Mautner5314a402013-09-26 12:40:16 -0700475 boolean pauseBackStacks(boolean userLeaving) {
Craig Mautnercf910b02013-04-23 11:23:27 -0700476 boolean someActivityPaused = false;
477 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
478 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner5314a402013-09-26 12:40:16 -0700479 if (!isFrontStack(stack) && stack.mResumedActivity != null) {
480 if (DEBUG_STATES) Slog.d(TAG, "pauseBackStacks: stack=" + stack +
Craig Mautnerac6f8432013-07-17 13:24:59 -0700481 " mResumedActivity=" + stack.mResumedActivity);
Craig Mautnercf910b02013-04-23 11:23:27 -0700482 stack.startPausingLocked(userLeaving, false);
483 someActivityPaused = true;
484 }
485 }
486 return someActivityPaused;
487 }
488
Craig Mautnerde4ef022013-04-07 19:01:33 -0700489 boolean allPausedActivitiesComplete() {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700490 boolean pausing = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700491 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
492 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner69ada552013-04-18 13:51:51 -0700493 final ActivityRecord r = stack.mPausingActivity;
494 if (r != null && r.state != ActivityState.PAUSED
495 && r.state != ActivityState.STOPPED
496 && r.state != ActivityState.STOPPING) {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700497 if (DEBUG_STATES) {
498 Slog.d(TAG, "allPausedActivitiesComplete: r=" + r + " state=" + r.state);
499 pausing = false;
500 } else {
501 return false;
502 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700503 }
504 }
Craig Mautnerac6f8432013-07-17 13:24:59 -0700505 return pausing;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700506 }
507
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700508 void reportActivityVisibleLocked(ActivityRecord r) {
Craig Mautner858d8a62013-04-23 17:08:34 -0700509 for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700510 WaitResult w = mWaitingActivityVisible.get(i);
511 w.timeout = false;
512 if (r != null) {
513 w.who = new ComponentName(r.info.packageName, r.info.name);
514 }
515 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
516 w.thisTime = w.totalTime;
517 }
518 mService.notifyAll();
519 dismissKeyguard();
520 }
521
522 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
523 long thisTime, long totalTime) {
524 for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
Craig Mautnerc64f73e2013-04-24 16:44:56 -0700525 WaitResult w = mWaitingActivityLaunched.remove(i);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700526 w.timeout = timeout;
527 if (r != null) {
528 w.who = new ComponentName(r.info.packageName, r.info.name);
529 }
530 w.thisTime = thisTime;
531 w.totalTime = totalTime;
532 }
533 mService.notifyAll();
534 }
535
Craig Mautner29219d92013-04-16 20:19:12 -0700536 ActivityRecord topRunningActivityLocked() {
Craig Mautner1602ec22013-05-12 10:24:27 -0700537 final ActivityStack focusedStack = getFocusedStack();
538 ActivityRecord r = focusedStack.topRunningActivityLocked(null);
539 if (r != null) {
540 return r;
Craig Mautner29219d92013-04-16 20:19:12 -0700541 }
Craig Mautner1602ec22013-05-12 10:24:27 -0700542
Craig Mautner29219d92013-04-16 20:19:12 -0700543 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
544 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700545 if (stack != focusedStack && isFrontStack(stack)) {
Craig Mautner29219d92013-04-16 20:19:12 -0700546 r = stack.topRunningActivityLocked(null);
547 if (r != null) {
548 return r;
549 }
550 }
551 }
552 return null;
553 }
554
Craig Mautner20e72272013-04-01 13:45:53 -0700555 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
556 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
557 ActivityRecord r = null;
Craig Mautnerc0fd8052013-09-19 11:20:17 -0700558
559 // Gather all of the running tasks for each stack into runningTaskLists.
560 final int numStacks = mStacks.size();
561 ArrayList<RunningTaskInfo>[] runningTaskLists = new ArrayList[numStacks];
562 for (int stackNdx = numStacks - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner20e72272013-04-01 13:45:53 -0700563 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerc0fd8052013-09-19 11:20:17 -0700564 ArrayList<RunningTaskInfo> stackTaskList = new ArrayList<RunningTaskInfo>();
565 runningTaskLists[stackNdx] = stackTaskList;
566 final ActivityRecord ar = stack.getTasksLocked(receiver, pending, stackTaskList);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700567 if (isFrontStack(stack)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700568 r = ar;
569 }
570 }
Craig Mautnerc0fd8052013-09-19 11:20:17 -0700571
572 // The lists are already sorted from most recent to oldest. Just pull the most recent off
573 // each list and add it to list. Stop when all lists are empty or maxNum reached.
574 while (maxNum > 0) {
575 long mostRecentActiveTime = Long.MIN_VALUE;
576 ArrayList<RunningTaskInfo> selectedStackList = null;
577 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
578 ArrayList<RunningTaskInfo> stackTaskList = runningTaskLists[stackNdx];
579 if (!stackTaskList.isEmpty()) {
580 final long lastActiveTime = stackTaskList.get(0).lastActiveTime;
581 if (lastActiveTime > mostRecentActiveTime) {
582 mostRecentActiveTime = lastActiveTime;
583 selectedStackList = stackTaskList;
584 }
585 }
586 }
587 if (selectedStackList != null) {
588 list.add(selectedStackList.remove(0));
589 --maxNum;
590 } else {
591 break;
592 }
593 }
594
Craig Mautner20e72272013-04-01 13:45:53 -0700595 return r;
596 }
597
Craig Mautner23ac33b2013-04-01 16:26:35 -0700598 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
599 String profileFile, ParcelFileDescriptor profileFd, int userId) {
600 // Collect information about the target of the Intent.
601 ActivityInfo aInfo;
602 try {
603 ResolveInfo rInfo =
604 AppGlobals.getPackageManager().resolveIntent(
605 intent, resolvedType,
606 PackageManager.MATCH_DEFAULT_ONLY
607 | ActivityManagerService.STOCK_PM_FLAGS, userId);
608 aInfo = rInfo != null ? rInfo.activityInfo : null;
609 } catch (RemoteException e) {
610 aInfo = null;
611 }
612
613 if (aInfo != null) {
614 // Store the found target back into the intent, because now that
615 // we have it we never want to do this again. For example, if the
616 // user navigates back to this point in the history, we should
617 // always restart the exact same activity.
618 intent.setComponent(new ComponentName(
619 aInfo.applicationInfo.packageName, aInfo.name));
620
621 // Don't debug things in the system process
622 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
623 if (!aInfo.processName.equals("system")) {
624 mService.setDebugApp(aInfo.processName, true, false);
625 }
626 }
627
628 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
629 if (!aInfo.processName.equals("system")) {
630 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
631 }
632 }
633
634 if (profileFile != null) {
635 if (!aInfo.processName.equals("system")) {
636 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
637 profileFile, profileFd,
638 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
639 }
640 }
641 }
642 return aInfo;
643 }
644
Craig Mautner2219a1b2013-03-25 09:44:30 -0700645 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700646 moveHomeStack(true);
Craig Mautner6170f732013-04-02 13:05:23 -0700647 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
Craig Mautner2219a1b2013-03-25 09:44:30 -0700648 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700649 }
650
Craig Mautner23ac33b2013-04-01 16:26:35 -0700651 final int startActivityMayWait(IApplicationThread caller, int callingUid,
652 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
653 String resultWho, int requestCode, int startFlags, String profileFile,
654 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
655 Bundle options, int userId) {
656 // Refuse possible leaked file descriptors
657 if (intent != null && intent.hasFileDescriptors()) {
658 throw new IllegalArgumentException("File descriptors passed in Intent");
659 }
660 boolean componentSpecified = intent.getComponent() != null;
661
662 // Don't modify the client's object!
663 intent = new Intent(intent);
664
665 // Collect information about the target of the Intent.
666 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
667 profileFile, profileFd, userId);
668
669 synchronized (mService) {
670 int callingPid;
671 if (callingUid >= 0) {
672 callingPid = -1;
673 } else if (caller == null) {
674 callingPid = Binder.getCallingPid();
675 callingUid = Binder.getCallingUid();
676 } else {
677 callingPid = callingUid = -1;
678 }
679
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700680 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -0700681 stack.mConfigWillChange = config != null
Craig Mautner23ac33b2013-04-01 16:26:35 -0700682 && mService.mConfiguration.diff(config) != 0;
683 if (DEBUG_CONFIGURATION) Slog.v(TAG,
Craig Mautnerde4ef022013-04-07 19:01:33 -0700684 "Starting activity when config will change = " + stack.mConfigWillChange);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700685
686 final long origId = Binder.clearCallingIdentity();
687
688 if (aInfo != null &&
689 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
690 // This may be a heavy-weight process! Check to see if we already
691 // have another, different heavy-weight process running.
692 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
693 if (mService.mHeavyWeightProcess != null &&
694 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
695 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700696 int realCallingUid = callingUid;
697 if (caller != null) {
698 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
699 if (callerApp != null) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700700 realCallingUid = callerApp.info.uid;
701 } else {
702 Slog.w(TAG, "Unable to find app for caller " + caller
Craig Mautner76ea2242013-05-15 11:40:05 -0700703 + " (pid=" + callingPid + ") when starting: "
Craig Mautner23ac33b2013-04-01 16:26:35 -0700704 + intent.toString());
705 ActivityOptions.abort(options);
706 return ActivityManager.START_PERMISSION_DENIED;
707 }
708 }
709
710 IIntentSender target = mService.getIntentSenderLocked(
711 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
712 realCallingUid, userId, null, null, 0, new Intent[] { intent },
713 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
714 | PendingIntent.FLAG_ONE_SHOT, null);
715
716 Intent newIntent = new Intent();
717 if (requestCode >= 0) {
718 // Caller is requesting a result.
719 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
720 }
721 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
722 new IntentSender(target));
723 if (mService.mHeavyWeightProcess.activities.size() > 0) {
724 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
725 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
726 hist.packageName);
727 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
728 hist.task.taskId);
729 }
730 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
731 aInfo.packageName);
732 newIntent.setFlags(intent.getFlags());
733 newIntent.setClassName("android",
734 HeavyWeightSwitcherActivity.class.getName());
735 intent = newIntent;
736 resolvedType = null;
737 caller = null;
738 callingUid = Binder.getCallingUid();
739 callingPid = Binder.getCallingPid();
740 componentSpecified = true;
741 try {
742 ResolveInfo rInfo =
743 AppGlobals.getPackageManager().resolveIntent(
744 intent, null,
745 PackageManager.MATCH_DEFAULT_ONLY
746 | ActivityManagerService.STOCK_PM_FLAGS, userId);
747 aInfo = rInfo != null ? rInfo.activityInfo : null;
748 aInfo = mService.getActivityInfoForUser(aInfo, userId);
749 } catch (RemoteException e) {
750 aInfo = null;
751 }
752 }
753 }
754 }
755
Craig Mautner6170f732013-04-02 13:05:23 -0700756 int res = startActivityLocked(caller, intent, resolvedType,
Craig Mautner23ac33b2013-04-01 16:26:35 -0700757 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
758 callingPackage, startFlags, options, componentSpecified, null);
759
Craig Mautnerde4ef022013-04-07 19:01:33 -0700760 if (stack.mConfigWillChange) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700761 // If the caller also wants to switch to a new configuration,
762 // do so now. This allows a clean switch, as we are waiting
763 // for the current activity to pause (so we will not destroy
764 // it), and have not yet started the next activity.
765 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
766 "updateConfiguration()");
Craig Mautnerde4ef022013-04-07 19:01:33 -0700767 stack.mConfigWillChange = false;
Craig Mautner23ac33b2013-04-01 16:26:35 -0700768 if (DEBUG_CONFIGURATION) Slog.v(TAG,
769 "Updating to new configuration after starting activity.");
770 mService.updateConfigurationLocked(config, null, false, false);
771 }
772
773 Binder.restoreCallingIdentity(origId);
774
775 if (outResult != null) {
776 outResult.result = res;
777 if (res == ActivityManager.START_SUCCESS) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700778 mWaitingActivityLaunched.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700779 do {
780 try {
781 mService.wait();
782 } catch (InterruptedException e) {
783 }
784 } while (!outResult.timeout && outResult.who == null);
785 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700786 ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700787 if (r.nowVisible) {
788 outResult.timeout = false;
789 outResult.who = new ComponentName(r.info.packageName, r.info.name);
790 outResult.totalTime = 0;
791 outResult.thisTime = 0;
792 } else {
793 outResult.thisTime = SystemClock.uptimeMillis();
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700794 mWaitingActivityVisible.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700795 do {
796 try {
797 mService.wait();
798 } catch (InterruptedException e) {
799 }
800 } while (!outResult.timeout && outResult.who == null);
801 }
802 }
803 }
804
805 return res;
806 }
807 }
808
809 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
810 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
811 Bundle options, int userId) {
812 if (intents == null) {
813 throw new NullPointerException("intents is null");
814 }
815 if (resolvedTypes == null) {
816 throw new NullPointerException("resolvedTypes is null");
817 }
818 if (intents.length != resolvedTypes.length) {
819 throw new IllegalArgumentException("intents are length different than resolvedTypes");
820 }
821
Craig Mautner23ac33b2013-04-01 16:26:35 -0700822
823 int callingPid;
824 if (callingUid >= 0) {
825 callingPid = -1;
826 } else if (caller == null) {
827 callingPid = Binder.getCallingPid();
828 callingUid = Binder.getCallingUid();
829 } else {
830 callingPid = callingUid = -1;
831 }
832 final long origId = Binder.clearCallingIdentity();
833 try {
834 synchronized (mService) {
Craig Mautner76ea2242013-05-15 11:40:05 -0700835 ActivityRecord[] outActivity = new ActivityRecord[1];
Craig Mautner23ac33b2013-04-01 16:26:35 -0700836 for (int i=0; i<intents.length; i++) {
837 Intent intent = intents[i];
838 if (intent == null) {
839 continue;
840 }
841
842 // Refuse possible leaked file descriptors
843 if (intent != null && intent.hasFileDescriptors()) {
844 throw new IllegalArgumentException("File descriptors passed in Intent");
845 }
846
847 boolean componentSpecified = intent.getComponent() != null;
848
849 // Don't modify the client's object!
850 intent = new Intent(intent);
851
852 // Collect information about the target of the Intent.
853 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
854 0, null, null, userId);
855 // TODO: New, check if this is correct
856 aInfo = mService.getActivityInfoForUser(aInfo, userId);
857
858 if (aInfo != null &&
859 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
860 != 0) {
861 throw new IllegalArgumentException(
862 "FLAG_CANT_SAVE_STATE not supported here");
863 }
864
865 Bundle theseOptions;
866 if (options != null && i == intents.length-1) {
867 theseOptions = options;
868 } else {
869 theseOptions = null;
870 }
Craig Mautner6170f732013-04-02 13:05:23 -0700871 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Craig Mautner23ac33b2013-04-01 16:26:35 -0700872 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
873 0, theseOptions, componentSpecified, outActivity);
874 if (res < 0) {
875 return res;
876 }
877
878 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
879 }
880 }
881 } finally {
882 Binder.restoreCallingIdentity(origId);
883 }
884
885 return ActivityManager.START_SUCCESS;
886 }
887
Craig Mautner2420ead2013-04-01 17:13:20 -0700888 final boolean realStartActivityLocked(ActivityRecord r,
889 ProcessRecord app, boolean andResume, boolean checkConfig)
890 throws RemoteException {
891
892 r.startFreezingScreenLocked(app, 0);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700893 mWindowManager.setAppVisibility(r.appToken, true);
Craig Mautner2420ead2013-04-01 17:13:20 -0700894
895 // schedule launch ticks to collect information about slow apps.
896 r.startLaunchTickingLocked();
897
898 // Have the window manager re-evaluate the orientation of
899 // the screen based on the new activity order. Note that
900 // as a result of this, it can call back into the activity
901 // manager with a new orientation. We don't care about that,
902 // because the activity is not currently running so we are
903 // just restarting it anyway.
904 if (checkConfig) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700905 Configuration config = mWindowManager.updateOrientationFromAppTokens(
Craig Mautner2420ead2013-04-01 17:13:20 -0700906 mService.mConfiguration,
907 r.mayFreezeScreenLocked(app) ? r.appToken : null);
908 mService.updateConfigurationLocked(config, r, false, false);
909 }
910
911 r.app = app;
912 app.waitingToKill = null;
913 r.launchCount++;
914 r.lastLaunchTime = SystemClock.uptimeMillis();
915
916 if (localLOGV) Slog.v(TAG, "Launching: " + r);
917
918 int idx = app.activities.indexOf(r);
919 if (idx < 0) {
920 app.activities.add(r);
921 }
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -0700922 mService.updateLruProcessLocked(app, true, true);
Craig Mautner2420ead2013-04-01 17:13:20 -0700923
924 final ActivityStack stack = r.task.stack;
925 try {
926 if (app.thread == null) {
927 throw new RemoteException();
928 }
929 List<ResultInfo> results = null;
930 List<Intent> newIntents = null;
931 if (andResume) {
932 results = r.results;
933 newIntents = r.newIntents;
934 }
935 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
936 + " icicle=" + r.icicle
937 + " with results=" + results + " newIntents=" + newIntents
938 + " andResume=" + andResume);
939 if (andResume) {
940 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
941 r.userId, System.identityHashCode(r),
942 r.task.taskId, r.shortComponentName);
943 }
Craig Mautnerac6f8432013-07-17 13:24:59 -0700944 if (r.isHomeActivity() && r.isNotResolverActivity()) {
Craig Mautner4ef26932013-09-18 15:15:52 -0700945 // Home process is the root process of the task.
946 mService.mHomeProcess = r.task.mActivities.get(0).app;
Craig Mautner2420ead2013-04-01 17:13:20 -0700947 }
948 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
949 r.sleeping = false;
950 r.forceNewConfig = false;
951 mService.showAskCompatModeDialogLocked(r);
952 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
953 String profileFile = null;
954 ParcelFileDescriptor profileFd = null;
955 boolean profileAutoStop = false;
956 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
957 if (mService.mProfileProc == null || mService.mProfileProc == app) {
958 mService.mProfileProc = app;
959 profileFile = mService.mProfileFile;
960 profileFd = mService.mProfileFd;
961 profileAutoStop = mService.mAutoStopProfiler;
962 }
963 }
964 app.hasShownUi = true;
965 app.pendingUiClean = true;
966 if (profileFd != null) {
967 try {
968 profileFd = profileFd.dup();
969 } catch (IOException e) {
970 if (profileFd != null) {
971 try {
972 profileFd.close();
973 } catch (IOException o) {
974 }
975 profileFd = null;
976 }
977 }
978 }
Dianne Hackborna413dc02013-07-12 12:02:55 -0700979 app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
Craig Mautner2420ead2013-04-01 17:13:20 -0700980 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
981 System.identityHashCode(r), r.info,
Dianne Hackborna413dc02013-07-12 12:02:55 -0700982 new Configuration(mService.mConfiguration), r.compat,
983 app.repProcState, r.icicle, results, newIntents, !andResume,
Craig Mautner2420ead2013-04-01 17:13:20 -0700984 mService.isNextTransitionForward(), profileFile, profileFd,
985 profileAutoStop);
986
987 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
988 // This may be a heavy-weight process! Note that the package
989 // manager will ensure that only activity can run in the main
990 // process of the .apk, which is the only thing that will be
991 // considered heavy-weight.
992 if (app.processName.equals(app.info.packageName)) {
993 if (mService.mHeavyWeightProcess != null
994 && mService.mHeavyWeightProcess != app) {
995 Slog.w(TAG, "Starting new heavy weight process " + app
996 + " when already running "
997 + mService.mHeavyWeightProcess);
998 }
999 mService.mHeavyWeightProcess = app;
1000 Message msg = mService.mHandler.obtainMessage(
1001 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
1002 msg.obj = r;
1003 mService.mHandler.sendMessage(msg);
1004 }
1005 }
1006
1007 } catch (RemoteException e) {
1008 if (r.launchFailed) {
1009 // This is the second time we failed -- finish activity
1010 // and give up.
1011 Slog.e(TAG, "Second failure launching "
1012 + r.intent.getComponent().flattenToShortString()
1013 + ", giving up", e);
1014 mService.appDiedLocked(app, app.pid, app.thread);
1015 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
1016 "2nd-crash", false);
1017 return false;
1018 }
1019
1020 // This is the first time we failed -- restart process and
1021 // retry.
1022 app.activities.remove(r);
1023 throw e;
1024 }
1025
1026 r.launchFailed = false;
1027 if (stack.updateLRUListLocked(r)) {
1028 Slog.w(TAG, "Activity " + r
1029 + " being launched, but already in LRU list");
1030 }
1031
1032 if (andResume) {
1033 // As part of the process of launching, ActivityThread also performs
1034 // a resume.
1035 stack.minimalResumeActivityLocked(r);
1036 } else {
1037 // This activity is not starting in the resumed state... which
1038 // should look like we asked it to pause+stop (but remain visible),
1039 // and it has done so and reported back the current icicle and
1040 // other state.
1041 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
1042 + " (starting in stopped state)");
1043 r.state = ActivityState.STOPPED;
1044 r.stopped = true;
1045 }
1046
1047 // Launch the new version setup screen if needed. We do this -after-
1048 // launching the initial activity (that is, home), so that it can have
1049 // a chance to initialize itself while in the background, making the
1050 // switch back to it faster and look better.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001051 if (isFrontStack(stack)) {
Craig Mautner2420ead2013-04-01 17:13:20 -07001052 mService.startSetupActivityLocked();
1053 }
1054
1055 return true;
1056 }
1057
Craig Mautnere79d42682013-04-01 19:01:53 -07001058 void startSpecificActivityLocked(ActivityRecord r,
1059 boolean andResume, boolean checkConfig) {
1060 // Is this activity's application already running?
1061 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07001062 r.info.applicationInfo.uid, true);
Craig Mautnere79d42682013-04-01 19:01:53 -07001063
1064 r.task.stack.setLaunchTime(r);
1065
1066 if (app != null && app.thread != null) {
1067 try {
Dianne Hackbornd2932242013-08-05 18:18:42 -07001068 app.addPackage(r.info.packageName, mService.mProcessStats);
Craig Mautnere79d42682013-04-01 19:01:53 -07001069 realStartActivityLocked(r, app, andResume, checkConfig);
1070 return;
1071 } catch (RemoteException e) {
1072 Slog.w(TAG, "Exception when starting activity "
1073 + r.intent.getComponent().flattenToShortString(), e);
1074 }
1075
1076 // If a dead object exception was thrown -- fall through to
1077 // restart the application.
1078 }
1079
1080 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07001081 "activity", r.intent.getComponent(), false, false, true);
Craig Mautnere79d42682013-04-01 19:01:53 -07001082 }
1083
Craig Mautner6170f732013-04-02 13:05:23 -07001084 final int startActivityLocked(IApplicationThread caller,
1085 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
1086 String resultWho, int requestCode,
1087 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
1088 boolean componentSpecified, ActivityRecord[] outActivity) {
1089 int err = ActivityManager.START_SUCCESS;
1090
1091 ProcessRecord callerApp = null;
1092 if (caller != null) {
1093 callerApp = mService.getRecordForAppLocked(caller);
1094 if (callerApp != null) {
1095 callingPid = callerApp.pid;
1096 callingUid = callerApp.info.uid;
1097 } else {
1098 Slog.w(TAG, "Unable to find app for caller " + caller
1099 + " (pid=" + callingPid + ") when starting: "
1100 + intent.toString());
1101 err = ActivityManager.START_PERMISSION_DENIED;
1102 }
1103 }
1104
1105 if (err == ActivityManager.START_SUCCESS) {
1106 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
1107 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
1108 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
1109 }
1110
1111 ActivityRecord sourceRecord = null;
1112 ActivityRecord resultRecord = null;
1113 if (resultTo != null) {
1114 sourceRecord = isInAnyStackLocked(resultTo);
1115 if (DEBUG_RESULTS) Slog.v(
1116 TAG, "Will send result to " + resultTo + " " + sourceRecord);
1117 if (sourceRecord != null) {
1118 if (requestCode >= 0 && !sourceRecord.finishing) {
1119 resultRecord = sourceRecord;
1120 }
1121 }
1122 }
1123 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
1124
1125 int launchFlags = intent.getFlags();
1126
1127 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
1128 && sourceRecord != null) {
1129 // Transfer the result target from the source activity to the new
1130 // one being started, including any failures.
1131 if (requestCode >= 0) {
1132 ActivityOptions.abort(options);
1133 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
1134 }
1135 resultRecord = sourceRecord.resultTo;
1136 resultWho = sourceRecord.resultWho;
1137 requestCode = sourceRecord.requestCode;
1138 sourceRecord.resultTo = null;
1139 if (resultRecord != null) {
1140 resultRecord.removeResultsLocked(
1141 sourceRecord, resultWho, requestCode);
1142 }
1143 }
1144
1145 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
1146 // We couldn't find a class that can handle the given Intent.
1147 // That's the end of that!
1148 err = ActivityManager.START_INTENT_NOT_RESOLVED;
1149 }
1150
1151 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
1152 // We couldn't find the specific class specified in the Intent.
1153 // Also the end of the line.
1154 err = ActivityManager.START_CLASS_NOT_FOUND;
1155 }
1156
1157 if (err != ActivityManager.START_SUCCESS) {
1158 if (resultRecord != null) {
1159 resultStack.sendActivityResultLocked(-1,
1160 resultRecord, resultWho, requestCode,
1161 Activity.RESULT_CANCELED, null);
1162 }
1163 setDismissKeyguard(false);
1164 ActivityOptions.abort(options);
1165 return err;
1166 }
1167
1168 final int startAnyPerm = mService.checkPermission(
1169 START_ANY_ACTIVITY, callingPid, callingUid);
1170 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
1171 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
1172 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
1173 if (resultRecord != null) {
1174 resultStack.sendActivityResultLocked(-1,
1175 resultRecord, resultWho, requestCode,
1176 Activity.RESULT_CANCELED, null);
1177 }
1178 setDismissKeyguard(false);
1179 String msg;
1180 if (!aInfo.exported) {
1181 msg = "Permission Denial: starting " + intent.toString()
1182 + " from " + callerApp + " (pid=" + callingPid
1183 + ", uid=" + callingUid + ")"
1184 + " not exported from uid " + aInfo.applicationInfo.uid;
1185 } else {
1186 msg = "Permission Denial: starting " + intent.toString()
1187 + " from " + callerApp + " (pid=" + callingPid
1188 + ", uid=" + callingUid + ")"
1189 + " requires " + aInfo.permission;
1190 }
1191 Slog.w(TAG, msg);
1192 throw new SecurityException(msg);
1193 }
1194
Ben Gruverdd72c9e2013-08-06 12:34:17 -07001195 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
Ben Gruverb6223792013-07-29 16:35:40 -07001196 callingPid, resolvedType, aInfo.applicationInfo);
Ben Gruver5e207332013-04-03 17:41:37 -07001197
Craig Mautner6170f732013-04-02 13:05:23 -07001198 if (mService.mController != null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001199 try {
1200 // The Intent we give to the watcher has the extra data
1201 // stripped off, since it can contain private information.
1202 Intent watchIntent = intent.cloneFilter();
Ben Gruver5e207332013-04-03 17:41:37 -07001203 abort |= !mService.mController.activityStarting(watchIntent,
Craig Mautner6170f732013-04-02 13:05:23 -07001204 aInfo.applicationInfo.packageName);
1205 } catch (RemoteException e) {
1206 mService.mController = null;
1207 }
Ben Gruver5e207332013-04-03 17:41:37 -07001208 }
Craig Mautner6170f732013-04-02 13:05:23 -07001209
Ben Gruver5e207332013-04-03 17:41:37 -07001210 if (abort) {
1211 if (resultRecord != null) {
1212 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Craig Mautner6170f732013-04-02 13:05:23 -07001213 Activity.RESULT_CANCELED, null);
Craig Mautner6170f732013-04-02 13:05:23 -07001214 }
Ben Gruver5e207332013-04-03 17:41:37 -07001215 // We pretend to the caller that it was really started, but
1216 // they will just get a cancel result.
1217 setDismissKeyguard(false);
1218 ActivityOptions.abort(options);
1219 return ActivityManager.START_SUCCESS;
Craig Mautner6170f732013-04-02 13:05:23 -07001220 }
1221
1222 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1223 intent, resolvedType, aInfo, mService.mConfiguration,
Craig Mautnerde4ef022013-04-07 19:01:33 -07001224 resultRecord, resultWho, requestCode, componentSpecified, this);
Craig Mautner6170f732013-04-02 13:05:23 -07001225 if (outActivity != null) {
1226 outActivity[0] = r;
1227 }
1228
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001229 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001230 if (stack.mResumedActivity == null
1231 || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
Craig Mautner6170f732013-04-02 13:05:23 -07001232 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1233 PendingActivityLaunch pal =
Craig Mautnerde4ef022013-04-07 19:01:33 -07001234 new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
Craig Mautner6170f732013-04-02 13:05:23 -07001235 mService.mPendingActivityLaunches.add(pal);
1236 setDismissKeyguard(false);
1237 ActivityOptions.abort(options);
1238 return ActivityManager.START_SWITCHES_CANCELED;
1239 }
1240 }
1241
1242 if (mService.mDidAppSwitch) {
1243 // This is the second allowed switch since we stopped switches,
1244 // so now just generally allow switches. Use case: user presses
1245 // home (switches disabled, switch to home, mDidAppSwitch now true);
1246 // user taps a home icon (coming from home so allowed, we hit here
1247 // and now allow anyone to switch again).
1248 mService.mAppSwitchesAllowedTime = 0;
1249 } else {
1250 mService.mDidAppSwitch = true;
1251 }
1252
1253 mService.doPendingActivityLaunchesLocked(false);
1254
Craig Mautner8849a5e2013-04-02 16:41:03 -07001255 err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
Craig Mautner10385a12013-09-22 21:08:32 -07001256
1257 if (allPausedActivitiesComplete()) {
1258 // If someone asked to have the keyguard dismissed on the next
Craig Mautner6170f732013-04-02 13:05:23 -07001259 // activity start, but we are not actually doing an activity
1260 // switch... just dismiss the keyguard now, because we
1261 // probably want to see whatever is behind it.
1262 dismissKeyguard();
1263 }
1264 return err;
1265 }
1266
Craig Mautnerac6f8432013-07-17 13:24:59 -07001267 ActivityStack adjustStackFocus(ActivityRecord r) {
Craig Mautner1d001b62013-06-18 16:52:43 -07001268 final TaskRecord task = r.task;
1269 if (r.isApplicationActivity() || (task != null && task.isApplicationTask())) {
Craig Mautnerac6f8432013-07-17 13:24:59 -07001270 if (task != null) {
1271 if (mFocusedStack != task.stack) {
1272 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1273 "adjustStackFocus: Setting focused stack to r=" + r + " task=" + task);
1274 mFocusedStack = task.stack;
1275 } else {
1276 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1277 "adjustStackFocus: Focused stack already=" + mFocusedStack);
1278 }
1279 return mFocusedStack;
1280 }
1281
1282 if (mFocusedStack != null) {
1283 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1284 "adjustStackFocus: Have a focused stack=" + mFocusedStack);
1285 return mFocusedStack;
1286 }
1287
1288 for (int stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
1289 ActivityStack stack = mStacks.get(stackNdx);
1290 if (!stack.isHomeStack()) {
1291 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1292 "adjustStackFocus: Setting focused stack=" + stack);
1293 mFocusedStack = stack;
1294 return mFocusedStack;
Craig Mautner858d8a62013-04-23 17:08:34 -07001295 }
1296 }
Craig Mautnerac6f8432013-07-17 13:24:59 -07001297
1298 // Time to create the first app stack for this user.
1299 int stackId = mService.createStack(-1, HOME_STACK_ID,
1300 StackBox.TASK_STACK_GOES_OVER, 1.0f);
1301 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack r=" + r +
1302 " stackId=" + stackId);
1303 mFocusedStack = getStack(stackId);
Craig Mautner29219d92013-04-16 20:19:12 -07001304 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001305 }
1306 return mHomeStack;
1307 }
1308
Craig Mautner29219d92013-04-16 20:19:12 -07001309 void setFocusedStack(ActivityRecord r) {
1310 if (r == null) {
1311 return;
1312 }
Craig Mautner86d67a42013-05-14 10:34:38 -07001313 if (!r.isApplicationActivity() || (r.task != null && !r.task.isApplicationTask())) {
Craig Mautner29219d92013-04-16 20:19:12 -07001314 if (mStackState != STACK_STATE_HOME_IN_FRONT) {
Craig Mautnere7c58b62013-06-12 20:19:00 -07001315 if (DEBUG_STACK || DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: mStackState old=" +
Craig Mautner76ea2242013-05-15 11:40:05 -07001316 stackStateToString(mStackState) + " new=" +
1317 stackStateToString(STACK_STATE_HOME_TO_FRONT) +
1318 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001319 mStackState = STACK_STATE_HOME_TO_FRONT;
1320 }
1321 } else {
Craig Mautnerac6f8432013-07-17 13:24:59 -07001322 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1323 "setFocusedStack: Setting focused stack to r=" + r + " task=" + r.task +
1324 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001325 mFocusedStack = r.task.stack;
1326 if (mStackState != STACK_STATE_HOME_IN_BACK) {
Craig Mautner76ea2242013-05-15 11:40:05 -07001327 if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
1328 stackStateToString(mStackState) + " new=" +
1329 stackStateToString(STACK_STATE_HOME_TO_BACK) +
1330 " Callers=" + Debug.getCallers(3));
Craig Mautner29219d92013-04-16 20:19:12 -07001331 mStackState = STACK_STATE_HOME_TO_BACK;
1332 }
1333 }
1334 }
1335
Craig Mautner8849a5e2013-04-02 16:41:03 -07001336 final int startActivityUncheckedLocked(ActivityRecord r,
1337 ActivityRecord sourceRecord, int startFlags, boolean doResume,
1338 Bundle options) {
1339 final Intent intent = r.intent;
1340 final int callingUid = r.launchedFromUid;
1341
1342 int launchFlags = intent.getFlags();
1343
Craig Mautner8849a5e2013-04-02 16:41:03 -07001344 // We'll invoke onUserLeaving before onPause only if the launching
1345 // activity did not explicitly state that this is an automated launch.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001346 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1347 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001348
1349 // If the caller has asked not to resume at this point, we make note
1350 // of this in the record so that we can skip it when trying to find
1351 // the top running activity.
1352 if (!doResume) {
1353 r.delayedResume = true;
1354 }
1355
1356 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1357
1358 // If the onlyIfNeeded flag is set, then we can do this if the activity
1359 // being launched is the same as the one making the call... or, as
1360 // a special case, if we do not know the caller then we count the
1361 // current top activity as the caller.
1362 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1363 ActivityRecord checkedCaller = sourceRecord;
1364 if (checkedCaller == null) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001365 checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001366 }
1367 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1368 // Caller is not the same as launcher, so always needed.
1369 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1370 }
1371 }
1372
1373 if (sourceRecord == null) {
1374 // This activity is not being started from another... in this
1375 // case we -always- start a new task.
1376 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Craig Mautner29219d92013-04-16 20:19:12 -07001377 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1378 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001379 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1380 }
1381 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1382 // The original activity who is starting us is running as a single
1383 // instance... this new activity it is starting must go on its
1384 // own task.
1385 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1386 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1387 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1388 // The activity being started is a single instance... it always
1389 // gets launched into its own task.
1390 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1391 }
1392
Craig Mautnerde4ef022013-04-07 19:01:33 -07001393 final ActivityStack sourceStack;
Craig Mautner525f3d92013-05-07 14:01:50 -07001394 TaskRecord sourceTask;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001395 if (sourceRecord != null) {
1396 sourceTask = sourceRecord.task;
1397 sourceStack = sourceTask.stack;
1398 } else {
1399 sourceTask = null;
1400 sourceStack = null;
1401 }
1402
Craig Mautner8849a5e2013-04-02 16:41:03 -07001403 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1404 // For whatever reason this activity is being launched into a new
1405 // task... yet the caller has requested a result back. Well, that
1406 // is pretty messed up, so instead immediately send back a cancel
1407 // and let the new task continue launched as normal without a
1408 // dependency on its originator.
1409 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1410 r.resultTo.task.stack.sendActivityResultLocked(-1,
1411 r.resultTo, r.resultWho, r.requestCode,
1412 Activity.RESULT_CANCELED, null);
1413 r.resultTo = null;
1414 }
1415
1416 boolean addingToTask = false;
1417 boolean movedHome = false;
1418 TaskRecord reuseTask = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001419 ActivityStack targetStack;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001420 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1421 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1422 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1423 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1424 // If bring to front is requested, and no result is requested, and
1425 // we can find a task that was started with this same
1426 // component, then instead of launching bring that one to the front.
1427 if (r.resultTo == null) {
1428 // See if there is a task to bring to the front. If this is
1429 // a SINGLE_INSTANCE activity, there can be one and only one
1430 // instance of it in the history, and it is always in its own
1431 // unique task, so we do a special search.
1432 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
Craig Mautnerac6f8432013-07-17 13:24:59 -07001433 ? findTaskLocked(r)
Craig Mautner8849a5e2013-04-02 16:41:03 -07001434 : findActivityLocked(intent, r.info);
1435 if (intentActivity != null) {
Craig Mautner29219d92013-04-16 20:19:12 -07001436 if (r.task == null) {
1437 r.task = intentActivity.task;
1438 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001439 targetStack = intentActivity.task.stack;
Craig Mautner0f922742013-08-06 08:44:42 -07001440 targetStack.mLastPausedActivity = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001441 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001442 if (intentActivity.task.intent == null) {
1443 // This task was started because of movement of
1444 // the activity based on affinity... now that we
1445 // are actually launching it, we can assign the
1446 // base intent.
1447 intentActivity.task.setIntent(intent, r.info);
1448 }
1449 // If the target task is not in the front, then we need
1450 // to bring it to the front... except... well, with
1451 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
1452 // to have the same behavior as if a new instance was
1453 // being started, which means not bringing it to the front
1454 // if the caller is not itself in the front.
Craig Mautner165640b2013-04-20 10:34:33 -07001455 final ActivityStack lastStack = getLastStack();
1456 ActivityRecord curTop = lastStack == null?
1457 null : lastStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner7504d7b2013-09-17 10:50:53 -07001458 if (curTop != null && (curTop.task != intentActivity.task ||
1459 curTop.task != lastStack.topTask())) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001460 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Craig Mautnerd0f964f2013-08-07 11:16:33 -07001461 if (sourceRecord == null || (sourceStack.topActivity() != null &&
1462 sourceStack.topActivity().task == sourceRecord.task)) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001463 // We really do want to push this one into the
1464 // user's face, right now.
1465 movedHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001466 if ((launchFlags &
Craig Mautner29219d92013-04-16 20:19:12 -07001467 (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1468 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
Craig Mautnere12a4a62013-08-29 12:24:56 -07001469 // Caller wants to appear on home activity.
Craig Mautnerae7ecab2013-09-18 11:48:14 -07001470 intentActivity.task.mOnTopOfHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001471 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001472 targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1473 options = null;
1474 }
1475 }
1476 // If the caller has requested that the target task be
1477 // reset, then do so.
1478 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1479 intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1480 }
1481 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1482 // We don't need to start a new activity, and
1483 // the client said not to do anything if that
1484 // is the case, so this is it! And for paranoia, make
1485 // sure we have correctly resumed the top activity.
1486 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001487 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001488 resumeTopActivitiesLocked(targetStack, null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001489 } else {
1490 ActivityOptions.abort(options);
1491 }
Craig Mautner29219d92013-04-16 20:19:12 -07001492 if (r.task == null) Slog.v(TAG,
1493 "startActivityUncheckedLocked: task left null",
1494 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001495 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1496 }
1497 if ((launchFlags &
1498 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1499 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1500 // The caller has requested to completely replace any
1501 // existing task with its new activity. Well that should
1502 // not be too hard...
1503 reuseTask = intentActivity.task;
1504 reuseTask.performClearTaskLocked();
1505 reuseTask.setIntent(r.intent, r.info);
1506 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1507 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1508 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1509 // In this situation we want to remove all activities
1510 // from the task up to the one being started. In most
1511 // cases this means we are resetting the task to its
1512 // initial state.
1513 ActivityRecord top =
1514 intentActivity.task.performClearTaskLocked(r, launchFlags);
1515 if (top != null) {
1516 if (top.frontOfTask) {
1517 // Activity aliases may mean we use different
1518 // intents for the top activity, so make sure
1519 // the task now has the identity of the new
1520 // intent.
1521 top.task.setIntent(r.intent, r.info);
1522 }
1523 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1524 r, top.task);
1525 top.deliverNewIntentLocked(callingUid, r.intent);
1526 } else {
1527 // A special case: we need to
1528 // start the activity because it is not currently
1529 // running, and the caller has asked to clear the
1530 // current task to have this activity at the top.
1531 addingToTask = true;
1532 // Now pretend like this activity is being started
1533 // by the top of its task, so it is put in the
1534 // right place.
1535 sourceRecord = intentActivity;
1536 }
1537 } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1538 // In this case the top activity on the task is the
1539 // same as the one being launched, so we take that
1540 // as a request to bring the task to the foreground.
1541 // If the top activity in the task is the root
1542 // activity, deliver this new intent to it if it
1543 // desires.
1544 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1545 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1546 && intentActivity.realActivity.equals(r.realActivity)) {
1547 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1548 intentActivity.task);
1549 if (intentActivity.frontOfTask) {
1550 intentActivity.task.setIntent(r.intent, r.info);
1551 }
1552 intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1553 } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1554 // In this case we are launching the root activity
1555 // of the task, but with a different intent. We
1556 // should start a new instance on top.
1557 addingToTask = true;
1558 sourceRecord = intentActivity;
1559 }
1560 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1561 // In this case an activity is being launched in to an
1562 // existing task, without resetting that task. This
1563 // is typically the situation of launching an activity
1564 // from a notification or shortcut. We want to place
1565 // the new activity on top of the current task.
1566 addingToTask = true;
1567 sourceRecord = intentActivity;
1568 } else if (!intentActivity.task.rootWasReset) {
1569 // In this case we are launching in to an existing task
1570 // that has not yet been started from its front door.
1571 // The current task has been brought to the front.
1572 // Ideally, we'd probably like to place this new task
1573 // at the bottom of its stack, but that's a little hard
1574 // to do with the current organization of the code so
1575 // for now we'll just drop it.
1576 intentActivity.task.setIntent(r.intent, r.info);
1577 }
1578 if (!addingToTask && reuseTask == null) {
1579 // We didn't do anything... but it was needed (a.k.a., client
1580 // don't use that intent!) And for paranoia, make
1581 // sure we have correctly resumed the top activity.
1582 if (doResume) {
Craig Mautnere12a4a62013-08-29 12:24:56 -07001583 // Reset flag so it gets correctly reevaluated.
Craig Mautnerae7ecab2013-09-18 11:48:14 -07001584 intentActivity.task.mOnTopOfHome = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001585 setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1586 targetStack.resumeTopActivityLocked(null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001587 } else {
1588 ActivityOptions.abort(options);
1589 }
Craig Mautner29219d92013-04-16 20:19:12 -07001590 if (r.task == null) Slog.v(TAG,
1591 "startActivityUncheckedLocked: task left null",
1592 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001593 return ActivityManager.START_TASK_TO_FRONT;
1594 }
1595 }
1596 }
1597 }
1598
1599 //String uri = r.intent.toURI();
1600 //Intent intent2 = new Intent(uri);
1601 //Slog.i(TAG, "Given intent: " + r.intent);
1602 //Slog.i(TAG, "URI is: " + uri);
1603 //Slog.i(TAG, "To intent: " + intent2);
1604
1605 if (r.packageName != null) {
1606 // If the activity being launched is the same as the one currently
1607 // at the top, then we need to check if it should only be launched
1608 // once.
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001609 ActivityStack topStack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001610 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001611 if (top != null && r.resultTo == null) {
1612 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1613 if (top.app != null && top.app.thread != null) {
1614 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1615 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1616 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1617 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1618 top.task);
1619 // For paranoia, make sure we have correctly
1620 // resumed the top activity.
Craig Mautner0f922742013-08-06 08:44:42 -07001621 topStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001622 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001623 setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001624 resumeTopActivitiesLocked();
Craig Mautner8849a5e2013-04-02 16:41:03 -07001625 }
1626 ActivityOptions.abort(options);
1627 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1628 // We don't need to start a new activity, and
1629 // the client said not to do anything if that
1630 // is the case, so this is it!
Craig Mautner29219d92013-04-16 20:19:12 -07001631 if (r.task == null) Slog.v(TAG,
1632 "startActivityUncheckedLocked: task left null",
1633 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001634 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1635 }
1636 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner29219d92013-04-16 20:19:12 -07001637 if (r.task == null) Slog.v(TAG,
1638 "startActivityUncheckedLocked: task left null",
1639 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001640 return ActivityManager.START_DELIVERED_TO_TOP;
1641 }
1642 }
1643 }
1644 }
1645
1646 } else {
1647 if (r.resultTo != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001648 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1649 r.requestCode, Activity.RESULT_CANCELED, null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001650 }
1651 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001652 if (r.task == null) Slog.v(TAG,
1653 "startActivityUncheckedLocked: task left null",
1654 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001655 return ActivityManager.START_CLASS_NOT_FOUND;
1656 }
1657
1658 boolean newTask = false;
1659 boolean keepCurTransition = false;
1660
1661 // Should this be considered a new task?
1662 if (r.resultTo == null && !addingToTask
1663 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Craig Mautnerac6f8432013-07-17 13:24:59 -07001664 targetStack = adjustStackFocus(r);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001665 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001666 if (reuseTask == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001667 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1668 null, true);
1669 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1670 r.task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001671 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001672 r.setTask(reuseTask, reuseTask, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001673 }
1674 newTask = true;
1675 if (!movedHome) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001676 if ((launchFlags &
1677 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1678 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1679 // Caller wants to appear on home activity, so before starting
1680 // their own activity we will bring home to the front.
Craig Mautnerae7ecab2013-09-18 11:48:14 -07001681 r.task.mOnTopOfHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001682 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001683 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001684 } else if (sourceRecord != null) {
Craig Mautner525f3d92013-05-07 14:01:50 -07001685 sourceTask = sourceRecord.task;
1686 targetStack = sourceTask.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001687 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001688 if (!addingToTask &&
1689 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1690 // In this case, we are adding the activity to an existing
1691 // task, but the caller has asked to clear that task if the
1692 // activity is already running.
Craig Mautner525f3d92013-05-07 14:01:50 -07001693 ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001694 keepCurTransition = true;
1695 if (top != null) {
1696 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1697 top.deliverNewIntentLocked(callingUid, r.intent);
1698 // For paranoia, make sure we have correctly
1699 // resumed the top activity.
Craig Mautner0f922742013-08-06 08:44:42 -07001700 targetStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001701 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001702 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001703 targetStack.resumeTopActivityLocked(null);
1704 }
1705 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001706 if (r.task == null) Slog.v(TAG,
1707 "startActivityUncheckedLocked: task left null",
1708 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001709 return ActivityManager.START_DELIVERED_TO_TOP;
1710 }
1711 } else if (!addingToTask &&
1712 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1713 // In this case, we are launching an activity in our own task
1714 // that may already be running somewhere in the history, and
1715 // we want to shuffle it to the front of the stack if so.
Craig Mautner525f3d92013-05-07 14:01:50 -07001716 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001717 if (top != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001718 final TaskRecord task = top.task;
1719 task.moveActivityToFrontLocked(top);
1720 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001721 top.updateOptionsLocked(options);
1722 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner0f922742013-08-06 08:44:42 -07001723 targetStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001724 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001725 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001726 targetStack.resumeTopActivityLocked(null);
1727 }
1728 return ActivityManager.START_DELIVERED_TO_TOP;
1729 }
1730 }
1731 // An existing activity is starting this new activity, so we want
1732 // to keep the new one in the same task as the one that is starting
1733 // it.
Craig Mautner525f3d92013-05-07 14:01:50 -07001734 r.setTask(sourceTask, sourceRecord.thumbHolder, false);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001735 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1736 + " in existing task " + r.task);
1737
1738 } else {
1739 // This not being started from an existing activity, and not part
1740 // of a new task... just put it in the top task, though these days
1741 // this case should never happen.
Craig Mautnerac6f8432013-07-17 13:24:59 -07001742 targetStack = adjustStackFocus(r);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001743 moveHomeStack(targetStack.isHomeStack());
Craig Mautner1602ec22013-05-12 10:24:27 -07001744 ActivityRecord prev = targetStack.topActivity();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001745 r.setTask(prev != null ? prev.task
1746 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1747 null, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001748 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1749 + " in new guessed " + r.task);
1750 }
1751
1752 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1753 intent, r.getUriPermissionsLocked());
1754
1755 if (newTask) {
1756 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1757 }
1758 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001759 setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
Craig Mautner0f922742013-08-06 08:44:42 -07001760 targetStack.mLastPausedActivity = null;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001761 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
Craig Mautner1d001b62013-06-18 16:52:43 -07001762 mService.setFocusedActivityLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001763 return ActivityManager.START_SUCCESS;
1764 }
1765
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001766 void acquireLaunchWakelock() {
1767 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
1768 throw new IllegalStateException("Calling must be system uid");
1769 }
1770 mLaunchingActivity.acquire();
1771 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
1772 // To be safe, don't allow the wake lock to be held for too long.
1773 mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
1774 }
1775 }
1776
Craig Mautnerf3333272013-04-22 10:55:53 -07001777 // Checked.
1778 final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
1779 Configuration config) {
1780 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
1781
Craig Mautnerf3333272013-04-22 10:55:53 -07001782 ArrayList<ActivityRecord> stops = null;
1783 ArrayList<ActivityRecord> finishes = null;
1784 ArrayList<UserStartedState> startingUsers = null;
1785 int NS = 0;
1786 int NF = 0;
1787 IApplicationThread sendThumbnail = null;
1788 boolean booting = false;
1789 boolean enableScreen = false;
1790 boolean activityRemoved = false;
1791
1792 ActivityRecord r = ActivityRecord.forToken(token);
1793 if (r != null) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07001794 if (DEBUG_IDLE) Slog.d(TAG, "activityIdleInternalLocked: Callers=" +
1795 Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07001796 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
1797 r.finishLaunchTickingLocked();
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001798 if (fromTimeout) {
1799 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
Craig Mautnerf3333272013-04-22 10:55:53 -07001800 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001801
1802 // This is a hack to semi-deal with a race condition
1803 // in the client where it can be constructed with a
1804 // newer configuration from when we asked it to launch.
1805 // We'll update with whatever configuration it now says
1806 // it used to launch.
1807 if (config != null) {
1808 r.configuration = config;
1809 }
1810
1811 // We are now idle. If someone is waiting for a thumbnail from
1812 // us, we can now deliver.
1813 r.idle = true;
1814
1815 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
1816 sendThumbnail = r.app.thread;
1817 r.thumbnailNeeded = false;
1818 }
1819
1820 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
1821 if (!mService.mBooted && isFrontStack(r.task.stack)) {
1822 mService.mBooted = true;
1823 enableScreen = true;
1824 }
1825 }
1826
1827 if (allResumedActivitiesIdle()) {
1828 if (r != null) {
1829 mService.scheduleAppGcsLocked();
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001830 }
1831
1832 if (mLaunchingActivity.isHeld()) {
1833 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
1834 if (VALIDATE_WAKE_LOCK_CALLER &&
1835 Binder.getCallingUid() != Process.myUid()) {
1836 throw new IllegalStateException("Calling must be system uid");
1837 }
1838 mLaunchingActivity.release();
1839 }
1840 ensureActivitiesVisibleLocked(null, 0);
Craig Mautnerf3333272013-04-22 10:55:53 -07001841 }
1842
1843 // Atomically retrieve all of the other things to do.
1844 stops = processStoppingActivitiesLocked(true);
1845 NS = stops != null ? stops.size() : 0;
1846 if ((NF=mFinishingActivities.size()) > 0) {
1847 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
1848 mFinishingActivities.clear();
1849 }
1850
1851 final ArrayList<ActivityRecord> thumbnails;
1852 final int NT = mCancelledThumbnails.size();
1853 if (NT > 0) {
1854 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
1855 mCancelledThumbnails.clear();
1856 } else {
1857 thumbnails = null;
1858 }
1859
1860 if (isFrontStack(mHomeStack)) {
1861 booting = mService.mBooting;
1862 mService.mBooting = false;
1863 }
1864
1865 if (mStartingUsers.size() > 0) {
1866 startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
1867 mStartingUsers.clear();
1868 }
1869
1870 // Perform the following actions from unsynchronized state.
1871 final IApplicationThread thumbnailThread = sendThumbnail;
1872 mHandler.post(new Runnable() {
1873 @Override
1874 public void run() {
1875 if (thumbnailThread != null) {
1876 try {
1877 thumbnailThread.requestThumbnail(token);
1878 } catch (Exception e) {
1879 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
1880 mService.sendPendingThumbnail(null, token, null, null, true);
1881 }
1882 }
1883
1884 // Report back to any thumbnail receivers.
1885 for (int i = 0; i < NT; i++) {
1886 ActivityRecord r = thumbnails.get(i);
1887 mService.sendPendingThumbnail(r, null, null, null, true);
1888 }
1889 }
1890 });
1891
1892 // Stop any activities that are scheduled to do so but have been
1893 // waiting for the next one to start.
1894 for (int i = 0; i < NS; i++) {
1895 r = stops.get(i);
1896 final ActivityStack stack = r.task.stack;
1897 if (r.finishing) {
1898 stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
1899 } else {
1900 stack.stopActivityLocked(r);
1901 }
1902 }
1903
1904 // Finish any activities that are scheduled to do so but have been
1905 // waiting for the next one to start.
1906 for (int i = 0; i < NF; i++) {
1907 r = finishes.get(i);
1908 activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle");
1909 }
1910
1911 if (booting) {
1912 mService.finishBooting();
1913 } else if (startingUsers != null) {
1914 for (int i = 0; i < startingUsers.size(); i++) {
1915 mService.finishUserSwitch(startingUsers.get(i));
1916 }
1917 }
1918
1919 mService.trimApplications();
1920 //dump();
1921 //mWindowManager.dump();
1922
1923 if (enableScreen) {
1924 mService.enableScreenAfterBoot();
1925 }
1926
1927 if (activityRemoved) {
Craig Mautner05d29032013-05-03 13:40:13 -07001928 resumeTopActivitiesLocked();
Craig Mautnerf3333272013-04-22 10:55:53 -07001929 }
1930
Craig Mautner7ea5bd42013-07-05 15:27:08 -07001931 return r;
Craig Mautnerf3333272013-04-22 10:55:53 -07001932 }
1933
Craig Mautner8d341ef2013-03-26 09:03:27 -07001934 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
Craig Mautner6b74cb52013-09-27 17:02:21 -07001935 boolean launchHomeTaskNext = false;
1936 final ActivityStack focusedStack = getFocusedStack();
Craig Mautner8d341ef2013-03-26 09:03:27 -07001937 final int numStacks = mStacks.size();
1938 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Craig Mautner6b74cb52013-09-27 17:02:21 -07001939 final ActivityStack stack = mStacks.get(stackNdx);
1940 // Only update launchHomeTaskNext for the focused stack.
1941 launchHomeTaskNext |= (stack == focusedStack && stack.handleAppDiedLocked(app));
1942 }
1943
1944 if (!restarting) {
1945 if (launchHomeTaskNext) {
1946 resumeHomeActivity(null);
1947 } else {
1948 if (!resumeTopActivitiesLocked(focusedStack, null, null)) {
1949 // If there was nothing to resume, and we are not already
1950 // restarting this process, but there is a visible activity that
1951 // is hosted by the process... then make sure all visible
1952 // activities are running, taking care of restarting this
1953 // process.
1954 ensureActivitiesVisibleLocked(null, 0);
1955 }
1956 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001957 }
1958 }
1959
1960 void closeSystemDialogsLocked() {
1961 final int numStacks = mStacks.size();
1962 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1963 final ActivityStack stack = mStacks.get(stackNdx);
1964 stack.closeSystemDialogsLocked();
1965 }
1966 }
1967
1968 /**
1969 * @return true if some activity was finished (or would have finished if doit were true).
1970 */
1971 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1972 boolean didSomething = false;
1973 final int numStacks = mStacks.size();
1974 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1975 final ActivityStack stack = mStacks.get(stackNdx);
1976 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1977 didSomething = true;
1978 }
1979 }
1980 return didSomething;
1981 }
1982
Dianne Hackborna413dc02013-07-12 12:02:55 -07001983 void updatePreviousProcessLocked(ActivityRecord r) {
1984 // Now that this process has stopped, we may want to consider
1985 // it to be the previous app to try to keep around in case
1986 // the user wants to return to it.
1987
1988 // First, found out what is currently the foreground app, so that
1989 // we don't blow away the previous app if this activity is being
1990 // hosted by the process that is actually still the foreground.
1991 ProcessRecord fgApp = null;
1992 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1993 final ActivityStack stack = mStacks.get(stackNdx);
1994 if (isFrontStack(stack)) {
1995 if (stack.mResumedActivity != null) {
1996 fgApp = stack.mResumedActivity.app;
1997 } else if (stack.mPausingActivity != null) {
1998 fgApp = stack.mPausingActivity.app;
1999 }
2000 break;
2001 }
2002 }
2003
2004 // Now set this one as the previous process, only if that really
2005 // makes sense to.
2006 if (r.app != null && fgApp != null && r.app != fgApp
2007 && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
Craig Mautner4ef26932013-09-18 15:15:52 -07002008 && r.app != mService.mHomeProcess) {
Dianne Hackborna413dc02013-07-12 12:02:55 -07002009 mService.mPreviousProcess = r.app;
2010 mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
2011 }
2012 }
2013
Craig Mautner05d29032013-05-03 13:40:13 -07002014 boolean resumeTopActivitiesLocked() {
2015 return resumeTopActivitiesLocked(null, null, null);
2016 }
2017
2018 boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
2019 Bundle targetOptions) {
2020 if (targetStack == null) {
2021 targetStack = getFocusedStack();
2022 }
2023 boolean result = false;
Craig Mautnerdbcb31f2013-04-02 12:32:53 -07002024 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerf88c50f2013-04-18 19:25:12 -07002025 final ActivityStack stack = mStacks.get(stackNdx);
2026 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07002027 if (stack == targetStack) {
2028 result = stack.resumeTopActivityLocked(target, targetOptions);
2029 } else {
2030 stack.resumeTopActivityLocked(null);
2031 }
Craig Mautnerf88c50f2013-04-18 19:25:12 -07002032 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002033 }
Craig Mautner05d29032013-05-03 13:40:13 -07002034 return result;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002035 }
2036
2037 void finishTopRunningActivityLocked(ProcessRecord app) {
2038 final int numStacks = mStacks.size();
2039 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2040 final ActivityStack stack = mStacks.get(stackNdx);
2041 stack.finishTopRunningActivityLocked(app);
2042 }
2043 }
2044
Craig Mautner8d341ef2013-03-26 09:03:27 -07002045 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
2046 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2047 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002048 if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack=" +
Craig Mautner1d001b62013-06-18 16:52:43 -07002049 mStacks.get(stackNdx));
Craig Mautner8d341ef2013-03-26 09:03:27 -07002050 return;
2051 }
2052 }
2053 }
2054
Craig Mautner967212c2013-04-13 21:10:58 -07002055 ActivityStack getStack(int stackId) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002056 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2057 final ActivityStack stack = mStacks.get(stackNdx);
2058 if (stack.getStackId() == stackId) {
2059 return stack;
2060 }
2061 }
2062 return null;
2063 }
2064
Craig Mautner967212c2013-04-13 21:10:58 -07002065 ArrayList<ActivityStack> getStacks() {
2066 return new ArrayList<ActivityStack>(mStacks);
2067 }
2068
2069 int createStack() {
Craig Mautner858d8a62013-04-23 17:08:34 -07002070 while (true) {
2071 if (++mLastStackId <= HOME_STACK_ID) {
2072 mLastStackId = HOME_STACK_ID + 1;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002073 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002074 if (getStack(mLastStackId) == null) {
2075 break;
2076 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002077 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002078 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
2079 return mLastStackId;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002080 }
2081
2082 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07002083 final TaskRecord task = anyTaskForIdLocked(taskId);
2084 if (task == null) {
2085 return;
2086 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002087 final ActivityStack stack = getStack(stackId);
2088 if (stack == null) {
2089 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
2090 return;
2091 }
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07002092 removeTask(task);
2093 stack.addTask(task, toTop);
Craig Mautnerb3b36ba2013-05-20 13:21:10 -07002094 mWindowManager.addTask(taskId, stackId, toTop);
Craig Mautner05d29032013-05-03 13:40:13 -07002095 resumeTopActivitiesLocked();
Craig Mautner8d341ef2013-03-26 09:03:27 -07002096 }
2097
Craig Mautnerac6f8432013-07-17 13:24:59 -07002098 ActivityRecord findTaskLocked(ActivityRecord r) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07002099 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerac6f8432013-07-17 13:24:59 -07002100 final ActivityStack stack = mStacks.get(stackNdx);
2101 if (!r.isApplicationActivity() && !stack.isHomeStack()) {
2102 continue;
2103 }
2104 final ActivityRecord ar = stack.findTaskLocked(r);
Craig Mautner8849a5e2013-04-02 16:41:03 -07002105 if (ar != null) {
2106 return ar;
2107 }
2108 }
2109 return null;
2110 }
2111
2112 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
2113 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2114 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
2115 if (ar != null) {
2116 return ar;
2117 }
2118 }
2119 return null;
2120 }
2121
Craig Mautner8d341ef2013-03-26 09:03:27 -07002122 void goingToSleepLocked() {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002123 scheduleSleepTimeout();
2124 if (!mGoingToSleep.isHeld()) {
2125 mGoingToSleep.acquire();
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002126 if (mLaunchingActivity.isHeld()) {
2127 if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
2128 throw new IllegalStateException("Calling must be system uid");
Craig Mautner0eea92c2013-05-16 13:35:39 -07002129 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002130 mLaunchingActivity.release();
2131 mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
Craig Mautner0eea92c2013-05-16 13:35:39 -07002132 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002133 }
Amith Yamasanice15e152013-09-19 12:30:32 -07002134 checkReadyForSleepLocked();
Craig Mautner8d341ef2013-03-26 09:03:27 -07002135 }
2136
2137 boolean shutdownLocked(int timeout) {
2138 boolean timedout = false;
Craig Mautner0eea92c2013-05-16 13:35:39 -07002139 goingToSleepLocked();
Craig Mautner0eea92c2013-05-16 13:35:39 -07002140
2141 final long endTime = System.currentTimeMillis() + timeout;
2142 while (true) {
2143 boolean cantShutdown = false;
2144 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2145 cantShutdown |= mStacks.get(stackNdx).checkReadyForSleepLocked();
2146 }
2147 if (cantShutdown) {
2148 long timeRemaining = endTime - System.currentTimeMillis();
2149 if (timeRemaining > 0) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002150 try {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002151 mService.wait(timeRemaining);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002152 } catch (InterruptedException e) {
2153 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002154 } else {
2155 Slog.w(TAG, "Activity manager shutdown timed out");
2156 timedout = true;
2157 break;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002158 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002159 } else {
2160 break;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002161 }
2162 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002163
2164 // Force checkReadyForSleep to complete.
2165 mSleepTimeout = true;
2166 checkReadyForSleepLocked();
2167
Craig Mautner8d341ef2013-03-26 09:03:27 -07002168 return timedout;
2169 }
2170
2171 void comeOutOfSleepIfNeededLocked() {
Craig Mautner0eea92c2013-05-16 13:35:39 -07002172 removeSleepTimeouts();
2173 if (mGoingToSleep.isHeld()) {
2174 mGoingToSleep.release();
2175 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002176 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002177 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002178 stack.awakeFromSleepingLocked();
Craig Mautner5314a402013-09-26 12:40:16 -07002179 if (isFrontStack(stack)) {
2180 resumeTopActivitiesLocked();
2181 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002182 }
Craig Mautner0eea92c2013-05-16 13:35:39 -07002183 mGoingToSleepActivities.clear();
2184 }
2185
2186 void activitySleptLocked(ActivityRecord r) {
2187 mGoingToSleepActivities.remove(r);
2188 checkReadyForSleepLocked();
2189 }
2190
2191 void checkReadyForSleepLocked() {
2192 if (!mService.isSleepingOrShuttingDown()) {
2193 // Do not care.
2194 return;
2195 }
2196
2197 if (!mSleepTimeout) {
2198 boolean dontSleep = false;
2199 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2200 dontSleep |= mStacks.get(stackNdx).checkReadyForSleepLocked();
2201 }
2202
2203 if (mStoppingActivities.size() > 0) {
2204 // Still need to tell some activities to stop; can't sleep yet.
2205 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
2206 + mStoppingActivities.size() + " activities");
2207 scheduleIdleLocked();
2208 dontSleep = true;
2209 }
2210
2211 if (mGoingToSleepActivities.size() > 0) {
2212 // Still need to tell some activities to sleep; can't sleep yet.
2213 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
2214 + mGoingToSleepActivities.size() + " activities");
2215 dontSleep = true;
2216 }
2217
2218 if (dontSleep) {
2219 return;
2220 }
2221 }
2222
2223 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2224 mStacks.get(stackNdx).goToSleep();
2225 }
2226
2227 removeSleepTimeouts();
2228
2229 if (mGoingToSleep.isHeld()) {
2230 mGoingToSleep.release();
2231 }
2232 if (mService.mShuttingDown) {
2233 mService.notifyAll();
2234 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002235 }
2236
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002237 boolean reportResumedActivityLocked(ActivityRecord r) {
2238 final ActivityStack stack = r.task.stack;
2239 if (isFrontStack(stack)) {
Jeff Sharkey5782da72013-04-25 14:32:30 -07002240 mService.updateUsageStats(r, true);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002241 }
2242 if (allResumedActivitiesComplete()) {
2243 ensureActivitiesVisibleLocked(null, 0);
2244 mWindowManager.executeAppTransition();
2245 return true;
2246 }
2247 return false;
2248 }
2249
Craig Mautner8d341ef2013-03-26 09:03:27 -07002250 void handleAppCrashLocked(ProcessRecord app) {
2251 final int numStacks = mStacks.size();
2252 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2253 final ActivityStack stack = mStacks.get(stackNdx);
2254 stack.handleAppCrashLocked(app);
2255 }
2256 }
2257
Craig Mautnerde4ef022013-04-07 19:01:33 -07002258 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
Craig Mautner580ea812013-04-25 12:58:38 -07002259 // First the front stacks. In case any are not fullscreen and are in front of home.
2260 boolean showHomeBehindStack = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07002261 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner580ea812013-04-25 12:58:38 -07002262 final ActivityStack stack = mStacks.get(stackNdx);
2263 if (isFrontStack(stack)) {
2264 showHomeBehindStack =
2265 stack.ensureActivitiesVisibleLocked(starting, configChanges);
2266 }
2267 }
2268 // Now do back stacks.
2269 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2270 final ActivityStack stack = mStacks.get(stackNdx);
2271 if (!isFrontStack(stack)) {
2272 stack.ensureActivitiesVisibleLocked(starting, configChanges, showHomeBehindStack);
2273 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002274 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002275 }
2276
2277 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
2278 final int numStacks = mStacks.size();
2279 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2280 final ActivityStack stack = mStacks.get(stackNdx);
2281 stack.scheduleDestroyActivities(app, false, reason);
2282 }
2283 }
2284
2285 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner2420ead2013-04-01 17:13:20 -07002286 mCurrentUser = userId;
Craig Mautnerac6f8432013-07-17 13:24:59 -07002287
2288 final String homePackageName = mService.getHomePackageName();
2289 if (homePackageName != null) {
2290 setHomePackageName(mCurrentUser, homePackageName);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002291 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002292
2293 mStartingUsers.add(uss);
Craig Mautnerac6f8432013-07-17 13:24:59 -07002294 boolean haveActivities = false;
2295 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2296 haveActivities |= mStacks.get(stackNdx).switchUserLocked(userId);
2297 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002298
2299 resumeTopActivitiesLocked();
2300
Craig Mautner8d341ef2013-03-26 09:03:27 -07002301 return haveActivities;
Craig Mautner2219a1b2013-03-25 09:44:30 -07002302 }
2303
Craig Mautnerde4ef022013-04-07 19:01:33 -07002304 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
2305 int N = mStoppingActivities.size();
2306 if (N <= 0) return null;
2307
2308 ArrayList<ActivityRecord> stops = null;
2309
2310 final boolean nowVisible = allResumedActivitiesVisible();
2311 for (int i=0; i<N; i++) {
2312 ActivityRecord s = mStoppingActivities.get(i);
2313 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
2314 + nowVisible + " waitingVisible=" + s.waitingVisible
2315 + " finishing=" + s.finishing);
2316 if (s.waitingVisible && nowVisible) {
2317 mWaitingVisibleActivities.remove(s);
2318 s.waitingVisible = false;
2319 if (s.finishing) {
2320 // If this activity is finishing, it is sitting on top of
2321 // everyone else but we now know it is no longer needed...
2322 // so get rid of it. Otherwise, we need to go through the
2323 // normal flow and hide it once we determine that it is
2324 // hidden by the activities in front of it.
2325 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002326 mWindowManager.setAppVisibility(s.appToken, false);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002327 }
2328 }
2329 if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
2330 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
2331 if (stops == null) {
2332 stops = new ArrayList<ActivityRecord>();
2333 }
2334 stops.add(s);
2335 mStoppingActivities.remove(i);
2336 N--;
2337 i--;
2338 }
2339 }
2340
2341 return stops;
2342 }
2343
Craig Mautnercf910b02013-04-23 11:23:27 -07002344 void validateTopActivitiesLocked() {
2345 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2346 final ActivityStack stack = mStacks.get(stackNdx);
2347 final ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002348 final ActivityState state = r == null ? ActivityState.DESTROYED : r.state;
Craig Mautnercf910b02013-04-23 11:23:27 -07002349 if (isFrontStack(stack)) {
2350 if (r == null) {
2351 Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
2352 } else {
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002353 final ActivityRecord pausing = stack.mPausingActivity;
2354 if (pausing != null && pausing == r) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002355 Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002356 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002357 }
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002358 if (state != ActivityState.INITIALIZING && state != ActivityState.RESUMED) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002359 Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002360 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002361 }
2362 }
2363 } else {
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002364 final ActivityRecord resumed = stack.mResumedActivity;
2365 if (resumed != null && resumed == r) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002366 Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002367 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002368 }
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002369 if (r != null && (state == ActivityState.INITIALIZING
2370 || state == ActivityState.RESUMED)) {
Craig Mautnercf910b02013-04-23 11:23:27 -07002371 Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
Craig Mautnerf0ac5c82013-06-24 11:21:57 -07002372 " state=" + state);
Craig Mautnercf910b02013-04-23 11:23:27 -07002373 }
2374 }
2375 }
2376 }
2377
Craig Mautner76ea2242013-05-15 11:40:05 -07002378 private static String stackStateToString(int stackState) {
2379 switch (stackState) {
2380 case STACK_STATE_HOME_IN_FRONT: return "STACK_STATE_HOME_IN_FRONT";
2381 case STACK_STATE_HOME_TO_BACK: return "STACK_STATE_HOME_TO_BACK";
2382 case STACK_STATE_HOME_IN_BACK: return "STACK_STATE_HOME_IN_BACK";
2383 case STACK_STATE_HOME_TO_FRONT: return "STACK_STATE_HOME_TO_FRONT";
2384 default: return "Unknown stackState=" + stackState;
2385 }
2386 }
2387
Craig Mautner27084302013-03-25 08:05:25 -07002388 public void dump(PrintWriter pw, String prefix) {
2389 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
2390 pw.println(mDismissKeyguardOnNextActivity);
Craig Mautner76ea2242013-05-15 11:40:05 -07002391 pw.print(prefix); pw.print("mStackState="); pw.println(stackStateToString(mStackState));
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002392 pw.print(prefix); pw.println("mSleepTimeout: " + mSleepTimeout);
2393 pw.print(prefix); pw.println("mCurTaskId: " + mCurTaskId);
Craig Mautnerac6f8432013-07-17 13:24:59 -07002394 pw.print(prefix); pw.print("mHomePackageNames:");
2395 for (int i = 0; i < mHomePackageNames.size(); ++i) {
2396 pw.print(" ("); pw.print(mHomePackageNames.keyAt(i)); pw.print(",");
2397 pw.print(mHomePackageNames.valueAt(i)); pw.print(")");
2398 }
2399 pw.println();
Craig Mautner27084302013-03-25 08:05:25 -07002400 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002401
Craig Mautner20e72272013-04-01 13:45:53 -07002402 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002403 return getFocusedStack().getDumpActivitiesLocked(name);
Craig Mautner20e72272013-04-01 13:45:53 -07002404 }
2405
Dianne Hackborn390517b2013-05-30 15:03:32 -07002406 static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
2407 boolean needSep, String prefix) {
2408 if (activity != null) {
2409 if (dumpPackage == null || dumpPackage.equals(activity.packageName)) {
2410 if (needSep) {
2411 pw.println();
Dianne Hackborn390517b2013-05-30 15:03:32 -07002412 }
2413 pw.print(prefix);
2414 pw.println(activity);
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002415 return true;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002416 }
2417 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002418 return false;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002419 }
2420
Craig Mautner8d341ef2013-03-26 09:03:27 -07002421 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
2422 boolean dumpClient, String dumpPackage) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002423 boolean printed = false;
2424 boolean needSep = false;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002425 final int numStacks = mStacks.size();
2426 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2427 final ActivityStack stack = mStacks.get(stackNdx);
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002428 StringBuilder stackHeader = new StringBuilder(128);
2429 stackHeader.append(" Stack #");
2430 stackHeader.append(mStacks.indexOf(stack));
2431 stackHeader.append(":");
2432 printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, needSep,
2433 stackHeader.toString());
2434 printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll,
2435 false, dumpPackage, true, " Running activities (most recent first):", null);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002436
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002437 needSep = printed;
2438 boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002439 " mPausingActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002440 if (pr) {
2441 printed = true;
2442 needSep = false;
2443 }
2444 pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002445 " mResumedActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002446 if (pr) {
2447 printed = true;
2448 needSep = false;
2449 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002450 if (dumpAll) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002451 pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
Dianne Hackborn390517b2013-05-30 15:03:32 -07002452 " mLastPausedActivity: ");
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002453 if (pr) {
2454 printed = true;
Craig Mautner0f922742013-08-06 08:44:42 -07002455 needSep = true;
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002456 }
Craig Mautner0f922742013-08-06 08:44:42 -07002457 printed |= printThisActivity(pw, stack.mLastNoHistoryActivity, dumpPackage,
2458 needSep, " mLastNoHistoryActivity: ");
Craig Mautner8d341ef2013-03-26 09:03:27 -07002459 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002460 needSep = printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002461 }
2462
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002463 printed |= dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll,
2464 false, dumpPackage, true, " Activities waiting to finish:", null);
2465 printed |= dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll,
2466 false, dumpPackage, true, " Activities waiting to stop:", null);
2467 printed |= dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
2468 false, dumpPackage, true, " Activities waiting for another to become visible:",
2469 null);
2470 printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll,
2471 false, dumpPackage, true, " Activities waiting to sleep:", null);
2472 printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll,
2473 false, dumpPackage, true, " Activities waiting to sleep:", null);
Craig Mautnerf3333272013-04-22 10:55:53 -07002474
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002475 return printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002476 }
2477
Dianne Hackborn390517b2013-05-30 15:03:32 -07002478 static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
Craig Mautner8d341ef2013-03-26 09:03:27 -07002479 String prefix, String label, boolean complete, boolean brief, boolean client,
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002480 String dumpPackage, boolean needNL, String header1, String header2) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07002481 TaskRecord lastTask = null;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002482 String innerPrefix = null;
2483 String[] args = null;
2484 boolean printed = false;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002485 for (int i=list.size()-1; i>=0; i--) {
2486 final ActivityRecord r = list.get(i);
2487 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
2488 continue;
2489 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07002490 if (innerPrefix == null) {
2491 innerPrefix = prefix + " ";
2492 args = new String[0];
2493 }
2494 printed = true;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002495 final boolean full = !brief && (complete || !r.isInHistory());
2496 if (needNL) {
Dianne Hackborn390517b2013-05-30 15:03:32 -07002497 pw.println("");
Craig Mautner8d341ef2013-03-26 09:03:27 -07002498 needNL = false;
2499 }
Dianne Hackborn7ad34e52013-06-05 18:41:45 -07002500 if (header1 != null) {
2501 pw.println(header1);
2502 header1 = null;
2503 }
2504 if (header2 != null) {
2505 pw.println(header2);
2506 header2 = null;
Dianne Hackborn390517b2013-05-30 15:03:32 -07002507 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002508 if (lastTask != r.task) {
2509 lastTask = r.task;
2510 pw.print(prefix);
2511 pw.print(full ? "* " : " ");
2512 pw.println(lastTask);
2513 if (full) {
2514 lastTask.dump(pw, prefix + " ");
2515 } else if (complete) {
2516 // Complete + brief == give a summary. Isn't that obvious?!?
2517 if (lastTask.intent != null) {
2518 pw.print(prefix); pw.print(" ");
2519 pw.println(lastTask.intent.toInsecureStringWithClip());
2520 }
2521 }
2522 }
2523 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
2524 pw.print(" #"); pw.print(i); pw.print(": ");
2525 pw.println(r);
2526 if (full) {
2527 r.dump(pw, innerPrefix);
2528 } else if (complete) {
2529 // Complete + brief == give a summary. Isn't that obvious?!?
2530 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
2531 if (r.app != null) {
2532 pw.print(innerPrefix); pw.println(r.app);
2533 }
2534 }
2535 if (client && r.app != null && r.app.thread != null) {
2536 // flush anything that is already in the PrintWriter since the thread is going
2537 // to write to the file descriptor directly
2538 pw.flush();
2539 try {
2540 TransferPipe tp = new TransferPipe();
2541 try {
2542 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
2543 r.appToken, innerPrefix, args);
2544 // Short timeout, since blocking here can
2545 // deadlock with the application.
2546 tp.go(fd, 2000);
2547 } finally {
2548 tp.kill();
2549 }
2550 } catch (IOException e) {
2551 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
2552 } catch (RemoteException e) {
2553 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
2554 }
2555 needNL = true;
2556 }
2557 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07002558 return printed;
Craig Mautner8d341ef2013-03-26 09:03:27 -07002559 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002560
Craig Mautnerf3333272013-04-22 10:55:53 -07002561 void scheduleIdleTimeoutLocked(ActivityRecord next) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002562 if (DEBUG_IDLE) Slog.d(TAG, "scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4));
Craig Mautnerc64f73e2013-04-24 16:44:56 -07002563 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
2564 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
Craig Mautnerf3333272013-04-22 10:55:53 -07002565 }
2566
2567 final void scheduleIdleLocked() {
Craig Mautner05d29032013-05-03 13:40:13 -07002568 mHandler.sendEmptyMessage(IDLE_NOW_MSG);
Craig Mautnerf3333272013-04-22 10:55:53 -07002569 }
2570
2571 void removeTimeoutsForActivityLocked(ActivityRecord r) {
Craig Mautnerb59dcfd2013-05-06 13:12:58 -07002572 if (DEBUG_IDLE) Slog.d(TAG, "removeTimeoutsForActivity: Callers=" + Debug.getCallers(4));
Craig Mautnerf3333272013-04-22 10:55:53 -07002573 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
2574 }
2575
Craig Mautner05d29032013-05-03 13:40:13 -07002576 final void scheduleResumeTopActivities() {
2577 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2578 }
2579
Craig Mautner0eea92c2013-05-16 13:35:39 -07002580 void removeSleepTimeouts() {
2581 mSleepTimeout = false;
2582 mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
2583 }
2584
2585 final void scheduleSleepTimeout() {
2586 removeSleepTimeouts();
2587 mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT);
2588 }
2589
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002590 private final class ActivityStackSupervisorHandler extends Handler {
Craig Mautnerf3333272013-04-22 10:55:53 -07002591
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002592 public ActivityStackSupervisorHandler(Looper looper) {
2593 super(looper);
2594 }
2595
Craig Mautnerf3333272013-04-22 10:55:53 -07002596 void activityIdleInternal(ActivityRecord r) {
2597 synchronized (mService) {
2598 activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
2599 }
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002600 }
2601
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002602 @Override
2603 public void handleMessage(Message msg) {
2604 switch (msg.what) {
Craig Mautnerf3333272013-04-22 10:55:53 -07002605 case IDLE_TIMEOUT_MSG: {
Craig Mautner5eda9b32013-07-02 11:58:16 -07002606 if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_TIMEOUT_MSG: r=" + msg.obj);
Craig Mautnerf3333272013-04-22 10:55:53 -07002607 if (mService.mDidDexOpt) {
2608 mService.mDidDexOpt = false;
2609 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2610 nmsg.obj = msg.obj;
2611 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
2612 return;
2613 }
2614 // We don't at this point know if the activity is fullscreen,
2615 // so we need to be conservative and assume it isn't.
2616 activityIdleInternal((ActivityRecord)msg.obj);
2617 } break;
2618 case IDLE_NOW_MSG: {
Craig Mautner5eda9b32013-07-02 11:58:16 -07002619 if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_NOW_MSG: r=" + msg.obj);
Craig Mautnerf3333272013-04-22 10:55:53 -07002620 activityIdleInternal((ActivityRecord)msg.obj);
2621 } break;
Craig Mautner05d29032013-05-03 13:40:13 -07002622 case RESUME_TOP_ACTIVITY_MSG: {
2623 synchronized (mService) {
2624 resumeTopActivitiesLocked();
2625 }
2626 } break;
Craig Mautner0eea92c2013-05-16 13:35:39 -07002627 case SLEEP_TIMEOUT_MSG: {
2628 synchronized (mService) {
2629 if (mService.isSleepingOrShuttingDown()) {
2630 Slog.w(TAG, "Sleep timeout! Sleeping now.");
2631 mSleepTimeout = true;
2632 checkReadyForSleepLocked();
2633 }
2634 }
2635 } break;
Craig Mautner7ea5bd42013-07-05 15:27:08 -07002636 case LAUNCH_TIMEOUT_MSG: {
2637 if (mService.mDidDexOpt) {
2638 mService.mDidDexOpt = false;
2639 mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
2640 return;
2641 }
2642 synchronized (mService) {
2643 if (mLaunchingActivity.isHeld()) {
2644 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
2645 if (VALIDATE_WAKE_LOCK_CALLER
2646 && Binder.getCallingUid() != Process.myUid()) {
2647 throw new IllegalStateException("Calling must be system uid");
2648 }
2649 mLaunchingActivity.release();
2650 }
2651 }
2652 } break;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002653 }
2654 }
2655 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002656
Craig Mautnerac6f8432013-07-17 13:24:59 -07002657 String getHomePackageName() {
2658 return mHomePackageNames.get(mCurrentUser);
2659 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002660
Craig Mautnerac6f8432013-07-17 13:24:59 -07002661 void setHomePackageName(int userId, String homePackageName) {
2662 if (DEBUG_SWITCH) Slog.d(TAG, "setHomePackageName: user=" + userId + " package="
2663 + homePackageName);
2664 mHomePackageNames.put(userId, homePackageName);
Craig Mautner858d8a62013-04-23 17:08:34 -07002665 }
Craig Mautner27084302013-03-25 08:05:25 -07002666}