blob: 82944a96f717315dd1865e88f5893dc209b921b6 [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 Mautner6170f732013-04-02 13:05:23 -070025import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
Craig Mautner2420ead2013-04-01 17:13:20 -070026import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
Craig Mautner8849a5e2013-04-02 16:41:03 -070027import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
28import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
Craig Mautner8d341ef2013-03-26 09:03:27 -070029import static com.android.server.am.ActivityManagerService.TAG;
30
Craig Mautner2420ead2013-04-01 17:13:20 -070031import android.app.Activity;
Craig Mautner23ac33b2013-04-01 16:26:35 -070032import android.app.ActivityManager;
33import android.app.ActivityOptions;
34import android.app.AppGlobals;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070035import android.app.IActivityManager;
Craig Mautner23ac33b2013-04-01 16:26:35 -070036import android.app.IApplicationThread;
Craig Mautner20e72272013-04-01 13:45:53 -070037import android.app.IThumbnailReceiver;
Craig Mautner23ac33b2013-04-01 16:26:35 -070038import android.app.PendingIntent;
Craig Mautner20e72272013-04-01 13:45:53 -070039import android.app.ActivityManager.RunningTaskInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070040import android.app.IActivityManager.WaitResult;
Craig Mautner2420ead2013-04-01 17:13:20 -070041import android.app.ResultInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070042import android.content.ComponentName;
Craig Mautner2219a1b2013-03-25 09:44:30 -070043import android.content.Context;
Craig Mautner23ac33b2013-04-01 16:26:35 -070044import android.content.IIntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070045import android.content.Intent;
Craig Mautner23ac33b2013-04-01 16:26:35 -070046import android.content.IntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070047import android.content.pm.ActivityInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070048import android.content.pm.ApplicationInfo;
49import android.content.pm.PackageManager;
50import android.content.pm.ResolveInfo;
51import android.content.res.Configuration;
52import android.os.Binder;
Craig Mautner8d341ef2013-03-26 09:03:27 -070053import android.os.Bundle;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070054import android.os.Handler;
Craig Mautner23ac33b2013-04-01 16:26:35 -070055import android.os.IBinder;
Craig Mautner2219a1b2013-03-25 09:44:30 -070056import android.os.Looper;
Craig Mautner2420ead2013-04-01 17:13:20 -070057import android.os.Message;
Craig Mautner23ac33b2013-04-01 16:26:35 -070058import android.os.ParcelFileDescriptor;
Craig Mautner8d341ef2013-03-26 09:03:27 -070059import android.os.RemoteException;
Craig Mautner23ac33b2013-04-01 16:26:35 -070060import android.os.SystemClock;
Craig Mautner6170f732013-04-02 13:05:23 -070061import android.os.UserHandle;
Craig Mautner2420ead2013-04-01 17:13:20 -070062import android.util.EventLog;
Craig Mautner8d341ef2013-03-26 09:03:27 -070063import android.util.Slog;
Craig Mautner858d8a62013-04-23 17:08:34 -070064import android.util.SparseArray;
Craig Mautner2219a1b2013-03-25 09:44:30 -070065
Craig Mautner23ac33b2013-04-01 16:26:35 -070066import com.android.internal.app.HeavyWeightSwitcherActivity;
Craig Mautner6170f732013-04-02 13:05:23 -070067import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
Craig Mautner2420ead2013-04-01 17:13:20 -070068import com.android.server.am.ActivityStack.ActivityState;
Craig Mautnerde4ef022013-04-07 19:01:33 -070069import com.android.server.wm.StackBox;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070070import com.android.server.wm.WindowManagerService;
Craig Mautner23ac33b2013-04-01 16:26:35 -070071
Craig Mautner8d341ef2013-03-26 09:03:27 -070072import java.io.FileDescriptor;
73import java.io.IOException;
Craig Mautner27084302013-03-25 08:05:25 -070074import java.io.PrintWriter;
Craig Mautner2219a1b2013-03-25 09:44:30 -070075import java.util.ArrayList;
Craig Mautner8d341ef2013-03-26 09:03:27 -070076import java.util.List;
Craig Mautner27084302013-03-25 08:05:25 -070077
78public class ActivityStackSupervisor {
Craig Mautnera9a3fb12013-04-18 10:01:00 -070079 static final boolean DEBUG_STACK = ActivityManagerService.DEBUG_STACK;
80
Craig Mautnerde4ef022013-04-07 19:01:33 -070081 static final boolean DEBUG = ActivityManagerService.DEBUG || false;
82 static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
83 static final boolean DEBUG_APP = DEBUG || false;
84 static final boolean DEBUG_SAVED_STATE = DEBUG || false;
85 static final boolean DEBUG_STATES = DEBUG || false;
Craig Mautner2420ead2013-04-01 17:13:20 -070086
Craig Mautner2219a1b2013-03-25 09:44:30 -070087 public static final int HOME_STACK_ID = 0;
Craig Mautner27084302013-03-25 08:05:25 -070088
Craig Mautnerf3333272013-04-22 10:55:53 -070089 /** How long we wait until giving up on the last activity telling us it is idle. */
90 static final int IDLE_TIMEOUT = 10*1000;
91
92 static final int IDLE_TIMEOUT_MSG = ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
93 static final int IDLE_NOW_MSG = ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG + 1;
94
Craig Mautner27084302013-03-25 08:05:25 -070095 final ActivityManagerService mService;
Craig Mautner2219a1b2013-03-25 09:44:30 -070096 final Context mContext;
97 final Looper mLooper;
Craig Mautner27084302013-03-25 08:05:25 -070098
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070099 final ActivityStackSupervisorHandler mHandler;
100
101 /** Short cut */
102 WindowManagerService mWindowManager;
103
Craig Mautner27084302013-03-25 08:05:25 -0700104 /** Dismiss the keyguard after the next activity is displayed? */
105 private boolean mDismissKeyguardOnNextActivity = false;
106
Craig Mautner8d341ef2013-03-26 09:03:27 -0700107 /** Identifier counter for all ActivityStacks */
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700108 private int mLastStackId = HOME_STACK_ID;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700109
110 /** Task identifier that activities are currently being started in. Incremented each time a
111 * new task is created. */
112 private int mCurTaskId = 0;
113
Craig Mautner2420ead2013-04-01 17:13:20 -0700114 /** The current user */
115 private int mCurrentUser;
116
Craig Mautner8d341ef2013-03-26 09:03:27 -0700117 /** The stack containing the launcher app */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700118 private ActivityStack mHomeStack;
Craig Mautner20e72272013-04-01 13:45:53 -0700119
Craig Mautnerde4ef022013-04-07 19:01:33 -0700120 /** The non-home stack currently receiving input or launching the next activity. If home is
Craig Mautner29219d92013-04-16 20:19:12 -0700121 * in front then mHomeStack overrides mFocusedStack. */
122 private ActivityStack mFocusedStack;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700123
124 /** All the non-launcher stacks */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700125 private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
126
Craig Mautnerde4ef022013-04-07 19:01:33 -0700127 private static final int STACK_STATE_HOME_IN_FRONT = 0;
128 private static final int STACK_STATE_HOME_TO_BACK = 1;
129 private static final int STACK_STATE_HOME_IN_BACK = 2;
130 private static final int STACK_STATE_HOME_TO_FRONT = 3;
131 private int mStackState = STACK_STATE_HOME_IN_FRONT;
132
133 /** List of activities that are waiting for a new activity to become visible before completing
134 * whatever operation they are supposed to do. */
135 final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();
136
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700137 /** List of processes waiting to find out about the next visible activity. */
138 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible =
139 new ArrayList<IActivityManager.WaitResult>();
140
141 /** List of processes waiting to find out about the next launched activity. */
142 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched =
143 new ArrayList<IActivityManager.WaitResult>();
144
Craig Mautnerde4ef022013-04-07 19:01:33 -0700145 /** List of activities that are ready to be stopped, but waiting for the next activity to
146 * settle down before doing so. */
147 final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();
148
Craig Mautnerf3333272013-04-22 10:55:53 -0700149 /** List of activities that are ready to be finished, but waiting for the previous activity to
150 * settle down before doing so. It contains ActivityRecord objects. */
151 final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<ActivityRecord>();
152
153 /** List of ActivityRecord objects that have been finished and must still report back to a
154 * pending thumbnail receiver. */
155 final ArrayList<ActivityRecord> mCancelledThumbnails = new ArrayList<ActivityRecord>();
156
157 /** Used on user changes */
158 final ArrayList<UserStartedState> mStartingUsers = new ArrayList<UserStartedState>();
159
Craig Mautnerde4ef022013-04-07 19:01:33 -0700160 /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity
161 * is being brought in front of us. */
162 boolean mUserLeaving = false;
163
Craig Mautner858d8a62013-04-23 17:08:34 -0700164 /** Stacks belonging to users other than mCurrentUser. Indexed by userId. */
165 final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
166
Craig Mautner2219a1b2013-03-25 09:44:30 -0700167 public ActivityStackSupervisor(ActivityManagerService service, Context context,
168 Looper looper) {
Craig Mautner27084302013-03-25 08:05:25 -0700169 mService = service;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700170 mContext = context;
171 mLooper = looper;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700172 mHandler = new ActivityStackSupervisorHandler(looper);
Craig Mautner2219a1b2013-03-25 09:44:30 -0700173 }
174
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700175 void setWindowManager(WindowManagerService wm) {
176 mWindowManager = wm;
177 mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700178 mStacks.add(mHomeStack);
Craig Mautner27084302013-03-25 08:05:25 -0700179 }
180
181 void dismissKeyguard() {
182 if (mDismissKeyguardOnNextActivity) {
183 mDismissKeyguardOnNextActivity = false;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700184 mWindowManager.dismissKeyguard();
Craig Mautner27084302013-03-25 08:05:25 -0700185 }
186 }
187
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700188 ActivityStack getFocusedStack() {
Craig Mautnerf88c50f2013-04-18 19:25:12 -0700189 if (mFocusedStack == null) {
190 return mHomeStack;
191 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700192 switch (mStackState) {
193 case STACK_STATE_HOME_IN_FRONT:
194 case STACK_STATE_HOME_TO_FRONT:
195 return mHomeStack;
196 case STACK_STATE_HOME_IN_BACK:
197 case STACK_STATE_HOME_TO_BACK:
198 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700199 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700200 }
Craig Mautner20e72272013-04-01 13:45:53 -0700201 }
202
Craig Mautnerde4ef022013-04-07 19:01:33 -0700203 ActivityStack getLastStack() {
204 switch (mStackState) {
205 case STACK_STATE_HOME_IN_FRONT:
206 case STACK_STATE_HOME_TO_BACK:
207 return mHomeStack;
208 case STACK_STATE_HOME_TO_FRONT:
209 case STACK_STATE_HOME_IN_BACK:
210 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700211 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700212 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700213 }
214
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700215 boolean isFocusedStack(ActivityStack stack) {
216 return getFocusedStack() == stack;
217 }
218
Craig Mautnerde4ef022013-04-07 19:01:33 -0700219 boolean isFrontStack(ActivityStack stack) {
Craig Mautner858d8a62013-04-23 17:08:34 -0700220 if (stack.mCurrentUser != mCurrentUser) {
221 return false;
222 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700223 return !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
Craig Mautner20e72272013-04-01 13:45:53 -0700224 }
225
Craig Mautnerde4ef022013-04-07 19:01:33 -0700226 void moveHomeStack(boolean toFront) {
227 final boolean homeInFront = isFrontStack(mHomeStack);
228 if (homeInFront ^ toFront) {
229 mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
230 }
231 }
232
Craig Mautner69ada552013-04-18 13:51:51 -0700233 boolean resumeHomeActivity(ActivityRecord prev) {
234 moveHomeStack(true);
235 if (prev != null) {
236 prev.mLaunchHomeTaskNext = false;
237 }
238 if (mHomeStack.topRunningActivityLocked(null) != null) {
239 return mHomeStack.resumeTopActivityLocked(prev);
240 }
241 return mService.startHomeActivityLocked(mCurrentUser);
242 }
243
Craig Mautnerde4ef022013-04-07 19:01:33 -0700244 final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r,
245 ActivityStack stack) {
246 if (stack == mHomeStack) {
247 return;
248 }
249 if ((sourceRecord == null && getLastStack() == mHomeStack) ||
250 (sourceRecord != null && sourceRecord.isHomeActivity)) {
251 if (r == null) {
252 r = stack.topRunningActivityLocked(null);
253 }
254 if (r != null && !r.isHomeActivity && r.isRootActivity()) {
255 r.mLaunchHomeTaskNext = true;
256 }
257 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700258 }
259
Craig Mautner27084302013-03-25 08:05:25 -0700260 void setDismissKeyguard(boolean dismiss) {
261 mDismissKeyguardOnNextActivity = dismiss;
262 }
263
Craig Mautner8d341ef2013-03-26 09:03:27 -0700264 TaskRecord anyTaskForIdLocked(int id) {
265 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
266 ActivityStack stack = mStacks.get(stackNdx);
267 TaskRecord task = stack.taskForIdLocked(id);
268 if (task != null) {
269 return task;
270 }
271 }
272 return null;
273 }
274
Craig Mautner6170f732013-04-02 13:05:23 -0700275 ActivityRecord isInAnyStackLocked(IBinder token) {
276 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
277 final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
278 if (r != null) {
279 return r;
280 }
281 }
282 return null;
283 }
284
Craig Mautner8d341ef2013-03-26 09:03:27 -0700285 int getNextTaskId() {
286 do {
287 mCurTaskId++;
288 if (mCurTaskId <= 0) {
289 mCurTaskId = 1;
290 }
291 } while (anyTaskForIdLocked(mCurTaskId) != null);
292 return mCurTaskId;
293 }
294
Craig Mautnerde4ef022013-04-07 19:01:33 -0700295 void removeTask(TaskRecord task) {
296 final ActivityStack stack = task.stack;
297 if (stack.removeTask(task) && !stack.isHomeStack()) {
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700298 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700299 mStacks.remove(stack);
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700300 final int stackId = stack.mStackId;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700301 final int nextStackId = mWindowManager.removeStack(stackId);
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700302 // TODO: Perhaps we need to let the ActivityManager determine the next focus...
Craig Mautner29219d92013-04-16 20:19:12 -0700303 if (mFocusedStack.mStackId == stackId) {
304 mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700305 }
306 }
307 }
308
309 ActivityRecord resumedAppLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700310 ActivityStack stack = getFocusedStack();
311 if (stack == null) {
312 return null;
313 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700314 ActivityRecord resumedActivity = stack.mResumedActivity;
315 if (resumedActivity == null || resumedActivity.app == null) {
316 resumedActivity = stack.mPausingActivity;
317 if (resumedActivity == null || resumedActivity.app == null) {
318 resumedActivity = stack.topRunningActivityLocked(null);
319 }
320 }
321 return resumedActivity;
322 }
323
Craig Mautner20e72272013-04-01 13:45:53 -0700324 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
325 boolean didSomething = false;
326 final String processName = app.processName;
327 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
328 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner858d8a62013-04-23 17:08:34 -0700329 if (!isFrontStack(stack)) {
330 continue;
331 }
Craig Mautner20e72272013-04-01 13:45:53 -0700332 ActivityRecord hr = stack.topRunningActivityLocked(null);
333 if (hr != null) {
334 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
335 && processName.equals(hr.processName)) {
336 try {
337 if (headless) {
338 Slog.e(TAG, "Starting activities not supported on headless device: "
339 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700340 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700341 didSomething = true;
342 }
343 } catch (Exception e) {
344 Slog.w(TAG, "Exception in new application when starting activity "
345 + hr.intent.getComponent().flattenToShortString(), e);
346 throw e;
347 }
348 } else {
349 stack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
350 }
351 }
352 }
353 return didSomething;
354 }
355
356 boolean allResumedActivitiesIdle() {
357 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700358 final ActivityRecord resumedActivity = mStacks.get(stackNdx).mResumedActivity;
359 if (resumedActivity == null || !resumedActivity.idle) {
Craig Mautner20e72272013-04-01 13:45:53 -0700360 return false;
361 }
362 }
363 return true;
364 }
365
Craig Mautnerde4ef022013-04-07 19:01:33 -0700366 boolean allResumedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700367 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
368 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner967212c2013-04-13 21:10:58 -0700369 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700370 final ActivityRecord r = stack.mResumedActivity;
371 if (r != null && r.state != ActivityState.RESUMED) {
372 return false;
373 }
374 }
375 }
376 // TODO: Not sure if this should check if all Paused are complete too.
377 switch (mStackState) {
378 case STACK_STATE_HOME_TO_BACK:
379 mStackState = STACK_STATE_HOME_IN_BACK;
380 break;
381 case STACK_STATE_HOME_TO_FRONT:
382 mStackState = STACK_STATE_HOME_IN_FRONT;
383 break;
384 }
385 return true;
386 }
387
388 boolean allResumedActivitiesVisible() {
389 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
390 final ActivityStack stack = mStacks.get(stackNdx);
391 final ActivityRecord r = stack.mResumedActivity;
392 if (r != null && (!r.nowVisible || r.waitingVisible)) {
393 return false;
394 }
395 }
396 return true;
397 }
398
Craig Mautnercf910b02013-04-23 11:23:27 -0700399 boolean pauseBackStacks(boolean userLeaving) {
400 boolean someActivityPaused = false;
401 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
402 final ActivityStack stack = mStacks.get(stackNdx);
403 if (!isFrontStack(stack) && stack.mResumedActivity != null) {
404 stack.startPausingLocked(userLeaving, false);
405 someActivityPaused = true;
406 }
407 }
408 return someActivityPaused;
409 }
410
Craig Mautnerde4ef022013-04-07 19:01:33 -0700411 boolean allPausedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700412 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
413 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner69ada552013-04-18 13:51:51 -0700414 final ActivityRecord r = stack.mPausingActivity;
415 if (r != null && r.state != ActivityState.PAUSED
416 && r.state != ActivityState.STOPPED
417 && r.state != ActivityState.STOPPING) {
418 return false;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700419 }
420 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700421 return true;
422 }
423
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700424 void reportActivityVisibleLocked(ActivityRecord r) {
Craig Mautner858d8a62013-04-23 17:08:34 -0700425 for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700426 WaitResult w = mWaitingActivityVisible.get(i);
427 w.timeout = false;
428 if (r != null) {
429 w.who = new ComponentName(r.info.packageName, r.info.name);
430 }
431 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
432 w.thisTime = w.totalTime;
433 }
434 mService.notifyAll();
435 dismissKeyguard();
436 }
437
438 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
439 long thisTime, long totalTime) {
440 for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
Craig Mautnerc64f73e2013-04-24 16:44:56 -0700441 WaitResult w = mWaitingActivityLaunched.remove(i);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700442 w.timeout = timeout;
443 if (r != null) {
444 w.who = new ComponentName(r.info.packageName, r.info.name);
445 }
446 w.thisTime = thisTime;
447 w.totalTime = totalTime;
448 }
449 mService.notifyAll();
450 }
451
Craig Mautner29219d92013-04-16 20:19:12 -0700452 ActivityRecord topRunningActivityLocked() {
453 ActivityRecord r = null;
454 if (mFocusedStack != null) {
455 r = mFocusedStack.topRunningActivityLocked(null);
456 if (r != null) {
457 return r;
458 }
459 }
460 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
461 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner858d8a62013-04-23 17:08:34 -0700462 if (stack.mCurrentUser != mCurrentUser) {
463 continue;
464 }
Craig Mautner29219d92013-04-16 20:19:12 -0700465 if (stack != mFocusedStack && isFrontStack(stack)) {
466 r = stack.topRunningActivityLocked(null);
467 if (r != null) {
468 return r;
469 }
470 }
471 }
472 return null;
473 }
474
Craig Mautner20e72272013-04-01 13:45:53 -0700475 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
476 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
477 ActivityRecord r = null;
478 final int numStacks = mStacks.size();
479 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
480 final ActivityStack stack = mStacks.get(stackNdx);
481 final ActivityRecord ar =
482 stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700483 if (isFrontStack(stack)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700484 r = ar;
485 }
486 }
487 return r;
488 }
489
Craig Mautner23ac33b2013-04-01 16:26:35 -0700490 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
491 String profileFile, ParcelFileDescriptor profileFd, int userId) {
492 // Collect information about the target of the Intent.
493 ActivityInfo aInfo;
494 try {
495 ResolveInfo rInfo =
496 AppGlobals.getPackageManager().resolveIntent(
497 intent, resolvedType,
498 PackageManager.MATCH_DEFAULT_ONLY
499 | ActivityManagerService.STOCK_PM_FLAGS, userId);
500 aInfo = rInfo != null ? rInfo.activityInfo : null;
501 } catch (RemoteException e) {
502 aInfo = null;
503 }
504
505 if (aInfo != null) {
506 // Store the found target back into the intent, because now that
507 // we have it we never want to do this again. For example, if the
508 // user navigates back to this point in the history, we should
509 // always restart the exact same activity.
510 intent.setComponent(new ComponentName(
511 aInfo.applicationInfo.packageName, aInfo.name));
512
513 // Don't debug things in the system process
514 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
515 if (!aInfo.processName.equals("system")) {
516 mService.setDebugApp(aInfo.processName, true, false);
517 }
518 }
519
520 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
521 if (!aInfo.processName.equals("system")) {
522 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
523 }
524 }
525
526 if (profileFile != null) {
527 if (!aInfo.processName.equals("system")) {
528 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
529 profileFile, profileFd,
530 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
531 }
532 }
533 }
534 return aInfo;
535 }
536
Craig Mautner2219a1b2013-03-25 09:44:30 -0700537 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700538 moveHomeStack(true);
Craig Mautner6170f732013-04-02 13:05:23 -0700539 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
Craig Mautner2219a1b2013-03-25 09:44:30 -0700540 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700541 }
542
Craig Mautner23ac33b2013-04-01 16:26:35 -0700543 final int startActivityMayWait(IApplicationThread caller, int callingUid,
544 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
545 String resultWho, int requestCode, int startFlags, String profileFile,
546 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
547 Bundle options, int userId) {
548 // Refuse possible leaked file descriptors
549 if (intent != null && intent.hasFileDescriptors()) {
550 throw new IllegalArgumentException("File descriptors passed in Intent");
551 }
552 boolean componentSpecified = intent.getComponent() != null;
553
554 // Don't modify the client's object!
555 intent = new Intent(intent);
556
557 // Collect information about the target of the Intent.
558 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
559 profileFile, profileFd, userId);
560
561 synchronized (mService) {
562 int callingPid;
563 if (callingUid >= 0) {
564 callingPid = -1;
565 } else if (caller == null) {
566 callingPid = Binder.getCallingPid();
567 callingUid = Binder.getCallingUid();
568 } else {
569 callingPid = callingUid = -1;
570 }
571
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700572 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -0700573 stack.mConfigWillChange = config != null
Craig Mautner23ac33b2013-04-01 16:26:35 -0700574 && mService.mConfiguration.diff(config) != 0;
575 if (DEBUG_CONFIGURATION) Slog.v(TAG,
Craig Mautnerde4ef022013-04-07 19:01:33 -0700576 "Starting activity when config will change = " + stack.mConfigWillChange);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700577
578 final long origId = Binder.clearCallingIdentity();
579
580 if (aInfo != null &&
581 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
582 // This may be a heavy-weight process! Check to see if we already
583 // have another, different heavy-weight process running.
584 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
585 if (mService.mHeavyWeightProcess != null &&
586 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
587 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
588 int realCallingPid = callingPid;
589 int realCallingUid = callingUid;
590 if (caller != null) {
591 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
592 if (callerApp != null) {
593 realCallingPid = callerApp.pid;
594 realCallingUid = callerApp.info.uid;
595 } else {
596 Slog.w(TAG, "Unable to find app for caller " + caller
597 + " (pid=" + realCallingPid + ") when starting: "
598 + intent.toString());
599 ActivityOptions.abort(options);
600 return ActivityManager.START_PERMISSION_DENIED;
601 }
602 }
603
604 IIntentSender target = mService.getIntentSenderLocked(
605 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
606 realCallingUid, userId, null, null, 0, new Intent[] { intent },
607 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
608 | PendingIntent.FLAG_ONE_SHOT, null);
609
610 Intent newIntent = new Intent();
611 if (requestCode >= 0) {
612 // Caller is requesting a result.
613 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
614 }
615 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
616 new IntentSender(target));
617 if (mService.mHeavyWeightProcess.activities.size() > 0) {
618 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
619 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
620 hist.packageName);
621 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
622 hist.task.taskId);
623 }
624 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
625 aInfo.packageName);
626 newIntent.setFlags(intent.getFlags());
627 newIntent.setClassName("android",
628 HeavyWeightSwitcherActivity.class.getName());
629 intent = newIntent;
630 resolvedType = null;
631 caller = null;
632 callingUid = Binder.getCallingUid();
633 callingPid = Binder.getCallingPid();
634 componentSpecified = true;
635 try {
636 ResolveInfo rInfo =
637 AppGlobals.getPackageManager().resolveIntent(
638 intent, null,
639 PackageManager.MATCH_DEFAULT_ONLY
640 | ActivityManagerService.STOCK_PM_FLAGS, userId);
641 aInfo = rInfo != null ? rInfo.activityInfo : null;
642 aInfo = mService.getActivityInfoForUser(aInfo, userId);
643 } catch (RemoteException e) {
644 aInfo = null;
645 }
646 }
647 }
648 }
649
Craig Mautner6170f732013-04-02 13:05:23 -0700650 int res = startActivityLocked(caller, intent, resolvedType,
Craig Mautner23ac33b2013-04-01 16:26:35 -0700651 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
652 callingPackage, startFlags, options, componentSpecified, null);
653
Craig Mautnerde4ef022013-04-07 19:01:33 -0700654 if (stack.mConfigWillChange) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700655 // If the caller also wants to switch to a new configuration,
656 // do so now. This allows a clean switch, as we are waiting
657 // for the current activity to pause (so we will not destroy
658 // it), and have not yet started the next activity.
659 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
660 "updateConfiguration()");
Craig Mautnerde4ef022013-04-07 19:01:33 -0700661 stack.mConfigWillChange = false;
Craig Mautner23ac33b2013-04-01 16:26:35 -0700662 if (DEBUG_CONFIGURATION) Slog.v(TAG,
663 "Updating to new configuration after starting activity.");
664 mService.updateConfigurationLocked(config, null, false, false);
665 }
666
667 Binder.restoreCallingIdentity(origId);
668
669 if (outResult != null) {
670 outResult.result = res;
671 if (res == ActivityManager.START_SUCCESS) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700672 mWaitingActivityLaunched.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700673 do {
674 try {
675 mService.wait();
676 } catch (InterruptedException e) {
677 }
678 } while (!outResult.timeout && outResult.who == null);
679 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700680 ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700681 if (r.nowVisible) {
682 outResult.timeout = false;
683 outResult.who = new ComponentName(r.info.packageName, r.info.name);
684 outResult.totalTime = 0;
685 outResult.thisTime = 0;
686 } else {
687 outResult.thisTime = SystemClock.uptimeMillis();
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700688 mWaitingActivityVisible.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700689 do {
690 try {
691 mService.wait();
692 } catch (InterruptedException e) {
693 }
694 } while (!outResult.timeout && outResult.who == null);
695 }
696 }
697 }
698
699 return res;
700 }
701 }
702
703 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
704 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
705 Bundle options, int userId) {
706 if (intents == null) {
707 throw new NullPointerException("intents is null");
708 }
709 if (resolvedTypes == null) {
710 throw new NullPointerException("resolvedTypes is null");
711 }
712 if (intents.length != resolvedTypes.length) {
713 throw new IllegalArgumentException("intents are length different than resolvedTypes");
714 }
715
716 ActivityRecord[] outActivity = new ActivityRecord[1];
717
718 int callingPid;
719 if (callingUid >= 0) {
720 callingPid = -1;
721 } else if (caller == null) {
722 callingPid = Binder.getCallingPid();
723 callingUid = Binder.getCallingUid();
724 } else {
725 callingPid = callingUid = -1;
726 }
727 final long origId = Binder.clearCallingIdentity();
728 try {
729 synchronized (mService) {
730
731 for (int i=0; i<intents.length; i++) {
732 Intent intent = intents[i];
733 if (intent == null) {
734 continue;
735 }
736
737 // Refuse possible leaked file descriptors
738 if (intent != null && intent.hasFileDescriptors()) {
739 throw new IllegalArgumentException("File descriptors passed in Intent");
740 }
741
742 boolean componentSpecified = intent.getComponent() != null;
743
744 // Don't modify the client's object!
745 intent = new Intent(intent);
746
747 // Collect information about the target of the Intent.
748 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
749 0, null, null, userId);
750 // TODO: New, check if this is correct
751 aInfo = mService.getActivityInfoForUser(aInfo, userId);
752
753 if (aInfo != null &&
754 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
755 != 0) {
756 throw new IllegalArgumentException(
757 "FLAG_CANT_SAVE_STATE not supported here");
758 }
759
760 Bundle theseOptions;
761 if (options != null && i == intents.length-1) {
762 theseOptions = options;
763 } else {
764 theseOptions = null;
765 }
Craig Mautner6170f732013-04-02 13:05:23 -0700766 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Craig Mautner23ac33b2013-04-01 16:26:35 -0700767 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
768 0, theseOptions, componentSpecified, outActivity);
769 if (res < 0) {
770 return res;
771 }
772
773 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
774 }
775 }
776 } finally {
777 Binder.restoreCallingIdentity(origId);
778 }
779
780 return ActivityManager.START_SUCCESS;
781 }
782
Craig Mautner2420ead2013-04-01 17:13:20 -0700783 final boolean realStartActivityLocked(ActivityRecord r,
784 ProcessRecord app, boolean andResume, boolean checkConfig)
785 throws RemoteException {
786
787 r.startFreezingScreenLocked(app, 0);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700788 mWindowManager.setAppVisibility(r.appToken, true);
Craig Mautner2420ead2013-04-01 17:13:20 -0700789
790 // schedule launch ticks to collect information about slow apps.
791 r.startLaunchTickingLocked();
792
793 // Have the window manager re-evaluate the orientation of
794 // the screen based on the new activity order. Note that
795 // as a result of this, it can call back into the activity
796 // manager with a new orientation. We don't care about that,
797 // because the activity is not currently running so we are
798 // just restarting it anyway.
799 if (checkConfig) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700800 Configuration config = mWindowManager.updateOrientationFromAppTokens(
Craig Mautner2420ead2013-04-01 17:13:20 -0700801 mService.mConfiguration,
802 r.mayFreezeScreenLocked(app) ? r.appToken : null);
803 mService.updateConfigurationLocked(config, r, false, false);
804 }
805
806 r.app = app;
807 app.waitingToKill = null;
808 r.launchCount++;
809 r.lastLaunchTime = SystemClock.uptimeMillis();
810
811 if (localLOGV) Slog.v(TAG, "Launching: " + r);
812
813 int idx = app.activities.indexOf(r);
814 if (idx < 0) {
815 app.activities.add(r);
816 }
817 mService.updateLruProcessLocked(app, true);
818
819 final ActivityStack stack = r.task.stack;
820 try {
821 if (app.thread == null) {
822 throw new RemoteException();
823 }
824 List<ResultInfo> results = null;
825 List<Intent> newIntents = null;
826 if (andResume) {
827 results = r.results;
828 newIntents = r.newIntents;
829 }
830 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
831 + " icicle=" + r.icicle
832 + " with results=" + results + " newIntents=" + newIntents
833 + " andResume=" + andResume);
834 if (andResume) {
835 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
836 r.userId, System.identityHashCode(r),
837 r.task.taskId, r.shortComponentName);
838 }
839 if (r.isHomeActivity) {
840 mService.mHomeProcess = app;
841 }
842 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
843 r.sleeping = false;
844 r.forceNewConfig = false;
845 mService.showAskCompatModeDialogLocked(r);
846 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
847 String profileFile = null;
848 ParcelFileDescriptor profileFd = null;
849 boolean profileAutoStop = false;
850 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
851 if (mService.mProfileProc == null || mService.mProfileProc == app) {
852 mService.mProfileProc = app;
853 profileFile = mService.mProfileFile;
854 profileFd = mService.mProfileFd;
855 profileAutoStop = mService.mAutoStopProfiler;
856 }
857 }
858 app.hasShownUi = true;
859 app.pendingUiClean = true;
860 if (profileFd != null) {
861 try {
862 profileFd = profileFd.dup();
863 } catch (IOException e) {
864 if (profileFd != null) {
865 try {
866 profileFd.close();
867 } catch (IOException o) {
868 }
869 profileFd = null;
870 }
871 }
872 }
873 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
874 System.identityHashCode(r), r.info,
875 new Configuration(mService.mConfiguration),
876 r.compat, r.icicle, results, newIntents, !andResume,
877 mService.isNextTransitionForward(), profileFile, profileFd,
878 profileAutoStop);
879
880 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
881 // This may be a heavy-weight process! Note that the package
882 // manager will ensure that only activity can run in the main
883 // process of the .apk, which is the only thing that will be
884 // considered heavy-weight.
885 if (app.processName.equals(app.info.packageName)) {
886 if (mService.mHeavyWeightProcess != null
887 && mService.mHeavyWeightProcess != app) {
888 Slog.w(TAG, "Starting new heavy weight process " + app
889 + " when already running "
890 + mService.mHeavyWeightProcess);
891 }
892 mService.mHeavyWeightProcess = app;
893 Message msg = mService.mHandler.obtainMessage(
894 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
895 msg.obj = r;
896 mService.mHandler.sendMessage(msg);
897 }
898 }
899
900 } catch (RemoteException e) {
901 if (r.launchFailed) {
902 // This is the second time we failed -- finish activity
903 // and give up.
904 Slog.e(TAG, "Second failure launching "
905 + r.intent.getComponent().flattenToShortString()
906 + ", giving up", e);
907 mService.appDiedLocked(app, app.pid, app.thread);
908 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
909 "2nd-crash", false);
910 return false;
911 }
912
913 // This is the first time we failed -- restart process and
914 // retry.
915 app.activities.remove(r);
916 throw e;
917 }
918
919 r.launchFailed = false;
920 if (stack.updateLRUListLocked(r)) {
921 Slog.w(TAG, "Activity " + r
922 + " being launched, but already in LRU list");
923 }
924
925 if (andResume) {
926 // As part of the process of launching, ActivityThread also performs
927 // a resume.
928 stack.minimalResumeActivityLocked(r);
929 } else {
930 // This activity is not starting in the resumed state... which
931 // should look like we asked it to pause+stop (but remain visible),
932 // and it has done so and reported back the current icicle and
933 // other state.
934 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
935 + " (starting in stopped state)");
936 r.state = ActivityState.STOPPED;
937 r.stopped = true;
938 }
939
940 // Launch the new version setup screen if needed. We do this -after-
941 // launching the initial activity (that is, home), so that it can have
942 // a chance to initialize itself while in the background, making the
943 // switch back to it faster and look better.
Craig Mautnerde4ef022013-04-07 19:01:33 -0700944 if (isFrontStack(stack)) {
Craig Mautner2420ead2013-04-01 17:13:20 -0700945 mService.startSetupActivityLocked();
946 }
947
948 return true;
949 }
950
Craig Mautnere79d42682013-04-01 19:01:53 -0700951 void startSpecificActivityLocked(ActivityRecord r,
952 boolean andResume, boolean checkConfig) {
953 // Is this activity's application already running?
954 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
955 r.info.applicationInfo.uid);
956
957 r.task.stack.setLaunchTime(r);
958
959 if (app != null && app.thread != null) {
960 try {
961 app.addPackage(r.info.packageName);
962 realStartActivityLocked(r, app, andResume, checkConfig);
963 return;
964 } catch (RemoteException e) {
965 Slog.w(TAG, "Exception when starting activity "
966 + r.intent.getComponent().flattenToShortString(), e);
967 }
968
969 // If a dead object exception was thrown -- fall through to
970 // restart the application.
971 }
972
973 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
974 "activity", r.intent.getComponent(), false, false);
975 }
976
Craig Mautner6170f732013-04-02 13:05:23 -0700977 final int startActivityLocked(IApplicationThread caller,
978 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
979 String resultWho, int requestCode,
980 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
981 boolean componentSpecified, ActivityRecord[] outActivity) {
982 int err = ActivityManager.START_SUCCESS;
983
984 ProcessRecord callerApp = null;
985 if (caller != null) {
986 callerApp = mService.getRecordForAppLocked(caller);
987 if (callerApp != null) {
988 callingPid = callerApp.pid;
989 callingUid = callerApp.info.uid;
990 } else {
991 Slog.w(TAG, "Unable to find app for caller " + caller
992 + " (pid=" + callingPid + ") when starting: "
993 + intent.toString());
994 err = ActivityManager.START_PERMISSION_DENIED;
995 }
996 }
997
998 if (err == ActivityManager.START_SUCCESS) {
999 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
1000 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
1001 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
1002 }
1003
1004 ActivityRecord sourceRecord = null;
1005 ActivityRecord resultRecord = null;
1006 if (resultTo != null) {
1007 sourceRecord = isInAnyStackLocked(resultTo);
1008 if (DEBUG_RESULTS) Slog.v(
1009 TAG, "Will send result to " + resultTo + " " + sourceRecord);
1010 if (sourceRecord != null) {
1011 if (requestCode >= 0 && !sourceRecord.finishing) {
1012 resultRecord = sourceRecord;
1013 }
1014 }
1015 }
1016 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
1017
1018 int launchFlags = intent.getFlags();
1019
1020 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
1021 && sourceRecord != null) {
1022 // Transfer the result target from the source activity to the new
1023 // one being started, including any failures.
1024 if (requestCode >= 0) {
1025 ActivityOptions.abort(options);
1026 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
1027 }
1028 resultRecord = sourceRecord.resultTo;
1029 resultWho = sourceRecord.resultWho;
1030 requestCode = sourceRecord.requestCode;
1031 sourceRecord.resultTo = null;
1032 if (resultRecord != null) {
1033 resultRecord.removeResultsLocked(
1034 sourceRecord, resultWho, requestCode);
1035 }
1036 }
1037
1038 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
1039 // We couldn't find a class that can handle the given Intent.
1040 // That's the end of that!
1041 err = ActivityManager.START_INTENT_NOT_RESOLVED;
1042 }
1043
1044 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
1045 // We couldn't find the specific class specified in the Intent.
1046 // Also the end of the line.
1047 err = ActivityManager.START_CLASS_NOT_FOUND;
1048 }
1049
1050 if (err != ActivityManager.START_SUCCESS) {
1051 if (resultRecord != null) {
1052 resultStack.sendActivityResultLocked(-1,
1053 resultRecord, resultWho, requestCode,
1054 Activity.RESULT_CANCELED, null);
1055 }
1056 setDismissKeyguard(false);
1057 ActivityOptions.abort(options);
1058 return err;
1059 }
1060
1061 final int startAnyPerm = mService.checkPermission(
1062 START_ANY_ACTIVITY, callingPid, callingUid);
1063 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
1064 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
1065 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
1066 if (resultRecord != null) {
1067 resultStack.sendActivityResultLocked(-1,
1068 resultRecord, resultWho, requestCode,
1069 Activity.RESULT_CANCELED, null);
1070 }
1071 setDismissKeyguard(false);
1072 String msg;
1073 if (!aInfo.exported) {
1074 msg = "Permission Denial: starting " + intent.toString()
1075 + " from " + callerApp + " (pid=" + callingPid
1076 + ", uid=" + callingUid + ")"
1077 + " not exported from uid " + aInfo.applicationInfo.uid;
1078 } else {
1079 msg = "Permission Denial: starting " + intent.toString()
1080 + " from " + callerApp + " (pid=" + callingPid
1081 + ", uid=" + callingUid + ")"
1082 + " requires " + aInfo.permission;
1083 }
1084 Slog.w(TAG, msg);
1085 throw new SecurityException(msg);
1086 }
1087
Ben Gruver6617c3c2013-04-03 18:45:22 -07001088 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
Ben Gruver7b879f42013-04-08 14:56:55 -07001089 callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo);
Ben Gruver5e207332013-04-03 17:41:37 -07001090
Craig Mautner6170f732013-04-02 13:05:23 -07001091 if (mService.mController != null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001092 try {
1093 // The Intent we give to the watcher has the extra data
1094 // stripped off, since it can contain private information.
1095 Intent watchIntent = intent.cloneFilter();
Ben Gruver5e207332013-04-03 17:41:37 -07001096 abort |= !mService.mController.activityStarting(watchIntent,
Craig Mautner6170f732013-04-02 13:05:23 -07001097 aInfo.applicationInfo.packageName);
1098 } catch (RemoteException e) {
1099 mService.mController = null;
1100 }
Ben Gruver5e207332013-04-03 17:41:37 -07001101 }
Craig Mautner6170f732013-04-02 13:05:23 -07001102
Ben Gruver5e207332013-04-03 17:41:37 -07001103 if (abort) {
1104 if (resultRecord != null) {
1105 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Craig Mautner6170f732013-04-02 13:05:23 -07001106 Activity.RESULT_CANCELED, null);
Craig Mautner6170f732013-04-02 13:05:23 -07001107 }
Ben Gruver5e207332013-04-03 17:41:37 -07001108 // We pretend to the caller that it was really started, but
1109 // they will just get a cancel result.
1110 setDismissKeyguard(false);
1111 ActivityOptions.abort(options);
1112 return ActivityManager.START_SUCCESS;
Craig Mautner6170f732013-04-02 13:05:23 -07001113 }
1114
1115 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1116 intent, resolvedType, aInfo, mService.mConfiguration,
Craig Mautnerde4ef022013-04-07 19:01:33 -07001117 resultRecord, resultWho, requestCode, componentSpecified, this);
Craig Mautner6170f732013-04-02 13:05:23 -07001118 if (outActivity != null) {
1119 outActivity[0] = r;
1120 }
1121
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001122 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001123 if (stack.mResumedActivity == null
1124 || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
Craig Mautner6170f732013-04-02 13:05:23 -07001125 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1126 PendingActivityLaunch pal =
Craig Mautnerde4ef022013-04-07 19:01:33 -07001127 new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
Craig Mautner6170f732013-04-02 13:05:23 -07001128 mService.mPendingActivityLaunches.add(pal);
1129 setDismissKeyguard(false);
1130 ActivityOptions.abort(options);
1131 return ActivityManager.START_SWITCHES_CANCELED;
1132 }
1133 }
1134
1135 if (mService.mDidAppSwitch) {
1136 // This is the second allowed switch since we stopped switches,
1137 // so now just generally allow switches. Use case: user presses
1138 // home (switches disabled, switch to home, mDidAppSwitch now true);
1139 // user taps a home icon (coming from home so allowed, we hit here
1140 // and now allow anyone to switch again).
1141 mService.mAppSwitchesAllowedTime = 0;
1142 } else {
1143 mService.mDidAppSwitch = true;
1144 }
1145
1146 mService.doPendingActivityLaunchesLocked(false);
1147
Craig Mautner8849a5e2013-04-02 16:41:03 -07001148 err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001149 if (stack.mPausingActivity == null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001150 // Someone asked to have the keyguard dismissed on the next
1151 // activity start, but we are not actually doing an activity
1152 // switch... just dismiss the keyguard now, because we
1153 // probably want to see whatever is behind it.
1154 dismissKeyguard();
1155 }
1156 return err;
1157 }
1158
Craig Mautnerde4ef022013-04-07 19:01:33 -07001159 ActivityStack getCorrectStack(ActivityRecord r) {
1160 if (!r.isHomeActivity) {
Craig Mautner858d8a62013-04-23 17:08:34 -07001161 int stackNdx;
1162 for (stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
1163 if (mStacks.get(stackNdx).mCurrentUser == mCurrentUser) {
1164 break;
1165 }
1166 }
1167 if (stackNdx == 0) {
1168 // Time to create the first app stack for this user.
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001169 int stackId = mService.createStack(-1, HOME_STACK_ID,
1170 StackBox.TASK_STACK_GOES_OVER, 1.0f);
Craig Mautner29219d92013-04-16 20:19:12 -07001171 mFocusedStack = getStack(stackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001172 }
Craig Mautner29219d92013-04-16 20:19:12 -07001173 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001174 }
1175 return mHomeStack;
1176 }
1177
Craig Mautner29219d92013-04-16 20:19:12 -07001178 void setFocusedStack(ActivityRecord r) {
1179 if (r == null) {
1180 return;
1181 }
1182 if (r.isHomeActivity) {
1183 if (mStackState != STACK_STATE_HOME_IN_FRONT) {
1184 mStackState = STACK_STATE_HOME_TO_FRONT;
1185 }
1186 } else {
1187 mFocusedStack = r.task.stack;
1188 if (mStackState != STACK_STATE_HOME_IN_BACK) {
1189 mStackState = STACK_STATE_HOME_TO_BACK;
1190 }
1191 }
1192 }
1193
Craig Mautner8849a5e2013-04-02 16:41:03 -07001194 final int startActivityUncheckedLocked(ActivityRecord r,
1195 ActivityRecord sourceRecord, int startFlags, boolean doResume,
1196 Bundle options) {
1197 final Intent intent = r.intent;
1198 final int callingUid = r.launchedFromUid;
1199
1200 int launchFlags = intent.getFlags();
1201
Craig Mautner8849a5e2013-04-02 16:41:03 -07001202 // We'll invoke onUserLeaving before onPause only if the launching
1203 // activity did not explicitly state that this is an automated launch.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001204 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1205 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001206
1207 // If the caller has asked not to resume at this point, we make note
1208 // of this in the record so that we can skip it when trying to find
1209 // the top running activity.
1210 if (!doResume) {
1211 r.delayedResume = true;
1212 }
1213
1214 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1215
1216 // If the onlyIfNeeded flag is set, then we can do this if the activity
1217 // being launched is the same as the one making the call... or, as
1218 // a special case, if we do not know the caller then we count the
1219 // current top activity as the caller.
1220 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1221 ActivityRecord checkedCaller = sourceRecord;
1222 if (checkedCaller == null) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001223 checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001224 }
1225 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1226 // Caller is not the same as launcher, so always needed.
1227 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1228 }
1229 }
1230
1231 if (sourceRecord == null) {
1232 // This activity is not being started from another... in this
1233 // case we -always- start a new task.
1234 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Craig Mautner29219d92013-04-16 20:19:12 -07001235 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1236 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001237 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1238 }
1239 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1240 // The original activity who is starting us is running as a single
1241 // instance... this new activity it is starting must go on its
1242 // own task.
1243 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1244 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1245 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1246 // The activity being started is a single instance... it always
1247 // gets launched into its own task.
1248 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1249 }
1250
Craig Mautnerde4ef022013-04-07 19:01:33 -07001251 final ActivityStack sourceStack;
1252 final TaskRecord sourceTask;
1253 if (sourceRecord != null) {
1254 sourceTask = sourceRecord.task;
1255 sourceStack = sourceTask.stack;
1256 } else {
1257 sourceTask = null;
1258 sourceStack = null;
1259 }
1260
Craig Mautner8849a5e2013-04-02 16:41:03 -07001261 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1262 // For whatever reason this activity is being launched into a new
1263 // task... yet the caller has requested a result back. Well, that
1264 // is pretty messed up, so instead immediately send back a cancel
1265 // and let the new task continue launched as normal without a
1266 // dependency on its originator.
1267 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1268 r.resultTo.task.stack.sendActivityResultLocked(-1,
1269 r.resultTo, r.resultWho, r.requestCode,
1270 Activity.RESULT_CANCELED, null);
1271 r.resultTo = null;
1272 }
1273
1274 boolean addingToTask = false;
1275 boolean movedHome = false;
1276 TaskRecord reuseTask = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001277 ActivityStack targetStack;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001278 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1279 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1280 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1281 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1282 // If bring to front is requested, and no result is requested, and
1283 // we can find a task that was started with this same
1284 // component, then instead of launching bring that one to the front.
1285 if (r.resultTo == null) {
1286 // See if there is a task to bring to the front. If this is
1287 // a SINGLE_INSTANCE activity, there can be one and only one
1288 // instance of it in the history, and it is always in its own
1289 // unique task, so we do a special search.
1290 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
1291 ? findTaskLocked(intent, r.info)
1292 : findActivityLocked(intent, r.info);
1293 if (intentActivity != null) {
Craig Mautner29219d92013-04-16 20:19:12 -07001294 if (r.task == null) {
1295 r.task = intentActivity.task;
1296 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001297 targetStack = intentActivity.task.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001298 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001299 if (intentActivity.task.intent == null) {
1300 // This task was started because of movement of
1301 // the activity based on affinity... now that we
1302 // are actually launching it, we can assign the
1303 // base intent.
1304 intentActivity.task.setIntent(intent, r.info);
1305 }
1306 // If the target task is not in the front, then we need
1307 // to bring it to the front... except... well, with
1308 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
1309 // to have the same behavior as if a new instance was
1310 // being started, which means not bringing it to the front
1311 // if the caller is not itself in the front.
Craig Mautner165640b2013-04-20 10:34:33 -07001312 final ActivityStack lastStack = getLastStack();
1313 ActivityRecord curTop = lastStack == null?
1314 null : lastStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001315 if (curTop != null && curTop.task != intentActivity.task) {
1316 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001317 if (sourceRecord == null || sourceStack.topActivity() == sourceRecord) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001318 // We really do want to push this one into the
1319 // user's face, right now.
1320 movedHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001321 if ((launchFlags &
Craig Mautner29219d92013-04-16 20:19:12 -07001322 (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1323 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001324 // Caller wants to appear on home activity, so before starting
1325 // their own activity we will bring home to the front.
1326 r.mLaunchHomeTaskNext = true;
1327 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001328 targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1329 options = null;
1330 }
1331 }
1332 // If the caller has requested that the target task be
1333 // reset, then do so.
1334 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1335 intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1336 }
1337 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1338 // We don't need to start a new activity, and
1339 // the client said not to do anything if that
1340 // is the case, so this is it! And for paranoia, make
1341 // sure we have correctly resumed the top activity.
1342 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001343 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001344 targetStack.resumeTopActivityLocked(null, options);
1345 } else {
1346 ActivityOptions.abort(options);
1347 }
Craig Mautner29219d92013-04-16 20:19:12 -07001348 if (r.task == null) Slog.v(TAG,
1349 "startActivityUncheckedLocked: task left null",
1350 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001351 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1352 }
1353 if ((launchFlags &
1354 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1355 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1356 // The caller has requested to completely replace any
1357 // existing task with its new activity. Well that should
1358 // not be too hard...
1359 reuseTask = intentActivity.task;
1360 reuseTask.performClearTaskLocked();
1361 reuseTask.setIntent(r.intent, r.info);
1362 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1363 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1364 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1365 // In this situation we want to remove all activities
1366 // from the task up to the one being started. In most
1367 // cases this means we are resetting the task to its
1368 // initial state.
1369 ActivityRecord top =
1370 intentActivity.task.performClearTaskLocked(r, launchFlags);
1371 if (top != null) {
1372 if (top.frontOfTask) {
1373 // Activity aliases may mean we use different
1374 // intents for the top activity, so make sure
1375 // the task now has the identity of the new
1376 // intent.
1377 top.task.setIntent(r.intent, r.info);
1378 }
1379 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1380 r, top.task);
1381 top.deliverNewIntentLocked(callingUid, r.intent);
1382 } else {
1383 // A special case: we need to
1384 // start the activity because it is not currently
1385 // running, and the caller has asked to clear the
1386 // current task to have this activity at the top.
1387 addingToTask = true;
1388 // Now pretend like this activity is being started
1389 // by the top of its task, so it is put in the
1390 // right place.
1391 sourceRecord = intentActivity;
1392 }
1393 } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1394 // In this case the top activity on the task is the
1395 // same as the one being launched, so we take that
1396 // as a request to bring the task to the foreground.
1397 // If the top activity in the task is the root
1398 // activity, deliver this new intent to it if it
1399 // desires.
1400 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1401 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1402 && intentActivity.realActivity.equals(r.realActivity)) {
1403 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1404 intentActivity.task);
1405 if (intentActivity.frontOfTask) {
1406 intentActivity.task.setIntent(r.intent, r.info);
1407 }
1408 intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1409 } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1410 // In this case we are launching the root activity
1411 // of the task, but with a different intent. We
1412 // should start a new instance on top.
1413 addingToTask = true;
1414 sourceRecord = intentActivity;
1415 }
1416 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1417 // In this case an activity is being launched in to an
1418 // existing task, without resetting that task. This
1419 // is typically the situation of launching an activity
1420 // from a notification or shortcut. We want to place
1421 // the new activity on top of the current task.
1422 addingToTask = true;
1423 sourceRecord = intentActivity;
1424 } else if (!intentActivity.task.rootWasReset) {
1425 // In this case we are launching in to an existing task
1426 // that has not yet been started from its front door.
1427 // The current task has been brought to the front.
1428 // Ideally, we'd probably like to place this new task
1429 // at the bottom of its stack, but that's a little hard
1430 // to do with the current organization of the code so
1431 // for now we'll just drop it.
1432 intentActivity.task.setIntent(r.intent, r.info);
1433 }
1434 if (!addingToTask && reuseTask == null) {
1435 // We didn't do anything... but it was needed (a.k.a., client
1436 // don't use that intent!) And for paranoia, make
1437 // sure we have correctly resumed the top activity.
1438 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001439 setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1440 targetStack.resumeTopActivityLocked(null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001441 } else {
1442 ActivityOptions.abort(options);
1443 }
Craig Mautner29219d92013-04-16 20:19:12 -07001444 if (r.task == null) Slog.v(TAG,
1445 "startActivityUncheckedLocked: task left null",
1446 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001447 return ActivityManager.START_TASK_TO_FRONT;
1448 }
1449 }
1450 }
1451 }
1452
1453 //String uri = r.intent.toURI();
1454 //Intent intent2 = new Intent(uri);
1455 //Slog.i(TAG, "Given intent: " + r.intent);
1456 //Slog.i(TAG, "URI is: " + uri);
1457 //Slog.i(TAG, "To intent: " + intent2);
1458
1459 if (r.packageName != null) {
1460 // If the activity being launched is the same as the one currently
1461 // at the top, then we need to check if it should only be launched
1462 // once.
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001463 ActivityStack topStack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001464 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001465 if (top != null && r.resultTo == null) {
1466 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1467 if (top.app != null && top.app.thread != null) {
1468 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1469 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1470 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1471 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1472 top.task);
1473 // For paranoia, make sure we have correctly
1474 // resumed the top activity.
1475 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001476 setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
1477 topStack.resumeTopActivityLocked(null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001478 }
1479 ActivityOptions.abort(options);
1480 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1481 // We don't need to start a new activity, and
1482 // the client said not to do anything if that
1483 // is the case, so this is it!
Craig Mautner29219d92013-04-16 20:19:12 -07001484 if (r.task == null) Slog.v(TAG,
1485 "startActivityUncheckedLocked: task left null",
1486 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001487 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1488 }
1489 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner29219d92013-04-16 20:19:12 -07001490 if (r.task == null) Slog.v(TAG,
1491 "startActivityUncheckedLocked: task left null",
1492 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001493 return ActivityManager.START_DELIVERED_TO_TOP;
1494 }
1495 }
1496 }
1497 }
1498
1499 } else {
1500 if (r.resultTo != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001501 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1502 r.requestCode, Activity.RESULT_CANCELED, null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001503 }
1504 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001505 if (r.task == null) Slog.v(TAG,
1506 "startActivityUncheckedLocked: task left null",
1507 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001508 return ActivityManager.START_CLASS_NOT_FOUND;
1509 }
1510
1511 boolean newTask = false;
1512 boolean keepCurTransition = false;
1513
1514 // Should this be considered a new task?
1515 if (r.resultTo == null && !addingToTask
1516 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001517 targetStack = getCorrectStack(r);
1518 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001519 if (reuseTask == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001520 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1521 null, true);
1522 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1523 r.task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001524 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001525 r.setTask(reuseTask, reuseTask, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001526 }
1527 newTask = true;
1528 if (!movedHome) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001529 if ((launchFlags &
1530 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1531 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1532 // Caller wants to appear on home activity, so before starting
1533 // their own activity we will bring home to the front.
1534 r.mLaunchHomeTaskNext = true;
1535 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001536 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001537 } else if (sourceRecord != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001538 targetStack = sourceRecord.task.stack;
1539 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001540 if (!addingToTask &&
1541 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1542 // In this case, we are adding the activity to an existing
1543 // task, but the caller has asked to clear that task if the
1544 // activity is already running.
1545 ActivityRecord top = sourceRecord.task.performClearTaskLocked(r, launchFlags);
1546 keepCurTransition = true;
1547 if (top != null) {
1548 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1549 top.deliverNewIntentLocked(callingUid, r.intent);
1550 // For paranoia, make sure we have correctly
1551 // resumed the top activity.
1552 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001553 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001554 targetStack.resumeTopActivityLocked(null);
1555 }
1556 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001557 if (r.task == null) Slog.v(TAG,
1558 "startActivityUncheckedLocked: task left null",
1559 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001560 return ActivityManager.START_DELIVERED_TO_TOP;
1561 }
1562 } else if (!addingToTask &&
1563 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1564 // In this case, we are launching an activity in our own task
1565 // that may already be running somewhere in the history, and
1566 // we want to shuffle it to the front of the stack if so.
1567 final ActivityRecord top =
1568 targetStack.findActivityInHistoryLocked(r, sourceRecord.task);
1569 if (top != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001570 final TaskRecord task = top.task;
1571 task.moveActivityToFrontLocked(top);
1572 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001573 top.updateOptionsLocked(options);
1574 top.deliverNewIntentLocked(callingUid, r.intent);
1575 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001576 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001577 targetStack.resumeTopActivityLocked(null);
1578 }
Craig Mautner29219d92013-04-16 20:19:12 -07001579 if (r.task == null) Slog.v(TAG,
1580 "startActivityUncheckedLocked: task left null",
1581 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001582 return ActivityManager.START_DELIVERED_TO_TOP;
1583 }
1584 }
1585 // An existing activity is starting this new activity, so we want
1586 // to keep the new one in the same task as the one that is starting
1587 // it.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001588 r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001589 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1590 + " in existing task " + r.task);
1591
1592 } else {
1593 // This not being started from an existing activity, and not part
1594 // of a new task... just put it in the top task, though these days
1595 // this case should never happen.
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001596 ActivityStack lastStack = getLastStack();
1597 targetStack = lastStack != null ? lastStack : mHomeStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001598 moveHomeStack(targetStack.isHomeStack());
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001599 ActivityRecord prev = lastStack == null ? null : targetStack.topActivity();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001600 r.setTask(prev != null ? prev.task
1601 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1602 null, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001603 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1604 + " in new guessed " + r.task);
1605 }
1606
1607 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1608 intent, r.getUriPermissionsLocked());
1609
1610 if (newTask) {
1611 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1612 }
1613 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001614 setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001615 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
1616 return ActivityManager.START_SUCCESS;
1617 }
1618
Craig Mautnerf3333272013-04-22 10:55:53 -07001619 // Checked.
1620 final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
1621 Configuration config) {
1622 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
1623
1624 ActivityRecord res = null;
1625
1626 ArrayList<ActivityRecord> stops = null;
1627 ArrayList<ActivityRecord> finishes = null;
1628 ArrayList<UserStartedState> startingUsers = null;
1629 int NS = 0;
1630 int NF = 0;
1631 IApplicationThread sendThumbnail = null;
1632 boolean booting = false;
1633 boolean enableScreen = false;
1634 boolean activityRemoved = false;
1635
1636 ActivityRecord r = ActivityRecord.forToken(token);
1637 if (r != null) {
1638 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
1639 r.finishLaunchTickingLocked();
1640 res = r.task.stack.activityIdleInternalLocked(token, fromTimeout, config);
1641 if (res != null) {
1642 if (fromTimeout) {
1643 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
1644 }
1645
1646 // This is a hack to semi-deal with a race condition
1647 // in the client where it can be constructed with a
1648 // newer configuration from when we asked it to launch.
1649 // We'll update with whatever configuration it now says
1650 // it used to launch.
1651 if (config != null) {
1652 r.configuration = config;
1653 }
1654
1655 // We are now idle. If someone is waiting for a thumbnail from
1656 // us, we can now deliver.
1657 r.idle = true;
1658 if (allResumedActivitiesIdle()) {
1659 mService.scheduleAppGcsLocked();
1660 }
1661 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
1662 sendThumbnail = r.app.thread;
1663 r.thumbnailNeeded = false;
1664 }
1665
1666 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
1667 if (!mService.mBooted && isFrontStack(r.task.stack)) {
1668 mService.mBooted = true;
1669 enableScreen = true;
1670 }
1671 } else if (fromTimeout) {
1672 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
1673 }
1674 }
1675
1676 // Atomically retrieve all of the other things to do.
1677 stops = processStoppingActivitiesLocked(true);
1678 NS = stops != null ? stops.size() : 0;
1679 if ((NF=mFinishingActivities.size()) > 0) {
1680 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
1681 mFinishingActivities.clear();
1682 }
1683
1684 final ArrayList<ActivityRecord> thumbnails;
1685 final int NT = mCancelledThumbnails.size();
1686 if (NT > 0) {
1687 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
1688 mCancelledThumbnails.clear();
1689 } else {
1690 thumbnails = null;
1691 }
1692
1693 if (isFrontStack(mHomeStack)) {
1694 booting = mService.mBooting;
1695 mService.mBooting = false;
1696 }
1697
1698 if (mStartingUsers.size() > 0) {
1699 startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
1700 mStartingUsers.clear();
1701 }
1702
1703 // Perform the following actions from unsynchronized state.
1704 final IApplicationThread thumbnailThread = sendThumbnail;
1705 mHandler.post(new Runnable() {
1706 @Override
1707 public void run() {
1708 if (thumbnailThread != null) {
1709 try {
1710 thumbnailThread.requestThumbnail(token);
1711 } catch (Exception e) {
1712 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
1713 mService.sendPendingThumbnail(null, token, null, null, true);
1714 }
1715 }
1716
1717 // Report back to any thumbnail receivers.
1718 for (int i = 0; i < NT; i++) {
1719 ActivityRecord r = thumbnails.get(i);
1720 mService.sendPendingThumbnail(r, null, null, null, true);
1721 }
1722 }
1723 });
1724
1725 // Stop any activities that are scheduled to do so but have been
1726 // waiting for the next one to start.
1727 for (int i = 0; i < NS; i++) {
1728 r = stops.get(i);
1729 final ActivityStack stack = r.task.stack;
1730 if (r.finishing) {
1731 stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
1732 } else {
1733 stack.stopActivityLocked(r);
1734 }
1735 }
1736
1737 // Finish any activities that are scheduled to do so but have been
1738 // waiting for the next one to start.
1739 for (int i = 0; i < NF; i++) {
1740 r = finishes.get(i);
1741 activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle");
1742 }
1743
1744 if (booting) {
1745 mService.finishBooting();
1746 } else if (startingUsers != null) {
1747 for (int i = 0; i < startingUsers.size(); i++) {
1748 mService.finishUserSwitch(startingUsers.get(i));
1749 }
1750 }
1751
1752 mService.trimApplications();
1753 //dump();
1754 //mWindowManager.dump();
1755
1756 if (enableScreen) {
1757 mService.enableScreenAfterBoot();
1758 }
1759
1760 if (activityRemoved) {
1761 getFocusedStack().resumeTopActivityLocked(null);
1762 }
1763
1764 return res;
1765 }
1766
Craig Mautner8d341ef2013-03-26 09:03:27 -07001767 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
1768 // Just in case.
1769 final int numStacks = mStacks.size();
1770 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Craig Mautnere79d42682013-04-01 19:01:53 -07001771 mStacks.get(stackNdx).handleAppDiedLocked(app, restarting);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001772 }
1773 }
1774
1775 void closeSystemDialogsLocked() {
1776 final int numStacks = mStacks.size();
1777 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1778 final ActivityStack stack = mStacks.get(stackNdx);
1779 stack.closeSystemDialogsLocked();
1780 }
1781 }
1782
1783 /**
1784 * @return true if some activity was finished (or would have finished if doit were true).
1785 */
1786 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1787 boolean didSomething = false;
1788 final int numStacks = mStacks.size();
1789 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1790 final ActivityStack stack = mStacks.get(stackNdx);
1791 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1792 didSomething = true;
1793 }
1794 }
1795 return didSomething;
1796 }
1797
Craig Mautner858d8a62013-04-23 17:08:34 -07001798 void resumeTopActivitiesLocked() {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -07001799 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001800 final ActivityStack stack = mStacks.get(stackNdx);
1801 if (isFrontStack(stack)) {
1802 stack.resumeTopActivityLocked(null);
1803 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001804 }
1805 }
1806
1807 void finishTopRunningActivityLocked(ProcessRecord app) {
1808 final int numStacks = mStacks.size();
1809 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1810 final ActivityStack stack = mStacks.get(stackNdx);
1811 stack.finishTopRunningActivityLocked(app);
1812 }
1813 }
1814
Craig Mautner8d341ef2013-03-26 09:03:27 -07001815 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
1816 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1817 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
1818 return;
1819 }
1820 }
1821 }
1822
Craig Mautner967212c2013-04-13 21:10:58 -07001823 ActivityStack getStack(int stackId) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001824 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1825 final ActivityStack stack = mStacks.get(stackNdx);
1826 if (stack.getStackId() == stackId) {
1827 return stack;
1828 }
1829 }
1830 return null;
1831 }
1832
Craig Mautner967212c2013-04-13 21:10:58 -07001833 ArrayList<ActivityStack> getStacks() {
1834 return new ArrayList<ActivityStack>(mStacks);
1835 }
1836
1837 int createStack() {
Craig Mautner858d8a62013-04-23 17:08:34 -07001838 while (true) {
1839 if (++mLastStackId <= HOME_STACK_ID) {
1840 mLastStackId = HOME_STACK_ID + 1;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001841 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001842 if (getStack(mLastStackId) == null) {
1843 break;
1844 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001845 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001846 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
1847 return mLastStackId;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001848 }
1849
1850 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
1851 final ActivityStack stack = getStack(stackId);
1852 if (stack == null) {
1853 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
1854 return;
1855 }
1856 stack.moveTask(taskId, toTop);
Craig Mautner967212c2013-04-13 21:10:58 -07001857 stack.resumeTopActivityLocked(null);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001858 }
1859
Craig Mautner8849a5e2013-04-02 16:41:03 -07001860 ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
1861 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1862 final ActivityRecord ar = mStacks.get(stackNdx).findTaskLocked(intent, info);
1863 if (ar != null) {
1864 return ar;
1865 }
1866 }
1867 return null;
1868 }
1869
1870 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
1871 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1872 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
1873 if (ar != null) {
1874 return ar;
1875 }
1876 }
1877 return null;
1878 }
1879
Craig Mautner8d341ef2013-03-26 09:03:27 -07001880 void goingToSleepLocked() {
1881 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1882 mStacks.get(stackNdx).stopIfSleepingLocked();
1883 }
1884 }
1885
1886 boolean shutdownLocked(int timeout) {
1887 boolean timedout = false;
1888 final int numStacks = mStacks.size();
1889 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1890 final ActivityStack stack = mStacks.get(stackNdx);
1891 if (stack.mResumedActivity != null) {
1892 stack.stopIfSleepingLocked();
1893 final long endTime = System.currentTimeMillis() + timeout;
1894 while (stack.mResumedActivity != null || stack.mPausingActivity != null) {
1895 long delay = endTime - System.currentTimeMillis();
1896 if (delay <= 0) {
1897 Slog.w(TAG, "Activity manager shutdown timed out");
1898 timedout = true;
1899 break;
1900 }
1901 try {
1902 mService.wait();
1903 } catch (InterruptedException e) {
1904 }
1905 }
1906 }
1907 }
1908 return timedout;
1909 }
1910
1911 void comeOutOfSleepIfNeededLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001912 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001913 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001914 stack.awakeFromSleepingLocked();
1915 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001916 stack.resumeTopActivityLocked(null);
1917 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001918 }
1919 }
1920
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001921 boolean reportResumedActivityLocked(ActivityRecord r) {
1922 final ActivityStack stack = r.task.stack;
1923 if (isFrontStack(stack)) {
1924 mService.reportResumedActivityLocked(r);
1925 mService.setFocusedActivityLocked(r);
1926 }
1927 if (allResumedActivitiesComplete()) {
1928 ensureActivitiesVisibleLocked(null, 0);
1929 mWindowManager.executeAppTransition();
1930 return true;
1931 }
1932 return false;
1933 }
1934
Craig Mautner8d341ef2013-03-26 09:03:27 -07001935 void handleAppCrashLocked(ProcessRecord app) {
1936 final int numStacks = mStacks.size();
1937 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1938 final ActivityStack stack = mStacks.get(stackNdx);
1939 stack.handleAppCrashLocked(app);
1940 }
1941 }
1942
Craig Mautnerde4ef022013-04-07 19:01:33 -07001943 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
1944 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1945 mStacks.get(stackNdx).ensureActivitiesVisibleLocked(starting, configChanges);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001946 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001947 }
1948
1949 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
1950 final int numStacks = mStacks.size();
1951 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1952 final ActivityStack stack = mStacks.get(stackNdx);
1953 stack.scheduleDestroyActivities(app, false, reason);
1954 }
1955 }
1956
1957 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner858d8a62013-04-23 17:08:34 -07001958 mUserStates.put(mCurrentUser, new UserState());
Craig Mautner2420ead2013-04-01 17:13:20 -07001959 mCurrentUser = userId;
Craig Mautner858d8a62013-04-23 17:08:34 -07001960 UserState userState = mUserStates.get(userId);
1961 if (userState != null) {
1962 userState.restore();
1963 mUserStates.delete(userId);
1964 } else {
1965 mFocusedStack = null;
1966 mStackState = STACK_STATE_HOME_IN_FRONT;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001967 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001968
1969 mStartingUsers.add(uss);
1970 boolean haveActivities = mHomeStack.switchUserLocked(userId, uss);
1971
1972 resumeTopActivitiesLocked();
1973
Craig Mautner8d341ef2013-03-26 09:03:27 -07001974 return haveActivities;
Craig Mautner2219a1b2013-03-25 09:44:30 -07001975 }
1976
Craig Mautnerde4ef022013-04-07 19:01:33 -07001977 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
1978 int N = mStoppingActivities.size();
1979 if (N <= 0) return null;
1980
1981 ArrayList<ActivityRecord> stops = null;
1982
1983 final boolean nowVisible = allResumedActivitiesVisible();
1984 for (int i=0; i<N; i++) {
1985 ActivityRecord s = mStoppingActivities.get(i);
1986 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
1987 + nowVisible + " waitingVisible=" + s.waitingVisible
1988 + " finishing=" + s.finishing);
1989 if (s.waitingVisible && nowVisible) {
1990 mWaitingVisibleActivities.remove(s);
1991 s.waitingVisible = false;
1992 if (s.finishing) {
1993 // If this activity is finishing, it is sitting on top of
1994 // everyone else but we now know it is no longer needed...
1995 // so get rid of it. Otherwise, we need to go through the
1996 // normal flow and hide it once we determine that it is
1997 // hidden by the activities in front of it.
1998 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001999 mWindowManager.setAppVisibility(s.appToken, false);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002000 }
2001 }
2002 if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
2003 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
2004 if (stops == null) {
2005 stops = new ArrayList<ActivityRecord>();
2006 }
2007 stops.add(s);
2008 mStoppingActivities.remove(i);
2009 N--;
2010 i--;
2011 }
2012 }
2013
2014 return stops;
2015 }
2016
Craig Mautnercf910b02013-04-23 11:23:27 -07002017 void validateTopActivitiesLocked() {
2018 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2019 final ActivityStack stack = mStacks.get(stackNdx);
2020 final ActivityRecord r = stack.topRunningActivityLocked(null);
2021 if (isFrontStack(stack)) {
2022 if (r == null) {
2023 Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
2024 } else {
2025 if (stack.mPausingActivity != null) {
2026 Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
2027 " state=" + r.state);
2028 }
2029 if (r.state != ActivityState.INITIALIZING &&
2030 r.state != ActivityState.RESUMED) {
2031 Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
2032 " state=" + r.state);
2033 }
2034 }
2035 } else {
2036 if (stack.mResumedActivity != null) {
2037 Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
2038 " state=" + r.state);
2039 }
2040 if (r != null && (r.state == ActivityState.INITIALIZING
2041 || r.state == ActivityState.RESUMED)) {
2042 Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
2043 " state=" + r.state);
2044 }
2045 }
2046 }
2047 }
2048
Craig Mautner27084302013-03-25 08:05:25 -07002049 public void dump(PrintWriter pw, String prefix) {
2050 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
2051 pw.println(mDismissKeyguardOnNextActivity);
2052 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002053
Craig Mautner20e72272013-04-01 13:45:53 -07002054 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002055 return getFocusedStack().getDumpActivitiesLocked(name);
Craig Mautner20e72272013-04-01 13:45:53 -07002056 }
2057
Craig Mautner8d341ef2013-03-26 09:03:27 -07002058 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
2059 boolean dumpClient, String dumpPackage) {
2060 final int numStacks = mStacks.size();
2061 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2062 final ActivityStack stack = mStacks.get(stackNdx);
2063 pw.print(" Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
2064 stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
2065 pw.println(" ");
2066 pw.println(" Running activities (most recent first):");
2067 dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false,
2068 dumpPackage);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002069 if (stack.mGoingToSleepActivities.size() > 0) {
2070 pw.println(" ");
2071 pw.println(" Activities waiting to sleep:");
2072 dumpHistoryList(fd, pw, stack.mGoingToSleepActivities, " ", "Sleep", false,
2073 !dumpAll, false, dumpPackage);
2074 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002075
Craig Mautner8d341ef2013-03-26 09:03:27 -07002076 pw.print(" Stack #"); pw.println(mStacks.indexOf(stack));
2077 if (stack.mPausingActivity != null) {
2078 pw.println(" mPausingActivity: " + stack.mPausingActivity);
2079 }
2080 pw.println(" mResumedActivity: " + stack.mResumedActivity);
2081 if (dumpAll) {
2082 pw.println(" mLastPausedActivity: " + stack.mLastPausedActivity);
2083 pw.println(" mSleepTimeout: " + stack.mSleepTimeout);
2084 }
2085 }
2086
Craig Mautnerf3333272013-04-22 10:55:53 -07002087 if (mFinishingActivities.size() > 0) {
2088 pw.println(" ");
2089 pw.println(" Activities waiting to finish:");
2090 dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll, false,
2091 dumpPackage);
2092 }
2093
Craig Mautnerde4ef022013-04-07 19:01:33 -07002094 if (mStoppingActivities.size() > 0) {
2095 pw.println(" ");
2096 pw.println(" Activities waiting to stop:");
2097 dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, false,
2098 dumpPackage);
2099 }
2100
2101 if (mWaitingVisibleActivities.size() > 0) {
2102 pw.println(" ");
2103 pw.println(" Activities waiting for another to become visible:");
2104 dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
2105 false, dumpPackage);
2106 }
2107
Craig Mautner8d341ef2013-03-26 09:03:27 -07002108 if (dumpAll) {
2109 pw.println(" ");
2110 pw.println(" mCurTaskId: " + mCurTaskId);
2111 }
2112 return true;
2113 }
2114
2115 static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
2116 String prefix, String label, boolean complete, boolean brief, boolean client,
2117 String dumpPackage) {
2118 TaskRecord lastTask = null;
2119 boolean needNL = false;
2120 final String innerPrefix = prefix + " ";
2121 final String[] args = new String[0];
2122 for (int i=list.size()-1; i>=0; i--) {
2123 final ActivityRecord r = list.get(i);
2124 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
2125 continue;
2126 }
2127 final boolean full = !brief && (complete || !r.isInHistory());
2128 if (needNL) {
2129 pw.println(" ");
2130 needNL = false;
2131 }
2132 if (lastTask != r.task) {
2133 lastTask = r.task;
2134 pw.print(prefix);
2135 pw.print(full ? "* " : " ");
2136 pw.println(lastTask);
2137 if (full) {
2138 lastTask.dump(pw, prefix + " ");
2139 } else if (complete) {
2140 // Complete + brief == give a summary. Isn't that obvious?!?
2141 if (lastTask.intent != null) {
2142 pw.print(prefix); pw.print(" ");
2143 pw.println(lastTask.intent.toInsecureStringWithClip());
2144 }
2145 }
2146 }
2147 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
2148 pw.print(" #"); pw.print(i); pw.print(": ");
2149 pw.println(r);
2150 if (full) {
2151 r.dump(pw, innerPrefix);
2152 } else if (complete) {
2153 // Complete + brief == give a summary. Isn't that obvious?!?
2154 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
2155 if (r.app != null) {
2156 pw.print(innerPrefix); pw.println(r.app);
2157 }
2158 }
2159 if (client && r.app != null && r.app.thread != null) {
2160 // flush anything that is already in the PrintWriter since the thread is going
2161 // to write to the file descriptor directly
2162 pw.flush();
2163 try {
2164 TransferPipe tp = new TransferPipe();
2165 try {
2166 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
2167 r.appToken, innerPrefix, args);
2168 // Short timeout, since blocking here can
2169 // deadlock with the application.
2170 tp.go(fd, 2000);
2171 } finally {
2172 tp.kill();
2173 }
2174 } catch (IOException e) {
2175 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
2176 } catch (RemoteException e) {
2177 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
2178 }
2179 needNL = true;
2180 }
2181 }
2182 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002183
Craig Mautnerf3333272013-04-22 10:55:53 -07002184 void scheduleIdleTimeoutLocked(ActivityRecord next) {
Craig Mautnerc64f73e2013-04-24 16:44:56 -07002185 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
2186 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
Craig Mautnerf3333272013-04-22 10:55:53 -07002187 }
2188
2189 final void scheduleIdleLocked() {
2190 mHandler.obtainMessage(IDLE_NOW_MSG).sendToTarget();
2191 }
2192
2193 void removeTimeoutsForActivityLocked(ActivityRecord r) {
2194 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
2195 }
2196
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002197 private final class ActivityStackSupervisorHandler extends Handler {
Craig Mautnerf3333272013-04-22 10:55:53 -07002198
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002199 public ActivityStackSupervisorHandler(Looper looper) {
2200 super(looper);
2201 }
2202
Craig Mautnerf3333272013-04-22 10:55:53 -07002203 void activityIdleInternal(ActivityRecord r) {
2204 synchronized (mService) {
2205 activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
2206 }
2207 }
2208
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002209 @Override
2210 public void handleMessage(Message msg) {
2211 switch (msg.what) {
Craig Mautnerf3333272013-04-22 10:55:53 -07002212 case IDLE_TIMEOUT_MSG: {
2213 if (mService.mDidDexOpt) {
2214 mService.mDidDexOpt = false;
2215 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2216 nmsg.obj = msg.obj;
2217 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
2218 return;
2219 }
2220 // We don't at this point know if the activity is fullscreen,
2221 // so we need to be conservative and assume it isn't.
2222 activityIdleInternal((ActivityRecord)msg.obj);
2223 } break;
2224 case IDLE_NOW_MSG: {
2225 activityIdleInternal((ActivityRecord)msg.obj);
2226 } break;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002227 }
2228 }
2229 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002230
2231 private final class UserState {
2232 final ActivityStack mSavedFocusedStack;
2233 final int mSavedStackState;
2234
2235 public UserState() {
2236 ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2237 mSavedFocusedStack = supervisor.mFocusedStack;
2238 mSavedStackState = supervisor.mStackState;
2239 }
2240
2241 void restore() {
2242 ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2243 supervisor.mFocusedStack = mSavedFocusedStack;
2244 supervisor.mStackState = mSavedStackState;
2245 }
2246 }
Craig Mautner27084302013-03-25 08:05:25 -07002247}