blob: 60b7061f271e20ca78c490c38d371beef7c0d7e3 [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 Mautner05d29032013-05-03 13:40:13 -070029import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
Craig Mautner8d341ef2013-03-26 09:03:27 -070030import static com.android.server.am.ActivityManagerService.TAG;
31
Craig Mautner2420ead2013-04-01 17:13:20 -070032import android.app.Activity;
Craig Mautner23ac33b2013-04-01 16:26:35 -070033import android.app.ActivityManager;
34import android.app.ActivityOptions;
35import android.app.AppGlobals;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070036import android.app.IActivityManager;
Craig Mautner23ac33b2013-04-01 16:26:35 -070037import android.app.IApplicationThread;
Craig Mautner20e72272013-04-01 13:45:53 -070038import android.app.IThumbnailReceiver;
Craig Mautner23ac33b2013-04-01 16:26:35 -070039import android.app.PendingIntent;
Craig Mautner20e72272013-04-01 13:45:53 -070040import android.app.ActivityManager.RunningTaskInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070041import android.app.IActivityManager.WaitResult;
Craig Mautner2420ead2013-04-01 17:13:20 -070042import android.app.ResultInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070043import android.content.ComponentName;
Craig Mautner2219a1b2013-03-25 09:44:30 -070044import android.content.Context;
Craig Mautner23ac33b2013-04-01 16:26:35 -070045import android.content.IIntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070046import android.content.Intent;
Craig Mautner23ac33b2013-04-01 16:26:35 -070047import android.content.IntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070048import android.content.pm.ActivityInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070049import android.content.pm.ApplicationInfo;
50import android.content.pm.PackageManager;
51import android.content.pm.ResolveInfo;
52import android.content.res.Configuration;
53import android.os.Binder;
Craig Mautner8d341ef2013-03-26 09:03:27 -070054import android.os.Bundle;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070055import android.os.Handler;
Craig Mautner23ac33b2013-04-01 16:26:35 -070056import android.os.IBinder;
Craig Mautner2219a1b2013-03-25 09:44:30 -070057import android.os.Looper;
Craig Mautner2420ead2013-04-01 17:13:20 -070058import android.os.Message;
Craig Mautner23ac33b2013-04-01 16:26:35 -070059import android.os.ParcelFileDescriptor;
Craig Mautner8d341ef2013-03-26 09:03:27 -070060import android.os.RemoteException;
Craig Mautner23ac33b2013-04-01 16:26:35 -070061import android.os.SystemClock;
Craig Mautner6170f732013-04-02 13:05:23 -070062import android.os.UserHandle;
Craig Mautner2420ead2013-04-01 17:13:20 -070063import android.util.EventLog;
Craig Mautner8d341ef2013-03-26 09:03:27 -070064import android.util.Slog;
Craig Mautner858d8a62013-04-23 17:08:34 -070065import android.util.SparseArray;
Craig Mautner2219a1b2013-03-25 09:44:30 -070066
Craig Mautner23ac33b2013-04-01 16:26:35 -070067import com.android.internal.app.HeavyWeightSwitcherActivity;
Craig Mautner6170f732013-04-02 13:05:23 -070068import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
Craig Mautner2420ead2013-04-01 17:13:20 -070069import com.android.server.am.ActivityStack.ActivityState;
Craig Mautnerde4ef022013-04-07 19:01:33 -070070import com.android.server.wm.StackBox;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070071import com.android.server.wm.WindowManagerService;
Craig Mautner23ac33b2013-04-01 16:26:35 -070072
Craig Mautner8d341ef2013-03-26 09:03:27 -070073import java.io.FileDescriptor;
74import java.io.IOException;
Craig Mautner27084302013-03-25 08:05:25 -070075import java.io.PrintWriter;
Craig Mautner2219a1b2013-03-25 09:44:30 -070076import java.util.ArrayList;
Craig Mautner8d341ef2013-03-26 09:03:27 -070077import java.util.List;
Craig Mautner27084302013-03-25 08:05:25 -070078
79public class ActivityStackSupervisor {
Craig Mautnera9a3fb12013-04-18 10:01:00 -070080 static final boolean DEBUG_STACK = ActivityManagerService.DEBUG_STACK;
81
Craig Mautnerde4ef022013-04-07 19:01:33 -070082 static final boolean DEBUG = ActivityManagerService.DEBUG || false;
83 static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
84 static final boolean DEBUG_APP = DEBUG || false;
85 static final boolean DEBUG_SAVED_STATE = DEBUG || false;
86 static final boolean DEBUG_STATES = DEBUG || false;
Craig Mautner2420ead2013-04-01 17:13:20 -070087
Craig Mautner2219a1b2013-03-25 09:44:30 -070088 public static final int HOME_STACK_ID = 0;
Craig Mautner27084302013-03-25 08:05:25 -070089
Craig Mautnerf3333272013-04-22 10:55:53 -070090 /** How long we wait until giving up on the last activity telling us it is idle. */
91 static final int IDLE_TIMEOUT = 10*1000;
92
Craig Mautner05d29032013-05-03 13:40:13 -070093 static final int IDLE_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG;
94 static final int IDLE_NOW_MSG = FIRST_SUPERVISOR_STACK_MSG + 1;
95 static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2;
Craig Mautnerf3333272013-04-22 10:55:53 -070096
Craig Mautner27084302013-03-25 08:05:25 -070097 final ActivityManagerService mService;
Craig Mautner2219a1b2013-03-25 09:44:30 -070098 final Context mContext;
99 final Looper mLooper;
Craig Mautner27084302013-03-25 08:05:25 -0700100
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700101 final ActivityStackSupervisorHandler mHandler;
102
103 /** Short cut */
104 WindowManagerService mWindowManager;
105
Craig Mautner27084302013-03-25 08:05:25 -0700106 /** Dismiss the keyguard after the next activity is displayed? */
107 private boolean mDismissKeyguardOnNextActivity = false;
108
Craig Mautner8d341ef2013-03-26 09:03:27 -0700109 /** Identifier counter for all ActivityStacks */
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700110 private int mLastStackId = HOME_STACK_ID;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700111
112 /** Task identifier that activities are currently being started in. Incremented each time a
113 * new task is created. */
114 private int mCurTaskId = 0;
115
Craig Mautner2420ead2013-04-01 17:13:20 -0700116 /** The current user */
117 private int mCurrentUser;
118
Craig Mautner8d341ef2013-03-26 09:03:27 -0700119 /** The stack containing the launcher app */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700120 private ActivityStack mHomeStack;
Craig Mautner20e72272013-04-01 13:45:53 -0700121
Craig Mautnerde4ef022013-04-07 19:01:33 -0700122 /** The non-home stack currently receiving input or launching the next activity. If home is
Craig Mautner29219d92013-04-16 20:19:12 -0700123 * in front then mHomeStack overrides mFocusedStack. */
124 private ActivityStack mFocusedStack;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700125
126 /** All the non-launcher stacks */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700127 private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
128
Craig Mautnerde4ef022013-04-07 19:01:33 -0700129 private static final int STACK_STATE_HOME_IN_FRONT = 0;
130 private static final int STACK_STATE_HOME_TO_BACK = 1;
131 private static final int STACK_STATE_HOME_IN_BACK = 2;
132 private static final int STACK_STATE_HOME_TO_FRONT = 3;
133 private int mStackState = STACK_STATE_HOME_IN_FRONT;
134
135 /** List of activities that are waiting for a new activity to become visible before completing
136 * whatever operation they are supposed to do. */
137 final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();
138
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700139 /** List of processes waiting to find out about the next visible activity. */
140 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible =
141 new ArrayList<IActivityManager.WaitResult>();
142
143 /** List of processes waiting to find out about the next launched activity. */
144 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched =
145 new ArrayList<IActivityManager.WaitResult>();
146
Craig Mautnerde4ef022013-04-07 19:01:33 -0700147 /** List of activities that are ready to be stopped, but waiting for the next activity to
148 * settle down before doing so. */
149 final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();
150
Craig Mautnerf3333272013-04-22 10:55:53 -0700151 /** List of activities that are ready to be finished, but waiting for the previous activity to
152 * settle down before doing so. It contains ActivityRecord objects. */
153 final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<ActivityRecord>();
154
155 /** List of ActivityRecord objects that have been finished and must still report back to a
156 * pending thumbnail receiver. */
157 final ArrayList<ActivityRecord> mCancelledThumbnails = new ArrayList<ActivityRecord>();
158
159 /** Used on user changes */
160 final ArrayList<UserStartedState> mStartingUsers = new ArrayList<UserStartedState>();
161
Craig Mautnerde4ef022013-04-07 19:01:33 -0700162 /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity
163 * is being brought in front of us. */
164 boolean mUserLeaving = false;
165
Craig Mautner858d8a62013-04-23 17:08:34 -0700166 /** Stacks belonging to users other than mCurrentUser. Indexed by userId. */
167 final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
168
Craig Mautner2219a1b2013-03-25 09:44:30 -0700169 public ActivityStackSupervisor(ActivityManagerService service, Context context,
170 Looper looper) {
Craig Mautner27084302013-03-25 08:05:25 -0700171 mService = service;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700172 mContext = context;
173 mLooper = looper;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700174 mHandler = new ActivityStackSupervisorHandler(looper);
Craig Mautner2219a1b2013-03-25 09:44:30 -0700175 }
176
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700177 void setWindowManager(WindowManagerService wm) {
178 mWindowManager = wm;
179 mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700180 mStacks.add(mHomeStack);
Craig Mautner27084302013-03-25 08:05:25 -0700181 }
182
183 void dismissKeyguard() {
184 if (mDismissKeyguardOnNextActivity) {
185 mDismissKeyguardOnNextActivity = false;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700186 mWindowManager.dismissKeyguard();
Craig Mautner27084302013-03-25 08:05:25 -0700187 }
188 }
189
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700190 ActivityStack getFocusedStack() {
Craig Mautnerf88c50f2013-04-18 19:25:12 -0700191 if (mFocusedStack == null) {
192 return mHomeStack;
193 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700194 switch (mStackState) {
195 case STACK_STATE_HOME_IN_FRONT:
196 case STACK_STATE_HOME_TO_FRONT:
197 return mHomeStack;
198 case STACK_STATE_HOME_IN_BACK:
199 case STACK_STATE_HOME_TO_BACK:
200 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700201 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700202 }
Craig Mautner20e72272013-04-01 13:45:53 -0700203 }
204
Craig Mautnerde4ef022013-04-07 19:01:33 -0700205 ActivityStack getLastStack() {
206 switch (mStackState) {
207 case STACK_STATE_HOME_IN_FRONT:
208 case STACK_STATE_HOME_TO_BACK:
209 return mHomeStack;
210 case STACK_STATE_HOME_TO_FRONT:
211 case STACK_STATE_HOME_IN_BACK:
212 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700213 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700214 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700215 }
216
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700217 boolean isFocusedStack(ActivityStack stack) {
218 return getFocusedStack() == stack;
219 }
220
Craig Mautnerde4ef022013-04-07 19:01:33 -0700221 boolean isFrontStack(ActivityStack stack) {
Craig Mautner858d8a62013-04-23 17:08:34 -0700222 if (stack.mCurrentUser != mCurrentUser) {
223 return false;
224 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700225 return !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
Craig Mautner20e72272013-04-01 13:45:53 -0700226 }
227
Craig Mautnerde4ef022013-04-07 19:01:33 -0700228 void moveHomeStack(boolean toFront) {
229 final boolean homeInFront = isFrontStack(mHomeStack);
230 if (homeInFront ^ toFront) {
231 mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
232 }
233 }
234
Craig Mautner69ada552013-04-18 13:51:51 -0700235 boolean resumeHomeActivity(ActivityRecord prev) {
236 moveHomeStack(true);
237 if (prev != null) {
238 prev.mLaunchHomeTaskNext = false;
239 }
240 if (mHomeStack.topRunningActivityLocked(null) != null) {
Craig Mautner05d29032013-05-03 13:40:13 -0700241 return resumeTopActivitiesLocked(mHomeStack, prev, null);
Craig Mautner69ada552013-04-18 13:51:51 -0700242 }
243 return mService.startHomeActivityLocked(mCurrentUser);
244 }
245
Craig Mautnerde4ef022013-04-07 19:01:33 -0700246 final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r,
247 ActivityStack stack) {
248 if (stack == mHomeStack) {
249 return;
250 }
251 if ((sourceRecord == null && getLastStack() == mHomeStack) ||
252 (sourceRecord != null && sourceRecord.isHomeActivity)) {
253 if (r == null) {
254 r = stack.topRunningActivityLocked(null);
255 }
256 if (r != null && !r.isHomeActivity && r.isRootActivity()) {
257 r.mLaunchHomeTaskNext = true;
258 }
259 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700260 }
261
Craig Mautner27084302013-03-25 08:05:25 -0700262 void setDismissKeyguard(boolean dismiss) {
263 mDismissKeyguardOnNextActivity = dismiss;
264 }
265
Craig Mautner8d341ef2013-03-26 09:03:27 -0700266 TaskRecord anyTaskForIdLocked(int id) {
267 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
268 ActivityStack stack = mStacks.get(stackNdx);
269 TaskRecord task = stack.taskForIdLocked(id);
270 if (task != null) {
271 return task;
272 }
273 }
274 return null;
275 }
276
Craig Mautner6170f732013-04-02 13:05:23 -0700277 ActivityRecord isInAnyStackLocked(IBinder token) {
278 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
279 final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
280 if (r != null) {
281 return r;
282 }
283 }
284 return null;
285 }
286
Craig Mautner8d341ef2013-03-26 09:03:27 -0700287 int getNextTaskId() {
288 do {
289 mCurTaskId++;
290 if (mCurTaskId <= 0) {
291 mCurTaskId = 1;
292 }
293 } while (anyTaskForIdLocked(mCurTaskId) != null);
294 return mCurTaskId;
295 }
296
Craig Mautnerde4ef022013-04-07 19:01:33 -0700297 void removeTask(TaskRecord task) {
298 final ActivityStack stack = task.stack;
299 if (stack.removeTask(task) && !stack.isHomeStack()) {
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700300 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700301 mStacks.remove(stack);
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700302 final int stackId = stack.mStackId;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700303 final int nextStackId = mWindowManager.removeStack(stackId);
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700304 // TODO: Perhaps we need to let the ActivityManager determine the next focus...
Craig Mautner29219d92013-04-16 20:19:12 -0700305 if (mFocusedStack.mStackId == stackId) {
306 mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700307 }
308 }
309 }
310
311 ActivityRecord resumedAppLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700312 ActivityStack stack = getFocusedStack();
313 if (stack == null) {
314 return null;
315 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700316 ActivityRecord resumedActivity = stack.mResumedActivity;
317 if (resumedActivity == null || resumedActivity.app == null) {
318 resumedActivity = stack.mPausingActivity;
319 if (resumedActivity == null || resumedActivity.app == null) {
320 resumedActivity = stack.topRunningActivityLocked(null);
321 }
322 }
323 return resumedActivity;
324 }
325
Craig Mautner20e72272013-04-01 13:45:53 -0700326 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
327 boolean didSomething = false;
328 final String processName = app.processName;
329 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
330 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner858d8a62013-04-23 17:08:34 -0700331 if (!isFrontStack(stack)) {
332 continue;
333 }
Craig Mautner20e72272013-04-01 13:45:53 -0700334 ActivityRecord hr = stack.topRunningActivityLocked(null);
335 if (hr != null) {
336 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
337 && processName.equals(hr.processName)) {
338 try {
339 if (headless) {
340 Slog.e(TAG, "Starting activities not supported on headless device: "
341 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700342 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700343 didSomething = true;
344 }
345 } catch (Exception e) {
346 Slog.w(TAG, "Exception in new application when starting activity "
347 + hr.intent.getComponent().flattenToShortString(), e);
348 throw e;
349 }
350 } else {
Craig Mautner580ea812013-04-25 12:58:38 -0700351 stack.ensureActivitiesVisibleLocked(hr, null, processName, 0, false);
Craig Mautner20e72272013-04-01 13:45:53 -0700352 }
353 }
354 }
355 return didSomething;
356 }
357
358 boolean allResumedActivitiesIdle() {
359 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700360 final ActivityRecord resumedActivity = mStacks.get(stackNdx).mResumedActivity;
361 if (resumedActivity == null || !resumedActivity.idle) {
Craig Mautner20e72272013-04-01 13:45:53 -0700362 return false;
363 }
364 }
365 return true;
366 }
367
Craig Mautnerde4ef022013-04-07 19:01:33 -0700368 boolean allResumedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700369 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
370 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner967212c2013-04-13 21:10:58 -0700371 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700372 final ActivityRecord r = stack.mResumedActivity;
373 if (r != null && r.state != ActivityState.RESUMED) {
374 return false;
375 }
376 }
377 }
378 // TODO: Not sure if this should check if all Paused are complete too.
379 switch (mStackState) {
380 case STACK_STATE_HOME_TO_BACK:
381 mStackState = STACK_STATE_HOME_IN_BACK;
382 break;
383 case STACK_STATE_HOME_TO_FRONT:
384 mStackState = STACK_STATE_HOME_IN_FRONT;
385 break;
386 }
387 return true;
388 }
389
390 boolean allResumedActivitiesVisible() {
391 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
392 final ActivityStack stack = mStacks.get(stackNdx);
393 final ActivityRecord r = stack.mResumedActivity;
394 if (r != null && (!r.nowVisible || r.waitingVisible)) {
395 return false;
396 }
397 }
398 return true;
399 }
400
Craig Mautnercf910b02013-04-23 11:23:27 -0700401 boolean pauseBackStacks(boolean userLeaving) {
402 boolean someActivityPaused = false;
403 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
404 final ActivityStack stack = mStacks.get(stackNdx);
405 if (!isFrontStack(stack) && stack.mResumedActivity != null) {
406 stack.startPausingLocked(userLeaving, false);
407 someActivityPaused = true;
408 }
409 }
410 return someActivityPaused;
411 }
412
Craig Mautnerde4ef022013-04-07 19:01:33 -0700413 boolean allPausedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700414 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
415 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner69ada552013-04-18 13:51:51 -0700416 final ActivityRecord r = stack.mPausingActivity;
417 if (r != null && r.state != ActivityState.PAUSED
418 && r.state != ActivityState.STOPPED
419 && r.state != ActivityState.STOPPING) {
420 return false;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700421 }
422 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700423 return true;
424 }
425
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700426 void reportActivityVisibleLocked(ActivityRecord r) {
Craig Mautner858d8a62013-04-23 17:08:34 -0700427 for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700428 WaitResult w = mWaitingActivityVisible.get(i);
429 w.timeout = false;
430 if (r != null) {
431 w.who = new ComponentName(r.info.packageName, r.info.name);
432 }
433 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
434 w.thisTime = w.totalTime;
435 }
436 mService.notifyAll();
437 dismissKeyguard();
438 }
439
440 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
441 long thisTime, long totalTime) {
442 for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
Craig Mautnerc64f73e2013-04-24 16:44:56 -0700443 WaitResult w = mWaitingActivityLaunched.remove(i);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700444 w.timeout = timeout;
445 if (r != null) {
446 w.who = new ComponentName(r.info.packageName, r.info.name);
447 }
448 w.thisTime = thisTime;
449 w.totalTime = totalTime;
450 }
451 mService.notifyAll();
452 }
453
Craig Mautner29219d92013-04-16 20:19:12 -0700454 ActivityRecord topRunningActivityLocked() {
455 ActivityRecord r = null;
456 if (mFocusedStack != null) {
457 r = mFocusedStack.topRunningActivityLocked(null);
458 if (r != null) {
459 return r;
460 }
461 }
462 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
463 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner858d8a62013-04-23 17:08:34 -0700464 if (stack.mCurrentUser != mCurrentUser) {
465 continue;
466 }
Craig Mautner29219d92013-04-16 20:19:12 -0700467 if (stack != mFocusedStack && isFrontStack(stack)) {
468 r = stack.topRunningActivityLocked(null);
469 if (r != null) {
470 return r;
471 }
472 }
473 }
474 return null;
475 }
476
Craig Mautner20e72272013-04-01 13:45:53 -0700477 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
478 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
479 ActivityRecord r = null;
480 final int numStacks = mStacks.size();
481 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
482 final ActivityStack stack = mStacks.get(stackNdx);
483 final ActivityRecord ar =
484 stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700485 if (isFrontStack(stack)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700486 r = ar;
487 }
488 }
489 return r;
490 }
491
Craig Mautner23ac33b2013-04-01 16:26:35 -0700492 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
493 String profileFile, ParcelFileDescriptor profileFd, int userId) {
494 // Collect information about the target of the Intent.
495 ActivityInfo aInfo;
496 try {
497 ResolveInfo rInfo =
498 AppGlobals.getPackageManager().resolveIntent(
499 intent, resolvedType,
500 PackageManager.MATCH_DEFAULT_ONLY
501 | ActivityManagerService.STOCK_PM_FLAGS, userId);
502 aInfo = rInfo != null ? rInfo.activityInfo : null;
503 } catch (RemoteException e) {
504 aInfo = null;
505 }
506
507 if (aInfo != null) {
508 // Store the found target back into the intent, because now that
509 // we have it we never want to do this again. For example, if the
510 // user navigates back to this point in the history, we should
511 // always restart the exact same activity.
512 intent.setComponent(new ComponentName(
513 aInfo.applicationInfo.packageName, aInfo.name));
514
515 // Don't debug things in the system process
516 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
517 if (!aInfo.processName.equals("system")) {
518 mService.setDebugApp(aInfo.processName, true, false);
519 }
520 }
521
522 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
523 if (!aInfo.processName.equals("system")) {
524 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
525 }
526 }
527
528 if (profileFile != null) {
529 if (!aInfo.processName.equals("system")) {
530 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
531 profileFile, profileFd,
532 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
533 }
534 }
535 }
536 return aInfo;
537 }
538
Craig Mautner2219a1b2013-03-25 09:44:30 -0700539 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700540 moveHomeStack(true);
Craig Mautner6170f732013-04-02 13:05:23 -0700541 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
Craig Mautner2219a1b2013-03-25 09:44:30 -0700542 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700543 }
544
Craig Mautner23ac33b2013-04-01 16:26:35 -0700545 final int startActivityMayWait(IApplicationThread caller, int callingUid,
546 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
547 String resultWho, int requestCode, int startFlags, String profileFile,
548 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
549 Bundle options, int userId) {
550 // Refuse possible leaked file descriptors
551 if (intent != null && intent.hasFileDescriptors()) {
552 throw new IllegalArgumentException("File descriptors passed in Intent");
553 }
554 boolean componentSpecified = intent.getComponent() != null;
555
556 // Don't modify the client's object!
557 intent = new Intent(intent);
558
559 // Collect information about the target of the Intent.
560 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
561 profileFile, profileFd, userId);
562
563 synchronized (mService) {
564 int callingPid;
565 if (callingUid >= 0) {
566 callingPid = -1;
567 } else if (caller == null) {
568 callingPid = Binder.getCallingPid();
569 callingUid = Binder.getCallingUid();
570 } else {
571 callingPid = callingUid = -1;
572 }
573
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700574 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -0700575 stack.mConfigWillChange = config != null
Craig Mautner23ac33b2013-04-01 16:26:35 -0700576 && mService.mConfiguration.diff(config) != 0;
577 if (DEBUG_CONFIGURATION) Slog.v(TAG,
Craig Mautnerde4ef022013-04-07 19:01:33 -0700578 "Starting activity when config will change = " + stack.mConfigWillChange);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700579
580 final long origId = Binder.clearCallingIdentity();
581
582 if (aInfo != null &&
583 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
584 // This may be a heavy-weight process! Check to see if we already
585 // have another, different heavy-weight process running.
586 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
587 if (mService.mHeavyWeightProcess != null &&
588 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
589 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
590 int realCallingPid = callingPid;
591 int realCallingUid = callingUid;
592 if (caller != null) {
593 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
594 if (callerApp != null) {
595 realCallingPid = callerApp.pid;
596 realCallingUid = callerApp.info.uid;
597 } else {
598 Slog.w(TAG, "Unable to find app for caller " + caller
599 + " (pid=" + realCallingPid + ") when starting: "
600 + intent.toString());
601 ActivityOptions.abort(options);
602 return ActivityManager.START_PERMISSION_DENIED;
603 }
604 }
605
606 IIntentSender target = mService.getIntentSenderLocked(
607 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
608 realCallingUid, userId, null, null, 0, new Intent[] { intent },
609 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
610 | PendingIntent.FLAG_ONE_SHOT, null);
611
612 Intent newIntent = new Intent();
613 if (requestCode >= 0) {
614 // Caller is requesting a result.
615 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
616 }
617 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
618 new IntentSender(target));
619 if (mService.mHeavyWeightProcess.activities.size() > 0) {
620 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
621 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
622 hist.packageName);
623 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
624 hist.task.taskId);
625 }
626 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
627 aInfo.packageName);
628 newIntent.setFlags(intent.getFlags());
629 newIntent.setClassName("android",
630 HeavyWeightSwitcherActivity.class.getName());
631 intent = newIntent;
632 resolvedType = null;
633 caller = null;
634 callingUid = Binder.getCallingUid();
635 callingPid = Binder.getCallingPid();
636 componentSpecified = true;
637 try {
638 ResolveInfo rInfo =
639 AppGlobals.getPackageManager().resolveIntent(
640 intent, null,
641 PackageManager.MATCH_DEFAULT_ONLY
642 | ActivityManagerService.STOCK_PM_FLAGS, userId);
643 aInfo = rInfo != null ? rInfo.activityInfo : null;
644 aInfo = mService.getActivityInfoForUser(aInfo, userId);
645 } catch (RemoteException e) {
646 aInfo = null;
647 }
648 }
649 }
650 }
651
Craig Mautner6170f732013-04-02 13:05:23 -0700652 int res = startActivityLocked(caller, intent, resolvedType,
Craig Mautner23ac33b2013-04-01 16:26:35 -0700653 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
654 callingPackage, startFlags, options, componentSpecified, null);
655
Craig Mautnerde4ef022013-04-07 19:01:33 -0700656 if (stack.mConfigWillChange) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700657 // If the caller also wants to switch to a new configuration,
658 // do so now. This allows a clean switch, as we are waiting
659 // for the current activity to pause (so we will not destroy
660 // it), and have not yet started the next activity.
661 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
662 "updateConfiguration()");
Craig Mautnerde4ef022013-04-07 19:01:33 -0700663 stack.mConfigWillChange = false;
Craig Mautner23ac33b2013-04-01 16:26:35 -0700664 if (DEBUG_CONFIGURATION) Slog.v(TAG,
665 "Updating to new configuration after starting activity.");
666 mService.updateConfigurationLocked(config, null, false, false);
667 }
668
669 Binder.restoreCallingIdentity(origId);
670
671 if (outResult != null) {
672 outResult.result = res;
673 if (res == ActivityManager.START_SUCCESS) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700674 mWaitingActivityLaunched.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700675 do {
676 try {
677 mService.wait();
678 } catch (InterruptedException e) {
679 }
680 } while (!outResult.timeout && outResult.who == null);
681 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700682 ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700683 if (r.nowVisible) {
684 outResult.timeout = false;
685 outResult.who = new ComponentName(r.info.packageName, r.info.name);
686 outResult.totalTime = 0;
687 outResult.thisTime = 0;
688 } else {
689 outResult.thisTime = SystemClock.uptimeMillis();
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700690 mWaitingActivityVisible.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700691 do {
692 try {
693 mService.wait();
694 } catch (InterruptedException e) {
695 }
696 } while (!outResult.timeout && outResult.who == null);
697 }
698 }
699 }
700
701 return res;
702 }
703 }
704
705 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
706 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
707 Bundle options, int userId) {
708 if (intents == null) {
709 throw new NullPointerException("intents is null");
710 }
711 if (resolvedTypes == null) {
712 throw new NullPointerException("resolvedTypes is null");
713 }
714 if (intents.length != resolvedTypes.length) {
715 throw new IllegalArgumentException("intents are length different than resolvedTypes");
716 }
717
718 ActivityRecord[] outActivity = new ActivityRecord[1];
719
720 int callingPid;
721 if (callingUid >= 0) {
722 callingPid = -1;
723 } else if (caller == null) {
724 callingPid = Binder.getCallingPid();
725 callingUid = Binder.getCallingUid();
726 } else {
727 callingPid = callingUid = -1;
728 }
729 final long origId = Binder.clearCallingIdentity();
730 try {
731 synchronized (mService) {
732
733 for (int i=0; i<intents.length; i++) {
734 Intent intent = intents[i];
735 if (intent == null) {
736 continue;
737 }
738
739 // Refuse possible leaked file descriptors
740 if (intent != null && intent.hasFileDescriptors()) {
741 throw new IllegalArgumentException("File descriptors passed in Intent");
742 }
743
744 boolean componentSpecified = intent.getComponent() != null;
745
746 // Don't modify the client's object!
747 intent = new Intent(intent);
748
749 // Collect information about the target of the Intent.
750 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
751 0, null, null, userId);
752 // TODO: New, check if this is correct
753 aInfo = mService.getActivityInfoForUser(aInfo, userId);
754
755 if (aInfo != null &&
756 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
757 != 0) {
758 throw new IllegalArgumentException(
759 "FLAG_CANT_SAVE_STATE not supported here");
760 }
761
762 Bundle theseOptions;
763 if (options != null && i == intents.length-1) {
764 theseOptions = options;
765 } else {
766 theseOptions = null;
767 }
Craig Mautner6170f732013-04-02 13:05:23 -0700768 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Craig Mautner23ac33b2013-04-01 16:26:35 -0700769 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
770 0, theseOptions, componentSpecified, outActivity);
771 if (res < 0) {
772 return res;
773 }
774
775 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
776 }
777 }
778 } finally {
779 Binder.restoreCallingIdentity(origId);
780 }
781
782 return ActivityManager.START_SUCCESS;
783 }
784
Craig Mautner2420ead2013-04-01 17:13:20 -0700785 final boolean realStartActivityLocked(ActivityRecord r,
786 ProcessRecord app, boolean andResume, boolean checkConfig)
787 throws RemoteException {
788
789 r.startFreezingScreenLocked(app, 0);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700790 mWindowManager.setAppVisibility(r.appToken, true);
Craig Mautner2420ead2013-04-01 17:13:20 -0700791
792 // schedule launch ticks to collect information about slow apps.
793 r.startLaunchTickingLocked();
794
795 // Have the window manager re-evaluate the orientation of
796 // the screen based on the new activity order. Note that
797 // as a result of this, it can call back into the activity
798 // manager with a new orientation. We don't care about that,
799 // because the activity is not currently running so we are
800 // just restarting it anyway.
801 if (checkConfig) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700802 Configuration config = mWindowManager.updateOrientationFromAppTokens(
Craig Mautner2420ead2013-04-01 17:13:20 -0700803 mService.mConfiguration,
804 r.mayFreezeScreenLocked(app) ? r.appToken : null);
805 mService.updateConfigurationLocked(config, r, false, false);
806 }
807
808 r.app = app;
809 app.waitingToKill = null;
810 r.launchCount++;
811 r.lastLaunchTime = SystemClock.uptimeMillis();
812
813 if (localLOGV) Slog.v(TAG, "Launching: " + r);
814
815 int idx = app.activities.indexOf(r);
816 if (idx < 0) {
817 app.activities.add(r);
818 }
819 mService.updateLruProcessLocked(app, true);
820
821 final ActivityStack stack = r.task.stack;
822 try {
823 if (app.thread == null) {
824 throw new RemoteException();
825 }
826 List<ResultInfo> results = null;
827 List<Intent> newIntents = null;
828 if (andResume) {
829 results = r.results;
830 newIntents = r.newIntents;
831 }
832 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
833 + " icicle=" + r.icicle
834 + " with results=" + results + " newIntents=" + newIntents
835 + " andResume=" + andResume);
836 if (andResume) {
837 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
838 r.userId, System.identityHashCode(r),
839 r.task.taskId, r.shortComponentName);
840 }
841 if (r.isHomeActivity) {
842 mService.mHomeProcess = app;
843 }
844 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
845 r.sleeping = false;
846 r.forceNewConfig = false;
847 mService.showAskCompatModeDialogLocked(r);
848 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
849 String profileFile = null;
850 ParcelFileDescriptor profileFd = null;
851 boolean profileAutoStop = false;
852 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
853 if (mService.mProfileProc == null || mService.mProfileProc == app) {
854 mService.mProfileProc = app;
855 profileFile = mService.mProfileFile;
856 profileFd = mService.mProfileFd;
857 profileAutoStop = mService.mAutoStopProfiler;
858 }
859 }
860 app.hasShownUi = true;
861 app.pendingUiClean = true;
862 if (profileFd != null) {
863 try {
864 profileFd = profileFd.dup();
865 } catch (IOException e) {
866 if (profileFd != null) {
867 try {
868 profileFd.close();
869 } catch (IOException o) {
870 }
871 profileFd = null;
872 }
873 }
874 }
875 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
876 System.identityHashCode(r), r.info,
877 new Configuration(mService.mConfiguration),
878 r.compat, r.icicle, results, newIntents, !andResume,
879 mService.isNextTransitionForward(), profileFile, profileFd,
880 profileAutoStop);
881
882 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
883 // This may be a heavy-weight process! Note that the package
884 // manager will ensure that only activity can run in the main
885 // process of the .apk, which is the only thing that will be
886 // considered heavy-weight.
887 if (app.processName.equals(app.info.packageName)) {
888 if (mService.mHeavyWeightProcess != null
889 && mService.mHeavyWeightProcess != app) {
890 Slog.w(TAG, "Starting new heavy weight process " + app
891 + " when already running "
892 + mService.mHeavyWeightProcess);
893 }
894 mService.mHeavyWeightProcess = app;
895 Message msg = mService.mHandler.obtainMessage(
896 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
897 msg.obj = r;
898 mService.mHandler.sendMessage(msg);
899 }
900 }
901
902 } catch (RemoteException e) {
903 if (r.launchFailed) {
904 // This is the second time we failed -- finish activity
905 // and give up.
906 Slog.e(TAG, "Second failure launching "
907 + r.intent.getComponent().flattenToShortString()
908 + ", giving up", e);
909 mService.appDiedLocked(app, app.pid, app.thread);
910 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
911 "2nd-crash", false);
912 return false;
913 }
914
915 // This is the first time we failed -- restart process and
916 // retry.
917 app.activities.remove(r);
918 throw e;
919 }
920
921 r.launchFailed = false;
922 if (stack.updateLRUListLocked(r)) {
923 Slog.w(TAG, "Activity " + r
924 + " being launched, but already in LRU list");
925 }
926
927 if (andResume) {
928 // As part of the process of launching, ActivityThread also performs
929 // a resume.
930 stack.minimalResumeActivityLocked(r);
931 } else {
932 // This activity is not starting in the resumed state... which
933 // should look like we asked it to pause+stop (but remain visible),
934 // and it has done so and reported back the current icicle and
935 // other state.
936 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
937 + " (starting in stopped state)");
938 r.state = ActivityState.STOPPED;
939 r.stopped = true;
940 }
941
942 // Launch the new version setup screen if needed. We do this -after-
943 // launching the initial activity (that is, home), so that it can have
944 // a chance to initialize itself while in the background, making the
945 // switch back to it faster and look better.
Craig Mautnerde4ef022013-04-07 19:01:33 -0700946 if (isFrontStack(stack)) {
Craig Mautner2420ead2013-04-01 17:13:20 -0700947 mService.startSetupActivityLocked();
948 }
949
950 return true;
951 }
952
Craig Mautnere79d42682013-04-01 19:01:53 -0700953 void startSpecificActivityLocked(ActivityRecord r,
954 boolean andResume, boolean checkConfig) {
955 // Is this activity's application already running?
956 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
957 r.info.applicationInfo.uid);
958
959 r.task.stack.setLaunchTime(r);
960
961 if (app != null && app.thread != null) {
962 try {
963 app.addPackage(r.info.packageName);
964 realStartActivityLocked(r, app, andResume, checkConfig);
965 return;
966 } catch (RemoteException e) {
967 Slog.w(TAG, "Exception when starting activity "
968 + r.intent.getComponent().flattenToShortString(), e);
969 }
970
971 // If a dead object exception was thrown -- fall through to
972 // restart the application.
973 }
974
975 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
976 "activity", r.intent.getComponent(), false, false);
977 }
978
Craig Mautner6170f732013-04-02 13:05:23 -0700979 final int startActivityLocked(IApplicationThread caller,
980 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
981 String resultWho, int requestCode,
982 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
983 boolean componentSpecified, ActivityRecord[] outActivity) {
984 int err = ActivityManager.START_SUCCESS;
985
986 ProcessRecord callerApp = null;
987 if (caller != null) {
988 callerApp = mService.getRecordForAppLocked(caller);
989 if (callerApp != null) {
990 callingPid = callerApp.pid;
991 callingUid = callerApp.info.uid;
992 } else {
993 Slog.w(TAG, "Unable to find app for caller " + caller
994 + " (pid=" + callingPid + ") when starting: "
995 + intent.toString());
996 err = ActivityManager.START_PERMISSION_DENIED;
997 }
998 }
999
1000 if (err == ActivityManager.START_SUCCESS) {
1001 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
1002 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
1003 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
1004 }
1005
1006 ActivityRecord sourceRecord = null;
1007 ActivityRecord resultRecord = null;
1008 if (resultTo != null) {
1009 sourceRecord = isInAnyStackLocked(resultTo);
1010 if (DEBUG_RESULTS) Slog.v(
1011 TAG, "Will send result to " + resultTo + " " + sourceRecord);
1012 if (sourceRecord != null) {
1013 if (requestCode >= 0 && !sourceRecord.finishing) {
1014 resultRecord = sourceRecord;
1015 }
1016 }
1017 }
1018 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
1019
1020 int launchFlags = intent.getFlags();
1021
1022 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
1023 && sourceRecord != null) {
1024 // Transfer the result target from the source activity to the new
1025 // one being started, including any failures.
1026 if (requestCode >= 0) {
1027 ActivityOptions.abort(options);
1028 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
1029 }
1030 resultRecord = sourceRecord.resultTo;
1031 resultWho = sourceRecord.resultWho;
1032 requestCode = sourceRecord.requestCode;
1033 sourceRecord.resultTo = null;
1034 if (resultRecord != null) {
1035 resultRecord.removeResultsLocked(
1036 sourceRecord, resultWho, requestCode);
1037 }
1038 }
1039
1040 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
1041 // We couldn't find a class that can handle the given Intent.
1042 // That's the end of that!
1043 err = ActivityManager.START_INTENT_NOT_RESOLVED;
1044 }
1045
1046 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
1047 // We couldn't find the specific class specified in the Intent.
1048 // Also the end of the line.
1049 err = ActivityManager.START_CLASS_NOT_FOUND;
1050 }
1051
1052 if (err != ActivityManager.START_SUCCESS) {
1053 if (resultRecord != null) {
1054 resultStack.sendActivityResultLocked(-1,
1055 resultRecord, resultWho, requestCode,
1056 Activity.RESULT_CANCELED, null);
1057 }
1058 setDismissKeyguard(false);
1059 ActivityOptions.abort(options);
1060 return err;
1061 }
1062
1063 final int startAnyPerm = mService.checkPermission(
1064 START_ANY_ACTIVITY, callingPid, callingUid);
1065 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
1066 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
1067 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
1068 if (resultRecord != null) {
1069 resultStack.sendActivityResultLocked(-1,
1070 resultRecord, resultWho, requestCode,
1071 Activity.RESULT_CANCELED, null);
1072 }
1073 setDismissKeyguard(false);
1074 String msg;
1075 if (!aInfo.exported) {
1076 msg = "Permission Denial: starting " + intent.toString()
1077 + " from " + callerApp + " (pid=" + callingPid
1078 + ", uid=" + callingUid + ")"
1079 + " not exported from uid " + aInfo.applicationInfo.uid;
1080 } else {
1081 msg = "Permission Denial: starting " + intent.toString()
1082 + " from " + callerApp + " (pid=" + callingPid
1083 + ", uid=" + callingUid + ")"
1084 + " requires " + aInfo.permission;
1085 }
1086 Slog.w(TAG, msg);
1087 throw new SecurityException(msg);
1088 }
1089
Ben Gruver6617c3c2013-04-03 18:45:22 -07001090 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
Ben Gruver7b879f42013-04-08 14:56:55 -07001091 callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo);
Ben Gruver5e207332013-04-03 17:41:37 -07001092
Craig Mautner6170f732013-04-02 13:05:23 -07001093 if (mService.mController != null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001094 try {
1095 // The Intent we give to the watcher has the extra data
1096 // stripped off, since it can contain private information.
1097 Intent watchIntent = intent.cloneFilter();
Ben Gruver5e207332013-04-03 17:41:37 -07001098 abort |= !mService.mController.activityStarting(watchIntent,
Craig Mautner6170f732013-04-02 13:05:23 -07001099 aInfo.applicationInfo.packageName);
1100 } catch (RemoteException e) {
1101 mService.mController = null;
1102 }
Ben Gruver5e207332013-04-03 17:41:37 -07001103 }
Craig Mautner6170f732013-04-02 13:05:23 -07001104
Ben Gruver5e207332013-04-03 17:41:37 -07001105 if (abort) {
1106 if (resultRecord != null) {
1107 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Craig Mautner6170f732013-04-02 13:05:23 -07001108 Activity.RESULT_CANCELED, null);
Craig Mautner6170f732013-04-02 13:05:23 -07001109 }
Ben Gruver5e207332013-04-03 17:41:37 -07001110 // We pretend to the caller that it was really started, but
1111 // they will just get a cancel result.
1112 setDismissKeyguard(false);
1113 ActivityOptions.abort(options);
1114 return ActivityManager.START_SUCCESS;
Craig Mautner6170f732013-04-02 13:05:23 -07001115 }
1116
1117 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1118 intent, resolvedType, aInfo, mService.mConfiguration,
Craig Mautnerde4ef022013-04-07 19:01:33 -07001119 resultRecord, resultWho, requestCode, componentSpecified, this);
Craig Mautner6170f732013-04-02 13:05:23 -07001120 if (outActivity != null) {
1121 outActivity[0] = r;
1122 }
1123
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001124 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001125 if (stack.mResumedActivity == null
1126 || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
Craig Mautner6170f732013-04-02 13:05:23 -07001127 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1128 PendingActivityLaunch pal =
Craig Mautnerde4ef022013-04-07 19:01:33 -07001129 new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
Craig Mautner6170f732013-04-02 13:05:23 -07001130 mService.mPendingActivityLaunches.add(pal);
1131 setDismissKeyguard(false);
1132 ActivityOptions.abort(options);
1133 return ActivityManager.START_SWITCHES_CANCELED;
1134 }
1135 }
1136
1137 if (mService.mDidAppSwitch) {
1138 // This is the second allowed switch since we stopped switches,
1139 // so now just generally allow switches. Use case: user presses
1140 // home (switches disabled, switch to home, mDidAppSwitch now true);
1141 // user taps a home icon (coming from home so allowed, we hit here
1142 // and now allow anyone to switch again).
1143 mService.mAppSwitchesAllowedTime = 0;
1144 } else {
1145 mService.mDidAppSwitch = true;
1146 }
1147
1148 mService.doPendingActivityLaunchesLocked(false);
1149
Craig Mautner8849a5e2013-04-02 16:41:03 -07001150 err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001151 if (stack.mPausingActivity == null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001152 // Someone asked to have the keyguard dismissed on the next
1153 // activity start, but we are not actually doing an activity
1154 // switch... just dismiss the keyguard now, because we
1155 // probably want to see whatever is behind it.
1156 dismissKeyguard();
1157 }
1158 return err;
1159 }
1160
Craig Mautnerde4ef022013-04-07 19:01:33 -07001161 ActivityStack getCorrectStack(ActivityRecord r) {
1162 if (!r.isHomeActivity) {
Craig Mautner858d8a62013-04-23 17:08:34 -07001163 int stackNdx;
1164 for (stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
1165 if (mStacks.get(stackNdx).mCurrentUser == mCurrentUser) {
1166 break;
1167 }
1168 }
1169 if (stackNdx == 0) {
1170 // Time to create the first app stack for this user.
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001171 int stackId = mService.createStack(-1, HOME_STACK_ID,
1172 StackBox.TASK_STACK_GOES_OVER, 1.0f);
Craig Mautner29219d92013-04-16 20:19:12 -07001173 mFocusedStack = getStack(stackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001174 }
Craig Mautner29219d92013-04-16 20:19:12 -07001175 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001176 }
1177 return mHomeStack;
1178 }
1179
Craig Mautner29219d92013-04-16 20:19:12 -07001180 void setFocusedStack(ActivityRecord r) {
1181 if (r == null) {
1182 return;
1183 }
1184 if (r.isHomeActivity) {
1185 if (mStackState != STACK_STATE_HOME_IN_FRONT) {
1186 mStackState = STACK_STATE_HOME_TO_FRONT;
1187 }
1188 } else {
1189 mFocusedStack = r.task.stack;
1190 if (mStackState != STACK_STATE_HOME_IN_BACK) {
1191 mStackState = STACK_STATE_HOME_TO_BACK;
1192 }
1193 }
1194 }
1195
Craig Mautner8849a5e2013-04-02 16:41:03 -07001196 final int startActivityUncheckedLocked(ActivityRecord r,
1197 ActivityRecord sourceRecord, int startFlags, boolean doResume,
1198 Bundle options) {
1199 final Intent intent = r.intent;
1200 final int callingUid = r.launchedFromUid;
1201
1202 int launchFlags = intent.getFlags();
1203
Craig Mautner8849a5e2013-04-02 16:41:03 -07001204 // We'll invoke onUserLeaving before onPause only if the launching
1205 // activity did not explicitly state that this is an automated launch.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001206 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1207 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001208
1209 // If the caller has asked not to resume at this point, we make note
1210 // of this in the record so that we can skip it when trying to find
1211 // the top running activity.
1212 if (!doResume) {
1213 r.delayedResume = true;
1214 }
1215
1216 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1217
1218 // If the onlyIfNeeded flag is set, then we can do this if the activity
1219 // being launched is the same as the one making the call... or, as
1220 // a special case, if we do not know the caller then we count the
1221 // current top activity as the caller.
1222 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1223 ActivityRecord checkedCaller = sourceRecord;
1224 if (checkedCaller == null) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001225 checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001226 }
1227 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1228 // Caller is not the same as launcher, so always needed.
1229 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1230 }
1231 }
1232
1233 if (sourceRecord == null) {
1234 // This activity is not being started from another... in this
1235 // case we -always- start a new task.
1236 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Craig Mautner29219d92013-04-16 20:19:12 -07001237 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1238 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001239 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1240 }
1241 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1242 // The original activity who is starting us is running as a single
1243 // instance... this new activity it is starting must go on its
1244 // own task.
1245 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1246 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1247 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1248 // The activity being started is a single instance... it always
1249 // gets launched into its own task.
1250 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1251 }
1252
Craig Mautnerde4ef022013-04-07 19:01:33 -07001253 final ActivityStack sourceStack;
1254 final TaskRecord sourceTask;
1255 if (sourceRecord != null) {
1256 sourceTask = sourceRecord.task;
1257 sourceStack = sourceTask.stack;
1258 } else {
1259 sourceTask = null;
1260 sourceStack = null;
1261 }
1262
Craig Mautner8849a5e2013-04-02 16:41:03 -07001263 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1264 // For whatever reason this activity is being launched into a new
1265 // task... yet the caller has requested a result back. Well, that
1266 // is pretty messed up, so instead immediately send back a cancel
1267 // and let the new task continue launched as normal without a
1268 // dependency on its originator.
1269 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1270 r.resultTo.task.stack.sendActivityResultLocked(-1,
1271 r.resultTo, r.resultWho, r.requestCode,
1272 Activity.RESULT_CANCELED, null);
1273 r.resultTo = null;
1274 }
1275
1276 boolean addingToTask = false;
1277 boolean movedHome = false;
1278 TaskRecord reuseTask = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001279 ActivityStack targetStack;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001280 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1281 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1282 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1283 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1284 // If bring to front is requested, and no result is requested, and
1285 // we can find a task that was started with this same
1286 // component, then instead of launching bring that one to the front.
1287 if (r.resultTo == null) {
1288 // See if there is a task to bring to the front. If this is
1289 // a SINGLE_INSTANCE activity, there can be one and only one
1290 // instance of it in the history, and it is always in its own
1291 // unique task, so we do a special search.
1292 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
1293 ? findTaskLocked(intent, r.info)
1294 : findActivityLocked(intent, r.info);
1295 if (intentActivity != null) {
Craig Mautner29219d92013-04-16 20:19:12 -07001296 if (r.task == null) {
1297 r.task = intentActivity.task;
1298 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001299 targetStack = intentActivity.task.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001300 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001301 if (intentActivity.task.intent == null) {
1302 // This task was started because of movement of
1303 // the activity based on affinity... now that we
1304 // are actually launching it, we can assign the
1305 // base intent.
1306 intentActivity.task.setIntent(intent, r.info);
1307 }
1308 // If the target task is not in the front, then we need
1309 // to bring it to the front... except... well, with
1310 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
1311 // to have the same behavior as if a new instance was
1312 // being started, which means not bringing it to the front
1313 // if the caller is not itself in the front.
Craig Mautner165640b2013-04-20 10:34:33 -07001314 final ActivityStack lastStack = getLastStack();
1315 ActivityRecord curTop = lastStack == null?
1316 null : lastStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001317 if (curTop != null && curTop.task != intentActivity.task) {
1318 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001319 if (sourceRecord == null || sourceStack.topActivity() == sourceRecord) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001320 // We really do want to push this one into the
1321 // user's face, right now.
1322 movedHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001323 if ((launchFlags &
Craig Mautner29219d92013-04-16 20:19:12 -07001324 (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1325 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001326 // Caller wants to appear on home activity, so before starting
1327 // their own activity we will bring home to the front.
1328 r.mLaunchHomeTaskNext = true;
1329 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001330 targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1331 options = null;
1332 }
1333 }
1334 // If the caller has requested that the target task be
1335 // reset, then do so.
1336 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1337 intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1338 }
1339 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1340 // We don't need to start a new activity, and
1341 // the client said not to do anything if that
1342 // is the case, so this is it! And for paranoia, make
1343 // sure we have correctly resumed the top activity.
1344 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001345 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001346 resumeTopActivitiesLocked(targetStack, null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001347 } else {
1348 ActivityOptions.abort(options);
1349 }
Craig Mautner29219d92013-04-16 20:19:12 -07001350 if (r.task == null) Slog.v(TAG,
1351 "startActivityUncheckedLocked: task left null",
1352 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001353 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1354 }
1355 if ((launchFlags &
1356 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1357 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1358 // The caller has requested to completely replace any
1359 // existing task with its new activity. Well that should
1360 // not be too hard...
1361 reuseTask = intentActivity.task;
1362 reuseTask.performClearTaskLocked();
1363 reuseTask.setIntent(r.intent, r.info);
1364 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1365 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1366 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1367 // In this situation we want to remove all activities
1368 // from the task up to the one being started. In most
1369 // cases this means we are resetting the task to its
1370 // initial state.
1371 ActivityRecord top =
1372 intentActivity.task.performClearTaskLocked(r, launchFlags);
1373 if (top != null) {
1374 if (top.frontOfTask) {
1375 // Activity aliases may mean we use different
1376 // intents for the top activity, so make sure
1377 // the task now has the identity of the new
1378 // intent.
1379 top.task.setIntent(r.intent, r.info);
1380 }
1381 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1382 r, top.task);
1383 top.deliverNewIntentLocked(callingUid, r.intent);
1384 } else {
1385 // A special case: we need to
1386 // start the activity because it is not currently
1387 // running, and the caller has asked to clear the
1388 // current task to have this activity at the top.
1389 addingToTask = true;
1390 // Now pretend like this activity is being started
1391 // by the top of its task, so it is put in the
1392 // right place.
1393 sourceRecord = intentActivity;
1394 }
1395 } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1396 // In this case the top activity on the task is the
1397 // same as the one being launched, so we take that
1398 // as a request to bring the task to the foreground.
1399 // If the top activity in the task is the root
1400 // activity, deliver this new intent to it if it
1401 // desires.
1402 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1403 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1404 && intentActivity.realActivity.equals(r.realActivity)) {
1405 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1406 intentActivity.task);
1407 if (intentActivity.frontOfTask) {
1408 intentActivity.task.setIntent(r.intent, r.info);
1409 }
1410 intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1411 } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1412 // In this case we are launching the root activity
1413 // of the task, but with a different intent. We
1414 // should start a new instance on top.
1415 addingToTask = true;
1416 sourceRecord = intentActivity;
1417 }
1418 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1419 // In this case an activity is being launched in to an
1420 // existing task, without resetting that task. This
1421 // is typically the situation of launching an activity
1422 // from a notification or shortcut. We want to place
1423 // the new activity on top of the current task.
1424 addingToTask = true;
1425 sourceRecord = intentActivity;
1426 } else if (!intentActivity.task.rootWasReset) {
1427 // In this case we are launching in to an existing task
1428 // that has not yet been started from its front door.
1429 // The current task has been brought to the front.
1430 // Ideally, we'd probably like to place this new task
1431 // at the bottom of its stack, but that's a little hard
1432 // to do with the current organization of the code so
1433 // for now we'll just drop it.
1434 intentActivity.task.setIntent(r.intent, r.info);
1435 }
1436 if (!addingToTask && reuseTask == null) {
1437 // We didn't do anything... but it was needed (a.k.a., client
1438 // don't use that intent!) And for paranoia, make
1439 // sure we have correctly resumed the top activity.
1440 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001441 setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1442 targetStack.resumeTopActivityLocked(null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001443 } else {
1444 ActivityOptions.abort(options);
1445 }
Craig Mautner29219d92013-04-16 20:19:12 -07001446 if (r.task == null) Slog.v(TAG,
1447 "startActivityUncheckedLocked: task left null",
1448 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001449 return ActivityManager.START_TASK_TO_FRONT;
1450 }
1451 }
1452 }
1453 }
1454
1455 //String uri = r.intent.toURI();
1456 //Intent intent2 = new Intent(uri);
1457 //Slog.i(TAG, "Given intent: " + r.intent);
1458 //Slog.i(TAG, "URI is: " + uri);
1459 //Slog.i(TAG, "To intent: " + intent2);
1460
1461 if (r.packageName != null) {
1462 // If the activity being launched is the same as the one currently
1463 // at the top, then we need to check if it should only be launched
1464 // once.
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001465 ActivityStack topStack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001466 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001467 if (top != null && r.resultTo == null) {
1468 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1469 if (top.app != null && top.app.thread != null) {
1470 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1471 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1472 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1473 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1474 top.task);
1475 // For paranoia, make sure we have correctly
1476 // resumed the top activity.
1477 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001478 setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
Craig Mautner05d29032013-05-03 13:40:13 -07001479 resumeTopActivitiesLocked();
Craig Mautner8849a5e2013-04-02 16:41:03 -07001480 }
1481 ActivityOptions.abort(options);
1482 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1483 // We don't need to start a new activity, and
1484 // the client said not to do anything if that
1485 // is the case, so this is it!
Craig Mautner29219d92013-04-16 20:19:12 -07001486 if (r.task == null) Slog.v(TAG,
1487 "startActivityUncheckedLocked: task left null",
1488 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001489 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1490 }
1491 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner29219d92013-04-16 20:19:12 -07001492 if (r.task == null) Slog.v(TAG,
1493 "startActivityUncheckedLocked: task left null",
1494 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001495 return ActivityManager.START_DELIVERED_TO_TOP;
1496 }
1497 }
1498 }
1499 }
1500
1501 } else {
1502 if (r.resultTo != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001503 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1504 r.requestCode, Activity.RESULT_CANCELED, null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001505 }
1506 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001507 if (r.task == null) Slog.v(TAG,
1508 "startActivityUncheckedLocked: task left null",
1509 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001510 return ActivityManager.START_CLASS_NOT_FOUND;
1511 }
1512
1513 boolean newTask = false;
1514 boolean keepCurTransition = false;
1515
1516 // Should this be considered a new task?
1517 if (r.resultTo == null && !addingToTask
1518 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001519 targetStack = getCorrectStack(r);
1520 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001521 if (reuseTask == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001522 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1523 null, true);
1524 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1525 r.task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001526 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001527 r.setTask(reuseTask, reuseTask, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001528 }
1529 newTask = true;
1530 if (!movedHome) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001531 if ((launchFlags &
1532 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1533 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1534 // Caller wants to appear on home activity, so before starting
1535 // their own activity we will bring home to the front.
1536 r.mLaunchHomeTaskNext = true;
1537 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001538 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001539 } else if (sourceRecord != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001540 targetStack = sourceRecord.task.stack;
1541 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001542 if (!addingToTask &&
1543 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1544 // In this case, we are adding the activity to an existing
1545 // task, but the caller has asked to clear that task if the
1546 // activity is already running.
1547 ActivityRecord top = sourceRecord.task.performClearTaskLocked(r, launchFlags);
1548 keepCurTransition = true;
1549 if (top != null) {
1550 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1551 top.deliverNewIntentLocked(callingUid, r.intent);
1552 // For paranoia, make sure we have correctly
1553 // resumed the top activity.
1554 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001555 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001556 targetStack.resumeTopActivityLocked(null);
1557 }
1558 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001559 if (r.task == null) Slog.v(TAG,
1560 "startActivityUncheckedLocked: task left null",
1561 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001562 return ActivityManager.START_DELIVERED_TO_TOP;
1563 }
1564 } else if (!addingToTask &&
1565 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1566 // In this case, we are launching an activity in our own task
1567 // that may already be running somewhere in the history, and
1568 // we want to shuffle it to the front of the stack if so.
1569 final ActivityRecord top =
1570 targetStack.findActivityInHistoryLocked(r, sourceRecord.task);
1571 if (top != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001572 final TaskRecord task = top.task;
1573 task.moveActivityToFrontLocked(top);
1574 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001575 top.updateOptionsLocked(options);
1576 top.deliverNewIntentLocked(callingUid, r.intent);
1577 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001578 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001579 targetStack.resumeTopActivityLocked(null);
1580 }
Craig Mautner29219d92013-04-16 20:19:12 -07001581 if (r.task == null) Slog.v(TAG,
1582 "startActivityUncheckedLocked: task left null",
1583 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001584 return ActivityManager.START_DELIVERED_TO_TOP;
1585 }
1586 }
1587 // An existing activity is starting this new activity, so we want
1588 // to keep the new one in the same task as the one that is starting
1589 // it.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001590 r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001591 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1592 + " in existing task " + r.task);
1593
1594 } else {
1595 // This not being started from an existing activity, and not part
1596 // of a new task... just put it in the top task, though these days
1597 // this case should never happen.
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001598 ActivityStack lastStack = getLastStack();
1599 targetStack = lastStack != null ? lastStack : mHomeStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001600 moveHomeStack(targetStack.isHomeStack());
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001601 ActivityRecord prev = lastStack == null ? null : targetStack.topActivity();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001602 r.setTask(prev != null ? prev.task
1603 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1604 null, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001605 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1606 + " in new guessed " + r.task);
1607 }
1608
1609 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1610 intent, r.getUriPermissionsLocked());
1611
1612 if (newTask) {
1613 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1614 }
1615 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001616 setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001617 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
1618 return ActivityManager.START_SUCCESS;
1619 }
1620
Craig Mautnerf3333272013-04-22 10:55:53 -07001621 // Checked.
1622 final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
1623 Configuration config) {
1624 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
1625
1626 ActivityRecord res = null;
1627
1628 ArrayList<ActivityRecord> stops = null;
1629 ArrayList<ActivityRecord> finishes = null;
1630 ArrayList<UserStartedState> startingUsers = null;
1631 int NS = 0;
1632 int NF = 0;
1633 IApplicationThread sendThumbnail = null;
1634 boolean booting = false;
1635 boolean enableScreen = false;
1636 boolean activityRemoved = false;
1637
1638 ActivityRecord r = ActivityRecord.forToken(token);
1639 if (r != null) {
1640 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
1641 r.finishLaunchTickingLocked();
1642 res = r.task.stack.activityIdleInternalLocked(token, fromTimeout, config);
1643 if (res != null) {
1644 if (fromTimeout) {
1645 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
1646 }
1647
1648 // This is a hack to semi-deal with a race condition
1649 // in the client where it can be constructed with a
1650 // newer configuration from when we asked it to launch.
1651 // We'll update with whatever configuration it now says
1652 // it used to launch.
1653 if (config != null) {
1654 r.configuration = config;
1655 }
1656
1657 // We are now idle. If someone is waiting for a thumbnail from
1658 // us, we can now deliver.
1659 r.idle = true;
1660 if (allResumedActivitiesIdle()) {
1661 mService.scheduleAppGcsLocked();
1662 }
1663 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
1664 sendThumbnail = r.app.thread;
1665 r.thumbnailNeeded = false;
1666 }
1667
1668 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
1669 if (!mService.mBooted && isFrontStack(r.task.stack)) {
1670 mService.mBooted = true;
1671 enableScreen = true;
1672 }
1673 } else if (fromTimeout) {
1674 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
1675 }
1676 }
1677
1678 // Atomically retrieve all of the other things to do.
1679 stops = processStoppingActivitiesLocked(true);
1680 NS = stops != null ? stops.size() : 0;
1681 if ((NF=mFinishingActivities.size()) > 0) {
1682 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
1683 mFinishingActivities.clear();
1684 }
1685
1686 final ArrayList<ActivityRecord> thumbnails;
1687 final int NT = mCancelledThumbnails.size();
1688 if (NT > 0) {
1689 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
1690 mCancelledThumbnails.clear();
1691 } else {
1692 thumbnails = null;
1693 }
1694
1695 if (isFrontStack(mHomeStack)) {
1696 booting = mService.mBooting;
1697 mService.mBooting = false;
1698 }
1699
1700 if (mStartingUsers.size() > 0) {
1701 startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
1702 mStartingUsers.clear();
1703 }
1704
1705 // Perform the following actions from unsynchronized state.
1706 final IApplicationThread thumbnailThread = sendThumbnail;
1707 mHandler.post(new Runnable() {
1708 @Override
1709 public void run() {
1710 if (thumbnailThread != null) {
1711 try {
1712 thumbnailThread.requestThumbnail(token);
1713 } catch (Exception e) {
1714 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
1715 mService.sendPendingThumbnail(null, token, null, null, true);
1716 }
1717 }
1718
1719 // Report back to any thumbnail receivers.
1720 for (int i = 0; i < NT; i++) {
1721 ActivityRecord r = thumbnails.get(i);
1722 mService.sendPendingThumbnail(r, null, null, null, true);
1723 }
1724 }
1725 });
1726
1727 // Stop any activities that are scheduled to do so but have been
1728 // waiting for the next one to start.
1729 for (int i = 0; i < NS; i++) {
1730 r = stops.get(i);
1731 final ActivityStack stack = r.task.stack;
1732 if (r.finishing) {
1733 stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
1734 } else {
1735 stack.stopActivityLocked(r);
1736 }
1737 }
1738
1739 // Finish any activities that are scheduled to do so but have been
1740 // waiting for the next one to start.
1741 for (int i = 0; i < NF; i++) {
1742 r = finishes.get(i);
1743 activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle");
1744 }
1745
1746 if (booting) {
1747 mService.finishBooting();
1748 } else if (startingUsers != null) {
1749 for (int i = 0; i < startingUsers.size(); i++) {
1750 mService.finishUserSwitch(startingUsers.get(i));
1751 }
1752 }
1753
1754 mService.trimApplications();
1755 //dump();
1756 //mWindowManager.dump();
1757
1758 if (enableScreen) {
1759 mService.enableScreenAfterBoot();
1760 }
1761
1762 if (activityRemoved) {
Craig Mautner05d29032013-05-03 13:40:13 -07001763 resumeTopActivitiesLocked();
Craig Mautnerf3333272013-04-22 10:55:53 -07001764 }
1765
1766 return res;
1767 }
1768
Craig Mautner8d341ef2013-03-26 09:03:27 -07001769 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
1770 // Just in case.
1771 final int numStacks = mStacks.size();
1772 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Craig Mautnere79d42682013-04-01 19:01:53 -07001773 mStacks.get(stackNdx).handleAppDiedLocked(app, restarting);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001774 }
1775 }
1776
1777 void closeSystemDialogsLocked() {
1778 final int numStacks = mStacks.size();
1779 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1780 final ActivityStack stack = mStacks.get(stackNdx);
1781 stack.closeSystemDialogsLocked();
1782 }
1783 }
1784
1785 /**
1786 * @return true if some activity was finished (or would have finished if doit were true).
1787 */
1788 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1789 boolean didSomething = false;
1790 final int numStacks = mStacks.size();
1791 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1792 final ActivityStack stack = mStacks.get(stackNdx);
1793 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1794 didSomething = true;
1795 }
1796 }
1797 return didSomething;
1798 }
1799
Craig Mautner05d29032013-05-03 13:40:13 -07001800 boolean resumeTopActivitiesLocked() {
1801 return resumeTopActivitiesLocked(null, null, null);
1802 }
1803
1804 boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
1805 Bundle targetOptions) {
1806 if (targetStack == null) {
1807 targetStack = getFocusedStack();
1808 }
1809 boolean result = false;
Craig Mautnerdbcb31f2013-04-02 12:32:53 -07001810 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001811 final ActivityStack stack = mStacks.get(stackNdx);
1812 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07001813 if (stack == targetStack) {
1814 result = stack.resumeTopActivityLocked(target, targetOptions);
1815 } else {
1816 stack.resumeTopActivityLocked(null);
1817 }
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001818 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001819 }
Craig Mautner05d29032013-05-03 13:40:13 -07001820 return result;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001821 }
1822
1823 void finishTopRunningActivityLocked(ProcessRecord app) {
1824 final int numStacks = mStacks.size();
1825 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1826 final ActivityStack stack = mStacks.get(stackNdx);
1827 stack.finishTopRunningActivityLocked(app);
1828 }
1829 }
1830
Craig Mautner8d341ef2013-03-26 09:03:27 -07001831 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
1832 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1833 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
1834 return;
1835 }
1836 }
1837 }
1838
Craig Mautner967212c2013-04-13 21:10:58 -07001839 ActivityStack getStack(int stackId) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001840 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1841 final ActivityStack stack = mStacks.get(stackNdx);
1842 if (stack.getStackId() == stackId) {
1843 return stack;
1844 }
1845 }
1846 return null;
1847 }
1848
Craig Mautner967212c2013-04-13 21:10:58 -07001849 ArrayList<ActivityStack> getStacks() {
1850 return new ArrayList<ActivityStack>(mStacks);
1851 }
1852
1853 int createStack() {
Craig Mautner858d8a62013-04-23 17:08:34 -07001854 while (true) {
1855 if (++mLastStackId <= HOME_STACK_ID) {
1856 mLastStackId = HOME_STACK_ID + 1;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001857 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001858 if (getStack(mLastStackId) == null) {
1859 break;
1860 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001861 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001862 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
1863 return mLastStackId;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001864 }
1865
1866 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
1867 final ActivityStack stack = getStack(stackId);
1868 if (stack == null) {
1869 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
1870 return;
1871 }
1872 stack.moveTask(taskId, toTop);
Craig Mautner05d29032013-05-03 13:40:13 -07001873 resumeTopActivitiesLocked();
Craig Mautner8d341ef2013-03-26 09:03:27 -07001874 }
1875
Craig Mautner8849a5e2013-04-02 16:41:03 -07001876 ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
1877 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1878 final ActivityRecord ar = mStacks.get(stackNdx).findTaskLocked(intent, info);
1879 if (ar != null) {
1880 return ar;
1881 }
1882 }
1883 return null;
1884 }
1885
1886 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
1887 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1888 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
1889 if (ar != null) {
1890 return ar;
1891 }
1892 }
1893 return null;
1894 }
1895
Craig Mautner8d341ef2013-03-26 09:03:27 -07001896 void goingToSleepLocked() {
1897 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1898 mStacks.get(stackNdx).stopIfSleepingLocked();
1899 }
1900 }
1901
1902 boolean shutdownLocked(int timeout) {
1903 boolean timedout = false;
1904 final int numStacks = mStacks.size();
1905 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1906 final ActivityStack stack = mStacks.get(stackNdx);
1907 if (stack.mResumedActivity != null) {
1908 stack.stopIfSleepingLocked();
1909 final long endTime = System.currentTimeMillis() + timeout;
1910 while (stack.mResumedActivity != null || stack.mPausingActivity != null) {
1911 long delay = endTime - System.currentTimeMillis();
1912 if (delay <= 0) {
1913 Slog.w(TAG, "Activity manager shutdown timed out");
1914 timedout = true;
1915 break;
1916 }
1917 try {
1918 mService.wait();
1919 } catch (InterruptedException e) {
1920 }
1921 }
1922 }
1923 }
1924 return timedout;
1925 }
1926
1927 void comeOutOfSleepIfNeededLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001928 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001929 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001930 stack.awakeFromSleepingLocked();
1931 if (isFrontStack(stack)) {
Craig Mautner05d29032013-05-03 13:40:13 -07001932 resumeTopActivitiesLocked();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001933 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001934 }
1935 }
1936
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001937 boolean reportResumedActivityLocked(ActivityRecord r) {
1938 final ActivityStack stack = r.task.stack;
1939 if (isFrontStack(stack)) {
Jeff Sharkey5782da72013-04-25 14:32:30 -07001940 mService.updateUsageStats(r, true);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001941 mService.setFocusedActivityLocked(r);
1942 }
1943 if (allResumedActivitiesComplete()) {
1944 ensureActivitiesVisibleLocked(null, 0);
1945 mWindowManager.executeAppTransition();
1946 return true;
1947 }
1948 return false;
1949 }
1950
Craig Mautner8d341ef2013-03-26 09:03:27 -07001951 void handleAppCrashLocked(ProcessRecord app) {
1952 final int numStacks = mStacks.size();
1953 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1954 final ActivityStack stack = mStacks.get(stackNdx);
1955 stack.handleAppCrashLocked(app);
1956 }
1957 }
1958
Craig Mautnerde4ef022013-04-07 19:01:33 -07001959 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
Craig Mautner580ea812013-04-25 12:58:38 -07001960 // First the front stacks. In case any are not fullscreen and are in front of home.
1961 boolean showHomeBehindStack = false;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001962 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner580ea812013-04-25 12:58:38 -07001963 final ActivityStack stack = mStacks.get(stackNdx);
1964 if (isFrontStack(stack)) {
1965 showHomeBehindStack =
1966 stack.ensureActivitiesVisibleLocked(starting, configChanges);
1967 }
1968 }
1969 // Now do back stacks.
1970 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1971 final ActivityStack stack = mStacks.get(stackNdx);
1972 if (!isFrontStack(stack)) {
1973 stack.ensureActivitiesVisibleLocked(starting, configChanges, showHomeBehindStack);
1974 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001975 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001976 }
1977
1978 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
1979 final int numStacks = mStacks.size();
1980 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1981 final ActivityStack stack = mStacks.get(stackNdx);
1982 stack.scheduleDestroyActivities(app, false, reason);
1983 }
1984 }
1985
1986 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner858d8a62013-04-23 17:08:34 -07001987 mUserStates.put(mCurrentUser, new UserState());
Craig Mautner2420ead2013-04-01 17:13:20 -07001988 mCurrentUser = userId;
Craig Mautner858d8a62013-04-23 17:08:34 -07001989 UserState userState = mUserStates.get(userId);
1990 if (userState != null) {
1991 userState.restore();
1992 mUserStates.delete(userId);
1993 } else {
1994 mFocusedStack = null;
1995 mStackState = STACK_STATE_HOME_IN_FRONT;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001996 }
Craig Mautner858d8a62013-04-23 17:08:34 -07001997
1998 mStartingUsers.add(uss);
1999 boolean haveActivities = mHomeStack.switchUserLocked(userId, uss);
2000
2001 resumeTopActivitiesLocked();
2002
Craig Mautner8d341ef2013-03-26 09:03:27 -07002003 return haveActivities;
Craig Mautner2219a1b2013-03-25 09:44:30 -07002004 }
2005
Craig Mautnerde4ef022013-04-07 19:01:33 -07002006 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
2007 int N = mStoppingActivities.size();
2008 if (N <= 0) return null;
2009
2010 ArrayList<ActivityRecord> stops = null;
2011
2012 final boolean nowVisible = allResumedActivitiesVisible();
2013 for (int i=0; i<N; i++) {
2014 ActivityRecord s = mStoppingActivities.get(i);
2015 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
2016 + nowVisible + " waitingVisible=" + s.waitingVisible
2017 + " finishing=" + s.finishing);
2018 if (s.waitingVisible && nowVisible) {
2019 mWaitingVisibleActivities.remove(s);
2020 s.waitingVisible = false;
2021 if (s.finishing) {
2022 // If this activity is finishing, it is sitting on top of
2023 // everyone else but we now know it is no longer needed...
2024 // so get rid of it. Otherwise, we need to go through the
2025 // normal flow and hide it once we determine that it is
2026 // hidden by the activities in front of it.
2027 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002028 mWindowManager.setAppVisibility(s.appToken, false);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002029 }
2030 }
2031 if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
2032 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
2033 if (stops == null) {
2034 stops = new ArrayList<ActivityRecord>();
2035 }
2036 stops.add(s);
2037 mStoppingActivities.remove(i);
2038 N--;
2039 i--;
2040 }
2041 }
2042
2043 return stops;
2044 }
2045
Craig Mautnercf910b02013-04-23 11:23:27 -07002046 void validateTopActivitiesLocked() {
2047 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2048 final ActivityStack stack = mStacks.get(stackNdx);
2049 final ActivityRecord r = stack.topRunningActivityLocked(null);
2050 if (isFrontStack(stack)) {
2051 if (r == null) {
2052 Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
2053 } else {
2054 if (stack.mPausingActivity != null) {
2055 Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
2056 " state=" + r.state);
2057 }
2058 if (r.state != ActivityState.INITIALIZING &&
2059 r.state != ActivityState.RESUMED) {
2060 Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
2061 " state=" + r.state);
2062 }
2063 }
2064 } else {
2065 if (stack.mResumedActivity != null) {
2066 Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
2067 " state=" + r.state);
2068 }
2069 if (r != null && (r.state == ActivityState.INITIALIZING
2070 || r.state == ActivityState.RESUMED)) {
2071 Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
2072 " state=" + r.state);
2073 }
2074 }
2075 }
2076 }
2077
Craig Mautner27084302013-03-25 08:05:25 -07002078 public void dump(PrintWriter pw, String prefix) {
2079 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
2080 pw.println(mDismissKeyguardOnNextActivity);
2081 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002082
Craig Mautner20e72272013-04-01 13:45:53 -07002083 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002084 return getFocusedStack().getDumpActivitiesLocked(name);
Craig Mautner20e72272013-04-01 13:45:53 -07002085 }
2086
Craig Mautner8d341ef2013-03-26 09:03:27 -07002087 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
2088 boolean dumpClient, String dumpPackage) {
2089 final int numStacks = mStacks.size();
2090 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2091 final ActivityStack stack = mStacks.get(stackNdx);
2092 pw.print(" Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
2093 stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
2094 pw.println(" ");
2095 pw.println(" Running activities (most recent first):");
2096 dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false,
2097 dumpPackage);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002098 if (stack.mGoingToSleepActivities.size() > 0) {
2099 pw.println(" ");
2100 pw.println(" Activities waiting to sleep:");
2101 dumpHistoryList(fd, pw, stack.mGoingToSleepActivities, " ", "Sleep", false,
2102 !dumpAll, false, dumpPackage);
2103 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002104
Craig Mautner8d341ef2013-03-26 09:03:27 -07002105 pw.print(" Stack #"); pw.println(mStacks.indexOf(stack));
2106 if (stack.mPausingActivity != null) {
2107 pw.println(" mPausingActivity: " + stack.mPausingActivity);
2108 }
2109 pw.println(" mResumedActivity: " + stack.mResumedActivity);
2110 if (dumpAll) {
2111 pw.println(" mLastPausedActivity: " + stack.mLastPausedActivity);
2112 pw.println(" mSleepTimeout: " + stack.mSleepTimeout);
2113 }
2114 }
2115
Craig Mautnerf3333272013-04-22 10:55:53 -07002116 if (mFinishingActivities.size() > 0) {
2117 pw.println(" ");
2118 pw.println(" Activities waiting to finish:");
2119 dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll, false,
2120 dumpPackage);
2121 }
2122
Craig Mautnerde4ef022013-04-07 19:01:33 -07002123 if (mStoppingActivities.size() > 0) {
2124 pw.println(" ");
2125 pw.println(" Activities waiting to stop:");
2126 dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, false,
2127 dumpPackage);
2128 }
2129
2130 if (mWaitingVisibleActivities.size() > 0) {
2131 pw.println(" ");
2132 pw.println(" Activities waiting for another to become visible:");
2133 dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
2134 false, dumpPackage);
2135 }
2136
Craig Mautner8d341ef2013-03-26 09:03:27 -07002137 if (dumpAll) {
2138 pw.println(" ");
2139 pw.println(" mCurTaskId: " + mCurTaskId);
2140 }
2141 return true;
2142 }
2143
2144 static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
2145 String prefix, String label, boolean complete, boolean brief, boolean client,
2146 String dumpPackage) {
2147 TaskRecord lastTask = null;
2148 boolean needNL = false;
2149 final String innerPrefix = prefix + " ";
2150 final String[] args = new String[0];
2151 for (int i=list.size()-1; i>=0; i--) {
2152 final ActivityRecord r = list.get(i);
2153 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
2154 continue;
2155 }
2156 final boolean full = !brief && (complete || !r.isInHistory());
2157 if (needNL) {
2158 pw.println(" ");
2159 needNL = false;
2160 }
2161 if (lastTask != r.task) {
2162 lastTask = r.task;
2163 pw.print(prefix);
2164 pw.print(full ? "* " : " ");
2165 pw.println(lastTask);
2166 if (full) {
2167 lastTask.dump(pw, prefix + " ");
2168 } else if (complete) {
2169 // Complete + brief == give a summary. Isn't that obvious?!?
2170 if (lastTask.intent != null) {
2171 pw.print(prefix); pw.print(" ");
2172 pw.println(lastTask.intent.toInsecureStringWithClip());
2173 }
2174 }
2175 }
2176 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
2177 pw.print(" #"); pw.print(i); pw.print(": ");
2178 pw.println(r);
2179 if (full) {
2180 r.dump(pw, innerPrefix);
2181 } else if (complete) {
2182 // Complete + brief == give a summary. Isn't that obvious?!?
2183 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
2184 if (r.app != null) {
2185 pw.print(innerPrefix); pw.println(r.app);
2186 }
2187 }
2188 if (client && r.app != null && r.app.thread != null) {
2189 // flush anything that is already in the PrintWriter since the thread is going
2190 // to write to the file descriptor directly
2191 pw.flush();
2192 try {
2193 TransferPipe tp = new TransferPipe();
2194 try {
2195 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
2196 r.appToken, innerPrefix, args);
2197 // Short timeout, since blocking here can
2198 // deadlock with the application.
2199 tp.go(fd, 2000);
2200 } finally {
2201 tp.kill();
2202 }
2203 } catch (IOException e) {
2204 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
2205 } catch (RemoteException e) {
2206 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
2207 }
2208 needNL = true;
2209 }
2210 }
2211 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002212
Craig Mautnerf3333272013-04-22 10:55:53 -07002213 void scheduleIdleTimeoutLocked(ActivityRecord next) {
Craig Mautnerc64f73e2013-04-24 16:44:56 -07002214 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
2215 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
Craig Mautnerf3333272013-04-22 10:55:53 -07002216 }
2217
2218 final void scheduleIdleLocked() {
Craig Mautner05d29032013-05-03 13:40:13 -07002219 mHandler.sendEmptyMessage(IDLE_NOW_MSG);
Craig Mautnerf3333272013-04-22 10:55:53 -07002220 }
2221
2222 void removeTimeoutsForActivityLocked(ActivityRecord r) {
2223 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
2224 }
2225
Craig Mautner05d29032013-05-03 13:40:13 -07002226 final void scheduleResumeTopActivities() {
2227 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2228 }
2229
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002230 private final class ActivityStackSupervisorHandler extends Handler {
Craig Mautnerf3333272013-04-22 10:55:53 -07002231
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002232 public ActivityStackSupervisorHandler(Looper looper) {
2233 super(looper);
2234 }
2235
Craig Mautnerf3333272013-04-22 10:55:53 -07002236 void activityIdleInternal(ActivityRecord r) {
2237 synchronized (mService) {
2238 activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
2239 }
2240 }
2241
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002242 @Override
2243 public void handleMessage(Message msg) {
2244 switch (msg.what) {
Craig Mautnerf3333272013-04-22 10:55:53 -07002245 case IDLE_TIMEOUT_MSG: {
2246 if (mService.mDidDexOpt) {
2247 mService.mDidDexOpt = false;
2248 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2249 nmsg.obj = msg.obj;
2250 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
2251 return;
2252 }
2253 // We don't at this point know if the activity is fullscreen,
2254 // so we need to be conservative and assume it isn't.
2255 activityIdleInternal((ActivityRecord)msg.obj);
2256 } break;
2257 case IDLE_NOW_MSG: {
2258 activityIdleInternal((ActivityRecord)msg.obj);
2259 } break;
Craig Mautner05d29032013-05-03 13:40:13 -07002260 case RESUME_TOP_ACTIVITY_MSG: {
2261 synchronized (mService) {
2262 resumeTopActivitiesLocked();
2263 }
2264 } break;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002265 }
2266 }
2267 }
Craig Mautner858d8a62013-04-23 17:08:34 -07002268
2269 private final class UserState {
2270 final ActivityStack mSavedFocusedStack;
2271 final int mSavedStackState;
2272
2273 public UserState() {
2274 ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2275 mSavedFocusedStack = supervisor.mFocusedStack;
2276 mSavedStackState = supervisor.mStackState;
2277 }
2278
2279 void restore() {
2280 ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2281 supervisor.mFocusedStack = mSavedFocusedStack;
2282 supervisor.mStackState = mSavedStackState;
2283 }
2284 }
Craig Mautner27084302013-03-25 08:05:25 -07002285}