blob: be3e26008ff205a1f010be8de0191ea0b81d97dc [file] [log] [blame]
Craig Mautner27084302013-03-25 08:05:25 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Craig Mautner6170f732013-04-02 13:05:23 -070019import static android.Manifest.permission.START_ANY_ACTIVITY;
Craig Mautner29219d92013-04-16 20:19:12 -070020import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
21import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Craig Mautner6170f732013-04-02 13:05:23 -070022import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Craig Mautner2420ead2013-04-01 17:13:20 -070023import static com.android.server.am.ActivityManagerService.localLOGV;
Craig Mautner23ac33b2013-04-01 16:26:35 -070024import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION;
Craig Mautner6170f732013-04-02 13:05:23 -070025import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
Craig Mautner2420ead2013-04-01 17:13:20 -070026import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
Craig Mautner8849a5e2013-04-02 16:41:03 -070027import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
28import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
Craig Mautner8d341ef2013-03-26 09:03:27 -070029import static com.android.server.am.ActivityManagerService.TAG;
30
Craig Mautner2420ead2013-04-01 17:13:20 -070031import android.app.Activity;
Craig Mautner23ac33b2013-04-01 16:26:35 -070032import android.app.ActivityManager;
33import android.app.ActivityOptions;
34import android.app.AppGlobals;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070035import android.app.IActivityManager;
Craig Mautner23ac33b2013-04-01 16:26:35 -070036import android.app.IApplicationThread;
Craig Mautner20e72272013-04-01 13:45:53 -070037import android.app.IThumbnailReceiver;
Craig Mautner23ac33b2013-04-01 16:26:35 -070038import android.app.PendingIntent;
Craig Mautner20e72272013-04-01 13:45:53 -070039import android.app.ActivityManager.RunningTaskInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070040import android.app.IActivityManager.WaitResult;
Craig Mautner2420ead2013-04-01 17:13:20 -070041import android.app.ResultInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070042import android.content.ComponentName;
Craig Mautner2219a1b2013-03-25 09:44:30 -070043import android.content.Context;
Craig Mautner23ac33b2013-04-01 16:26:35 -070044import android.content.IIntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070045import android.content.Intent;
Craig Mautner23ac33b2013-04-01 16:26:35 -070046import android.content.IntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070047import android.content.pm.ActivityInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070048import android.content.pm.ApplicationInfo;
49import android.content.pm.PackageManager;
50import android.content.pm.ResolveInfo;
51import android.content.res.Configuration;
52import android.os.Binder;
Craig Mautner8d341ef2013-03-26 09:03:27 -070053import android.os.Bundle;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070054import android.os.Handler;
Craig Mautner23ac33b2013-04-01 16:26:35 -070055import android.os.IBinder;
Craig Mautner2219a1b2013-03-25 09:44:30 -070056import android.os.Looper;
Craig Mautner2420ead2013-04-01 17:13:20 -070057import android.os.Message;
Craig Mautner23ac33b2013-04-01 16:26:35 -070058import android.os.ParcelFileDescriptor;
Craig Mautner8d341ef2013-03-26 09:03:27 -070059import android.os.RemoteException;
Craig Mautner23ac33b2013-04-01 16:26:35 -070060import android.os.SystemClock;
Craig Mautner6170f732013-04-02 13:05:23 -070061import android.os.UserHandle;
Craig Mautner2420ead2013-04-01 17:13:20 -070062import android.util.EventLog;
Craig Mautner8d341ef2013-03-26 09:03:27 -070063import android.util.Slog;
Craig Mautner2219a1b2013-03-25 09:44:30 -070064
Craig Mautner23ac33b2013-04-01 16:26:35 -070065import com.android.internal.app.HeavyWeightSwitcherActivity;
Craig Mautner6170f732013-04-02 13:05:23 -070066import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
Craig Mautner2420ead2013-04-01 17:13:20 -070067import com.android.server.am.ActivityStack.ActivityState;
Craig Mautnerde4ef022013-04-07 19:01:33 -070068import com.android.server.wm.StackBox;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070069import com.android.server.wm.WindowManagerService;
Craig Mautner23ac33b2013-04-01 16:26:35 -070070
Craig Mautner8d341ef2013-03-26 09:03:27 -070071import java.io.FileDescriptor;
72import java.io.IOException;
Craig Mautner27084302013-03-25 08:05:25 -070073import java.io.PrintWriter;
Craig Mautner2219a1b2013-03-25 09:44:30 -070074import java.util.ArrayList;
Craig Mautner8d341ef2013-03-26 09:03:27 -070075import java.util.List;
Craig Mautner27084302013-03-25 08:05:25 -070076
77public class ActivityStackSupervisor {
Craig Mautnera9a3fb12013-04-18 10:01:00 -070078 static final boolean DEBUG_STACK = ActivityManagerService.DEBUG_STACK;
79
Craig Mautnerde4ef022013-04-07 19:01:33 -070080 static final boolean DEBUG = ActivityManagerService.DEBUG || false;
81 static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
82 static final boolean DEBUG_APP = DEBUG || false;
83 static final boolean DEBUG_SAVED_STATE = DEBUG || false;
84 static final boolean DEBUG_STATES = DEBUG || false;
Craig Mautner2420ead2013-04-01 17:13:20 -070085
Craig Mautner2219a1b2013-03-25 09:44:30 -070086 public static final int HOME_STACK_ID = 0;
Craig Mautner27084302013-03-25 08:05:25 -070087
88 final ActivityManagerService mService;
Craig Mautner2219a1b2013-03-25 09:44:30 -070089 final Context mContext;
90 final Looper mLooper;
Craig Mautner27084302013-03-25 08:05:25 -070091
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070092 final ActivityStackSupervisorHandler mHandler;
93
94 /** Short cut */
95 WindowManagerService mWindowManager;
96
Craig Mautner27084302013-03-25 08:05:25 -070097 /** Dismiss the keyguard after the next activity is displayed? */
98 private boolean mDismissKeyguardOnNextActivity = false;
99
Craig Mautner8d341ef2013-03-26 09:03:27 -0700100 /** Identifier counter for all ActivityStacks */
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700101 private int mLastStackId = HOME_STACK_ID;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700102
103 /** Task identifier that activities are currently being started in. Incremented each time a
104 * new task is created. */
105 private int mCurTaskId = 0;
106
Craig Mautner2420ead2013-04-01 17:13:20 -0700107 /** The current user */
108 private int mCurrentUser;
109
Craig Mautner8d341ef2013-03-26 09:03:27 -0700110 /** The stack containing the launcher app */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700111 private ActivityStack mHomeStack;
Craig Mautner20e72272013-04-01 13:45:53 -0700112
Craig Mautnerde4ef022013-04-07 19:01:33 -0700113 /** The non-home stack currently receiving input or launching the next activity. If home is
Craig Mautner29219d92013-04-16 20:19:12 -0700114 * in front then mHomeStack overrides mFocusedStack. */
115 private ActivityStack mFocusedStack;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700116
117 /** All the non-launcher stacks */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700118 private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
119
Craig Mautnerde4ef022013-04-07 19:01:33 -0700120 private static final int STACK_STATE_HOME_IN_FRONT = 0;
121 private static final int STACK_STATE_HOME_TO_BACK = 1;
122 private static final int STACK_STATE_HOME_IN_BACK = 2;
123 private static final int STACK_STATE_HOME_TO_FRONT = 3;
124 private int mStackState = STACK_STATE_HOME_IN_FRONT;
125
126 /** List of activities that are waiting for a new activity to become visible before completing
127 * whatever operation they are supposed to do. */
128 final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();
129
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700130 /** List of processes waiting to find out about the next visible activity. */
131 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible =
132 new ArrayList<IActivityManager.WaitResult>();
133
134 /** List of processes waiting to find out about the next launched activity. */
135 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched =
136 new ArrayList<IActivityManager.WaitResult>();
137
Craig Mautnerde4ef022013-04-07 19:01:33 -0700138 /** List of activities that are ready to be stopped, but waiting for the next activity to
139 * settle down before doing so. */
140 final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();
141
142 /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity
143 * is being brought in front of us. */
144 boolean mUserLeaving = false;
145
Craig Mautner2219a1b2013-03-25 09:44:30 -0700146 public ActivityStackSupervisor(ActivityManagerService service, Context context,
147 Looper looper) {
Craig Mautner27084302013-03-25 08:05:25 -0700148 mService = service;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700149 mContext = context;
150 mLooper = looper;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700151 mHandler = new ActivityStackSupervisorHandler(looper);
Craig Mautner2219a1b2013-03-25 09:44:30 -0700152 }
153
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700154 void setWindowManager(WindowManagerService wm) {
155 mWindowManager = wm;
156 mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700157 mStacks.add(mHomeStack);
Craig Mautner27084302013-03-25 08:05:25 -0700158 }
159
160 void dismissKeyguard() {
161 if (mDismissKeyguardOnNextActivity) {
162 mDismissKeyguardOnNextActivity = false;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700163 mWindowManager.dismissKeyguard();
Craig Mautner27084302013-03-25 08:05:25 -0700164 }
165 }
166
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700167 ActivityStack getFocusedStack() {
Craig Mautnerf88c50f2013-04-18 19:25:12 -0700168 if (mFocusedStack == null) {
169 return mHomeStack;
170 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700171 switch (mStackState) {
172 case STACK_STATE_HOME_IN_FRONT:
173 case STACK_STATE_HOME_TO_FRONT:
174 return mHomeStack;
175 case STACK_STATE_HOME_IN_BACK:
176 case STACK_STATE_HOME_TO_BACK:
177 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700178 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700179 }
Craig Mautner20e72272013-04-01 13:45:53 -0700180 }
181
Craig Mautnerde4ef022013-04-07 19:01:33 -0700182 ActivityStack getLastStack() {
183 switch (mStackState) {
184 case STACK_STATE_HOME_IN_FRONT:
185 case STACK_STATE_HOME_TO_BACK:
186 return mHomeStack;
187 case STACK_STATE_HOME_TO_FRONT:
188 case STACK_STATE_HOME_IN_BACK:
189 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700190 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700191 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700192 }
193
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700194 boolean isFocusedStack(ActivityStack stack) {
195 return getFocusedStack() == stack;
196 }
197
Craig Mautnerde4ef022013-04-07 19:01:33 -0700198 boolean isFrontStack(ActivityStack stack) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700199 return !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
Craig Mautner20e72272013-04-01 13:45:53 -0700200 }
201
Craig Mautnerde4ef022013-04-07 19:01:33 -0700202 boolean homeIsInFront() {
203 return isFrontStack(mHomeStack);
204 }
205
206 void moveHomeStack(boolean toFront) {
207 final boolean homeInFront = isFrontStack(mHomeStack);
208 if (homeInFront ^ toFront) {
209 mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
210 }
211 }
212
Craig Mautner69ada552013-04-18 13:51:51 -0700213 boolean resumeHomeActivity(ActivityRecord prev) {
214 moveHomeStack(true);
215 if (prev != null) {
216 prev.mLaunchHomeTaskNext = false;
217 }
218 if (mHomeStack.topRunningActivityLocked(null) != null) {
219 return mHomeStack.resumeTopActivityLocked(prev);
220 }
221 return mService.startHomeActivityLocked(mCurrentUser);
222 }
223
Craig Mautnerde4ef022013-04-07 19:01:33 -0700224 final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r,
225 ActivityStack stack) {
226 if (stack == mHomeStack) {
227 return;
228 }
229 if ((sourceRecord == null && getLastStack() == mHomeStack) ||
230 (sourceRecord != null && sourceRecord.isHomeActivity)) {
231 if (r == null) {
232 r = stack.topRunningActivityLocked(null);
233 }
234 if (r != null && !r.isHomeActivity && r.isRootActivity()) {
235 r.mLaunchHomeTaskNext = true;
236 }
237 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700238 }
239
Craig Mautner27084302013-03-25 08:05:25 -0700240 void setDismissKeyguard(boolean dismiss) {
241 mDismissKeyguardOnNextActivity = dismiss;
242 }
243
Craig Mautner8d341ef2013-03-26 09:03:27 -0700244 TaskRecord anyTaskForIdLocked(int id) {
245 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
246 ActivityStack stack = mStacks.get(stackNdx);
247 TaskRecord task = stack.taskForIdLocked(id);
248 if (task != null) {
249 return task;
250 }
251 }
252 return null;
253 }
254
Craig Mautner6170f732013-04-02 13:05:23 -0700255 ActivityRecord isInAnyStackLocked(IBinder token) {
256 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
257 final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
258 if (r != null) {
259 return r;
260 }
261 }
262 return null;
263 }
264
Craig Mautner8d341ef2013-03-26 09:03:27 -0700265 int getNextTaskId() {
266 do {
267 mCurTaskId++;
268 if (mCurTaskId <= 0) {
269 mCurTaskId = 1;
270 }
271 } while (anyTaskForIdLocked(mCurTaskId) != null);
272 return mCurTaskId;
273 }
274
Craig Mautnerde4ef022013-04-07 19:01:33 -0700275 void removeTask(TaskRecord task) {
276 final ActivityStack stack = task.stack;
277 if (stack.removeTask(task) && !stack.isHomeStack()) {
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700278 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700279 mStacks.remove(stack);
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700280 final int stackId = stack.mStackId;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700281 final int nextStackId = mWindowManager.removeStack(stackId);
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700282 // TODO: Perhaps we need to let the ActivityManager determine the next focus...
Craig Mautner29219d92013-04-16 20:19:12 -0700283 if (mFocusedStack.mStackId == stackId) {
284 mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700285 }
286 }
287 }
288
289 ActivityRecord resumedAppLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700290 ActivityStack stack = getFocusedStack();
291 if (stack == null) {
292 return null;
293 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700294 ActivityRecord resumedActivity = stack.mResumedActivity;
295 if (resumedActivity == null || resumedActivity.app == null) {
296 resumedActivity = stack.mPausingActivity;
297 if (resumedActivity == null || resumedActivity.app == null) {
298 resumedActivity = stack.topRunningActivityLocked(null);
299 }
300 }
301 return resumedActivity;
302 }
303
Craig Mautner20e72272013-04-01 13:45:53 -0700304 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
305 boolean didSomething = false;
306 final String processName = app.processName;
307 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
308 final ActivityStack stack = mStacks.get(stackNdx);
309 ActivityRecord hr = stack.topRunningActivityLocked(null);
310 if (hr != null) {
311 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
312 && processName.equals(hr.processName)) {
313 try {
314 if (headless) {
315 Slog.e(TAG, "Starting activities not supported on headless device: "
316 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700317 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700318 didSomething = true;
319 }
320 } catch (Exception e) {
321 Slog.w(TAG, "Exception in new application when starting activity "
322 + hr.intent.getComponent().flattenToShortString(), e);
323 throw e;
324 }
325 } else {
326 stack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
327 }
328 }
329 }
330 return didSomething;
331 }
332
333 boolean allResumedActivitiesIdle() {
334 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700335 final ActivityRecord resumedActivity = mStacks.get(stackNdx).mResumedActivity;
336 if (resumedActivity == null || !resumedActivity.idle) {
Craig Mautner20e72272013-04-01 13:45:53 -0700337 return false;
338 }
339 }
340 return true;
341 }
342
Craig Mautnerde4ef022013-04-07 19:01:33 -0700343 boolean allResumedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700344 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
345 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner967212c2013-04-13 21:10:58 -0700346 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700347 final ActivityRecord r = stack.mResumedActivity;
348 if (r != null && r.state != ActivityState.RESUMED) {
349 return false;
350 }
351 }
352 }
353 // TODO: Not sure if this should check if all Paused are complete too.
354 switch (mStackState) {
355 case STACK_STATE_HOME_TO_BACK:
356 mStackState = STACK_STATE_HOME_IN_BACK;
357 break;
358 case STACK_STATE_HOME_TO_FRONT:
359 mStackState = STACK_STATE_HOME_IN_FRONT;
360 break;
361 }
362 return true;
363 }
364
365 boolean allResumedActivitiesVisible() {
366 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
367 final ActivityStack stack = mStacks.get(stackNdx);
368 final ActivityRecord r = stack.mResumedActivity;
369 if (r != null && (!r.nowVisible || r.waitingVisible)) {
370 return false;
371 }
372 }
373 return true;
374 }
375
376 boolean allPausedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700377 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
378 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner69ada552013-04-18 13:51:51 -0700379 final ActivityRecord r = stack.mPausingActivity;
380 if (r != null && r.state != ActivityState.PAUSED
381 && r.state != ActivityState.STOPPED
382 && r.state != ActivityState.STOPPING) {
383 return false;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700384 }
385 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700386 return true;
387 }
388
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700389 void reportActivityVisibleLocked(ActivityRecord r) {
390 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
391 WaitResult w = mWaitingActivityVisible.get(i);
392 w.timeout = false;
393 if (r != null) {
394 w.who = new ComponentName(r.info.packageName, r.info.name);
395 }
396 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
397 w.thisTime = w.totalTime;
398 }
399 mService.notifyAll();
400 dismissKeyguard();
401 }
402
403 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
404 long thisTime, long totalTime) {
405 for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
406 WaitResult w = mWaitingActivityLaunched.get(i);
407 w.timeout = timeout;
408 if (r != null) {
409 w.who = new ComponentName(r.info.packageName, r.info.name);
410 }
411 w.thisTime = thisTime;
412 w.totalTime = totalTime;
413 }
414 mService.notifyAll();
415 }
416
Craig Mautner29219d92013-04-16 20:19:12 -0700417 ActivityRecord topRunningActivityLocked() {
418 ActivityRecord r = null;
419 if (mFocusedStack != null) {
420 r = mFocusedStack.topRunningActivityLocked(null);
421 if (r != null) {
422 return r;
423 }
424 }
425 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
426 final ActivityStack stack = mStacks.get(stackNdx);
427 if (stack != mFocusedStack && isFrontStack(stack)) {
428 r = stack.topRunningActivityLocked(null);
429 if (r != null) {
430 return r;
431 }
432 }
433 }
434 return null;
435 }
436
Craig Mautner20e72272013-04-01 13:45:53 -0700437 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
438 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
439 ActivityRecord r = null;
440 final int numStacks = mStacks.size();
441 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
442 final ActivityStack stack = mStacks.get(stackNdx);
443 final ActivityRecord ar =
444 stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700445 if (isFrontStack(stack)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700446 r = ar;
447 }
448 }
449 return r;
450 }
451
Craig Mautner23ac33b2013-04-01 16:26:35 -0700452 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
453 String profileFile, ParcelFileDescriptor profileFd, int userId) {
454 // Collect information about the target of the Intent.
455 ActivityInfo aInfo;
456 try {
457 ResolveInfo rInfo =
458 AppGlobals.getPackageManager().resolveIntent(
459 intent, resolvedType,
460 PackageManager.MATCH_DEFAULT_ONLY
461 | ActivityManagerService.STOCK_PM_FLAGS, userId);
462 aInfo = rInfo != null ? rInfo.activityInfo : null;
463 } catch (RemoteException e) {
464 aInfo = null;
465 }
466
467 if (aInfo != null) {
468 // Store the found target back into the intent, because now that
469 // we have it we never want to do this again. For example, if the
470 // user navigates back to this point in the history, we should
471 // always restart the exact same activity.
472 intent.setComponent(new ComponentName(
473 aInfo.applicationInfo.packageName, aInfo.name));
474
475 // Don't debug things in the system process
476 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
477 if (!aInfo.processName.equals("system")) {
478 mService.setDebugApp(aInfo.processName, true, false);
479 }
480 }
481
482 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
483 if (!aInfo.processName.equals("system")) {
484 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
485 }
486 }
487
488 if (profileFile != null) {
489 if (!aInfo.processName.equals("system")) {
490 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
491 profileFile, profileFd,
492 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
493 }
494 }
495 }
496 return aInfo;
497 }
498
Craig Mautner2219a1b2013-03-25 09:44:30 -0700499 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700500 moveHomeStack(true);
Craig Mautner6170f732013-04-02 13:05:23 -0700501 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
Craig Mautner2219a1b2013-03-25 09:44:30 -0700502 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700503 }
504
Craig Mautner23ac33b2013-04-01 16:26:35 -0700505 final int startActivityMayWait(IApplicationThread caller, int callingUid,
506 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
507 String resultWho, int requestCode, int startFlags, String profileFile,
508 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
509 Bundle options, int userId) {
510 // Refuse possible leaked file descriptors
511 if (intent != null && intent.hasFileDescriptors()) {
512 throw new IllegalArgumentException("File descriptors passed in Intent");
513 }
514 boolean componentSpecified = intent.getComponent() != null;
515
516 // Don't modify the client's object!
517 intent = new Intent(intent);
518
519 // Collect information about the target of the Intent.
520 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
521 profileFile, profileFd, userId);
522
523 synchronized (mService) {
524 int callingPid;
525 if (callingUid >= 0) {
526 callingPid = -1;
527 } else if (caller == null) {
528 callingPid = Binder.getCallingPid();
529 callingUid = Binder.getCallingUid();
530 } else {
531 callingPid = callingUid = -1;
532 }
533
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700534 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -0700535 stack.mConfigWillChange = config != null
Craig Mautner23ac33b2013-04-01 16:26:35 -0700536 && mService.mConfiguration.diff(config) != 0;
537 if (DEBUG_CONFIGURATION) Slog.v(TAG,
Craig Mautnerde4ef022013-04-07 19:01:33 -0700538 "Starting activity when config will change = " + stack.mConfigWillChange);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700539
540 final long origId = Binder.clearCallingIdentity();
541
542 if (aInfo != null &&
543 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
544 // This may be a heavy-weight process! Check to see if we already
545 // have another, different heavy-weight process running.
546 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
547 if (mService.mHeavyWeightProcess != null &&
548 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
549 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
550 int realCallingPid = callingPid;
551 int realCallingUid = callingUid;
552 if (caller != null) {
553 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
554 if (callerApp != null) {
555 realCallingPid = callerApp.pid;
556 realCallingUid = callerApp.info.uid;
557 } else {
558 Slog.w(TAG, "Unable to find app for caller " + caller
559 + " (pid=" + realCallingPid + ") when starting: "
560 + intent.toString());
561 ActivityOptions.abort(options);
562 return ActivityManager.START_PERMISSION_DENIED;
563 }
564 }
565
566 IIntentSender target = mService.getIntentSenderLocked(
567 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
568 realCallingUid, userId, null, null, 0, new Intent[] { intent },
569 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
570 | PendingIntent.FLAG_ONE_SHOT, null);
571
572 Intent newIntent = new Intent();
573 if (requestCode >= 0) {
574 // Caller is requesting a result.
575 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
576 }
577 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
578 new IntentSender(target));
579 if (mService.mHeavyWeightProcess.activities.size() > 0) {
580 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
581 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
582 hist.packageName);
583 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
584 hist.task.taskId);
585 }
586 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
587 aInfo.packageName);
588 newIntent.setFlags(intent.getFlags());
589 newIntent.setClassName("android",
590 HeavyWeightSwitcherActivity.class.getName());
591 intent = newIntent;
592 resolvedType = null;
593 caller = null;
594 callingUid = Binder.getCallingUid();
595 callingPid = Binder.getCallingPid();
596 componentSpecified = true;
597 try {
598 ResolveInfo rInfo =
599 AppGlobals.getPackageManager().resolveIntent(
600 intent, null,
601 PackageManager.MATCH_DEFAULT_ONLY
602 | ActivityManagerService.STOCK_PM_FLAGS, userId);
603 aInfo = rInfo != null ? rInfo.activityInfo : null;
604 aInfo = mService.getActivityInfoForUser(aInfo, userId);
605 } catch (RemoteException e) {
606 aInfo = null;
607 }
608 }
609 }
610 }
611
Craig Mautner6170f732013-04-02 13:05:23 -0700612 int res = startActivityLocked(caller, intent, resolvedType,
Craig Mautner23ac33b2013-04-01 16:26:35 -0700613 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
614 callingPackage, startFlags, options, componentSpecified, null);
615
Craig Mautnerde4ef022013-04-07 19:01:33 -0700616 if (stack.mConfigWillChange) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700617 // If the caller also wants to switch to a new configuration,
618 // do so now. This allows a clean switch, as we are waiting
619 // for the current activity to pause (so we will not destroy
620 // it), and have not yet started the next activity.
621 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
622 "updateConfiguration()");
Craig Mautnerde4ef022013-04-07 19:01:33 -0700623 stack.mConfigWillChange = false;
Craig Mautner23ac33b2013-04-01 16:26:35 -0700624 if (DEBUG_CONFIGURATION) Slog.v(TAG,
625 "Updating to new configuration after starting activity.");
626 mService.updateConfigurationLocked(config, null, false, false);
627 }
628
629 Binder.restoreCallingIdentity(origId);
630
631 if (outResult != null) {
632 outResult.result = res;
633 if (res == ActivityManager.START_SUCCESS) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700634 mWaitingActivityLaunched.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700635 do {
636 try {
637 mService.wait();
638 } catch (InterruptedException e) {
639 }
640 } while (!outResult.timeout && outResult.who == null);
641 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700642 ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700643 if (r.nowVisible) {
644 outResult.timeout = false;
645 outResult.who = new ComponentName(r.info.packageName, r.info.name);
646 outResult.totalTime = 0;
647 outResult.thisTime = 0;
648 } else {
649 outResult.thisTime = SystemClock.uptimeMillis();
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700650 mWaitingActivityVisible.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700651 do {
652 try {
653 mService.wait();
654 } catch (InterruptedException e) {
655 }
656 } while (!outResult.timeout && outResult.who == null);
657 }
658 }
659 }
660
661 return res;
662 }
663 }
664
665 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
666 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
667 Bundle options, int userId) {
668 if (intents == null) {
669 throw new NullPointerException("intents is null");
670 }
671 if (resolvedTypes == null) {
672 throw new NullPointerException("resolvedTypes is null");
673 }
674 if (intents.length != resolvedTypes.length) {
675 throw new IllegalArgumentException("intents are length different than resolvedTypes");
676 }
677
678 ActivityRecord[] outActivity = new ActivityRecord[1];
679
680 int callingPid;
681 if (callingUid >= 0) {
682 callingPid = -1;
683 } else if (caller == null) {
684 callingPid = Binder.getCallingPid();
685 callingUid = Binder.getCallingUid();
686 } else {
687 callingPid = callingUid = -1;
688 }
689 final long origId = Binder.clearCallingIdentity();
690 try {
691 synchronized (mService) {
692
693 for (int i=0; i<intents.length; i++) {
694 Intent intent = intents[i];
695 if (intent == null) {
696 continue;
697 }
698
699 // Refuse possible leaked file descriptors
700 if (intent != null && intent.hasFileDescriptors()) {
701 throw new IllegalArgumentException("File descriptors passed in Intent");
702 }
703
704 boolean componentSpecified = intent.getComponent() != null;
705
706 // Don't modify the client's object!
707 intent = new Intent(intent);
708
709 // Collect information about the target of the Intent.
710 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
711 0, null, null, userId);
712 // TODO: New, check if this is correct
713 aInfo = mService.getActivityInfoForUser(aInfo, userId);
714
715 if (aInfo != null &&
716 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
717 != 0) {
718 throw new IllegalArgumentException(
719 "FLAG_CANT_SAVE_STATE not supported here");
720 }
721
722 Bundle theseOptions;
723 if (options != null && i == intents.length-1) {
724 theseOptions = options;
725 } else {
726 theseOptions = null;
727 }
Craig Mautner6170f732013-04-02 13:05:23 -0700728 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Craig Mautner23ac33b2013-04-01 16:26:35 -0700729 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
730 0, theseOptions, componentSpecified, outActivity);
731 if (res < 0) {
732 return res;
733 }
734
735 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
736 }
737 }
738 } finally {
739 Binder.restoreCallingIdentity(origId);
740 }
741
742 return ActivityManager.START_SUCCESS;
743 }
744
Craig Mautner2420ead2013-04-01 17:13:20 -0700745 final boolean realStartActivityLocked(ActivityRecord r,
746 ProcessRecord app, boolean andResume, boolean checkConfig)
747 throws RemoteException {
748
749 r.startFreezingScreenLocked(app, 0);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700750 mWindowManager.setAppVisibility(r.appToken, true);
Craig Mautner2420ead2013-04-01 17:13:20 -0700751
752 // schedule launch ticks to collect information about slow apps.
753 r.startLaunchTickingLocked();
754
755 // Have the window manager re-evaluate the orientation of
756 // the screen based on the new activity order. Note that
757 // as a result of this, it can call back into the activity
758 // manager with a new orientation. We don't care about that,
759 // because the activity is not currently running so we are
760 // just restarting it anyway.
761 if (checkConfig) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700762 Configuration config = mWindowManager.updateOrientationFromAppTokens(
Craig Mautner2420ead2013-04-01 17:13:20 -0700763 mService.mConfiguration,
764 r.mayFreezeScreenLocked(app) ? r.appToken : null);
765 mService.updateConfigurationLocked(config, r, false, false);
766 }
767
768 r.app = app;
769 app.waitingToKill = null;
770 r.launchCount++;
771 r.lastLaunchTime = SystemClock.uptimeMillis();
772
773 if (localLOGV) Slog.v(TAG, "Launching: " + r);
774
775 int idx = app.activities.indexOf(r);
776 if (idx < 0) {
777 app.activities.add(r);
778 }
779 mService.updateLruProcessLocked(app, true);
780
781 final ActivityStack stack = r.task.stack;
782 try {
783 if (app.thread == null) {
784 throw new RemoteException();
785 }
786 List<ResultInfo> results = null;
787 List<Intent> newIntents = null;
788 if (andResume) {
789 results = r.results;
790 newIntents = r.newIntents;
791 }
792 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
793 + " icicle=" + r.icicle
794 + " with results=" + results + " newIntents=" + newIntents
795 + " andResume=" + andResume);
796 if (andResume) {
797 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
798 r.userId, System.identityHashCode(r),
799 r.task.taskId, r.shortComponentName);
800 }
801 if (r.isHomeActivity) {
802 mService.mHomeProcess = app;
803 }
804 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
805 r.sleeping = false;
806 r.forceNewConfig = false;
807 mService.showAskCompatModeDialogLocked(r);
808 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
809 String profileFile = null;
810 ParcelFileDescriptor profileFd = null;
811 boolean profileAutoStop = false;
812 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
813 if (mService.mProfileProc == null || mService.mProfileProc == app) {
814 mService.mProfileProc = app;
815 profileFile = mService.mProfileFile;
816 profileFd = mService.mProfileFd;
817 profileAutoStop = mService.mAutoStopProfiler;
818 }
819 }
820 app.hasShownUi = true;
821 app.pendingUiClean = true;
822 if (profileFd != null) {
823 try {
824 profileFd = profileFd.dup();
825 } catch (IOException e) {
826 if (profileFd != null) {
827 try {
828 profileFd.close();
829 } catch (IOException o) {
830 }
831 profileFd = null;
832 }
833 }
834 }
835 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
836 System.identityHashCode(r), r.info,
837 new Configuration(mService.mConfiguration),
838 r.compat, r.icicle, results, newIntents, !andResume,
839 mService.isNextTransitionForward(), profileFile, profileFd,
840 profileAutoStop);
841
842 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
843 // This may be a heavy-weight process! Note that the package
844 // manager will ensure that only activity can run in the main
845 // process of the .apk, which is the only thing that will be
846 // considered heavy-weight.
847 if (app.processName.equals(app.info.packageName)) {
848 if (mService.mHeavyWeightProcess != null
849 && mService.mHeavyWeightProcess != app) {
850 Slog.w(TAG, "Starting new heavy weight process " + app
851 + " when already running "
852 + mService.mHeavyWeightProcess);
853 }
854 mService.mHeavyWeightProcess = app;
855 Message msg = mService.mHandler.obtainMessage(
856 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
857 msg.obj = r;
858 mService.mHandler.sendMessage(msg);
859 }
860 }
861
862 } catch (RemoteException e) {
863 if (r.launchFailed) {
864 // This is the second time we failed -- finish activity
865 // and give up.
866 Slog.e(TAG, "Second failure launching "
867 + r.intent.getComponent().flattenToShortString()
868 + ", giving up", e);
869 mService.appDiedLocked(app, app.pid, app.thread);
870 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
871 "2nd-crash", false);
872 return false;
873 }
874
875 // This is the first time we failed -- restart process and
876 // retry.
877 app.activities.remove(r);
878 throw e;
879 }
880
881 r.launchFailed = false;
882 if (stack.updateLRUListLocked(r)) {
883 Slog.w(TAG, "Activity " + r
884 + " being launched, but already in LRU list");
885 }
886
887 if (andResume) {
888 // As part of the process of launching, ActivityThread also performs
889 // a resume.
890 stack.minimalResumeActivityLocked(r);
891 } else {
892 // This activity is not starting in the resumed state... which
893 // should look like we asked it to pause+stop (but remain visible),
894 // and it has done so and reported back the current icicle and
895 // other state.
896 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
897 + " (starting in stopped state)");
898 r.state = ActivityState.STOPPED;
899 r.stopped = true;
900 }
901
902 // Launch the new version setup screen if needed. We do this -after-
903 // launching the initial activity (that is, home), so that it can have
904 // a chance to initialize itself while in the background, making the
905 // switch back to it faster and look better.
Craig Mautnerde4ef022013-04-07 19:01:33 -0700906 if (isFrontStack(stack)) {
Craig Mautner2420ead2013-04-01 17:13:20 -0700907 mService.startSetupActivityLocked();
908 }
909
910 return true;
911 }
912
Craig Mautnere79d42682013-04-01 19:01:53 -0700913 void startSpecificActivityLocked(ActivityRecord r,
914 boolean andResume, boolean checkConfig) {
915 // Is this activity's application already running?
916 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
917 r.info.applicationInfo.uid);
918
919 r.task.stack.setLaunchTime(r);
920
921 if (app != null && app.thread != null) {
922 try {
923 app.addPackage(r.info.packageName);
924 realStartActivityLocked(r, app, andResume, checkConfig);
925 return;
926 } catch (RemoteException e) {
927 Slog.w(TAG, "Exception when starting activity "
928 + r.intent.getComponent().flattenToShortString(), e);
929 }
930
931 // If a dead object exception was thrown -- fall through to
932 // restart the application.
933 }
934
935 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
936 "activity", r.intent.getComponent(), false, false);
937 }
938
Craig Mautner6170f732013-04-02 13:05:23 -0700939 final int startActivityLocked(IApplicationThread caller,
940 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
941 String resultWho, int requestCode,
942 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
943 boolean componentSpecified, ActivityRecord[] outActivity) {
944 int err = ActivityManager.START_SUCCESS;
945
946 ProcessRecord callerApp = null;
947 if (caller != null) {
948 callerApp = mService.getRecordForAppLocked(caller);
949 if (callerApp != null) {
950 callingPid = callerApp.pid;
951 callingUid = callerApp.info.uid;
952 } else {
953 Slog.w(TAG, "Unable to find app for caller " + caller
954 + " (pid=" + callingPid + ") when starting: "
955 + intent.toString());
956 err = ActivityManager.START_PERMISSION_DENIED;
957 }
958 }
959
960 if (err == ActivityManager.START_SUCCESS) {
961 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
962 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
963 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
964 }
965
966 ActivityRecord sourceRecord = null;
967 ActivityRecord resultRecord = null;
968 if (resultTo != null) {
969 sourceRecord = isInAnyStackLocked(resultTo);
970 if (DEBUG_RESULTS) Slog.v(
971 TAG, "Will send result to " + resultTo + " " + sourceRecord);
972 if (sourceRecord != null) {
973 if (requestCode >= 0 && !sourceRecord.finishing) {
974 resultRecord = sourceRecord;
975 }
976 }
977 }
978 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
979
980 int launchFlags = intent.getFlags();
981
982 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
983 && sourceRecord != null) {
984 // Transfer the result target from the source activity to the new
985 // one being started, including any failures.
986 if (requestCode >= 0) {
987 ActivityOptions.abort(options);
988 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
989 }
990 resultRecord = sourceRecord.resultTo;
991 resultWho = sourceRecord.resultWho;
992 requestCode = sourceRecord.requestCode;
993 sourceRecord.resultTo = null;
994 if (resultRecord != null) {
995 resultRecord.removeResultsLocked(
996 sourceRecord, resultWho, requestCode);
997 }
998 }
999
1000 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
1001 // We couldn't find a class that can handle the given Intent.
1002 // That's the end of that!
1003 err = ActivityManager.START_INTENT_NOT_RESOLVED;
1004 }
1005
1006 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
1007 // We couldn't find the specific class specified in the Intent.
1008 // Also the end of the line.
1009 err = ActivityManager.START_CLASS_NOT_FOUND;
1010 }
1011
1012 if (err != ActivityManager.START_SUCCESS) {
1013 if (resultRecord != null) {
1014 resultStack.sendActivityResultLocked(-1,
1015 resultRecord, resultWho, requestCode,
1016 Activity.RESULT_CANCELED, null);
1017 }
1018 setDismissKeyguard(false);
1019 ActivityOptions.abort(options);
1020 return err;
1021 }
1022
1023 final int startAnyPerm = mService.checkPermission(
1024 START_ANY_ACTIVITY, callingPid, callingUid);
1025 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
1026 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
1027 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
1028 if (resultRecord != null) {
1029 resultStack.sendActivityResultLocked(-1,
1030 resultRecord, resultWho, requestCode,
1031 Activity.RESULT_CANCELED, null);
1032 }
1033 setDismissKeyguard(false);
1034 String msg;
1035 if (!aInfo.exported) {
1036 msg = "Permission Denial: starting " + intent.toString()
1037 + " from " + callerApp + " (pid=" + callingPid
1038 + ", uid=" + callingUid + ")"
1039 + " not exported from uid " + aInfo.applicationInfo.uid;
1040 } else {
1041 msg = "Permission Denial: starting " + intent.toString()
1042 + " from " + callerApp + " (pid=" + callingPid
1043 + ", uid=" + callingUid + ")"
1044 + " requires " + aInfo.permission;
1045 }
1046 Slog.w(TAG, msg);
1047 throw new SecurityException(msg);
1048 }
1049
Ben Gruver6617c3c2013-04-03 18:45:22 -07001050 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
Ben Gruver7b879f42013-04-08 14:56:55 -07001051 callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo);
Ben Gruver5e207332013-04-03 17:41:37 -07001052
Craig Mautner6170f732013-04-02 13:05:23 -07001053 if (mService.mController != null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001054 try {
1055 // The Intent we give to the watcher has the extra data
1056 // stripped off, since it can contain private information.
1057 Intent watchIntent = intent.cloneFilter();
Ben Gruver5e207332013-04-03 17:41:37 -07001058 abort |= !mService.mController.activityStarting(watchIntent,
Craig Mautner6170f732013-04-02 13:05:23 -07001059 aInfo.applicationInfo.packageName);
1060 } catch (RemoteException e) {
1061 mService.mController = null;
1062 }
Ben Gruver5e207332013-04-03 17:41:37 -07001063 }
Craig Mautner6170f732013-04-02 13:05:23 -07001064
Ben Gruver5e207332013-04-03 17:41:37 -07001065 if (abort) {
1066 if (resultRecord != null) {
1067 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Craig Mautner6170f732013-04-02 13:05:23 -07001068 Activity.RESULT_CANCELED, null);
Craig Mautner6170f732013-04-02 13:05:23 -07001069 }
Ben Gruver5e207332013-04-03 17:41:37 -07001070 // We pretend to the caller that it was really started, but
1071 // they will just get a cancel result.
1072 setDismissKeyguard(false);
1073 ActivityOptions.abort(options);
1074 return ActivityManager.START_SUCCESS;
Craig Mautner6170f732013-04-02 13:05:23 -07001075 }
1076
1077 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1078 intent, resolvedType, aInfo, mService.mConfiguration,
Craig Mautnerde4ef022013-04-07 19:01:33 -07001079 resultRecord, resultWho, requestCode, componentSpecified, this);
Craig Mautner6170f732013-04-02 13:05:23 -07001080 if (outActivity != null) {
1081 outActivity[0] = r;
1082 }
1083
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001084 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001085 if (stack.mResumedActivity == null
1086 || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
Craig Mautner6170f732013-04-02 13:05:23 -07001087 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1088 PendingActivityLaunch pal =
Craig Mautnerde4ef022013-04-07 19:01:33 -07001089 new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
Craig Mautner6170f732013-04-02 13:05:23 -07001090 mService.mPendingActivityLaunches.add(pal);
1091 setDismissKeyguard(false);
1092 ActivityOptions.abort(options);
1093 return ActivityManager.START_SWITCHES_CANCELED;
1094 }
1095 }
1096
1097 if (mService.mDidAppSwitch) {
1098 // This is the second allowed switch since we stopped switches,
1099 // so now just generally allow switches. Use case: user presses
1100 // home (switches disabled, switch to home, mDidAppSwitch now true);
1101 // user taps a home icon (coming from home so allowed, we hit here
1102 // and now allow anyone to switch again).
1103 mService.mAppSwitchesAllowedTime = 0;
1104 } else {
1105 mService.mDidAppSwitch = true;
1106 }
1107
1108 mService.doPendingActivityLaunchesLocked(false);
1109
Craig Mautner8849a5e2013-04-02 16:41:03 -07001110 err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001111 if (stack.mPausingActivity == null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001112 // Someone asked to have the keyguard dismissed on the next
1113 // activity start, but we are not actually doing an activity
1114 // switch... just dismiss the keyguard now, because we
1115 // probably want to see whatever is behind it.
1116 dismissKeyguard();
1117 }
1118 return err;
1119 }
1120
Craig Mautnerde4ef022013-04-07 19:01:33 -07001121 ActivityStack getCorrectStack(ActivityRecord r) {
1122 if (!r.isHomeActivity) {
1123 if (mStacks.size() == 1) {
1124 // Time to create the first app stack.
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001125 int stackId = mService.createStack(-1, HOME_STACK_ID,
1126 StackBox.TASK_STACK_GOES_OVER, 1.0f);
Craig Mautner29219d92013-04-16 20:19:12 -07001127 mFocusedStack = getStack(stackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001128 }
Craig Mautner29219d92013-04-16 20:19:12 -07001129 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001130 }
1131 return mHomeStack;
1132 }
1133
Craig Mautner29219d92013-04-16 20:19:12 -07001134 void setFocusedStack(ActivityRecord r) {
1135 if (r == null) {
1136 return;
1137 }
1138 if (r.isHomeActivity) {
1139 if (mStackState != STACK_STATE_HOME_IN_FRONT) {
1140 mStackState = STACK_STATE_HOME_TO_FRONT;
1141 }
1142 } else {
1143 mFocusedStack = r.task.stack;
1144 if (mStackState != STACK_STATE_HOME_IN_BACK) {
1145 mStackState = STACK_STATE_HOME_TO_BACK;
1146 }
1147 }
1148 }
1149
Craig Mautner8849a5e2013-04-02 16:41:03 -07001150 final int startActivityUncheckedLocked(ActivityRecord r,
1151 ActivityRecord sourceRecord, int startFlags, boolean doResume,
1152 Bundle options) {
1153 final Intent intent = r.intent;
1154 final int callingUid = r.launchedFromUid;
1155
1156 int launchFlags = intent.getFlags();
1157
Craig Mautner8849a5e2013-04-02 16:41:03 -07001158 // We'll invoke onUserLeaving before onPause only if the launching
1159 // activity did not explicitly state that this is an automated launch.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001160 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1161 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001162
1163 // If the caller has asked not to resume at this point, we make note
1164 // of this in the record so that we can skip it when trying to find
1165 // the top running activity.
1166 if (!doResume) {
1167 r.delayedResume = true;
1168 }
1169
1170 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1171
1172 // If the onlyIfNeeded flag is set, then we can do this if the activity
1173 // being launched is the same as the one making the call... or, as
1174 // a special case, if we do not know the caller then we count the
1175 // current top activity as the caller.
1176 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1177 ActivityRecord checkedCaller = sourceRecord;
1178 if (checkedCaller == null) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001179 checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001180 }
1181 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1182 // Caller is not the same as launcher, so always needed.
1183 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1184 }
1185 }
1186
1187 if (sourceRecord == null) {
1188 // This activity is not being started from another... in this
1189 // case we -always- start a new task.
1190 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Craig Mautner29219d92013-04-16 20:19:12 -07001191 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1192 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001193 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1194 }
1195 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1196 // The original activity who is starting us is running as a single
1197 // instance... this new activity it is starting must go on its
1198 // own task.
1199 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1200 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1201 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1202 // The activity being started is a single instance... it always
1203 // gets launched into its own task.
1204 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1205 }
1206
Craig Mautnerde4ef022013-04-07 19:01:33 -07001207 final ActivityStack sourceStack;
1208 final TaskRecord sourceTask;
1209 if (sourceRecord != null) {
1210 sourceTask = sourceRecord.task;
1211 sourceStack = sourceTask.stack;
1212 } else {
1213 sourceTask = null;
1214 sourceStack = null;
1215 }
1216
Craig Mautner8849a5e2013-04-02 16:41:03 -07001217 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1218 // For whatever reason this activity is being launched into a new
1219 // task... yet the caller has requested a result back. Well, that
1220 // is pretty messed up, so instead immediately send back a cancel
1221 // and let the new task continue launched as normal without a
1222 // dependency on its originator.
1223 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1224 r.resultTo.task.stack.sendActivityResultLocked(-1,
1225 r.resultTo, r.resultWho, r.requestCode,
1226 Activity.RESULT_CANCELED, null);
1227 r.resultTo = null;
1228 }
1229
1230 boolean addingToTask = false;
1231 boolean movedHome = false;
1232 TaskRecord reuseTask = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001233 ActivityStack targetStack;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001234 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1235 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1236 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1237 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1238 // If bring to front is requested, and no result is requested, and
1239 // we can find a task that was started with this same
1240 // component, then instead of launching bring that one to the front.
1241 if (r.resultTo == null) {
1242 // See if there is a task to bring to the front. If this is
1243 // a SINGLE_INSTANCE activity, there can be one and only one
1244 // instance of it in the history, and it is always in its own
1245 // unique task, so we do a special search.
1246 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
1247 ? findTaskLocked(intent, r.info)
1248 : findActivityLocked(intent, r.info);
1249 if (intentActivity != null) {
Craig Mautner29219d92013-04-16 20:19:12 -07001250 if (r.task == null) {
1251 r.task = intentActivity.task;
1252 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001253 targetStack = intentActivity.task.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001254 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001255 if (intentActivity.task.intent == null) {
1256 // This task was started because of movement of
1257 // the activity based on affinity... now that we
1258 // are actually launching it, we can assign the
1259 // base intent.
1260 intentActivity.task.setIntent(intent, r.info);
1261 }
1262 // If the target task is not in the front, then we need
1263 // to bring it to the front... except... well, with
1264 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
1265 // to have the same behavior as if a new instance was
1266 // being started, which means not bringing it to the front
1267 // if the caller is not itself in the front.
Craig Mautner165640b2013-04-20 10:34:33 -07001268 final ActivityStack lastStack = getLastStack();
1269 ActivityRecord curTop = lastStack == null?
1270 null : lastStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001271 if (curTop != null && curTop.task != intentActivity.task) {
1272 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001273 if (sourceRecord == null || sourceStack.topActivity() == sourceRecord) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001274 // We really do want to push this one into the
1275 // user's face, right now.
1276 movedHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001277 if ((launchFlags &
Craig Mautner29219d92013-04-16 20:19:12 -07001278 (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1279 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001280 // Caller wants to appear on home activity, so before starting
1281 // their own activity we will bring home to the front.
1282 r.mLaunchHomeTaskNext = true;
1283 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001284 targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1285 options = null;
1286 }
1287 }
1288 // If the caller has requested that the target task be
1289 // reset, then do so.
1290 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1291 intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1292 }
1293 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1294 // We don't need to start a new activity, and
1295 // the client said not to do anything if that
1296 // is the case, so this is it! And for paranoia, make
1297 // sure we have correctly resumed the top activity.
1298 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001299 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001300 targetStack.resumeTopActivityLocked(null, options);
1301 } else {
1302 ActivityOptions.abort(options);
1303 }
Craig Mautner29219d92013-04-16 20:19:12 -07001304 if (r.task == null) Slog.v(TAG,
1305 "startActivityUncheckedLocked: task left null",
1306 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001307 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1308 }
1309 if ((launchFlags &
1310 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1311 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1312 // The caller has requested to completely replace any
1313 // existing task with its new activity. Well that should
1314 // not be too hard...
1315 reuseTask = intentActivity.task;
1316 reuseTask.performClearTaskLocked();
1317 reuseTask.setIntent(r.intent, r.info);
1318 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1319 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1320 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1321 // In this situation we want to remove all activities
1322 // from the task up to the one being started. In most
1323 // cases this means we are resetting the task to its
1324 // initial state.
1325 ActivityRecord top =
1326 intentActivity.task.performClearTaskLocked(r, launchFlags);
1327 if (top != null) {
1328 if (top.frontOfTask) {
1329 // Activity aliases may mean we use different
1330 // intents for the top activity, so make sure
1331 // the task now has the identity of the new
1332 // intent.
1333 top.task.setIntent(r.intent, r.info);
1334 }
1335 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1336 r, top.task);
1337 top.deliverNewIntentLocked(callingUid, r.intent);
1338 } else {
1339 // A special case: we need to
1340 // start the activity because it is not currently
1341 // running, and the caller has asked to clear the
1342 // current task to have this activity at the top.
1343 addingToTask = true;
1344 // Now pretend like this activity is being started
1345 // by the top of its task, so it is put in the
1346 // right place.
1347 sourceRecord = intentActivity;
1348 }
1349 } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1350 // In this case the top activity on the task is the
1351 // same as the one being launched, so we take that
1352 // as a request to bring the task to the foreground.
1353 // If the top activity in the task is the root
1354 // activity, deliver this new intent to it if it
1355 // desires.
1356 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1357 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1358 && intentActivity.realActivity.equals(r.realActivity)) {
1359 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1360 intentActivity.task);
1361 if (intentActivity.frontOfTask) {
1362 intentActivity.task.setIntent(r.intent, r.info);
1363 }
1364 intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1365 } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1366 // In this case we are launching the root activity
1367 // of the task, but with a different intent. We
1368 // should start a new instance on top.
1369 addingToTask = true;
1370 sourceRecord = intentActivity;
1371 }
1372 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1373 // In this case an activity is being launched in to an
1374 // existing task, without resetting that task. This
1375 // is typically the situation of launching an activity
1376 // from a notification or shortcut. We want to place
1377 // the new activity on top of the current task.
1378 addingToTask = true;
1379 sourceRecord = intentActivity;
1380 } else if (!intentActivity.task.rootWasReset) {
1381 // In this case we are launching in to an existing task
1382 // that has not yet been started from its front door.
1383 // The current task has been brought to the front.
1384 // Ideally, we'd probably like to place this new task
1385 // at the bottom of its stack, but that's a little hard
1386 // to do with the current organization of the code so
1387 // for now we'll just drop it.
1388 intentActivity.task.setIntent(r.intent, r.info);
1389 }
1390 if (!addingToTask && reuseTask == null) {
1391 // We didn't do anything... but it was needed (a.k.a., client
1392 // don't use that intent!) And for paranoia, make
1393 // sure we have correctly resumed the top activity.
1394 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001395 setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1396 targetStack.resumeTopActivityLocked(null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001397 } else {
1398 ActivityOptions.abort(options);
1399 }
Craig Mautner29219d92013-04-16 20:19:12 -07001400 if (r.task == null) Slog.v(TAG,
1401 "startActivityUncheckedLocked: task left null",
1402 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001403 return ActivityManager.START_TASK_TO_FRONT;
1404 }
1405 }
1406 }
1407 }
1408
1409 //String uri = r.intent.toURI();
1410 //Intent intent2 = new Intent(uri);
1411 //Slog.i(TAG, "Given intent: " + r.intent);
1412 //Slog.i(TAG, "URI is: " + uri);
1413 //Slog.i(TAG, "To intent: " + intent2);
1414
1415 if (r.packageName != null) {
1416 // If the activity being launched is the same as the one currently
1417 // at the top, then we need to check if it should only be launched
1418 // once.
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001419 ActivityStack topStack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001420 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001421 if (top != null && r.resultTo == null) {
1422 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1423 if (top.app != null && top.app.thread != null) {
1424 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1425 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1426 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1427 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1428 top.task);
1429 // For paranoia, make sure we have correctly
1430 // resumed the top activity.
1431 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001432 setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
1433 topStack.resumeTopActivityLocked(null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001434 }
1435 ActivityOptions.abort(options);
1436 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1437 // We don't need to start a new activity, and
1438 // the client said not to do anything if that
1439 // is the case, so this is it!
Craig Mautner29219d92013-04-16 20:19:12 -07001440 if (r.task == null) Slog.v(TAG,
1441 "startActivityUncheckedLocked: task left null",
1442 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001443 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1444 }
1445 top.deliverNewIntentLocked(callingUid, r.intent);
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_DELIVERED_TO_TOP;
1450 }
1451 }
1452 }
1453 }
1454
1455 } else {
1456 if (r.resultTo != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001457 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1458 r.requestCode, Activity.RESULT_CANCELED, null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001459 }
1460 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001461 if (r.task == null) Slog.v(TAG,
1462 "startActivityUncheckedLocked: task left null",
1463 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001464 return ActivityManager.START_CLASS_NOT_FOUND;
1465 }
1466
1467 boolean newTask = false;
1468 boolean keepCurTransition = false;
1469
1470 // Should this be considered a new task?
1471 if (r.resultTo == null && !addingToTask
1472 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001473 targetStack = getCorrectStack(r);
1474 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001475 if (reuseTask == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001476 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1477 null, true);
1478 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1479 r.task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001480 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001481 r.setTask(reuseTask, reuseTask, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001482 }
1483 newTask = true;
1484 if (!movedHome) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001485 if ((launchFlags &
1486 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1487 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1488 // Caller wants to appear on home activity, so before starting
1489 // their own activity we will bring home to the front.
1490 r.mLaunchHomeTaskNext = true;
1491 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001492 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001493 } else if (sourceRecord != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001494 targetStack = sourceRecord.task.stack;
1495 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001496 if (!addingToTask &&
1497 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1498 // In this case, we are adding the activity to an existing
1499 // task, but the caller has asked to clear that task if the
1500 // activity is already running.
1501 ActivityRecord top = sourceRecord.task.performClearTaskLocked(r, launchFlags);
1502 keepCurTransition = true;
1503 if (top != null) {
1504 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1505 top.deliverNewIntentLocked(callingUid, r.intent);
1506 // For paranoia, make sure we have correctly
1507 // resumed the top activity.
1508 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001509 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001510 targetStack.resumeTopActivityLocked(null);
1511 }
1512 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001513 if (r.task == null) Slog.v(TAG,
1514 "startActivityUncheckedLocked: task left null",
1515 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001516 return ActivityManager.START_DELIVERED_TO_TOP;
1517 }
1518 } else if (!addingToTask &&
1519 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1520 // In this case, we are launching an activity in our own task
1521 // that may already be running somewhere in the history, and
1522 // we want to shuffle it to the front of the stack if so.
1523 final ActivityRecord top =
1524 targetStack.findActivityInHistoryLocked(r, sourceRecord.task);
1525 if (top != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001526 final TaskRecord task = top.task;
1527 task.moveActivityToFrontLocked(top);
1528 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001529 top.updateOptionsLocked(options);
1530 top.deliverNewIntentLocked(callingUid, r.intent);
1531 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001532 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001533 targetStack.resumeTopActivityLocked(null);
1534 }
Craig Mautner29219d92013-04-16 20:19:12 -07001535 if (r.task == null) Slog.v(TAG,
1536 "startActivityUncheckedLocked: task left null",
1537 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001538 return ActivityManager.START_DELIVERED_TO_TOP;
1539 }
1540 }
1541 // An existing activity is starting this new activity, so we want
1542 // to keep the new one in the same task as the one that is starting
1543 // it.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001544 r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001545 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1546 + " in existing task " + r.task);
1547
1548 } else {
1549 // This not being started from an existing activity, and not part
1550 // of a new task... just put it in the top task, though these days
1551 // this case should never happen.
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001552 ActivityStack lastStack = getLastStack();
1553 targetStack = lastStack != null ? lastStack : mHomeStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001554 moveHomeStack(targetStack.isHomeStack());
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001555 ActivityRecord prev = lastStack == null ? null : targetStack.topActivity();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001556 r.setTask(prev != null ? prev.task
1557 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1558 null, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001559 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1560 + " in new guessed " + r.task);
1561 }
1562
1563 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1564 intent, r.getUriPermissionsLocked());
1565
1566 if (newTask) {
1567 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1568 }
1569 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001570 setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001571 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
1572 return ActivityManager.START_SUCCESS;
1573 }
1574
Craig Mautner8d341ef2013-03-26 09:03:27 -07001575 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
1576 // Just in case.
1577 final int numStacks = mStacks.size();
1578 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Craig Mautnere79d42682013-04-01 19:01:53 -07001579 mStacks.get(stackNdx).handleAppDiedLocked(app, restarting);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001580 }
1581 }
1582
1583 void closeSystemDialogsLocked() {
1584 final int numStacks = mStacks.size();
1585 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1586 final ActivityStack stack = mStacks.get(stackNdx);
1587 stack.closeSystemDialogsLocked();
1588 }
1589 }
1590
1591 /**
1592 * @return true if some activity was finished (or would have finished if doit were true).
1593 */
1594 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1595 boolean didSomething = false;
1596 final int numStacks = mStacks.size();
1597 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1598 final ActivityStack stack = mStacks.get(stackNdx);
1599 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1600 didSomething = true;
1601 }
1602 }
1603 return didSomething;
1604 }
1605
1606 void resumeTopActivityLocked() {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -07001607 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001608 final ActivityStack stack = mStacks.get(stackNdx);
1609 if (isFrontStack(stack)) {
1610 stack.resumeTopActivityLocked(null);
1611 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001612 }
1613 }
1614
1615 void finishTopRunningActivityLocked(ProcessRecord app) {
1616 final int numStacks = mStacks.size();
1617 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1618 final ActivityStack stack = mStacks.get(stackNdx);
1619 stack.finishTopRunningActivityLocked(app);
1620 }
1621 }
1622
1623 void scheduleIdleLocked() {
1624 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1625 mStacks.get(stackNdx).scheduleIdleLocked();
1626 }
1627 }
1628
1629 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
1630 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1631 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
1632 return;
1633 }
1634 }
1635 }
1636
Craig Mautner967212c2013-04-13 21:10:58 -07001637 ActivityStack getStack(int stackId) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001638 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1639 final ActivityStack stack = mStacks.get(stackNdx);
1640 if (stack.getStackId() == stackId) {
1641 return stack;
1642 }
1643 }
1644 return null;
1645 }
1646
Craig Mautner967212c2013-04-13 21:10:58 -07001647 ArrayList<ActivityStack> getStacks() {
1648 return new ArrayList<ActivityStack>(mStacks);
1649 }
1650
1651 int createStack() {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001652 synchronized (this) {
1653 while (true) {
1654 if (++mLastStackId <= HOME_STACK_ID) {
1655 mLastStackId = HOME_STACK_ID + 1;
1656 }
1657 if (getStack(mLastStackId) == null) {
1658 break;
1659 }
1660 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001661 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
Craig Mautner8d341ef2013-03-26 09:03:27 -07001662 return mLastStackId;
1663 }
1664 }
1665
1666 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
1667 final ActivityStack stack = getStack(stackId);
1668 if (stack == null) {
1669 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
1670 return;
1671 }
1672 stack.moveTask(taskId, toTop);
Craig Mautner967212c2013-04-13 21:10:58 -07001673 stack.resumeTopActivityLocked(null);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001674 }
1675
Craig Mautner8849a5e2013-04-02 16:41:03 -07001676 ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
1677 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1678 final ActivityRecord ar = mStacks.get(stackNdx).findTaskLocked(intent, info);
1679 if (ar != null) {
1680 return ar;
1681 }
1682 }
1683 return null;
1684 }
1685
1686 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
1687 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1688 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
1689 if (ar != null) {
1690 return ar;
1691 }
1692 }
1693 return null;
1694 }
1695
Craig Mautner8d341ef2013-03-26 09:03:27 -07001696 void goingToSleepLocked() {
1697 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1698 mStacks.get(stackNdx).stopIfSleepingLocked();
1699 }
1700 }
1701
1702 boolean shutdownLocked(int timeout) {
1703 boolean timedout = false;
1704 final int numStacks = mStacks.size();
1705 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1706 final ActivityStack stack = mStacks.get(stackNdx);
1707 if (stack.mResumedActivity != null) {
1708 stack.stopIfSleepingLocked();
1709 final long endTime = System.currentTimeMillis() + timeout;
1710 while (stack.mResumedActivity != null || stack.mPausingActivity != null) {
1711 long delay = endTime - System.currentTimeMillis();
1712 if (delay <= 0) {
1713 Slog.w(TAG, "Activity manager shutdown timed out");
1714 timedout = true;
1715 break;
1716 }
1717 try {
1718 mService.wait();
1719 } catch (InterruptedException e) {
1720 }
1721 }
1722 }
1723 }
1724 return timedout;
1725 }
1726
1727 void comeOutOfSleepIfNeededLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001728 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001729 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001730 stack.awakeFromSleepingLocked();
1731 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001732 stack.resumeTopActivityLocked(null);
1733 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001734 }
1735 }
1736
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001737 boolean reportResumedActivityLocked(ActivityRecord r) {
1738 final ActivityStack stack = r.task.stack;
1739 if (isFrontStack(stack)) {
1740 mService.reportResumedActivityLocked(r);
1741 mService.setFocusedActivityLocked(r);
1742 }
1743 if (allResumedActivitiesComplete()) {
1744 ensureActivitiesVisibleLocked(null, 0);
1745 mWindowManager.executeAppTransition();
1746 return true;
1747 }
1748 return false;
1749 }
1750
Craig Mautner8d341ef2013-03-26 09:03:27 -07001751 void handleAppCrashLocked(ProcessRecord app) {
1752 final int numStacks = mStacks.size();
1753 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1754 final ActivityStack stack = mStacks.get(stackNdx);
1755 stack.handleAppCrashLocked(app);
1756 }
1757 }
1758
Craig Mautnerde4ef022013-04-07 19:01:33 -07001759 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
1760 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1761 mStacks.get(stackNdx).ensureActivitiesVisibleLocked(starting, configChanges);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001762 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001763 }
1764
1765 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
1766 final int numStacks = mStacks.size();
1767 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1768 final ActivityStack stack = mStacks.get(stackNdx);
1769 stack.scheduleDestroyActivities(app, false, reason);
1770 }
1771 }
1772
1773 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner2420ead2013-04-01 17:13:20 -07001774 mCurrentUser = userId;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001775 boolean homeInBack = !homeIsInFront();
Craig Mautner8d341ef2013-03-26 09:03:27 -07001776 boolean haveActivities = false;
1777 final int numStacks = mStacks.size();
1778 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1779 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001780 if (stack.isHomeStack() ^ homeInBack) {
1781 haveActivities |= stack.switchUserLocked(userId, uss);
1782 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001783 }
1784 return haveActivities;
Craig Mautner2219a1b2013-03-25 09:44:30 -07001785 }
1786
Craig Mautnerde4ef022013-04-07 19:01:33 -07001787 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
1788 int N = mStoppingActivities.size();
1789 if (N <= 0) return null;
1790
1791 ArrayList<ActivityRecord> stops = null;
1792
1793 final boolean nowVisible = allResumedActivitiesVisible();
1794 for (int i=0; i<N; i++) {
1795 ActivityRecord s = mStoppingActivities.get(i);
1796 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
1797 + nowVisible + " waitingVisible=" + s.waitingVisible
1798 + " finishing=" + s.finishing);
1799 if (s.waitingVisible && nowVisible) {
1800 mWaitingVisibleActivities.remove(s);
1801 s.waitingVisible = false;
1802 if (s.finishing) {
1803 // If this activity is finishing, it is sitting on top of
1804 // everyone else but we now know it is no longer needed...
1805 // so get rid of it. Otherwise, we need to go through the
1806 // normal flow and hide it once we determine that it is
1807 // hidden by the activities in front of it.
1808 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001809 mWindowManager.setAppVisibility(s.appToken, false);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001810 }
1811 }
1812 if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
1813 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
1814 if (stops == null) {
1815 stops = new ArrayList<ActivityRecord>();
1816 }
1817 stops.add(s);
1818 mStoppingActivities.remove(i);
1819 N--;
1820 i--;
1821 }
1822 }
1823
1824 return stops;
1825 }
1826
Craig Mautner27084302013-03-25 08:05:25 -07001827 public void dump(PrintWriter pw, String prefix) {
1828 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
1829 pw.println(mDismissKeyguardOnNextActivity);
1830 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001831
Craig Mautner20e72272013-04-01 13:45:53 -07001832 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001833 return getFocusedStack().getDumpActivitiesLocked(name);
Craig Mautner20e72272013-04-01 13:45:53 -07001834 }
1835
Craig Mautner8d341ef2013-03-26 09:03:27 -07001836 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
1837 boolean dumpClient, String dumpPackage) {
1838 final int numStacks = mStacks.size();
1839 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1840 final ActivityStack stack = mStacks.get(stackNdx);
1841 pw.print(" Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
1842 stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
1843 pw.println(" ");
1844 pw.println(" Running activities (most recent first):");
1845 dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false,
1846 dumpPackage);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001847 if (stack.mGoingToSleepActivities.size() > 0) {
1848 pw.println(" ");
1849 pw.println(" Activities waiting to sleep:");
1850 dumpHistoryList(fd, pw, stack.mGoingToSleepActivities, " ", "Sleep", false,
1851 !dumpAll, false, dumpPackage);
1852 }
1853 if (stack.mFinishingActivities.size() > 0) {
1854 pw.println(" ");
1855 pw.println(" Activities waiting to finish:");
1856 dumpHistoryList(fd, pw, stack.mFinishingActivities, " ", "Fin", false,
1857 !dumpAll, false, dumpPackage);
1858 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001859
Craig Mautner8d341ef2013-03-26 09:03:27 -07001860 pw.print(" Stack #"); pw.println(mStacks.indexOf(stack));
1861 if (stack.mPausingActivity != null) {
1862 pw.println(" mPausingActivity: " + stack.mPausingActivity);
1863 }
1864 pw.println(" mResumedActivity: " + stack.mResumedActivity);
1865 if (dumpAll) {
1866 pw.println(" mLastPausedActivity: " + stack.mLastPausedActivity);
1867 pw.println(" mSleepTimeout: " + stack.mSleepTimeout);
1868 }
1869 }
1870
Craig Mautnerde4ef022013-04-07 19:01:33 -07001871 if (mStoppingActivities.size() > 0) {
1872 pw.println(" ");
1873 pw.println(" Activities waiting to stop:");
1874 dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, false,
1875 dumpPackage);
1876 }
1877
1878 if (mWaitingVisibleActivities.size() > 0) {
1879 pw.println(" ");
1880 pw.println(" Activities waiting for another to become visible:");
1881 dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
1882 false, dumpPackage);
1883 }
1884
Craig Mautner8d341ef2013-03-26 09:03:27 -07001885 if (dumpAll) {
1886 pw.println(" ");
1887 pw.println(" mCurTaskId: " + mCurTaskId);
1888 }
1889 return true;
1890 }
1891
1892 static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
1893 String prefix, String label, boolean complete, boolean brief, boolean client,
1894 String dumpPackage) {
1895 TaskRecord lastTask = null;
1896 boolean needNL = false;
1897 final String innerPrefix = prefix + " ";
1898 final String[] args = new String[0];
1899 for (int i=list.size()-1; i>=0; i--) {
1900 final ActivityRecord r = list.get(i);
1901 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
1902 continue;
1903 }
1904 final boolean full = !brief && (complete || !r.isInHistory());
1905 if (needNL) {
1906 pw.println(" ");
1907 needNL = false;
1908 }
1909 if (lastTask != r.task) {
1910 lastTask = r.task;
1911 pw.print(prefix);
1912 pw.print(full ? "* " : " ");
1913 pw.println(lastTask);
1914 if (full) {
1915 lastTask.dump(pw, prefix + " ");
1916 } else if (complete) {
1917 // Complete + brief == give a summary. Isn't that obvious?!?
1918 if (lastTask.intent != null) {
1919 pw.print(prefix); pw.print(" ");
1920 pw.println(lastTask.intent.toInsecureStringWithClip());
1921 }
1922 }
1923 }
1924 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
1925 pw.print(" #"); pw.print(i); pw.print(": ");
1926 pw.println(r);
1927 if (full) {
1928 r.dump(pw, innerPrefix);
1929 } else if (complete) {
1930 // Complete + brief == give a summary. Isn't that obvious?!?
1931 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
1932 if (r.app != null) {
1933 pw.print(innerPrefix); pw.println(r.app);
1934 }
1935 }
1936 if (client && r.app != null && r.app.thread != null) {
1937 // flush anything that is already in the PrintWriter since the thread is going
1938 // to write to the file descriptor directly
1939 pw.flush();
1940 try {
1941 TransferPipe tp = new TransferPipe();
1942 try {
1943 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
1944 r.appToken, innerPrefix, args);
1945 // Short timeout, since blocking here can
1946 // deadlock with the application.
1947 tp.go(fd, 2000);
1948 } finally {
1949 tp.kill();
1950 }
1951 } catch (IOException e) {
1952 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
1953 } catch (RemoteException e) {
1954 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
1955 }
1956 needNL = true;
1957 }
1958 }
1959 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001960
1961 private final class ActivityStackSupervisorHandler extends Handler {
1962 public ActivityStackSupervisorHandler(Looper looper) {
1963 super(looper);
1964 }
1965
1966 @Override
1967 public void handleMessage(Message msg) {
1968 switch (msg.what) {
1969
1970 }
1971 }
1972 }
Craig Mautner27084302013-03-25 08:05:25 -07001973}