blob: f236191356a5afa765433b34de08af451287ece1 [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;
20import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Craig Mautner2420ead2013-04-01 17:13:20 -070021import static com.android.server.am.ActivityManagerService.localLOGV;
Craig Mautner23ac33b2013-04-01 16:26:35 -070022import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION;
Craig Mautner6170f732013-04-02 13:05:23 -070023import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
Craig Mautner2420ead2013-04-01 17:13:20 -070024import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
Craig Mautner8d341ef2013-03-26 09:03:27 -070025import static com.android.server.am.ActivityManagerService.TAG;
26
Craig Mautner2420ead2013-04-01 17:13:20 -070027import android.app.Activity;
Craig Mautner23ac33b2013-04-01 16:26:35 -070028import android.app.ActivityManager;
29import android.app.ActivityOptions;
30import android.app.AppGlobals;
31import android.app.IApplicationThread;
Craig Mautner20e72272013-04-01 13:45:53 -070032import android.app.IThumbnailReceiver;
Craig Mautner23ac33b2013-04-01 16:26:35 -070033import android.app.PendingIntent;
Craig Mautner20e72272013-04-01 13:45:53 -070034import android.app.ActivityManager.RunningTaskInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070035import android.app.IActivityManager.WaitResult;
Craig Mautner2420ead2013-04-01 17:13:20 -070036import android.app.ResultInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070037import android.content.ComponentName;
Craig Mautner2219a1b2013-03-25 09:44:30 -070038import android.content.Context;
Craig Mautner23ac33b2013-04-01 16:26:35 -070039import android.content.IIntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070040import android.content.Intent;
Craig Mautner23ac33b2013-04-01 16:26:35 -070041import android.content.IntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070042import android.content.pm.ActivityInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070043import android.content.pm.ApplicationInfo;
44import android.content.pm.PackageManager;
45import android.content.pm.ResolveInfo;
46import android.content.res.Configuration;
47import android.os.Binder;
Craig Mautner8d341ef2013-03-26 09:03:27 -070048import android.os.Bundle;
Craig Mautner23ac33b2013-04-01 16:26:35 -070049import android.os.IBinder;
Craig Mautner2219a1b2013-03-25 09:44:30 -070050import android.os.Looper;
Craig Mautner2420ead2013-04-01 17:13:20 -070051import android.os.Message;
Craig Mautner23ac33b2013-04-01 16:26:35 -070052import android.os.ParcelFileDescriptor;
Craig Mautner8d341ef2013-03-26 09:03:27 -070053import android.os.RemoteException;
Craig Mautner23ac33b2013-04-01 16:26:35 -070054import android.os.SystemClock;
Craig Mautner6170f732013-04-02 13:05:23 -070055import android.os.UserHandle;
Craig Mautner2420ead2013-04-01 17:13:20 -070056import android.util.EventLog;
Craig Mautner8d341ef2013-03-26 09:03:27 -070057import android.util.Slog;
Craig Mautner2219a1b2013-03-25 09:44:30 -070058
Craig Mautner23ac33b2013-04-01 16:26:35 -070059import com.android.internal.app.HeavyWeightSwitcherActivity;
Craig Mautner6170f732013-04-02 13:05:23 -070060import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
Craig Mautner2420ead2013-04-01 17:13:20 -070061import com.android.server.am.ActivityStack.ActivityState;
Craig Mautner23ac33b2013-04-01 16:26:35 -070062
Craig Mautner8d341ef2013-03-26 09:03:27 -070063import java.io.FileDescriptor;
64import java.io.IOException;
Craig Mautner27084302013-03-25 08:05:25 -070065import java.io.PrintWriter;
Craig Mautner2219a1b2013-03-25 09:44:30 -070066import java.util.ArrayList;
Craig Mautner8d341ef2013-03-26 09:03:27 -070067import java.util.List;
Craig Mautner27084302013-03-25 08:05:25 -070068
69public class ActivityStackSupervisor {
Craig Mautner2420ead2013-04-01 17:13:20 -070070 static final boolean DEBUG_ADD_REMOVE = false;
71 static final boolean DEBUG_APP = false;
72 static final boolean DEBUG_SAVED_STATE = false;
73 static final boolean DEBUG_STATES = false;
74
Craig Mautner2219a1b2013-03-25 09:44:30 -070075 public static final int HOME_STACK_ID = 0;
Craig Mautner27084302013-03-25 08:05:25 -070076
77 final ActivityManagerService mService;
Craig Mautner2219a1b2013-03-25 09:44:30 -070078 final Context mContext;
79 final Looper mLooper;
Craig Mautner27084302013-03-25 08:05:25 -070080
81 /** Dismiss the keyguard after the next activity is displayed? */
82 private boolean mDismissKeyguardOnNextActivity = false;
83
Craig Mautner8d341ef2013-03-26 09:03:27 -070084 /** Identifier counter for all ActivityStacks */
85 private int mLastStackId = 0;
86
87 /** Task identifier that activities are currently being started in. Incremented each time a
88 * new task is created. */
89 private int mCurTaskId = 0;
90
Craig Mautner2420ead2013-04-01 17:13:20 -070091 /** The current user */
92 private int mCurrentUser;
93
Craig Mautner8d341ef2013-03-26 09:03:27 -070094 /** The stack containing the launcher app */
Craig Mautner2219a1b2013-03-25 09:44:30 -070095 private ActivityStack mHomeStack;
Craig Mautner20e72272013-04-01 13:45:53 -070096
97 /** The stack currently receiving input or launching the next activity */
Craig Mautner2219a1b2013-03-25 09:44:30 -070098 private ActivityStack mMainStack;
Craig Mautner8d341ef2013-03-26 09:03:27 -070099
100 /** All the non-launcher stacks */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700101 private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
102
103 public ActivityStackSupervisor(ActivityManagerService service, Context context,
104 Looper looper) {
Craig Mautner27084302013-03-25 08:05:25 -0700105 mService = service;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700106 mContext = context;
107 mLooper = looper;
108 }
109
Craig Mautner2420ead2013-04-01 17:13:20 -0700110 void init(int userId) {
111 mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID, this, userId);
Craig Mautner2219a1b2013-03-25 09:44:30 -0700112 setMainStack(mHomeStack);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700113 mStacks.add(mHomeStack);
Craig Mautner27084302013-03-25 08:05:25 -0700114 }
115
116 void dismissKeyguard() {
117 if (mDismissKeyguardOnNextActivity) {
118 mDismissKeyguardOnNextActivity = false;
119 mService.mWindowManager.dismissKeyguard();
120 }
121 }
122
Craig Mautner20e72272013-04-01 13:45:53 -0700123 boolean isHomeStackMain() {
124 return mHomeStack == mMainStack;
125 }
126
Craig Mautner2219a1b2013-03-25 09:44:30 -0700127 boolean isMainStack(ActivityStack stack) {
128 return stack == mMainStack;
129 }
130
Craig Mautner20e72272013-04-01 13:45:53 -0700131 ActivityStack getMainStack() {
132 return mMainStack;
133 }
134
Craig Mautner2219a1b2013-03-25 09:44:30 -0700135 void setMainStack(ActivityStack stack) {
136 mMainStack = stack;
137 }
138
Craig Mautner27084302013-03-25 08:05:25 -0700139 void setDismissKeyguard(boolean dismiss) {
140 mDismissKeyguardOnNextActivity = dismiss;
141 }
142
Craig Mautner8d341ef2013-03-26 09:03:27 -0700143 TaskRecord anyTaskForIdLocked(int id) {
144 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
145 ActivityStack stack = mStacks.get(stackNdx);
146 TaskRecord task = stack.taskForIdLocked(id);
147 if (task != null) {
148 return task;
149 }
150 }
151 return null;
152 }
153
Craig Mautner6170f732013-04-02 13:05:23 -0700154 ActivityRecord isInAnyStackLocked(IBinder token) {
155 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
156 final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
157 if (r != null) {
158 return r;
159 }
160 }
161 return null;
162 }
163
Craig Mautner8d341ef2013-03-26 09:03:27 -0700164 int getNextTaskId() {
165 do {
166 mCurTaskId++;
167 if (mCurTaskId <= 0) {
168 mCurTaskId = 1;
169 }
170 } while (anyTaskForIdLocked(mCurTaskId) != null);
171 return mCurTaskId;
172 }
173
Craig Mautner20e72272013-04-01 13:45:53 -0700174 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
175 boolean didSomething = false;
176 final String processName = app.processName;
177 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
178 final ActivityStack stack = mStacks.get(stackNdx);
179 ActivityRecord hr = stack.topRunningActivityLocked(null);
180 if (hr != null) {
181 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
182 && processName.equals(hr.processName)) {
183 try {
184 if (headless) {
185 Slog.e(TAG, "Starting activities not supported on headless device: "
186 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700187 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700188 didSomething = true;
189 }
190 } catch (Exception e) {
191 Slog.w(TAG, "Exception in new application when starting activity "
192 + hr.intent.getComponent().flattenToShortString(), e);
193 throw e;
194 }
195 } else {
196 stack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
197 }
198 }
199 }
200 return didSomething;
201 }
202
203 boolean allResumedActivitiesIdle() {
204 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700205 final ActivityRecord resumedActivity = mStacks.get(stackNdx).mResumedActivity;
206 if (resumedActivity == null || !resumedActivity.idle) {
Craig Mautner20e72272013-04-01 13:45:53 -0700207 return false;
208 }
209 }
210 return true;
211 }
212
213 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
214 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
215 ActivityRecord r = null;
216 final int numStacks = mStacks.size();
217 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
218 final ActivityStack stack = mStacks.get(stackNdx);
219 final ActivityRecord ar =
220 stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
221 if (isMainStack(stack)) {
222 r = ar;
223 }
224 }
225 return r;
226 }
227
Craig Mautner23ac33b2013-04-01 16:26:35 -0700228 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
229 String profileFile, ParcelFileDescriptor profileFd, int userId) {
230 // Collect information about the target of the Intent.
231 ActivityInfo aInfo;
232 try {
233 ResolveInfo rInfo =
234 AppGlobals.getPackageManager().resolveIntent(
235 intent, resolvedType,
236 PackageManager.MATCH_DEFAULT_ONLY
237 | ActivityManagerService.STOCK_PM_FLAGS, userId);
238 aInfo = rInfo != null ? rInfo.activityInfo : null;
239 } catch (RemoteException e) {
240 aInfo = null;
241 }
242
243 if (aInfo != null) {
244 // Store the found target back into the intent, because now that
245 // we have it we never want to do this again. For example, if the
246 // user navigates back to this point in the history, we should
247 // always restart the exact same activity.
248 intent.setComponent(new ComponentName(
249 aInfo.applicationInfo.packageName, aInfo.name));
250
251 // Don't debug things in the system process
252 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
253 if (!aInfo.processName.equals("system")) {
254 mService.setDebugApp(aInfo.processName, true, false);
255 }
256 }
257
258 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
259 if (!aInfo.processName.equals("system")) {
260 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
261 }
262 }
263
264 if (profileFile != null) {
265 if (!aInfo.processName.equals("system")) {
266 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
267 profileFile, profileFd,
268 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
269 }
270 }
271 }
272 return aInfo;
273 }
274
Craig Mautner2219a1b2013-03-25 09:44:30 -0700275 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
Craig Mautner6170f732013-04-02 13:05:23 -0700276 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
Craig Mautner2219a1b2013-03-25 09:44:30 -0700277 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700278 }
279
Craig Mautner23ac33b2013-04-01 16:26:35 -0700280 final int startActivityMayWait(IApplicationThread caller, int callingUid,
281 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
282 String resultWho, int requestCode, int startFlags, String profileFile,
283 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
284 Bundle options, int userId) {
285 // Refuse possible leaked file descriptors
286 if (intent != null && intent.hasFileDescriptors()) {
287 throw new IllegalArgumentException("File descriptors passed in Intent");
288 }
289 boolean componentSpecified = intent.getComponent() != null;
290
291 // Don't modify the client's object!
292 intent = new Intent(intent);
293
294 // Collect information about the target of the Intent.
295 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
296 profileFile, profileFd, userId);
297
298 synchronized (mService) {
299 int callingPid;
300 if (callingUid >= 0) {
301 callingPid = -1;
302 } else if (caller == null) {
303 callingPid = Binder.getCallingPid();
304 callingUid = Binder.getCallingUid();
305 } else {
306 callingPid = callingUid = -1;
307 }
308
309 mMainStack.mConfigWillChange = config != null
310 && mService.mConfiguration.diff(config) != 0;
311 if (DEBUG_CONFIGURATION) Slog.v(TAG,
312 "Starting activity when config will change = " + mMainStack.mConfigWillChange);
313
314 final long origId = Binder.clearCallingIdentity();
315
316 if (aInfo != null &&
317 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
318 // This may be a heavy-weight process! Check to see if we already
319 // have another, different heavy-weight process running.
320 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
321 if (mService.mHeavyWeightProcess != null &&
322 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
323 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
324 int realCallingPid = callingPid;
325 int realCallingUid = callingUid;
326 if (caller != null) {
327 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
328 if (callerApp != null) {
329 realCallingPid = callerApp.pid;
330 realCallingUid = callerApp.info.uid;
331 } else {
332 Slog.w(TAG, "Unable to find app for caller " + caller
333 + " (pid=" + realCallingPid + ") when starting: "
334 + intent.toString());
335 ActivityOptions.abort(options);
336 return ActivityManager.START_PERMISSION_DENIED;
337 }
338 }
339
340 IIntentSender target = mService.getIntentSenderLocked(
341 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
342 realCallingUid, userId, null, null, 0, new Intent[] { intent },
343 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
344 | PendingIntent.FLAG_ONE_SHOT, null);
345
346 Intent newIntent = new Intent();
347 if (requestCode >= 0) {
348 // Caller is requesting a result.
349 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
350 }
351 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
352 new IntentSender(target));
353 if (mService.mHeavyWeightProcess.activities.size() > 0) {
354 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
355 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
356 hist.packageName);
357 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
358 hist.task.taskId);
359 }
360 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
361 aInfo.packageName);
362 newIntent.setFlags(intent.getFlags());
363 newIntent.setClassName("android",
364 HeavyWeightSwitcherActivity.class.getName());
365 intent = newIntent;
366 resolvedType = null;
367 caller = null;
368 callingUid = Binder.getCallingUid();
369 callingPid = Binder.getCallingPid();
370 componentSpecified = true;
371 try {
372 ResolveInfo rInfo =
373 AppGlobals.getPackageManager().resolveIntent(
374 intent, null,
375 PackageManager.MATCH_DEFAULT_ONLY
376 | ActivityManagerService.STOCK_PM_FLAGS, userId);
377 aInfo = rInfo != null ? rInfo.activityInfo : null;
378 aInfo = mService.getActivityInfoForUser(aInfo, userId);
379 } catch (RemoteException e) {
380 aInfo = null;
381 }
382 }
383 }
384 }
385
Craig Mautner6170f732013-04-02 13:05:23 -0700386 int res = startActivityLocked(caller, intent, resolvedType,
Craig Mautner23ac33b2013-04-01 16:26:35 -0700387 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
388 callingPackage, startFlags, options, componentSpecified, null);
389
390 if (mMainStack.mConfigWillChange) {
391 // If the caller also wants to switch to a new configuration,
392 // do so now. This allows a clean switch, as we are waiting
393 // for the current activity to pause (so we will not destroy
394 // it), and have not yet started the next activity.
395 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
396 "updateConfiguration()");
397 mMainStack.mConfigWillChange = false;
398 if (DEBUG_CONFIGURATION) Slog.v(TAG,
399 "Updating to new configuration after starting activity.");
400 mService.updateConfigurationLocked(config, null, false, false);
401 }
402
403 Binder.restoreCallingIdentity(origId);
404
405 if (outResult != null) {
406 outResult.result = res;
407 if (res == ActivityManager.START_SUCCESS) {
408 mMainStack.mWaitingActivityLaunched.add(outResult);
409 do {
410 try {
411 mService.wait();
412 } catch (InterruptedException e) {
413 }
414 } while (!outResult.timeout && outResult.who == null);
415 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
416 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
417 if (r.nowVisible) {
418 outResult.timeout = false;
419 outResult.who = new ComponentName(r.info.packageName, r.info.name);
420 outResult.totalTime = 0;
421 outResult.thisTime = 0;
422 } else {
423 outResult.thisTime = SystemClock.uptimeMillis();
424 mMainStack.mWaitingActivityVisible.add(outResult);
425 do {
426 try {
427 mService.wait();
428 } catch (InterruptedException e) {
429 }
430 } while (!outResult.timeout && outResult.who == null);
431 }
432 }
433 }
434
435 return res;
436 }
437 }
438
439 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
440 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
441 Bundle options, int userId) {
442 if (intents == null) {
443 throw new NullPointerException("intents is null");
444 }
445 if (resolvedTypes == null) {
446 throw new NullPointerException("resolvedTypes is null");
447 }
448 if (intents.length != resolvedTypes.length) {
449 throw new IllegalArgumentException("intents are length different than resolvedTypes");
450 }
451
452 ActivityRecord[] outActivity = new ActivityRecord[1];
453
454 int callingPid;
455 if (callingUid >= 0) {
456 callingPid = -1;
457 } else if (caller == null) {
458 callingPid = Binder.getCallingPid();
459 callingUid = Binder.getCallingUid();
460 } else {
461 callingPid = callingUid = -1;
462 }
463 final long origId = Binder.clearCallingIdentity();
464 try {
465 synchronized (mService) {
466
467 for (int i=0; i<intents.length; i++) {
468 Intent intent = intents[i];
469 if (intent == null) {
470 continue;
471 }
472
473 // Refuse possible leaked file descriptors
474 if (intent != null && intent.hasFileDescriptors()) {
475 throw new IllegalArgumentException("File descriptors passed in Intent");
476 }
477
478 boolean componentSpecified = intent.getComponent() != null;
479
480 // Don't modify the client's object!
481 intent = new Intent(intent);
482
483 // Collect information about the target of the Intent.
484 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
485 0, null, null, userId);
486 // TODO: New, check if this is correct
487 aInfo = mService.getActivityInfoForUser(aInfo, userId);
488
489 if (aInfo != null &&
490 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
491 != 0) {
492 throw new IllegalArgumentException(
493 "FLAG_CANT_SAVE_STATE not supported here");
494 }
495
496 Bundle theseOptions;
497 if (options != null && i == intents.length-1) {
498 theseOptions = options;
499 } else {
500 theseOptions = null;
501 }
Craig Mautner6170f732013-04-02 13:05:23 -0700502 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Craig Mautner23ac33b2013-04-01 16:26:35 -0700503 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
504 0, theseOptions, componentSpecified, outActivity);
505 if (res < 0) {
506 return res;
507 }
508
509 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
510 }
511 }
512 } finally {
513 Binder.restoreCallingIdentity(origId);
514 }
515
516 return ActivityManager.START_SUCCESS;
517 }
518
Craig Mautner2420ead2013-04-01 17:13:20 -0700519 final boolean realStartActivityLocked(ActivityRecord r,
520 ProcessRecord app, boolean andResume, boolean checkConfig)
521 throws RemoteException {
522
523 r.startFreezingScreenLocked(app, 0);
524 mService.mWindowManager.setAppVisibility(r.appToken, true);
525
526 // schedule launch ticks to collect information about slow apps.
527 r.startLaunchTickingLocked();
528
529 // Have the window manager re-evaluate the orientation of
530 // the screen based on the new activity order. Note that
531 // as a result of this, it can call back into the activity
532 // manager with a new orientation. We don't care about that,
533 // because the activity is not currently running so we are
534 // just restarting it anyway.
535 if (checkConfig) {
536 Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
537 mService.mConfiguration,
538 r.mayFreezeScreenLocked(app) ? r.appToken : null);
539 mService.updateConfigurationLocked(config, r, false, false);
540 }
541
542 r.app = app;
543 app.waitingToKill = null;
544 r.launchCount++;
545 r.lastLaunchTime = SystemClock.uptimeMillis();
546
547 if (localLOGV) Slog.v(TAG, "Launching: " + r);
548
549 int idx = app.activities.indexOf(r);
550 if (idx < 0) {
551 app.activities.add(r);
552 }
553 mService.updateLruProcessLocked(app, true);
554
555 final ActivityStack stack = r.task.stack;
556 try {
557 if (app.thread == null) {
558 throw new RemoteException();
559 }
560 List<ResultInfo> results = null;
561 List<Intent> newIntents = null;
562 if (andResume) {
563 results = r.results;
564 newIntents = r.newIntents;
565 }
566 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
567 + " icicle=" + r.icicle
568 + " with results=" + results + " newIntents=" + newIntents
569 + " andResume=" + andResume);
570 if (andResume) {
571 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
572 r.userId, System.identityHashCode(r),
573 r.task.taskId, r.shortComponentName);
574 }
575 if (r.isHomeActivity) {
576 mService.mHomeProcess = app;
577 }
578 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
579 r.sleeping = false;
580 r.forceNewConfig = false;
581 mService.showAskCompatModeDialogLocked(r);
582 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
583 String profileFile = null;
584 ParcelFileDescriptor profileFd = null;
585 boolean profileAutoStop = false;
586 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
587 if (mService.mProfileProc == null || mService.mProfileProc == app) {
588 mService.mProfileProc = app;
589 profileFile = mService.mProfileFile;
590 profileFd = mService.mProfileFd;
591 profileAutoStop = mService.mAutoStopProfiler;
592 }
593 }
594 app.hasShownUi = true;
595 app.pendingUiClean = true;
596 if (profileFd != null) {
597 try {
598 profileFd = profileFd.dup();
599 } catch (IOException e) {
600 if (profileFd != null) {
601 try {
602 profileFd.close();
603 } catch (IOException o) {
604 }
605 profileFd = null;
606 }
607 }
608 }
609 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
610 System.identityHashCode(r), r.info,
611 new Configuration(mService.mConfiguration),
612 r.compat, r.icicle, results, newIntents, !andResume,
613 mService.isNextTransitionForward(), profileFile, profileFd,
614 profileAutoStop);
615
616 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
617 // This may be a heavy-weight process! Note that the package
618 // manager will ensure that only activity can run in the main
619 // process of the .apk, which is the only thing that will be
620 // considered heavy-weight.
621 if (app.processName.equals(app.info.packageName)) {
622 if (mService.mHeavyWeightProcess != null
623 && mService.mHeavyWeightProcess != app) {
624 Slog.w(TAG, "Starting new heavy weight process " + app
625 + " when already running "
626 + mService.mHeavyWeightProcess);
627 }
628 mService.mHeavyWeightProcess = app;
629 Message msg = mService.mHandler.obtainMessage(
630 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
631 msg.obj = r;
632 mService.mHandler.sendMessage(msg);
633 }
634 }
635
636 } catch (RemoteException e) {
637 if (r.launchFailed) {
638 // This is the second time we failed -- finish activity
639 // and give up.
640 Slog.e(TAG, "Second failure launching "
641 + r.intent.getComponent().flattenToShortString()
642 + ", giving up", e);
643 mService.appDiedLocked(app, app.pid, app.thread);
644 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
645 "2nd-crash", false);
646 return false;
647 }
648
649 // This is the first time we failed -- restart process and
650 // retry.
651 app.activities.remove(r);
652 throw e;
653 }
654
655 r.launchFailed = false;
656 if (stack.updateLRUListLocked(r)) {
657 Slog.w(TAG, "Activity " + r
658 + " being launched, but already in LRU list");
659 }
660
661 if (andResume) {
662 // As part of the process of launching, ActivityThread also performs
663 // a resume.
664 stack.minimalResumeActivityLocked(r);
665 } else {
666 // This activity is not starting in the resumed state... which
667 // should look like we asked it to pause+stop (but remain visible),
668 // and it has done so and reported back the current icicle and
669 // other state.
670 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
671 + " (starting in stopped state)");
672 r.state = ActivityState.STOPPED;
673 r.stopped = true;
674 }
675
676 // Launch the new version setup screen if needed. We do this -after-
677 // launching the initial activity (that is, home), so that it can have
678 // a chance to initialize itself while in the background, making the
679 // switch back to it faster and look better.
680 if (isMainStack(stack)) {
681 mService.startSetupActivityLocked();
682 }
683
684 return true;
685 }
686
Craig Mautnere79d42682013-04-01 19:01:53 -0700687 void startSpecificActivityLocked(ActivityRecord r,
688 boolean andResume, boolean checkConfig) {
689 // Is this activity's application already running?
690 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
691 r.info.applicationInfo.uid);
692
693 r.task.stack.setLaunchTime(r);
694
695 if (app != null && app.thread != null) {
696 try {
697 app.addPackage(r.info.packageName);
698 realStartActivityLocked(r, app, andResume, checkConfig);
699 return;
700 } catch (RemoteException e) {
701 Slog.w(TAG, "Exception when starting activity "
702 + r.intent.getComponent().flattenToShortString(), e);
703 }
704
705 // If a dead object exception was thrown -- fall through to
706 // restart the application.
707 }
708
709 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
710 "activity", r.intent.getComponent(), false, false);
711 }
712
Craig Mautner6170f732013-04-02 13:05:23 -0700713 final int startActivityLocked(IApplicationThread caller,
714 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
715 String resultWho, int requestCode,
716 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
717 boolean componentSpecified, ActivityRecord[] outActivity) {
718 int err = ActivityManager.START_SUCCESS;
719
720 ProcessRecord callerApp = null;
721 if (caller != null) {
722 callerApp = mService.getRecordForAppLocked(caller);
723 if (callerApp != null) {
724 callingPid = callerApp.pid;
725 callingUid = callerApp.info.uid;
726 } else {
727 Slog.w(TAG, "Unable to find app for caller " + caller
728 + " (pid=" + callingPid + ") when starting: "
729 + intent.toString());
730 err = ActivityManager.START_PERMISSION_DENIED;
731 }
732 }
733
734 if (err == ActivityManager.START_SUCCESS) {
735 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
736 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
737 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
738 }
739
740 ActivityRecord sourceRecord = null;
741 ActivityRecord resultRecord = null;
742 if (resultTo != null) {
743 sourceRecord = isInAnyStackLocked(resultTo);
744 if (DEBUG_RESULTS) Slog.v(
745 TAG, "Will send result to " + resultTo + " " + sourceRecord);
746 if (sourceRecord != null) {
747 if (requestCode >= 0 && !sourceRecord.finishing) {
748 resultRecord = sourceRecord;
749 }
750 }
751 }
752 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
753
754 int launchFlags = intent.getFlags();
755
756 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
757 && sourceRecord != null) {
758 // Transfer the result target from the source activity to the new
759 // one being started, including any failures.
760 if (requestCode >= 0) {
761 ActivityOptions.abort(options);
762 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
763 }
764 resultRecord = sourceRecord.resultTo;
765 resultWho = sourceRecord.resultWho;
766 requestCode = sourceRecord.requestCode;
767 sourceRecord.resultTo = null;
768 if (resultRecord != null) {
769 resultRecord.removeResultsLocked(
770 sourceRecord, resultWho, requestCode);
771 }
772 }
773
774 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
775 // We couldn't find a class that can handle the given Intent.
776 // That's the end of that!
777 err = ActivityManager.START_INTENT_NOT_RESOLVED;
778 }
779
780 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
781 // We couldn't find the specific class specified in the Intent.
782 // Also the end of the line.
783 err = ActivityManager.START_CLASS_NOT_FOUND;
784 }
785
786 if (err != ActivityManager.START_SUCCESS) {
787 if (resultRecord != null) {
788 resultStack.sendActivityResultLocked(-1,
789 resultRecord, resultWho, requestCode,
790 Activity.RESULT_CANCELED, null);
791 }
792 setDismissKeyguard(false);
793 ActivityOptions.abort(options);
794 return err;
795 }
796
797 final int startAnyPerm = mService.checkPermission(
798 START_ANY_ACTIVITY, callingPid, callingUid);
799 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
800 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
801 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
802 if (resultRecord != null) {
803 resultStack.sendActivityResultLocked(-1,
804 resultRecord, resultWho, requestCode,
805 Activity.RESULT_CANCELED, null);
806 }
807 setDismissKeyguard(false);
808 String msg;
809 if (!aInfo.exported) {
810 msg = "Permission Denial: starting " + intent.toString()
811 + " from " + callerApp + " (pid=" + callingPid
812 + ", uid=" + callingUid + ")"
813 + " not exported from uid " + aInfo.applicationInfo.uid;
814 } else {
815 msg = "Permission Denial: starting " + intent.toString()
816 + " from " + callerApp + " (pid=" + callingPid
817 + ", uid=" + callingUid + ")"
818 + " requires " + aInfo.permission;
819 }
820 Slog.w(TAG, msg);
821 throw new SecurityException(msg);
822 }
823
824 if (mService.mController != null) {
825 boolean abort = false;
826 try {
827 // The Intent we give to the watcher has the extra data
828 // stripped off, since it can contain private information.
829 Intent watchIntent = intent.cloneFilter();
830 abort = !mService.mController.activityStarting(watchIntent,
831 aInfo.applicationInfo.packageName);
832 } catch (RemoteException e) {
833 mService.mController = null;
834 }
835
836 if (abort) {
837 if (resultRecord != null) {
838 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
839 Activity.RESULT_CANCELED, null);
840 }
841 // We pretend to the caller that it was really started, but
842 // they will just get a cancel result.
843 setDismissKeyguard(false);
844 ActivityOptions.abort(options);
845 return ActivityManager.START_SUCCESS;
846 }
847 }
848
849 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
850 intent, resolvedType, aInfo, mService.mConfiguration,
851 resultRecord, resultWho, requestCode, componentSpecified);
852 if (outActivity != null) {
853 outActivity[0] = r;
854 }
855
856 if (mMainStack.mResumedActivity == null
857 || mMainStack.mResumedActivity.info.applicationInfo.uid != callingUid) {
858 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
859 PendingActivityLaunch pal =
860 new PendingActivityLaunch(r, sourceRecord, startFlags, mMainStack);
861 mService.mPendingActivityLaunches.add(pal);
862 setDismissKeyguard(false);
863 ActivityOptions.abort(options);
864 return ActivityManager.START_SWITCHES_CANCELED;
865 }
866 }
867
868 if (mService.mDidAppSwitch) {
869 // This is the second allowed switch since we stopped switches,
870 // so now just generally allow switches. Use case: user presses
871 // home (switches disabled, switch to home, mDidAppSwitch now true);
872 // user taps a home icon (coming from home so allowed, we hit here
873 // and now allow anyone to switch again).
874 mService.mAppSwitchesAllowedTime = 0;
875 } else {
876 mService.mDidAppSwitch = true;
877 }
878
879 mService.doPendingActivityLaunchesLocked(false);
880
881 err = mMainStack.startActivityUncheckedLocked(r, sourceRecord,
882 startFlags, true, options);
883 if (mMainStack.mPausingActivity == null) {
884 // Someone asked to have the keyguard dismissed on the next
885 // activity start, but we are not actually doing an activity
886 // switch... just dismiss the keyguard now, because we
887 // probably want to see whatever is behind it.
888 dismissKeyguard();
889 }
890 return err;
891 }
892
Craig Mautner8d341ef2013-03-26 09:03:27 -0700893 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
894 // Just in case.
895 final int numStacks = mStacks.size();
896 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Craig Mautnere79d42682013-04-01 19:01:53 -0700897 mStacks.get(stackNdx).handleAppDiedLocked(app, restarting);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700898 }
899 }
900
901 void closeSystemDialogsLocked() {
902 final int numStacks = mStacks.size();
903 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
904 final ActivityStack stack = mStacks.get(stackNdx);
905 stack.closeSystemDialogsLocked();
906 }
907 }
908
909 /**
910 * @return true if some activity was finished (or would have finished if doit were true).
911 */
912 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
913 boolean didSomething = false;
914 final int numStacks = mStacks.size();
915 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
916 final ActivityStack stack = mStacks.get(stackNdx);
917 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
918 didSomething = true;
919 }
920 }
921 return didSomething;
922 }
923
924 void resumeTopActivityLocked() {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700925 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner8d341ef2013-03-26 09:03:27 -0700926 mStacks.get(stackNdx).resumeTopActivityLocked(null);
927 }
928 }
929
930 void finishTopRunningActivityLocked(ProcessRecord app) {
931 final int numStacks = mStacks.size();
932 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
933 final ActivityStack stack = mStacks.get(stackNdx);
934 stack.finishTopRunningActivityLocked(app);
935 }
936 }
937
938 void scheduleIdleLocked() {
939 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
940 mStacks.get(stackNdx).scheduleIdleLocked();
941 }
942 }
943
944 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
945 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
946 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
947 return;
948 }
949 }
950 }
951
952 private ActivityStack getStack(int stackId) {
953 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
954 final ActivityStack stack = mStacks.get(stackNdx);
955 if (stack.getStackId() == stackId) {
956 return stack;
957 }
958 }
959 return null;
960 }
961
962 int createStack(int relativeStackId, int position, float weight) {
963 synchronized (this) {
964 while (true) {
965 if (++mLastStackId <= HOME_STACK_ID) {
966 mLastStackId = HOME_STACK_ID + 1;
967 }
968 if (getStack(mLastStackId) == null) {
969 break;
970 }
971 }
Craig Mautner2420ead2013-04-01 17:13:20 -0700972 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId, this,
973 mCurrentUser));
Craig Mautner8d341ef2013-03-26 09:03:27 -0700974 return mLastStackId;
975 }
976 }
977
978 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
979 final ActivityStack stack = getStack(stackId);
980 if (stack == null) {
981 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
982 return;
983 }
984 stack.moveTask(taskId, toTop);
985 }
986
987 void goingToSleepLocked() {
988 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
989 mStacks.get(stackNdx).stopIfSleepingLocked();
990 }
991 }
992
993 boolean shutdownLocked(int timeout) {
994 boolean timedout = false;
995 final int numStacks = mStacks.size();
996 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
997 final ActivityStack stack = mStacks.get(stackNdx);
998 if (stack.mResumedActivity != null) {
999 stack.stopIfSleepingLocked();
1000 final long endTime = System.currentTimeMillis() + timeout;
1001 while (stack.mResumedActivity != null || stack.mPausingActivity != null) {
1002 long delay = endTime - System.currentTimeMillis();
1003 if (delay <= 0) {
1004 Slog.w(TAG, "Activity manager shutdown timed out");
1005 timedout = true;
1006 break;
1007 }
1008 try {
1009 mService.wait();
1010 } catch (InterruptedException e) {
1011 }
1012 }
1013 }
1014 }
1015 return timedout;
1016 }
1017
1018 void comeOutOfSleepIfNeededLocked() {
1019 final int numStacks = mStacks.size();
1020 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1021 final ActivityStack stack = mStacks.get(stackNdx);
1022 stack.awakeFromSleepingLocked();
1023 stack.resumeTopActivityLocked(null);
1024 }
1025 }
1026
1027 void handleAppCrashLocked(ProcessRecord app) {
1028 final int numStacks = mStacks.size();
1029 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1030 final ActivityStack stack = mStacks.get(stackNdx);
1031 stack.handleAppCrashLocked(app);
1032 }
1033 }
1034
1035 boolean updateConfigurationLocked(int changes, ActivityRecord starting) {
1036 boolean kept = true;
1037 final int numStacks = mStacks.size();
1038 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1039 final ActivityStack stack = mStacks.get(stackNdx);
1040 if (changes != 0 && starting == null) {
1041 // If the configuration changed, and the caller is not already
1042 // in the process of starting an activity, then find the top
1043 // activity to check if its configuration needs to change.
1044 starting = stack.topRunningActivityLocked(null);
1045 }
1046
1047 if (starting != null) {
1048 if (!stack.ensureActivityConfigurationLocked(starting, changes)) {
1049 kept = false;
1050 }
1051 // And we need to make sure at this point that all other activities
1052 // are made visible with the correct configuration.
1053 stack.ensureActivitiesVisibleLocked(starting, changes);
1054 }
1055 }
1056 return kept;
1057 }
1058
1059 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
1060 final int numStacks = mStacks.size();
1061 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1062 final ActivityStack stack = mStacks.get(stackNdx);
1063 stack.scheduleDestroyActivities(app, false, reason);
1064 }
1065 }
1066
1067 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner2420ead2013-04-01 17:13:20 -07001068 mCurrentUser = userId;
Craig Mautner8d341ef2013-03-26 09:03:27 -07001069 boolean haveActivities = false;
1070 final int numStacks = mStacks.size();
1071 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1072 final ActivityStack stack = mStacks.get(stackNdx);
1073 haveActivities |= stack.switchUserLocked(userId, uss);
1074 }
1075 return haveActivities;
Craig Mautner2219a1b2013-03-25 09:44:30 -07001076 }
1077
Craig Mautner27084302013-03-25 08:05:25 -07001078 public void dump(PrintWriter pw, String prefix) {
1079 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
1080 pw.println(mDismissKeyguardOnNextActivity);
1081 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001082
Craig Mautner20e72272013-04-01 13:45:53 -07001083 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
1084 return mMainStack.getDumpActivitiesLocked(name);
1085 }
1086
Craig Mautner8d341ef2013-03-26 09:03:27 -07001087 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
1088 boolean dumpClient, String dumpPackage) {
1089 final int numStacks = mStacks.size();
1090 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1091 final ActivityStack stack = mStacks.get(stackNdx);
1092 pw.print(" Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
1093 stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
1094 pw.println(" ");
1095 pw.println(" Running activities (most recent first):");
1096 dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false,
1097 dumpPackage);
1098 if (stack.mWaitingVisibleActivities.size() > 0) {
1099 pw.println(" ");
1100 pw.println(" Activities waiting for another to become visible:");
1101 dumpHistoryList(fd, pw, stack.mWaitingVisibleActivities, " ", "Wait", false,
1102 !dumpAll, false, dumpPackage);
1103 }
1104 if (stack.mStoppingActivities.size() > 0) {
1105 pw.println(" ");
1106 pw.println(" Activities waiting to stop:");
1107 dumpHistoryList(fd, pw, stack.mStoppingActivities, " ", "Stop", false,
1108 !dumpAll, false, dumpPackage);
1109 }
1110 if (stack.mGoingToSleepActivities.size() > 0) {
1111 pw.println(" ");
1112 pw.println(" Activities waiting to sleep:");
1113 dumpHistoryList(fd, pw, stack.mGoingToSleepActivities, " ", "Sleep", false,
1114 !dumpAll, false, dumpPackage);
1115 }
1116 if (stack.mFinishingActivities.size() > 0) {
1117 pw.println(" ");
1118 pw.println(" Activities waiting to finish:");
1119 dumpHistoryList(fd, pw, stack.mFinishingActivities, " ", "Fin", false,
1120 !dumpAll, false, dumpPackage);
1121 }
1122 }
1123
1124 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1125 final ActivityStack stack = mStacks.get(stackNdx);
1126 pw.print(" Stack #"); pw.println(mStacks.indexOf(stack));
1127 if (stack.mPausingActivity != null) {
1128 pw.println(" mPausingActivity: " + stack.mPausingActivity);
1129 }
1130 pw.println(" mResumedActivity: " + stack.mResumedActivity);
1131 if (dumpAll) {
1132 pw.println(" mLastPausedActivity: " + stack.mLastPausedActivity);
1133 pw.println(" mSleepTimeout: " + stack.mSleepTimeout);
1134 }
1135 }
1136
1137 if (dumpAll) {
1138 pw.println(" ");
1139 pw.println(" mCurTaskId: " + mCurTaskId);
1140 }
1141 return true;
1142 }
1143
1144 static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
1145 String prefix, String label, boolean complete, boolean brief, boolean client,
1146 String dumpPackage) {
1147 TaskRecord lastTask = null;
1148 boolean needNL = false;
1149 final String innerPrefix = prefix + " ";
1150 final String[] args = new String[0];
1151 for (int i=list.size()-1; i>=0; i--) {
1152 final ActivityRecord r = list.get(i);
1153 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
1154 continue;
1155 }
1156 final boolean full = !brief && (complete || !r.isInHistory());
1157 if (needNL) {
1158 pw.println(" ");
1159 needNL = false;
1160 }
1161 if (lastTask != r.task) {
1162 lastTask = r.task;
1163 pw.print(prefix);
1164 pw.print(full ? "* " : " ");
1165 pw.println(lastTask);
1166 if (full) {
1167 lastTask.dump(pw, prefix + " ");
1168 } else if (complete) {
1169 // Complete + brief == give a summary. Isn't that obvious?!?
1170 if (lastTask.intent != null) {
1171 pw.print(prefix); pw.print(" ");
1172 pw.println(lastTask.intent.toInsecureStringWithClip());
1173 }
1174 }
1175 }
1176 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
1177 pw.print(" #"); pw.print(i); pw.print(": ");
1178 pw.println(r);
1179 if (full) {
1180 r.dump(pw, innerPrefix);
1181 } else if (complete) {
1182 // Complete + brief == give a summary. Isn't that obvious?!?
1183 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
1184 if (r.app != null) {
1185 pw.print(innerPrefix); pw.println(r.app);
1186 }
1187 }
1188 if (client && r.app != null && r.app.thread != null) {
1189 // flush anything that is already in the PrintWriter since the thread is going
1190 // to write to the file descriptor directly
1191 pw.flush();
1192 try {
1193 TransferPipe tp = new TransferPipe();
1194 try {
1195 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
1196 r.appToken, innerPrefix, args);
1197 // Short timeout, since blocking here can
1198 // deadlock with the application.
1199 tp.go(fd, 2000);
1200 } finally {
1201 tp.kill();
1202 }
1203 } catch (IOException e) {
1204 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
1205 } catch (RemoteException e) {
1206 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
1207 }
1208 needNL = true;
1209 }
1210 }
1211 }
Craig Mautner27084302013-03-25 08:05:25 -07001212}