blob: 175a29ed3dd32209b44407671bdd938ebacb3602 [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 Mautner2420ead2013-04-01 17:13:20 -070019import static com.android.server.am.ActivityManagerService.localLOGV;
Craig Mautner8d341ef2013-03-26 09:03:27 -070020import static com.android.server.am.ActivityManagerService.DEBUG_CLEANUP;
Craig Mautner23ac33b2013-04-01 16:26:35 -070021import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION;
Craig Mautner8d341ef2013-03-26 09:03:27 -070022import static com.android.server.am.ActivityManagerService.DEBUG_PAUSE;
Craig Mautner2420ead2013-04-01 17:13:20 -070023import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
Craig Mautner8d341ef2013-03-26 09:03:27 -070024import static com.android.server.am.ActivityManagerService.TAG;
25
Craig Mautner2420ead2013-04-01 17:13:20 -070026import android.app.Activity;
Craig Mautner23ac33b2013-04-01 16:26:35 -070027import android.app.ActivityManager;
28import android.app.ActivityOptions;
29import android.app.AppGlobals;
30import android.app.IApplicationThread;
Craig Mautner20e72272013-04-01 13:45:53 -070031import android.app.IThumbnailReceiver;
Craig Mautner23ac33b2013-04-01 16:26:35 -070032import android.app.PendingIntent;
Craig Mautner20e72272013-04-01 13:45:53 -070033import android.app.ActivityManager.RunningTaskInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070034import android.app.IActivityManager.WaitResult;
Craig Mautner2420ead2013-04-01 17:13:20 -070035import android.app.ResultInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070036import android.content.ComponentName;
Craig Mautner2219a1b2013-03-25 09:44:30 -070037import android.content.Context;
Craig Mautner23ac33b2013-04-01 16:26:35 -070038import android.content.IIntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070039import android.content.Intent;
Craig Mautner23ac33b2013-04-01 16:26:35 -070040import android.content.IntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070041import android.content.pm.ActivityInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070042import android.content.pm.ApplicationInfo;
43import android.content.pm.PackageManager;
44import android.content.pm.ResolveInfo;
45import android.content.res.Configuration;
46import android.os.Binder;
Craig Mautner8d341ef2013-03-26 09:03:27 -070047import android.os.Bundle;
Craig Mautner23ac33b2013-04-01 16:26:35 -070048import android.os.IBinder;
Craig Mautner2219a1b2013-03-25 09:44:30 -070049import android.os.Looper;
Craig Mautner2420ead2013-04-01 17:13:20 -070050import android.os.Message;
Craig Mautner23ac33b2013-04-01 16:26:35 -070051import android.os.ParcelFileDescriptor;
Craig Mautner8d341ef2013-03-26 09:03:27 -070052import android.os.RemoteException;
Craig Mautner23ac33b2013-04-01 16:26:35 -070053import android.os.SystemClock;
Craig Mautner2420ead2013-04-01 17:13:20 -070054import android.util.EventLog;
Craig Mautner8d341ef2013-03-26 09:03:27 -070055import android.util.Slog;
Craig Mautner2219a1b2013-03-25 09:44:30 -070056
Craig Mautner23ac33b2013-04-01 16:26:35 -070057import com.android.internal.app.HeavyWeightSwitcherActivity;
Craig Mautner2420ead2013-04-01 17:13:20 -070058import com.android.server.am.ActivityStack.ActivityState;
Craig Mautner23ac33b2013-04-01 16:26:35 -070059
Craig Mautner8d341ef2013-03-26 09:03:27 -070060import java.io.FileDescriptor;
61import java.io.IOException;
Craig Mautner27084302013-03-25 08:05:25 -070062import java.io.PrintWriter;
Craig Mautner2219a1b2013-03-25 09:44:30 -070063import java.util.ArrayList;
Craig Mautner8d341ef2013-03-26 09:03:27 -070064import java.util.List;
Craig Mautner27084302013-03-25 08:05:25 -070065
66public class ActivityStackSupervisor {
Craig Mautner2420ead2013-04-01 17:13:20 -070067 static final boolean DEBUG_ADD_REMOVE = false;
68 static final boolean DEBUG_APP = false;
69 static final boolean DEBUG_SAVED_STATE = false;
70 static final boolean DEBUG_STATES = false;
71
Craig Mautner2219a1b2013-03-25 09:44:30 -070072 public static final int HOME_STACK_ID = 0;
Craig Mautner27084302013-03-25 08:05:25 -070073
74 final ActivityManagerService mService;
Craig Mautner2219a1b2013-03-25 09:44:30 -070075 final Context mContext;
76 final Looper mLooper;
Craig Mautner27084302013-03-25 08:05:25 -070077
78 /** Dismiss the keyguard after the next activity is displayed? */
79 private boolean mDismissKeyguardOnNextActivity = false;
80
Craig Mautner8d341ef2013-03-26 09:03:27 -070081 /** Identifier counter for all ActivityStacks */
82 private int mLastStackId = 0;
83
84 /** Task identifier that activities are currently being started in. Incremented each time a
85 * new task is created. */
86 private int mCurTaskId = 0;
87
Craig Mautner2420ead2013-04-01 17:13:20 -070088 /** The current user */
89 private int mCurrentUser;
90
Craig Mautner8d341ef2013-03-26 09:03:27 -070091 /** The stack containing the launcher app */
Craig Mautner2219a1b2013-03-25 09:44:30 -070092 private ActivityStack mHomeStack;
Craig Mautner20e72272013-04-01 13:45:53 -070093
94 /** The stack currently receiving input or launching the next activity */
Craig Mautner2219a1b2013-03-25 09:44:30 -070095 private ActivityStack mMainStack;
Craig Mautner8d341ef2013-03-26 09:03:27 -070096
97 /** All the non-launcher stacks */
Craig Mautner2219a1b2013-03-25 09:44:30 -070098 private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
99
100 public ActivityStackSupervisor(ActivityManagerService service, Context context,
101 Looper looper) {
Craig Mautner27084302013-03-25 08:05:25 -0700102 mService = service;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700103 mContext = context;
104 mLooper = looper;
105 }
106
Craig Mautner2420ead2013-04-01 17:13:20 -0700107 void init(int userId) {
108 mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID, this, userId);
Craig Mautner2219a1b2013-03-25 09:44:30 -0700109 setMainStack(mHomeStack);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700110 mStacks.add(mHomeStack);
Craig Mautner27084302013-03-25 08:05:25 -0700111 }
112
113 void dismissKeyguard() {
114 if (mDismissKeyguardOnNextActivity) {
115 mDismissKeyguardOnNextActivity = false;
116 mService.mWindowManager.dismissKeyguard();
117 }
118 }
119
Craig Mautner20e72272013-04-01 13:45:53 -0700120 boolean isHomeStackMain() {
121 return mHomeStack == mMainStack;
122 }
123
Craig Mautner2219a1b2013-03-25 09:44:30 -0700124 boolean isMainStack(ActivityStack stack) {
125 return stack == mMainStack;
126 }
127
Craig Mautner20e72272013-04-01 13:45:53 -0700128 ActivityStack getMainStack() {
129 return mMainStack;
130 }
131
Craig Mautner2219a1b2013-03-25 09:44:30 -0700132 void setMainStack(ActivityStack stack) {
133 mMainStack = stack;
134 }
135
Craig Mautner27084302013-03-25 08:05:25 -0700136 void setDismissKeyguard(boolean dismiss) {
137 mDismissKeyguardOnNextActivity = dismiss;
138 }
139
Craig Mautner8d341ef2013-03-26 09:03:27 -0700140 TaskRecord anyTaskForIdLocked(int id) {
141 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
142 ActivityStack stack = mStacks.get(stackNdx);
143 TaskRecord task = stack.taskForIdLocked(id);
144 if (task != null) {
145 return task;
146 }
147 }
148 return null;
149 }
150
151 int getNextTaskId() {
152 do {
153 mCurTaskId++;
154 if (mCurTaskId <= 0) {
155 mCurTaskId = 1;
156 }
157 } while (anyTaskForIdLocked(mCurTaskId) != null);
158 return mCurTaskId;
159 }
160
Craig Mautner20e72272013-04-01 13:45:53 -0700161 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
162 boolean didSomething = false;
163 final String processName = app.processName;
164 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
165 final ActivityStack stack = mStacks.get(stackNdx);
166 ActivityRecord hr = stack.topRunningActivityLocked(null);
167 if (hr != null) {
168 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
169 && processName.equals(hr.processName)) {
170 try {
171 if (headless) {
172 Slog.e(TAG, "Starting activities not supported on headless device: "
173 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700174 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700175 didSomething = true;
176 }
177 } catch (Exception e) {
178 Slog.w(TAG, "Exception in new application when starting activity "
179 + hr.intent.getComponent().flattenToShortString(), e);
180 throw e;
181 }
182 } else {
183 stack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
184 }
185 }
186 }
187 return didSomething;
188 }
189
190 boolean allResumedActivitiesIdle() {
191 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
192 if (mStacks.get(stackNdx).mResumedActivity == null ||
193 !mStacks.get(stackNdx).mResumedActivity.idle) {
194 return false;
195 }
196 }
197 return true;
198 }
199
200 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
201 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
202 ActivityRecord r = null;
203 final int numStacks = mStacks.size();
204 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
205 final ActivityStack stack = mStacks.get(stackNdx);
206 final ActivityRecord ar =
207 stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
208 if (isMainStack(stack)) {
209 r = ar;
210 }
211 }
212 return r;
213 }
214
Craig Mautner23ac33b2013-04-01 16:26:35 -0700215 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
216 String profileFile, ParcelFileDescriptor profileFd, int userId) {
217 // Collect information about the target of the Intent.
218 ActivityInfo aInfo;
219 try {
220 ResolveInfo rInfo =
221 AppGlobals.getPackageManager().resolveIntent(
222 intent, resolvedType,
223 PackageManager.MATCH_DEFAULT_ONLY
224 | ActivityManagerService.STOCK_PM_FLAGS, userId);
225 aInfo = rInfo != null ? rInfo.activityInfo : null;
226 } catch (RemoteException e) {
227 aInfo = null;
228 }
229
230 if (aInfo != null) {
231 // Store the found target back into the intent, because now that
232 // we have it we never want to do this again. For example, if the
233 // user navigates back to this point in the history, we should
234 // always restart the exact same activity.
235 intent.setComponent(new ComponentName(
236 aInfo.applicationInfo.packageName, aInfo.name));
237
238 // Don't debug things in the system process
239 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
240 if (!aInfo.processName.equals("system")) {
241 mService.setDebugApp(aInfo.processName, true, false);
242 }
243 }
244
245 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
246 if (!aInfo.processName.equals("system")) {
247 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
248 }
249 }
250
251 if (profileFile != null) {
252 if (!aInfo.processName.equals("system")) {
253 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
254 profileFile, profileFd,
255 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
256 }
257 }
258 }
259 return aInfo;
260 }
261
Craig Mautner2219a1b2013-03-25 09:44:30 -0700262 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
263 mHomeStack.startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
264 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700265 }
266
Craig Mautner23ac33b2013-04-01 16:26:35 -0700267 final int startActivityMayWait(IApplicationThread caller, int callingUid,
268 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
269 String resultWho, int requestCode, int startFlags, String profileFile,
270 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
271 Bundle options, int userId) {
272 // Refuse possible leaked file descriptors
273 if (intent != null && intent.hasFileDescriptors()) {
274 throw new IllegalArgumentException("File descriptors passed in Intent");
275 }
276 boolean componentSpecified = intent.getComponent() != null;
277
278 // Don't modify the client's object!
279 intent = new Intent(intent);
280
281 // Collect information about the target of the Intent.
282 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
283 profileFile, profileFd, userId);
284
285 synchronized (mService) {
286 int callingPid;
287 if (callingUid >= 0) {
288 callingPid = -1;
289 } else if (caller == null) {
290 callingPid = Binder.getCallingPid();
291 callingUid = Binder.getCallingUid();
292 } else {
293 callingPid = callingUid = -1;
294 }
295
296 mMainStack.mConfigWillChange = config != null
297 && mService.mConfiguration.diff(config) != 0;
298 if (DEBUG_CONFIGURATION) Slog.v(TAG,
299 "Starting activity when config will change = " + mMainStack.mConfigWillChange);
300
301 final long origId = Binder.clearCallingIdentity();
302
303 if (aInfo != null &&
304 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
305 // This may be a heavy-weight process! Check to see if we already
306 // have another, different heavy-weight process running.
307 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
308 if (mService.mHeavyWeightProcess != null &&
309 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
310 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
311 int realCallingPid = callingPid;
312 int realCallingUid = callingUid;
313 if (caller != null) {
314 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
315 if (callerApp != null) {
316 realCallingPid = callerApp.pid;
317 realCallingUid = callerApp.info.uid;
318 } else {
319 Slog.w(TAG, "Unable to find app for caller " + caller
320 + " (pid=" + realCallingPid + ") when starting: "
321 + intent.toString());
322 ActivityOptions.abort(options);
323 return ActivityManager.START_PERMISSION_DENIED;
324 }
325 }
326
327 IIntentSender target = mService.getIntentSenderLocked(
328 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
329 realCallingUid, userId, null, null, 0, new Intent[] { intent },
330 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
331 | PendingIntent.FLAG_ONE_SHOT, null);
332
333 Intent newIntent = new Intent();
334 if (requestCode >= 0) {
335 // Caller is requesting a result.
336 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
337 }
338 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
339 new IntentSender(target));
340 if (mService.mHeavyWeightProcess.activities.size() > 0) {
341 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
342 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
343 hist.packageName);
344 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
345 hist.task.taskId);
346 }
347 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
348 aInfo.packageName);
349 newIntent.setFlags(intent.getFlags());
350 newIntent.setClassName("android",
351 HeavyWeightSwitcherActivity.class.getName());
352 intent = newIntent;
353 resolvedType = null;
354 caller = null;
355 callingUid = Binder.getCallingUid();
356 callingPid = Binder.getCallingPid();
357 componentSpecified = true;
358 try {
359 ResolveInfo rInfo =
360 AppGlobals.getPackageManager().resolveIntent(
361 intent, null,
362 PackageManager.MATCH_DEFAULT_ONLY
363 | ActivityManagerService.STOCK_PM_FLAGS, userId);
364 aInfo = rInfo != null ? rInfo.activityInfo : null;
365 aInfo = mService.getActivityInfoForUser(aInfo, userId);
366 } catch (RemoteException e) {
367 aInfo = null;
368 }
369 }
370 }
371 }
372
373 int res = mMainStack.startActivityLocked(caller, intent, resolvedType,
374 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
375 callingPackage, startFlags, options, componentSpecified, null);
376
377 if (mMainStack.mConfigWillChange) {
378 // If the caller also wants to switch to a new configuration,
379 // do so now. This allows a clean switch, as we are waiting
380 // for the current activity to pause (so we will not destroy
381 // it), and have not yet started the next activity.
382 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
383 "updateConfiguration()");
384 mMainStack.mConfigWillChange = false;
385 if (DEBUG_CONFIGURATION) Slog.v(TAG,
386 "Updating to new configuration after starting activity.");
387 mService.updateConfigurationLocked(config, null, false, false);
388 }
389
390 Binder.restoreCallingIdentity(origId);
391
392 if (outResult != null) {
393 outResult.result = res;
394 if (res == ActivityManager.START_SUCCESS) {
395 mMainStack.mWaitingActivityLaunched.add(outResult);
396 do {
397 try {
398 mService.wait();
399 } catch (InterruptedException e) {
400 }
401 } while (!outResult.timeout && outResult.who == null);
402 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
403 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
404 if (r.nowVisible) {
405 outResult.timeout = false;
406 outResult.who = new ComponentName(r.info.packageName, r.info.name);
407 outResult.totalTime = 0;
408 outResult.thisTime = 0;
409 } else {
410 outResult.thisTime = SystemClock.uptimeMillis();
411 mMainStack.mWaitingActivityVisible.add(outResult);
412 do {
413 try {
414 mService.wait();
415 } catch (InterruptedException e) {
416 }
417 } while (!outResult.timeout && outResult.who == null);
418 }
419 }
420 }
421
422 return res;
423 }
424 }
425
426 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
427 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
428 Bundle options, int userId) {
429 if (intents == null) {
430 throw new NullPointerException("intents is null");
431 }
432 if (resolvedTypes == null) {
433 throw new NullPointerException("resolvedTypes is null");
434 }
435 if (intents.length != resolvedTypes.length) {
436 throw new IllegalArgumentException("intents are length different than resolvedTypes");
437 }
438
439 ActivityRecord[] outActivity = new ActivityRecord[1];
440
441 int callingPid;
442 if (callingUid >= 0) {
443 callingPid = -1;
444 } else if (caller == null) {
445 callingPid = Binder.getCallingPid();
446 callingUid = Binder.getCallingUid();
447 } else {
448 callingPid = callingUid = -1;
449 }
450 final long origId = Binder.clearCallingIdentity();
451 try {
452 synchronized (mService) {
453
454 for (int i=0; i<intents.length; i++) {
455 Intent intent = intents[i];
456 if (intent == null) {
457 continue;
458 }
459
460 // Refuse possible leaked file descriptors
461 if (intent != null && intent.hasFileDescriptors()) {
462 throw new IllegalArgumentException("File descriptors passed in Intent");
463 }
464
465 boolean componentSpecified = intent.getComponent() != null;
466
467 // Don't modify the client's object!
468 intent = new Intent(intent);
469
470 // Collect information about the target of the Intent.
471 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
472 0, null, null, userId);
473 // TODO: New, check if this is correct
474 aInfo = mService.getActivityInfoForUser(aInfo, userId);
475
476 if (aInfo != null &&
477 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
478 != 0) {
479 throw new IllegalArgumentException(
480 "FLAG_CANT_SAVE_STATE not supported here");
481 }
482
483 Bundle theseOptions;
484 if (options != null && i == intents.length-1) {
485 theseOptions = options;
486 } else {
487 theseOptions = null;
488 }
489 int res = mMainStack.startActivityLocked(caller, intent, resolvedTypes[i],
490 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
491 0, theseOptions, componentSpecified, outActivity);
492 if (res < 0) {
493 return res;
494 }
495
496 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
497 }
498 }
499 } finally {
500 Binder.restoreCallingIdentity(origId);
501 }
502
503 return ActivityManager.START_SUCCESS;
504 }
505
Craig Mautner2420ead2013-04-01 17:13:20 -0700506 final boolean realStartActivityLocked(ActivityRecord r,
507 ProcessRecord app, boolean andResume, boolean checkConfig)
508 throws RemoteException {
509
510 r.startFreezingScreenLocked(app, 0);
511 mService.mWindowManager.setAppVisibility(r.appToken, true);
512
513 // schedule launch ticks to collect information about slow apps.
514 r.startLaunchTickingLocked();
515
516 // Have the window manager re-evaluate the orientation of
517 // the screen based on the new activity order. Note that
518 // as a result of this, it can call back into the activity
519 // manager with a new orientation. We don't care about that,
520 // because the activity is not currently running so we are
521 // just restarting it anyway.
522 if (checkConfig) {
523 Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
524 mService.mConfiguration,
525 r.mayFreezeScreenLocked(app) ? r.appToken : null);
526 mService.updateConfigurationLocked(config, r, false, false);
527 }
528
529 r.app = app;
530 app.waitingToKill = null;
531 r.launchCount++;
532 r.lastLaunchTime = SystemClock.uptimeMillis();
533
534 if (localLOGV) Slog.v(TAG, "Launching: " + r);
535
536 int idx = app.activities.indexOf(r);
537 if (idx < 0) {
538 app.activities.add(r);
539 }
540 mService.updateLruProcessLocked(app, true);
541
542 final ActivityStack stack = r.task.stack;
543 try {
544 if (app.thread == null) {
545 throw new RemoteException();
546 }
547 List<ResultInfo> results = null;
548 List<Intent> newIntents = null;
549 if (andResume) {
550 results = r.results;
551 newIntents = r.newIntents;
552 }
553 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
554 + " icicle=" + r.icicle
555 + " with results=" + results + " newIntents=" + newIntents
556 + " andResume=" + andResume);
557 if (andResume) {
558 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
559 r.userId, System.identityHashCode(r),
560 r.task.taskId, r.shortComponentName);
561 }
562 if (r.isHomeActivity) {
563 mService.mHomeProcess = app;
564 }
565 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
566 r.sleeping = false;
567 r.forceNewConfig = false;
568 mService.showAskCompatModeDialogLocked(r);
569 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
570 String profileFile = null;
571 ParcelFileDescriptor profileFd = null;
572 boolean profileAutoStop = false;
573 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
574 if (mService.mProfileProc == null || mService.mProfileProc == app) {
575 mService.mProfileProc = app;
576 profileFile = mService.mProfileFile;
577 profileFd = mService.mProfileFd;
578 profileAutoStop = mService.mAutoStopProfiler;
579 }
580 }
581 app.hasShownUi = true;
582 app.pendingUiClean = true;
583 if (profileFd != null) {
584 try {
585 profileFd = profileFd.dup();
586 } catch (IOException e) {
587 if (profileFd != null) {
588 try {
589 profileFd.close();
590 } catch (IOException o) {
591 }
592 profileFd = null;
593 }
594 }
595 }
596 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
597 System.identityHashCode(r), r.info,
598 new Configuration(mService.mConfiguration),
599 r.compat, r.icicle, results, newIntents, !andResume,
600 mService.isNextTransitionForward(), profileFile, profileFd,
601 profileAutoStop);
602
603 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
604 // This may be a heavy-weight process! Note that the package
605 // manager will ensure that only activity can run in the main
606 // process of the .apk, which is the only thing that will be
607 // considered heavy-weight.
608 if (app.processName.equals(app.info.packageName)) {
609 if (mService.mHeavyWeightProcess != null
610 && mService.mHeavyWeightProcess != app) {
611 Slog.w(TAG, "Starting new heavy weight process " + app
612 + " when already running "
613 + mService.mHeavyWeightProcess);
614 }
615 mService.mHeavyWeightProcess = app;
616 Message msg = mService.mHandler.obtainMessage(
617 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
618 msg.obj = r;
619 mService.mHandler.sendMessage(msg);
620 }
621 }
622
623 } catch (RemoteException e) {
624 if (r.launchFailed) {
625 // This is the second time we failed -- finish activity
626 // and give up.
627 Slog.e(TAG, "Second failure launching "
628 + r.intent.getComponent().flattenToShortString()
629 + ", giving up", e);
630 mService.appDiedLocked(app, app.pid, app.thread);
631 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
632 "2nd-crash", false);
633 return false;
634 }
635
636 // This is the first time we failed -- restart process and
637 // retry.
638 app.activities.remove(r);
639 throw e;
640 }
641
642 r.launchFailed = false;
643 if (stack.updateLRUListLocked(r)) {
644 Slog.w(TAG, "Activity " + r
645 + " being launched, but already in LRU list");
646 }
647
648 if (andResume) {
649 // As part of the process of launching, ActivityThread also performs
650 // a resume.
651 stack.minimalResumeActivityLocked(r);
652 } else {
653 // This activity is not starting in the resumed state... which
654 // should look like we asked it to pause+stop (but remain visible),
655 // and it has done so and reported back the current icicle and
656 // other state.
657 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
658 + " (starting in stopped state)");
659 r.state = ActivityState.STOPPED;
660 r.stopped = true;
661 }
662
663 // Launch the new version setup screen if needed. We do this -after-
664 // launching the initial activity (that is, home), so that it can have
665 // a chance to initialize itself while in the background, making the
666 // switch back to it faster and look better.
667 if (isMainStack(stack)) {
668 mService.startSetupActivityLocked();
669 }
670
671 return true;
672 }
673
Craig Mautner8d341ef2013-03-26 09:03:27 -0700674 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
675 // Just in case.
676 final int numStacks = mStacks.size();
677 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
678 final ActivityStack stack = mStacks.get(stackNdx);
679 if (stack.mPausingActivity != null && stack.mPausingActivity.app == app) {
680 if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG,
681 "App died while pausing: " + stack.mPausingActivity);
682 stack.mPausingActivity = null;
683 }
684 if (stack.mLastPausedActivity != null && stack.mLastPausedActivity.app == app) {
685 stack.mLastPausedActivity = null;
686 }
687
688 // Remove this application's activities from active lists.
689 boolean hasVisibleActivities = stack.removeHistoryRecordsForAppLocked(app);
690
691 if (!restarting) {
692 if (!stack.resumeTopActivityLocked(null)) {
693 // If there was nothing to resume, and we are not already
694 // restarting this process, but there is a visible activity that
695 // is hosted by the process... then make sure all visible
696 // activities are running, taking care of restarting this
697 // process.
698 if (hasVisibleActivities) {
699 stack.ensureActivitiesVisibleLocked(null, 0);
700 }
701 }
702 }
703 }
704 }
705
706 void closeSystemDialogsLocked() {
707 final int numStacks = mStacks.size();
708 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
709 final ActivityStack stack = mStacks.get(stackNdx);
710 stack.closeSystemDialogsLocked();
711 }
712 }
713
714 /**
715 * @return true if some activity was finished (or would have finished if doit were true).
716 */
717 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
718 boolean didSomething = false;
719 final int numStacks = mStacks.size();
720 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
721 final ActivityStack stack = mStacks.get(stackNdx);
722 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
723 didSomething = true;
724 }
725 }
726 return didSomething;
727 }
728
729 void resumeTopActivityLocked() {
730 final int start, end;
Craig Mautner20e72272013-04-01 13:45:53 -0700731 if (isHomeStackMain()) {
Craig Mautner8d341ef2013-03-26 09:03:27 -0700732 start = 0;
733 end = 1;
734 } else {
735 start = 1;
736 end = mStacks.size();
737 }
738 for (int stackNdx = start; stackNdx < end; ++stackNdx) {
739 mStacks.get(stackNdx).resumeTopActivityLocked(null);
740 }
741 }
742
743 void finishTopRunningActivityLocked(ProcessRecord app) {
744 final int numStacks = mStacks.size();
745 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
746 final ActivityStack stack = mStacks.get(stackNdx);
747 stack.finishTopRunningActivityLocked(app);
748 }
749 }
750
751 void scheduleIdleLocked() {
752 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
753 mStacks.get(stackNdx).scheduleIdleLocked();
754 }
755 }
756
757 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
758 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
759 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
760 return;
761 }
762 }
763 }
764
765 private ActivityStack getStack(int stackId) {
766 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
767 final ActivityStack stack = mStacks.get(stackNdx);
768 if (stack.getStackId() == stackId) {
769 return stack;
770 }
771 }
772 return null;
773 }
774
775 int createStack(int relativeStackId, int position, float weight) {
776 synchronized (this) {
777 while (true) {
778 if (++mLastStackId <= HOME_STACK_ID) {
779 mLastStackId = HOME_STACK_ID + 1;
780 }
781 if (getStack(mLastStackId) == null) {
782 break;
783 }
784 }
Craig Mautner2420ead2013-04-01 17:13:20 -0700785 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId, this,
786 mCurrentUser));
Craig Mautner8d341ef2013-03-26 09:03:27 -0700787 return mLastStackId;
788 }
789 }
790
791 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
792 final ActivityStack stack = getStack(stackId);
793 if (stack == null) {
794 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
795 return;
796 }
797 stack.moveTask(taskId, toTop);
798 }
799
800 void goingToSleepLocked() {
801 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
802 mStacks.get(stackNdx).stopIfSleepingLocked();
803 }
804 }
805
806 boolean shutdownLocked(int timeout) {
807 boolean timedout = false;
808 final int numStacks = mStacks.size();
809 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
810 final ActivityStack stack = mStacks.get(stackNdx);
811 if (stack.mResumedActivity != null) {
812 stack.stopIfSleepingLocked();
813 final long endTime = System.currentTimeMillis() + timeout;
814 while (stack.mResumedActivity != null || stack.mPausingActivity != null) {
815 long delay = endTime - System.currentTimeMillis();
816 if (delay <= 0) {
817 Slog.w(TAG, "Activity manager shutdown timed out");
818 timedout = true;
819 break;
820 }
821 try {
822 mService.wait();
823 } catch (InterruptedException e) {
824 }
825 }
826 }
827 }
828 return timedout;
829 }
830
831 void comeOutOfSleepIfNeededLocked() {
832 final int numStacks = mStacks.size();
833 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
834 final ActivityStack stack = mStacks.get(stackNdx);
835 stack.awakeFromSleepingLocked();
836 stack.resumeTopActivityLocked(null);
837 }
838 }
839
840 void handleAppCrashLocked(ProcessRecord app) {
841 final int numStacks = mStacks.size();
842 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
843 final ActivityStack stack = mStacks.get(stackNdx);
844 stack.handleAppCrashLocked(app);
845 }
846 }
847
848 boolean updateConfigurationLocked(int changes, ActivityRecord starting) {
849 boolean kept = true;
850 final int numStacks = mStacks.size();
851 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
852 final ActivityStack stack = mStacks.get(stackNdx);
853 if (changes != 0 && starting == null) {
854 // If the configuration changed, and the caller is not already
855 // in the process of starting an activity, then find the top
856 // activity to check if its configuration needs to change.
857 starting = stack.topRunningActivityLocked(null);
858 }
859
860 if (starting != null) {
861 if (!stack.ensureActivityConfigurationLocked(starting, changes)) {
862 kept = false;
863 }
864 // And we need to make sure at this point that all other activities
865 // are made visible with the correct configuration.
866 stack.ensureActivitiesVisibleLocked(starting, changes);
867 }
868 }
869 return kept;
870 }
871
872 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
873 final int numStacks = mStacks.size();
874 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
875 final ActivityStack stack = mStacks.get(stackNdx);
876 stack.scheduleDestroyActivities(app, false, reason);
877 }
878 }
879
880 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner2420ead2013-04-01 17:13:20 -0700881 mCurrentUser = userId;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700882 boolean haveActivities = false;
883 final int numStacks = mStacks.size();
884 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
885 final ActivityStack stack = mStacks.get(stackNdx);
886 haveActivities |= stack.switchUserLocked(userId, uss);
887 }
888 return haveActivities;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700889 }
890
Craig Mautner27084302013-03-25 08:05:25 -0700891 public void dump(PrintWriter pw, String prefix) {
892 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
893 pw.println(mDismissKeyguardOnNextActivity);
894 }
Craig Mautner8d341ef2013-03-26 09:03:27 -0700895
Craig Mautner20e72272013-04-01 13:45:53 -0700896 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
897 return mMainStack.getDumpActivitiesLocked(name);
898 }
899
Craig Mautner8d341ef2013-03-26 09:03:27 -0700900 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
901 boolean dumpClient, String dumpPackage) {
902 final int numStacks = mStacks.size();
903 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
904 final ActivityStack stack = mStacks.get(stackNdx);
905 pw.print(" Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
906 stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
907 pw.println(" ");
908 pw.println(" Running activities (most recent first):");
909 dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false,
910 dumpPackage);
911 if (stack.mWaitingVisibleActivities.size() > 0) {
912 pw.println(" ");
913 pw.println(" Activities waiting for another to become visible:");
914 dumpHistoryList(fd, pw, stack.mWaitingVisibleActivities, " ", "Wait", false,
915 !dumpAll, false, dumpPackage);
916 }
917 if (stack.mStoppingActivities.size() > 0) {
918 pw.println(" ");
919 pw.println(" Activities waiting to stop:");
920 dumpHistoryList(fd, pw, stack.mStoppingActivities, " ", "Stop", false,
921 !dumpAll, false, dumpPackage);
922 }
923 if (stack.mGoingToSleepActivities.size() > 0) {
924 pw.println(" ");
925 pw.println(" Activities waiting to sleep:");
926 dumpHistoryList(fd, pw, stack.mGoingToSleepActivities, " ", "Sleep", false,
927 !dumpAll, false, dumpPackage);
928 }
929 if (stack.mFinishingActivities.size() > 0) {
930 pw.println(" ");
931 pw.println(" Activities waiting to finish:");
932 dumpHistoryList(fd, pw, stack.mFinishingActivities, " ", "Fin", false,
933 !dumpAll, false, dumpPackage);
934 }
935 }
936
937 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
938 final ActivityStack stack = mStacks.get(stackNdx);
939 pw.print(" Stack #"); pw.println(mStacks.indexOf(stack));
940 if (stack.mPausingActivity != null) {
941 pw.println(" mPausingActivity: " + stack.mPausingActivity);
942 }
943 pw.println(" mResumedActivity: " + stack.mResumedActivity);
944 if (dumpAll) {
945 pw.println(" mLastPausedActivity: " + stack.mLastPausedActivity);
946 pw.println(" mSleepTimeout: " + stack.mSleepTimeout);
947 }
948 }
949
950 if (dumpAll) {
951 pw.println(" ");
952 pw.println(" mCurTaskId: " + mCurTaskId);
953 }
954 return true;
955 }
956
957 static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
958 String prefix, String label, boolean complete, boolean brief, boolean client,
959 String dumpPackage) {
960 TaskRecord lastTask = null;
961 boolean needNL = false;
962 final String innerPrefix = prefix + " ";
963 final String[] args = new String[0];
964 for (int i=list.size()-1; i>=0; i--) {
965 final ActivityRecord r = list.get(i);
966 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
967 continue;
968 }
969 final boolean full = !brief && (complete || !r.isInHistory());
970 if (needNL) {
971 pw.println(" ");
972 needNL = false;
973 }
974 if (lastTask != r.task) {
975 lastTask = r.task;
976 pw.print(prefix);
977 pw.print(full ? "* " : " ");
978 pw.println(lastTask);
979 if (full) {
980 lastTask.dump(pw, prefix + " ");
981 } else if (complete) {
982 // Complete + brief == give a summary. Isn't that obvious?!?
983 if (lastTask.intent != null) {
984 pw.print(prefix); pw.print(" ");
985 pw.println(lastTask.intent.toInsecureStringWithClip());
986 }
987 }
988 }
989 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
990 pw.print(" #"); pw.print(i); pw.print(": ");
991 pw.println(r);
992 if (full) {
993 r.dump(pw, innerPrefix);
994 } else if (complete) {
995 // Complete + brief == give a summary. Isn't that obvious?!?
996 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
997 if (r.app != null) {
998 pw.print(innerPrefix); pw.println(r.app);
999 }
1000 }
1001 if (client && r.app != null && r.app.thread != null) {
1002 // flush anything that is already in the PrintWriter since the thread is going
1003 // to write to the file descriptor directly
1004 pw.flush();
1005 try {
1006 TransferPipe tp = new TransferPipe();
1007 try {
1008 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
1009 r.appToken, innerPrefix, args);
1010 // Short timeout, since blocking here can
1011 // deadlock with the application.
1012 tp.go(fd, 2000);
1013 } finally {
1014 tp.kill();
1015 }
1016 } catch (IOException e) {
1017 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
1018 } catch (RemoteException e) {
1019 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
1020 }
1021 needNL = true;
1022 }
1023 }
1024 }
Craig Mautner27084302013-03-25 08:05:25 -07001025}