blob: 7b8ad430a3784e7ebecf2b2a66cd38f322b5090e [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 Mautner8849a5e2013-04-02 16:41:03 -070025import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
26import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
Craig Mautner8d341ef2013-03-26 09:03:27 -070027import static com.android.server.am.ActivityManagerService.TAG;
28
Craig Mautner2420ead2013-04-01 17:13:20 -070029import android.app.Activity;
Craig Mautner23ac33b2013-04-01 16:26:35 -070030import android.app.ActivityManager;
31import android.app.ActivityOptions;
32import android.app.AppGlobals;
33import android.app.IApplicationThread;
Craig Mautner20e72272013-04-01 13:45:53 -070034import android.app.IThumbnailReceiver;
Craig Mautner23ac33b2013-04-01 16:26:35 -070035import android.app.PendingIntent;
Craig Mautner20e72272013-04-01 13:45:53 -070036import android.app.ActivityManager.RunningTaskInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070037import android.app.IActivityManager.WaitResult;
Craig Mautner2420ead2013-04-01 17:13:20 -070038import android.app.ResultInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070039import android.content.ComponentName;
Craig Mautner2219a1b2013-03-25 09:44:30 -070040import android.content.Context;
Craig Mautner23ac33b2013-04-01 16:26:35 -070041import android.content.IIntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070042import android.content.Intent;
Craig Mautner23ac33b2013-04-01 16:26:35 -070043import android.content.IntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070044import android.content.pm.ActivityInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070045import android.content.pm.ApplicationInfo;
46import android.content.pm.PackageManager;
47import android.content.pm.ResolveInfo;
48import android.content.res.Configuration;
49import android.os.Binder;
Craig Mautner8d341ef2013-03-26 09:03:27 -070050import android.os.Bundle;
Craig Mautner23ac33b2013-04-01 16:26:35 -070051import android.os.IBinder;
Craig Mautner2219a1b2013-03-25 09:44:30 -070052import android.os.Looper;
Craig Mautner2420ead2013-04-01 17:13:20 -070053import android.os.Message;
Craig Mautner23ac33b2013-04-01 16:26:35 -070054import android.os.ParcelFileDescriptor;
Craig Mautner8d341ef2013-03-26 09:03:27 -070055import android.os.RemoteException;
Craig Mautner23ac33b2013-04-01 16:26:35 -070056import android.os.SystemClock;
Craig Mautner6170f732013-04-02 13:05:23 -070057import android.os.UserHandle;
Craig Mautner2420ead2013-04-01 17:13:20 -070058import android.util.EventLog;
Craig Mautner8d341ef2013-03-26 09:03:27 -070059import android.util.Slog;
Craig Mautner2219a1b2013-03-25 09:44:30 -070060
Craig Mautner23ac33b2013-04-01 16:26:35 -070061import com.android.internal.app.HeavyWeightSwitcherActivity;
Craig Mautner6170f732013-04-02 13:05:23 -070062import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
Craig Mautner2420ead2013-04-01 17:13:20 -070063import com.android.server.am.ActivityStack.ActivityState;
Craig Mautnerde4ef022013-04-07 19:01:33 -070064import com.android.server.wm.StackBox;
Craig Mautner23ac33b2013-04-01 16:26:35 -070065
Craig Mautner8d341ef2013-03-26 09:03:27 -070066import java.io.FileDescriptor;
67import java.io.IOException;
Craig Mautner27084302013-03-25 08:05:25 -070068import java.io.PrintWriter;
Craig Mautner2219a1b2013-03-25 09:44:30 -070069import java.util.ArrayList;
Craig Mautner8d341ef2013-03-26 09:03:27 -070070import java.util.List;
Craig Mautner27084302013-03-25 08:05:25 -070071
72public class ActivityStackSupervisor {
Craig Mautnerde4ef022013-04-07 19:01:33 -070073 static final boolean DEBUG = ActivityManagerService.DEBUG || false;
74 static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
75 static final boolean DEBUG_APP = DEBUG || false;
76 static final boolean DEBUG_SAVED_STATE = DEBUG || false;
77 static final boolean DEBUG_STATES = DEBUG || false;
Craig Mautner2420ead2013-04-01 17:13:20 -070078
Craig Mautner2219a1b2013-03-25 09:44:30 -070079 public static final int HOME_STACK_ID = 0;
Craig Mautner27084302013-03-25 08:05:25 -070080
81 final ActivityManagerService mService;
Craig Mautner2219a1b2013-03-25 09:44:30 -070082 final Context mContext;
83 final Looper mLooper;
Craig Mautner27084302013-03-25 08:05:25 -070084
85 /** Dismiss the keyguard after the next activity is displayed? */
86 private boolean mDismissKeyguardOnNextActivity = false;
87
Craig Mautner8d341ef2013-03-26 09:03:27 -070088 /** Identifier counter for all ActivityStacks */
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -070089 private int mLastStackId = HOME_STACK_ID;
Craig Mautner8d341ef2013-03-26 09:03:27 -070090
91 /** Task identifier that activities are currently being started in. Incremented each time a
92 * new task is created. */
93 private int mCurTaskId = 0;
94
Craig Mautner2420ead2013-04-01 17:13:20 -070095 /** The current user */
96 private int mCurrentUser;
97
Craig Mautner8d341ef2013-03-26 09:03:27 -070098 /** The stack containing the launcher app */
Craig Mautner2219a1b2013-03-25 09:44:30 -070099 private ActivityStack mHomeStack;
Craig Mautner20e72272013-04-01 13:45:53 -0700100
Craig Mautnerde4ef022013-04-07 19:01:33 -0700101 /** The non-home stack currently receiving input or launching the next activity. If home is
102 * in front then mHomeStack overrides mMainStack. */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700103 private ActivityStack mMainStack;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700104
105 /** All the non-launcher stacks */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700106 private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
107
Craig Mautnerde4ef022013-04-07 19:01:33 -0700108 private static final int STACK_STATE_HOME_IN_FRONT = 0;
109 private static final int STACK_STATE_HOME_TO_BACK = 1;
110 private static final int STACK_STATE_HOME_IN_BACK = 2;
111 private static final int STACK_STATE_HOME_TO_FRONT = 3;
112 private int mStackState = STACK_STATE_HOME_IN_FRONT;
113
114 /** List of activities that are waiting for a new activity to become visible before completing
115 * whatever operation they are supposed to do. */
116 final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();
117
118 /** List of activities that are ready to be stopped, but waiting for the next activity to
119 * settle down before doing so. */
120 final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();
121
122 /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity
123 * is being brought in front of us. */
124 boolean mUserLeaving = false;
125
Craig Mautner2219a1b2013-03-25 09:44:30 -0700126 public ActivityStackSupervisor(ActivityManagerService service, Context context,
127 Looper looper) {
Craig Mautner27084302013-03-25 08:05:25 -0700128 mService = service;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700129 mContext = context;
130 mLooper = looper;
131 }
132
Craig Mautner2420ead2013-04-01 17:13:20 -0700133 void init(int userId) {
134 mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID, this, userId);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700135 mStacks.add(mHomeStack);
Craig Mautner27084302013-03-25 08:05:25 -0700136 }
137
138 void dismissKeyguard() {
139 if (mDismissKeyguardOnNextActivity) {
140 mDismissKeyguardOnNextActivity = false;
141 mService.mWindowManager.dismissKeyguard();
142 }
143 }
144
Craig Mautnerde4ef022013-04-07 19:01:33 -0700145 ActivityStack getTopStack() {
146 switch (mStackState) {
147 case STACK_STATE_HOME_IN_FRONT:
148 case STACK_STATE_HOME_TO_FRONT:
149 return mHomeStack;
150 case STACK_STATE_HOME_IN_BACK:
151 case STACK_STATE_HOME_TO_BACK:
152 default:
153 return mMainStack;
154 }
Craig Mautner20e72272013-04-01 13:45:53 -0700155 }
156
Craig Mautnerde4ef022013-04-07 19:01:33 -0700157 ActivityStack getLastStack() {
158 switch (mStackState) {
159 case STACK_STATE_HOME_IN_FRONT:
160 case STACK_STATE_HOME_TO_BACK:
161 return mHomeStack;
162 case STACK_STATE_HOME_TO_FRONT:
163 case STACK_STATE_HOME_IN_BACK:
164 default:
165 return mMainStack;
166 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700167 }
168
Craig Mautnerde4ef022013-04-07 19:01:33 -0700169 boolean isFrontStack(ActivityStack stack) {
Craig Mautner967212c2013-04-13 21:10:58 -0700170 return !(stack.isHomeStack() ^ getTopStack().isHomeStack());
Craig Mautner20e72272013-04-01 13:45:53 -0700171 }
172
Craig Mautnerde4ef022013-04-07 19:01:33 -0700173 boolean homeIsInFront() {
174 return isFrontStack(mHomeStack);
175 }
176
177 void moveHomeStack(boolean toFront) {
178 final boolean homeInFront = isFrontStack(mHomeStack);
179 if (homeInFront ^ toFront) {
180 mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
181 }
182 }
183
184 final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r,
185 ActivityStack stack) {
186 if (stack == mHomeStack) {
187 return;
188 }
189 if ((sourceRecord == null && getLastStack() == mHomeStack) ||
190 (sourceRecord != null && sourceRecord.isHomeActivity)) {
191 if (r == null) {
192 r = stack.topRunningActivityLocked(null);
193 }
194 if (r != null && !r.isHomeActivity && r.isRootActivity()) {
195 r.mLaunchHomeTaskNext = true;
196 }
197 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700198 }
199
Craig Mautner27084302013-03-25 08:05:25 -0700200 void setDismissKeyguard(boolean dismiss) {
201 mDismissKeyguardOnNextActivity = dismiss;
202 }
203
Craig Mautner8d341ef2013-03-26 09:03:27 -0700204 TaskRecord anyTaskForIdLocked(int id) {
205 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
206 ActivityStack stack = mStacks.get(stackNdx);
207 TaskRecord task = stack.taskForIdLocked(id);
208 if (task != null) {
209 return task;
210 }
211 }
212 return null;
213 }
214
Craig Mautner6170f732013-04-02 13:05:23 -0700215 ActivityRecord isInAnyStackLocked(IBinder token) {
216 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
217 final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
218 if (r != null) {
219 return r;
220 }
221 }
222 return null;
223 }
224
Craig Mautner8d341ef2013-03-26 09:03:27 -0700225 int getNextTaskId() {
226 do {
227 mCurTaskId++;
228 if (mCurTaskId <= 0) {
229 mCurTaskId = 1;
230 }
231 } while (anyTaskForIdLocked(mCurTaskId) != null);
232 return mCurTaskId;
233 }
234
Craig Mautnerde4ef022013-04-07 19:01:33 -0700235 void removeTask(TaskRecord task) {
236 final ActivityStack stack = task.stack;
237 if (stack.removeTask(task) && !stack.isHomeStack()) {
238 mStacks.remove(stack);
239 final int oldStackId = stack.mStackId;
240 final int newMainStackId = mService.mWindowManager.removeStack(oldStackId);
241 if (newMainStackId == HOME_STACK_ID) {
242 return;
243 }
244 if (mMainStack.mStackId == oldStackId) {
245 mMainStack = getStack(newMainStackId);
246 }
247 }
248 }
249
250 ActivityRecord resumedAppLocked() {
251 ActivityStack stack = getTopStack();
252 ActivityRecord resumedActivity = stack.mResumedActivity;
253 if (resumedActivity == null || resumedActivity.app == null) {
254 resumedActivity = stack.mPausingActivity;
255 if (resumedActivity == null || resumedActivity.app == null) {
256 resumedActivity = stack.topRunningActivityLocked(null);
257 }
258 }
259 return resumedActivity;
260 }
261
Craig Mautner20e72272013-04-01 13:45:53 -0700262 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
263 boolean didSomething = false;
264 final String processName = app.processName;
265 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
266 final ActivityStack stack = mStacks.get(stackNdx);
267 ActivityRecord hr = stack.topRunningActivityLocked(null);
268 if (hr != null) {
269 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
270 && processName.equals(hr.processName)) {
271 try {
272 if (headless) {
273 Slog.e(TAG, "Starting activities not supported on headless device: "
274 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700275 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700276 didSomething = true;
277 }
278 } catch (Exception e) {
279 Slog.w(TAG, "Exception in new application when starting activity "
280 + hr.intent.getComponent().flattenToShortString(), e);
281 throw e;
282 }
283 } else {
284 stack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
285 }
286 }
287 }
288 return didSomething;
289 }
290
291 boolean allResumedActivitiesIdle() {
292 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700293 final ActivityRecord resumedActivity = mStacks.get(stackNdx).mResumedActivity;
294 if (resumedActivity == null || !resumedActivity.idle) {
Craig Mautner20e72272013-04-01 13:45:53 -0700295 return false;
296 }
297 }
298 return true;
299 }
300
Craig Mautnerde4ef022013-04-07 19:01:33 -0700301 boolean allResumedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700302 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
303 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner967212c2013-04-13 21:10:58 -0700304 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700305 final ActivityRecord r = stack.mResumedActivity;
306 if (r != null && r.state != ActivityState.RESUMED) {
307 return false;
308 }
309 }
310 }
311 // TODO: Not sure if this should check if all Paused are complete too.
312 switch (mStackState) {
313 case STACK_STATE_HOME_TO_BACK:
314 mStackState = STACK_STATE_HOME_IN_BACK;
315 break;
316 case STACK_STATE_HOME_TO_FRONT:
317 mStackState = STACK_STATE_HOME_IN_FRONT;
318 break;
319 }
320 return true;
321 }
322
323 boolean allResumedActivitiesVisible() {
324 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
325 final ActivityStack stack = mStacks.get(stackNdx);
326 final ActivityRecord r = stack.mResumedActivity;
327 if (r != null && (!r.nowVisible || r.waitingVisible)) {
328 return false;
329 }
330 }
331 return true;
332 }
333
334 boolean allPausedActivitiesComplete() {
335 final boolean homeInBack = !homeIsInFront();
336 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
337 final ActivityStack stack = mStacks.get(stackNdx);
338 if (stack.isHomeStack() ^ homeInBack) {
339 final ActivityRecord r = stack.mLastPausedActivity;
340 if (r != null && r.state != ActivityState.PAUSED
341 && r.state != ActivityState.STOPPED
342 && r.state != ActivityState.STOPPING) {
343 return false;
344 }
345 }
346 }
347 // TODO: Not sure if this should check if all Resumed are complete too.
348 switch (mStackState) {
349 case STACK_STATE_HOME_TO_BACK:
350 mStackState = STACK_STATE_HOME_IN_BACK;
351 break;
352 case STACK_STATE_HOME_TO_FRONT:
353 mStackState = STACK_STATE_HOME_IN_FRONT;
354 break;
355 }
356 return true;
357 }
358
Craig Mautner20e72272013-04-01 13:45:53 -0700359 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
360 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
361 ActivityRecord r = null;
362 final int numStacks = mStacks.size();
363 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
364 final ActivityStack stack = mStacks.get(stackNdx);
365 final ActivityRecord ar =
366 stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700367 if (isFrontStack(stack)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700368 r = ar;
369 }
370 }
371 return r;
372 }
373
Craig Mautner23ac33b2013-04-01 16:26:35 -0700374 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
375 String profileFile, ParcelFileDescriptor profileFd, int userId) {
376 // Collect information about the target of the Intent.
377 ActivityInfo aInfo;
378 try {
379 ResolveInfo rInfo =
380 AppGlobals.getPackageManager().resolveIntent(
381 intent, resolvedType,
382 PackageManager.MATCH_DEFAULT_ONLY
383 | ActivityManagerService.STOCK_PM_FLAGS, userId);
384 aInfo = rInfo != null ? rInfo.activityInfo : null;
385 } catch (RemoteException e) {
386 aInfo = null;
387 }
388
389 if (aInfo != null) {
390 // Store the found target back into the intent, because now that
391 // we have it we never want to do this again. For example, if the
392 // user navigates back to this point in the history, we should
393 // always restart the exact same activity.
394 intent.setComponent(new ComponentName(
395 aInfo.applicationInfo.packageName, aInfo.name));
396
397 // Don't debug things in the system process
398 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
399 if (!aInfo.processName.equals("system")) {
400 mService.setDebugApp(aInfo.processName, true, false);
401 }
402 }
403
404 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
405 if (!aInfo.processName.equals("system")) {
406 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
407 }
408 }
409
410 if (profileFile != null) {
411 if (!aInfo.processName.equals("system")) {
412 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
413 profileFile, profileFd,
414 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
415 }
416 }
417 }
418 return aInfo;
419 }
420
Craig Mautner2219a1b2013-03-25 09:44:30 -0700421 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700422 moveHomeStack(true);
Craig Mautner6170f732013-04-02 13:05:23 -0700423 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
Craig Mautner2219a1b2013-03-25 09:44:30 -0700424 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700425 }
426
Craig Mautner23ac33b2013-04-01 16:26:35 -0700427 final int startActivityMayWait(IApplicationThread caller, int callingUid,
428 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
429 String resultWho, int requestCode, int startFlags, String profileFile,
430 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
431 Bundle options, int userId) {
432 // Refuse possible leaked file descriptors
433 if (intent != null && intent.hasFileDescriptors()) {
434 throw new IllegalArgumentException("File descriptors passed in Intent");
435 }
436 boolean componentSpecified = intent.getComponent() != null;
437
438 // Don't modify the client's object!
439 intent = new Intent(intent);
440
441 // Collect information about the target of the Intent.
442 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
443 profileFile, profileFd, userId);
444
445 synchronized (mService) {
446 int callingPid;
447 if (callingUid >= 0) {
448 callingPid = -1;
449 } else if (caller == null) {
450 callingPid = Binder.getCallingPid();
451 callingUid = Binder.getCallingUid();
452 } else {
453 callingPid = callingUid = -1;
454 }
455
Craig Mautnerde4ef022013-04-07 19:01:33 -0700456 final ActivityStack stack = getTopStack();
457 stack.mConfigWillChange = config != null
Craig Mautner23ac33b2013-04-01 16:26:35 -0700458 && mService.mConfiguration.diff(config) != 0;
459 if (DEBUG_CONFIGURATION) Slog.v(TAG,
Craig Mautnerde4ef022013-04-07 19:01:33 -0700460 "Starting activity when config will change = " + stack.mConfigWillChange);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700461
462 final long origId = Binder.clearCallingIdentity();
463
464 if (aInfo != null &&
465 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
466 // This may be a heavy-weight process! Check to see if we already
467 // have another, different heavy-weight process running.
468 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
469 if (mService.mHeavyWeightProcess != null &&
470 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
471 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
472 int realCallingPid = callingPid;
473 int realCallingUid = callingUid;
474 if (caller != null) {
475 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
476 if (callerApp != null) {
477 realCallingPid = callerApp.pid;
478 realCallingUid = callerApp.info.uid;
479 } else {
480 Slog.w(TAG, "Unable to find app for caller " + caller
481 + " (pid=" + realCallingPid + ") when starting: "
482 + intent.toString());
483 ActivityOptions.abort(options);
484 return ActivityManager.START_PERMISSION_DENIED;
485 }
486 }
487
488 IIntentSender target = mService.getIntentSenderLocked(
489 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
490 realCallingUid, userId, null, null, 0, new Intent[] { intent },
491 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
492 | PendingIntent.FLAG_ONE_SHOT, null);
493
494 Intent newIntent = new Intent();
495 if (requestCode >= 0) {
496 // Caller is requesting a result.
497 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
498 }
499 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
500 new IntentSender(target));
501 if (mService.mHeavyWeightProcess.activities.size() > 0) {
502 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
503 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
504 hist.packageName);
505 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
506 hist.task.taskId);
507 }
508 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
509 aInfo.packageName);
510 newIntent.setFlags(intent.getFlags());
511 newIntent.setClassName("android",
512 HeavyWeightSwitcherActivity.class.getName());
513 intent = newIntent;
514 resolvedType = null;
515 caller = null;
516 callingUid = Binder.getCallingUid();
517 callingPid = Binder.getCallingPid();
518 componentSpecified = true;
519 try {
520 ResolveInfo rInfo =
521 AppGlobals.getPackageManager().resolveIntent(
522 intent, null,
523 PackageManager.MATCH_DEFAULT_ONLY
524 | ActivityManagerService.STOCK_PM_FLAGS, userId);
525 aInfo = rInfo != null ? rInfo.activityInfo : null;
526 aInfo = mService.getActivityInfoForUser(aInfo, userId);
527 } catch (RemoteException e) {
528 aInfo = null;
529 }
530 }
531 }
532 }
533
Craig Mautner6170f732013-04-02 13:05:23 -0700534 int res = startActivityLocked(caller, intent, resolvedType,
Craig Mautner23ac33b2013-04-01 16:26:35 -0700535 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
536 callingPackage, startFlags, options, componentSpecified, null);
537
Craig Mautnerde4ef022013-04-07 19:01:33 -0700538 if (stack.mConfigWillChange) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700539 // If the caller also wants to switch to a new configuration,
540 // do so now. This allows a clean switch, as we are waiting
541 // for the current activity to pause (so we will not destroy
542 // it), and have not yet started the next activity.
543 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
544 "updateConfiguration()");
Craig Mautnerde4ef022013-04-07 19:01:33 -0700545 stack.mConfigWillChange = false;
Craig Mautner23ac33b2013-04-01 16:26:35 -0700546 if (DEBUG_CONFIGURATION) Slog.v(TAG,
547 "Updating to new configuration after starting activity.");
548 mService.updateConfigurationLocked(config, null, false, false);
549 }
550
551 Binder.restoreCallingIdentity(origId);
552
553 if (outResult != null) {
554 outResult.result = res;
555 if (res == ActivityManager.START_SUCCESS) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700556 stack.mWaitingActivityLaunched.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700557 do {
558 try {
559 mService.wait();
560 } catch (InterruptedException e) {
561 }
562 } while (!outResult.timeout && outResult.who == null);
563 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700564 ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700565 if (r.nowVisible) {
566 outResult.timeout = false;
567 outResult.who = new ComponentName(r.info.packageName, r.info.name);
568 outResult.totalTime = 0;
569 outResult.thisTime = 0;
570 } else {
571 outResult.thisTime = SystemClock.uptimeMillis();
Craig Mautnerde4ef022013-04-07 19:01:33 -0700572 stack.mWaitingActivityVisible.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700573 do {
574 try {
575 mService.wait();
576 } catch (InterruptedException e) {
577 }
578 } while (!outResult.timeout && outResult.who == null);
579 }
580 }
581 }
582
583 return res;
584 }
585 }
586
587 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
588 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
589 Bundle options, int userId) {
590 if (intents == null) {
591 throw new NullPointerException("intents is null");
592 }
593 if (resolvedTypes == null) {
594 throw new NullPointerException("resolvedTypes is null");
595 }
596 if (intents.length != resolvedTypes.length) {
597 throw new IllegalArgumentException("intents are length different than resolvedTypes");
598 }
599
600 ActivityRecord[] outActivity = new ActivityRecord[1];
601
602 int callingPid;
603 if (callingUid >= 0) {
604 callingPid = -1;
605 } else if (caller == null) {
606 callingPid = Binder.getCallingPid();
607 callingUid = Binder.getCallingUid();
608 } else {
609 callingPid = callingUid = -1;
610 }
611 final long origId = Binder.clearCallingIdentity();
612 try {
613 synchronized (mService) {
614
615 for (int i=0; i<intents.length; i++) {
616 Intent intent = intents[i];
617 if (intent == null) {
618 continue;
619 }
620
621 // Refuse possible leaked file descriptors
622 if (intent != null && intent.hasFileDescriptors()) {
623 throw new IllegalArgumentException("File descriptors passed in Intent");
624 }
625
626 boolean componentSpecified = intent.getComponent() != null;
627
628 // Don't modify the client's object!
629 intent = new Intent(intent);
630
631 // Collect information about the target of the Intent.
632 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
633 0, null, null, userId);
634 // TODO: New, check if this is correct
635 aInfo = mService.getActivityInfoForUser(aInfo, userId);
636
637 if (aInfo != null &&
638 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
639 != 0) {
640 throw new IllegalArgumentException(
641 "FLAG_CANT_SAVE_STATE not supported here");
642 }
643
644 Bundle theseOptions;
645 if (options != null && i == intents.length-1) {
646 theseOptions = options;
647 } else {
648 theseOptions = null;
649 }
Craig Mautner6170f732013-04-02 13:05:23 -0700650 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Craig Mautner23ac33b2013-04-01 16:26:35 -0700651 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
652 0, theseOptions, componentSpecified, outActivity);
653 if (res < 0) {
654 return res;
655 }
656
657 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
658 }
659 }
660 } finally {
661 Binder.restoreCallingIdentity(origId);
662 }
663
664 return ActivityManager.START_SUCCESS;
665 }
666
Craig Mautner2420ead2013-04-01 17:13:20 -0700667 final boolean realStartActivityLocked(ActivityRecord r,
668 ProcessRecord app, boolean andResume, boolean checkConfig)
669 throws RemoteException {
670
671 r.startFreezingScreenLocked(app, 0);
672 mService.mWindowManager.setAppVisibility(r.appToken, true);
673
674 // schedule launch ticks to collect information about slow apps.
675 r.startLaunchTickingLocked();
676
677 // Have the window manager re-evaluate the orientation of
678 // the screen based on the new activity order. Note that
679 // as a result of this, it can call back into the activity
680 // manager with a new orientation. We don't care about that,
681 // because the activity is not currently running so we are
682 // just restarting it anyway.
683 if (checkConfig) {
684 Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
685 mService.mConfiguration,
686 r.mayFreezeScreenLocked(app) ? r.appToken : null);
687 mService.updateConfigurationLocked(config, r, false, false);
688 }
689
690 r.app = app;
691 app.waitingToKill = null;
692 r.launchCount++;
693 r.lastLaunchTime = SystemClock.uptimeMillis();
694
695 if (localLOGV) Slog.v(TAG, "Launching: " + r);
696
697 int idx = app.activities.indexOf(r);
698 if (idx < 0) {
699 app.activities.add(r);
700 }
701 mService.updateLruProcessLocked(app, true);
702
703 final ActivityStack stack = r.task.stack;
704 try {
705 if (app.thread == null) {
706 throw new RemoteException();
707 }
708 List<ResultInfo> results = null;
709 List<Intent> newIntents = null;
710 if (andResume) {
711 results = r.results;
712 newIntents = r.newIntents;
713 }
714 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
715 + " icicle=" + r.icicle
716 + " with results=" + results + " newIntents=" + newIntents
717 + " andResume=" + andResume);
718 if (andResume) {
719 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
720 r.userId, System.identityHashCode(r),
721 r.task.taskId, r.shortComponentName);
722 }
723 if (r.isHomeActivity) {
724 mService.mHomeProcess = app;
725 }
726 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
727 r.sleeping = false;
728 r.forceNewConfig = false;
729 mService.showAskCompatModeDialogLocked(r);
730 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
731 String profileFile = null;
732 ParcelFileDescriptor profileFd = null;
733 boolean profileAutoStop = false;
734 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
735 if (mService.mProfileProc == null || mService.mProfileProc == app) {
736 mService.mProfileProc = app;
737 profileFile = mService.mProfileFile;
738 profileFd = mService.mProfileFd;
739 profileAutoStop = mService.mAutoStopProfiler;
740 }
741 }
742 app.hasShownUi = true;
743 app.pendingUiClean = true;
744 if (profileFd != null) {
745 try {
746 profileFd = profileFd.dup();
747 } catch (IOException e) {
748 if (profileFd != null) {
749 try {
750 profileFd.close();
751 } catch (IOException o) {
752 }
753 profileFd = null;
754 }
755 }
756 }
757 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
758 System.identityHashCode(r), r.info,
759 new Configuration(mService.mConfiguration),
760 r.compat, r.icicle, results, newIntents, !andResume,
761 mService.isNextTransitionForward(), profileFile, profileFd,
762 profileAutoStop);
763
764 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
765 // This may be a heavy-weight process! Note that the package
766 // manager will ensure that only activity can run in the main
767 // process of the .apk, which is the only thing that will be
768 // considered heavy-weight.
769 if (app.processName.equals(app.info.packageName)) {
770 if (mService.mHeavyWeightProcess != null
771 && mService.mHeavyWeightProcess != app) {
772 Slog.w(TAG, "Starting new heavy weight process " + app
773 + " when already running "
774 + mService.mHeavyWeightProcess);
775 }
776 mService.mHeavyWeightProcess = app;
777 Message msg = mService.mHandler.obtainMessage(
778 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
779 msg.obj = r;
780 mService.mHandler.sendMessage(msg);
781 }
782 }
783
784 } catch (RemoteException e) {
785 if (r.launchFailed) {
786 // This is the second time we failed -- finish activity
787 // and give up.
788 Slog.e(TAG, "Second failure launching "
789 + r.intent.getComponent().flattenToShortString()
790 + ", giving up", e);
791 mService.appDiedLocked(app, app.pid, app.thread);
792 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
793 "2nd-crash", false);
794 return false;
795 }
796
797 // This is the first time we failed -- restart process and
798 // retry.
799 app.activities.remove(r);
800 throw e;
801 }
802
803 r.launchFailed = false;
804 if (stack.updateLRUListLocked(r)) {
805 Slog.w(TAG, "Activity " + r
806 + " being launched, but already in LRU list");
807 }
808
809 if (andResume) {
810 // As part of the process of launching, ActivityThread also performs
811 // a resume.
812 stack.minimalResumeActivityLocked(r);
813 } else {
814 // This activity is not starting in the resumed state... which
815 // should look like we asked it to pause+stop (but remain visible),
816 // and it has done so and reported back the current icicle and
817 // other state.
818 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
819 + " (starting in stopped state)");
820 r.state = ActivityState.STOPPED;
821 r.stopped = true;
822 }
823
824 // Launch the new version setup screen if needed. We do this -after-
825 // launching the initial activity (that is, home), so that it can have
826 // a chance to initialize itself while in the background, making the
827 // switch back to it faster and look better.
Craig Mautnerde4ef022013-04-07 19:01:33 -0700828 if (isFrontStack(stack)) {
Craig Mautner2420ead2013-04-01 17:13:20 -0700829 mService.startSetupActivityLocked();
830 }
831
832 return true;
833 }
834
Craig Mautnere79d42682013-04-01 19:01:53 -0700835 void startSpecificActivityLocked(ActivityRecord r,
836 boolean andResume, boolean checkConfig) {
837 // Is this activity's application already running?
838 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
839 r.info.applicationInfo.uid);
840
841 r.task.stack.setLaunchTime(r);
842
843 if (app != null && app.thread != null) {
844 try {
845 app.addPackage(r.info.packageName);
846 realStartActivityLocked(r, app, andResume, checkConfig);
847 return;
848 } catch (RemoteException e) {
849 Slog.w(TAG, "Exception when starting activity "
850 + r.intent.getComponent().flattenToShortString(), e);
851 }
852
853 // If a dead object exception was thrown -- fall through to
854 // restart the application.
855 }
856
857 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
858 "activity", r.intent.getComponent(), false, false);
859 }
860
Craig Mautner6170f732013-04-02 13:05:23 -0700861 final int startActivityLocked(IApplicationThread caller,
862 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
863 String resultWho, int requestCode,
864 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
865 boolean componentSpecified, ActivityRecord[] outActivity) {
866 int err = ActivityManager.START_SUCCESS;
867
868 ProcessRecord callerApp = null;
869 if (caller != null) {
870 callerApp = mService.getRecordForAppLocked(caller);
871 if (callerApp != null) {
872 callingPid = callerApp.pid;
873 callingUid = callerApp.info.uid;
874 } else {
875 Slog.w(TAG, "Unable to find app for caller " + caller
876 + " (pid=" + callingPid + ") when starting: "
877 + intent.toString());
878 err = ActivityManager.START_PERMISSION_DENIED;
879 }
880 }
881
882 if (err == ActivityManager.START_SUCCESS) {
883 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
884 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
885 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
886 }
887
888 ActivityRecord sourceRecord = null;
889 ActivityRecord resultRecord = null;
890 if (resultTo != null) {
891 sourceRecord = isInAnyStackLocked(resultTo);
892 if (DEBUG_RESULTS) Slog.v(
893 TAG, "Will send result to " + resultTo + " " + sourceRecord);
894 if (sourceRecord != null) {
895 if (requestCode >= 0 && !sourceRecord.finishing) {
896 resultRecord = sourceRecord;
897 }
898 }
899 }
900 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
901
902 int launchFlags = intent.getFlags();
903
904 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
905 && sourceRecord != null) {
906 // Transfer the result target from the source activity to the new
907 // one being started, including any failures.
908 if (requestCode >= 0) {
909 ActivityOptions.abort(options);
910 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
911 }
912 resultRecord = sourceRecord.resultTo;
913 resultWho = sourceRecord.resultWho;
914 requestCode = sourceRecord.requestCode;
915 sourceRecord.resultTo = null;
916 if (resultRecord != null) {
917 resultRecord.removeResultsLocked(
918 sourceRecord, resultWho, requestCode);
919 }
920 }
921
922 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
923 // We couldn't find a class that can handle the given Intent.
924 // That's the end of that!
925 err = ActivityManager.START_INTENT_NOT_RESOLVED;
926 }
927
928 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
929 // We couldn't find the specific class specified in the Intent.
930 // Also the end of the line.
931 err = ActivityManager.START_CLASS_NOT_FOUND;
932 }
933
934 if (err != ActivityManager.START_SUCCESS) {
935 if (resultRecord != null) {
936 resultStack.sendActivityResultLocked(-1,
937 resultRecord, resultWho, requestCode,
938 Activity.RESULT_CANCELED, null);
939 }
940 setDismissKeyguard(false);
941 ActivityOptions.abort(options);
942 return err;
943 }
944
945 final int startAnyPerm = mService.checkPermission(
946 START_ANY_ACTIVITY, callingPid, callingUid);
947 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
948 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
949 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
950 if (resultRecord != null) {
951 resultStack.sendActivityResultLocked(-1,
952 resultRecord, resultWho, requestCode,
953 Activity.RESULT_CANCELED, null);
954 }
955 setDismissKeyguard(false);
956 String msg;
957 if (!aInfo.exported) {
958 msg = "Permission Denial: starting " + intent.toString()
959 + " from " + callerApp + " (pid=" + callingPid
960 + ", uid=" + callingUid + ")"
961 + " not exported from uid " + aInfo.applicationInfo.uid;
962 } else {
963 msg = "Permission Denial: starting " + intent.toString()
964 + " from " + callerApp + " (pid=" + callingPid
965 + ", uid=" + callingUid + ")"
966 + " requires " + aInfo.permission;
967 }
968 Slog.w(TAG, msg);
969 throw new SecurityException(msg);
970 }
971
Ben Gruver6617c3c2013-04-03 18:45:22 -0700972 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
Ben Gruver7b879f42013-04-08 14:56:55 -0700973 callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo);
Ben Gruver5e207332013-04-03 17:41:37 -0700974
Craig Mautner6170f732013-04-02 13:05:23 -0700975 if (mService.mController != null) {
Craig Mautner6170f732013-04-02 13:05:23 -0700976 try {
977 // The Intent we give to the watcher has the extra data
978 // stripped off, since it can contain private information.
979 Intent watchIntent = intent.cloneFilter();
Ben Gruver5e207332013-04-03 17:41:37 -0700980 abort |= !mService.mController.activityStarting(watchIntent,
Craig Mautner6170f732013-04-02 13:05:23 -0700981 aInfo.applicationInfo.packageName);
982 } catch (RemoteException e) {
983 mService.mController = null;
984 }
Ben Gruver5e207332013-04-03 17:41:37 -0700985 }
Craig Mautner6170f732013-04-02 13:05:23 -0700986
Ben Gruver5e207332013-04-03 17:41:37 -0700987 if (abort) {
988 if (resultRecord != null) {
989 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Craig Mautner6170f732013-04-02 13:05:23 -0700990 Activity.RESULT_CANCELED, null);
Craig Mautner6170f732013-04-02 13:05:23 -0700991 }
Ben Gruver5e207332013-04-03 17:41:37 -0700992 // We pretend to the caller that it was really started, but
993 // they will just get a cancel result.
994 setDismissKeyguard(false);
995 ActivityOptions.abort(options);
996 return ActivityManager.START_SUCCESS;
Craig Mautner6170f732013-04-02 13:05:23 -0700997 }
998
999 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1000 intent, resolvedType, aInfo, mService.mConfiguration,
Craig Mautnerde4ef022013-04-07 19:01:33 -07001001 resultRecord, resultWho, requestCode, componentSpecified, this);
Craig Mautner6170f732013-04-02 13:05:23 -07001002 if (outActivity != null) {
1003 outActivity[0] = r;
1004 }
1005
Craig Mautnerde4ef022013-04-07 19:01:33 -07001006 final ActivityStack stack = getTopStack();
1007 if (stack.mResumedActivity == null
1008 || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
Craig Mautner6170f732013-04-02 13:05:23 -07001009 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1010 PendingActivityLaunch pal =
Craig Mautnerde4ef022013-04-07 19:01:33 -07001011 new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
Craig Mautner6170f732013-04-02 13:05:23 -07001012 mService.mPendingActivityLaunches.add(pal);
1013 setDismissKeyguard(false);
1014 ActivityOptions.abort(options);
1015 return ActivityManager.START_SWITCHES_CANCELED;
1016 }
1017 }
1018
1019 if (mService.mDidAppSwitch) {
1020 // This is the second allowed switch since we stopped switches,
1021 // so now just generally allow switches. Use case: user presses
1022 // home (switches disabled, switch to home, mDidAppSwitch now true);
1023 // user taps a home icon (coming from home so allowed, we hit here
1024 // and now allow anyone to switch again).
1025 mService.mAppSwitchesAllowedTime = 0;
1026 } else {
1027 mService.mDidAppSwitch = true;
1028 }
1029
1030 mService.doPendingActivityLaunchesLocked(false);
1031
Craig Mautner8849a5e2013-04-02 16:41:03 -07001032 err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001033 if (stack.mPausingActivity == null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001034 // Someone asked to have the keyguard dismissed on the next
1035 // activity start, but we are not actually doing an activity
1036 // switch... just dismiss the keyguard now, because we
1037 // probably want to see whatever is behind it.
1038 dismissKeyguard();
1039 }
1040 return err;
1041 }
1042
Craig Mautnerde4ef022013-04-07 19:01:33 -07001043 ActivityStack getCorrectStack(ActivityRecord r) {
1044 if (!r.isHomeActivity) {
1045 if (mStacks.size() == 1) {
1046 // Time to create the first app stack.
1047 int stackId =
1048 mService.createStack(HOME_STACK_ID, StackBox.TASK_STACK_GOES_OVER, 1.0f);
1049 mMainStack = getStack(stackId);
1050 }
1051 return mMainStack;
1052 }
1053 return mHomeStack;
1054 }
1055
Craig Mautner8849a5e2013-04-02 16:41:03 -07001056 final int startActivityUncheckedLocked(ActivityRecord r,
1057 ActivityRecord sourceRecord, int startFlags, boolean doResume,
1058 Bundle options) {
1059 final Intent intent = r.intent;
1060 final int callingUid = r.launchedFromUid;
1061
1062 int launchFlags = intent.getFlags();
1063
Craig Mautner8849a5e2013-04-02 16:41:03 -07001064 // We'll invoke onUserLeaving before onPause only if the launching
1065 // activity did not explicitly state that this is an automated launch.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001066 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1067 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001068
1069 // If the caller has asked not to resume at this point, we make note
1070 // of this in the record so that we can skip it when trying to find
1071 // the top running activity.
1072 if (!doResume) {
1073 r.delayedResume = true;
1074 }
1075
1076 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1077
1078 // If the onlyIfNeeded flag is set, then we can do this if the activity
1079 // being launched is the same as the one making the call... or, as
1080 // a special case, if we do not know the caller then we count the
1081 // current top activity as the caller.
1082 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1083 ActivityRecord checkedCaller = sourceRecord;
1084 if (checkedCaller == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001085 checkedCaller = getTopStack().topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001086 }
1087 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1088 // Caller is not the same as launcher, so always needed.
1089 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1090 }
1091 }
1092
1093 if (sourceRecord == null) {
1094 // This activity is not being started from another... in this
1095 // case we -always- start a new task.
1096 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
1097 Slog.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
1098 + intent);
1099 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1100 }
1101 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1102 // The original activity who is starting us is running as a single
1103 // instance... this new activity it is starting must go on its
1104 // own task.
1105 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1106 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1107 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1108 // The activity being started is a single instance... it always
1109 // gets launched into its own task.
1110 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1111 }
1112
Craig Mautnerde4ef022013-04-07 19:01:33 -07001113 final ActivityStack sourceStack;
1114 final TaskRecord sourceTask;
1115 if (sourceRecord != null) {
1116 sourceTask = sourceRecord.task;
1117 sourceStack = sourceTask.stack;
1118 } else {
1119 sourceTask = null;
1120 sourceStack = null;
1121 }
1122
Craig Mautner8849a5e2013-04-02 16:41:03 -07001123 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1124 // For whatever reason this activity is being launched into a new
1125 // task... yet the caller has requested a result back. Well, that
1126 // is pretty messed up, so instead immediately send back a cancel
1127 // and let the new task continue launched as normal without a
1128 // dependency on its originator.
1129 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1130 r.resultTo.task.stack.sendActivityResultLocked(-1,
1131 r.resultTo, r.resultWho, r.requestCode,
1132 Activity.RESULT_CANCELED, null);
1133 r.resultTo = null;
1134 }
1135
1136 boolean addingToTask = false;
1137 boolean movedHome = false;
1138 TaskRecord reuseTask = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001139 ActivityStack targetStack;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001140 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1141 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1142 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1143 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1144 // If bring to front is requested, and no result is requested, and
1145 // we can find a task that was started with this same
1146 // component, then instead of launching bring that one to the front.
1147 if (r.resultTo == null) {
1148 // See if there is a task to bring to the front. If this is
1149 // a SINGLE_INSTANCE activity, there can be one and only one
1150 // instance of it in the history, and it is always in its own
1151 // unique task, so we do a special search.
1152 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
1153 ? findTaskLocked(intent, r.info)
1154 : findActivityLocked(intent, r.info);
1155 if (intentActivity != null) {
1156 targetStack = intentActivity.task.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001157 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001158 if (intentActivity.task.intent == null) {
1159 // This task was started because of movement of
1160 // the activity based on affinity... now that we
1161 // are actually launching it, we can assign the
1162 // base intent.
1163 intentActivity.task.setIntent(intent, r.info);
1164 }
1165 // If the target task is not in the front, then we need
1166 // to bring it to the front... except... well, with
1167 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
1168 // to have the same behavior as if a new instance was
1169 // being started, which means not bringing it to the front
1170 // if the caller is not itself in the front.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001171 ActivityRecord curTop =
1172 targetStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001173 if (curTop != null && curTop.task != intentActivity.task) {
1174 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001175 if (sourceRecord == null || sourceStack.topActivity() == sourceRecord) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001176 // We really do want to push this one into the
1177 // user's face, right now.
1178 movedHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001179 if ((launchFlags &
1180 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1181 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1182 // Caller wants to appear on home activity, so before starting
1183 // their own activity we will bring home to the front.
1184 r.mLaunchHomeTaskNext = true;
1185 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001186 targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1187 options = null;
1188 }
1189 }
1190 // If the caller has requested that the target task be
1191 // reset, then do so.
1192 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1193 intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1194 }
1195 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1196 // We don't need to start a new activity, and
1197 // the client said not to do anything if that
1198 // is the case, so this is it! And for paranoia, make
1199 // sure we have correctly resumed the top activity.
1200 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001201 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001202 targetStack.resumeTopActivityLocked(null, options);
1203 } else {
1204 ActivityOptions.abort(options);
1205 }
1206 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1207 }
1208 if ((launchFlags &
1209 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1210 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1211 // The caller has requested to completely replace any
1212 // existing task with its new activity. Well that should
1213 // not be too hard...
1214 reuseTask = intentActivity.task;
1215 reuseTask.performClearTaskLocked();
1216 reuseTask.setIntent(r.intent, r.info);
1217 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1218 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1219 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1220 // In this situation we want to remove all activities
1221 // from the task up to the one being started. In most
1222 // cases this means we are resetting the task to its
1223 // initial state.
1224 ActivityRecord top =
1225 intentActivity.task.performClearTaskLocked(r, launchFlags);
1226 if (top != null) {
1227 if (top.frontOfTask) {
1228 // Activity aliases may mean we use different
1229 // intents for the top activity, so make sure
1230 // the task now has the identity of the new
1231 // intent.
1232 top.task.setIntent(r.intent, r.info);
1233 }
1234 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1235 r, top.task);
1236 top.deliverNewIntentLocked(callingUid, r.intent);
1237 } else {
1238 // A special case: we need to
1239 // start the activity because it is not currently
1240 // running, and the caller has asked to clear the
1241 // current task to have this activity at the top.
1242 addingToTask = true;
1243 // Now pretend like this activity is being started
1244 // by the top of its task, so it is put in the
1245 // right place.
1246 sourceRecord = intentActivity;
1247 }
1248 } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1249 // In this case the top activity on the task is the
1250 // same as the one being launched, so we take that
1251 // as a request to bring the task to the foreground.
1252 // If the top activity in the task is the root
1253 // activity, deliver this new intent to it if it
1254 // desires.
1255 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1256 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1257 && intentActivity.realActivity.equals(r.realActivity)) {
1258 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1259 intentActivity.task);
1260 if (intentActivity.frontOfTask) {
1261 intentActivity.task.setIntent(r.intent, r.info);
1262 }
1263 intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1264 } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1265 // In this case we are launching the root activity
1266 // of the task, but with a different intent. We
1267 // should start a new instance on top.
1268 addingToTask = true;
1269 sourceRecord = intentActivity;
1270 }
1271 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1272 // In this case an activity is being launched in to an
1273 // existing task, without resetting that task. This
1274 // is typically the situation of launching an activity
1275 // from a notification or shortcut. We want to place
1276 // the new activity on top of the current task.
1277 addingToTask = true;
1278 sourceRecord = intentActivity;
1279 } else if (!intentActivity.task.rootWasReset) {
1280 // In this case we are launching in to an existing task
1281 // that has not yet been started from its front door.
1282 // The current task has been brought to the front.
1283 // Ideally, we'd probably like to place this new task
1284 // at the bottom of its stack, but that's a little hard
1285 // to do with the current organization of the code so
1286 // for now we'll just drop it.
1287 intentActivity.task.setIntent(r.intent, r.info);
1288 }
1289 if (!addingToTask && reuseTask == null) {
1290 // We didn't do anything... but it was needed (a.k.a., client
1291 // don't use that intent!) And for paranoia, make
1292 // sure we have correctly resumed the top activity.
1293 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001294 setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1295 targetStack.resumeTopActivityLocked(null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001296 } else {
1297 ActivityOptions.abort(options);
1298 }
1299 return ActivityManager.START_TASK_TO_FRONT;
1300 }
1301 }
1302 }
1303 }
1304
1305 //String uri = r.intent.toURI();
1306 //Intent intent2 = new Intent(uri);
1307 //Slog.i(TAG, "Given intent: " + r.intent);
1308 //Slog.i(TAG, "URI is: " + uri);
1309 //Slog.i(TAG, "To intent: " + intent2);
1310
1311 if (r.packageName != null) {
1312 // If the activity being launched is the same as the one currently
1313 // at the top, then we need to check if it should only be launched
1314 // once.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001315 ActivityStack topStack = getTopStack();
1316 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001317 if (top != null && r.resultTo == null) {
1318 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1319 if (top.app != null && top.app.thread != null) {
1320 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1321 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1322 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1323 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1324 top.task);
1325 // For paranoia, make sure we have correctly
1326 // resumed the top activity.
1327 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001328 setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
1329 topStack.resumeTopActivityLocked(null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001330 }
1331 ActivityOptions.abort(options);
1332 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1333 // We don't need to start a new activity, and
1334 // the client said not to do anything if that
1335 // is the case, so this is it!
1336 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1337 }
1338 top.deliverNewIntentLocked(callingUid, r.intent);
1339 return ActivityManager.START_DELIVERED_TO_TOP;
1340 }
1341 }
1342 }
1343 }
1344
1345 } else {
1346 if (r.resultTo != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001347 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1348 r.requestCode, Activity.RESULT_CANCELED, null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001349 }
1350 ActivityOptions.abort(options);
1351 return ActivityManager.START_CLASS_NOT_FOUND;
1352 }
1353
1354 boolean newTask = false;
1355 boolean keepCurTransition = false;
1356
1357 // Should this be considered a new task?
1358 if (r.resultTo == null && !addingToTask
1359 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001360 targetStack = getCorrectStack(r);
1361 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001362 if (reuseTask == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001363 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1364 null, true);
1365 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1366 r.task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001367 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001368 r.setTask(reuseTask, reuseTask, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001369 }
1370 newTask = true;
1371 if (!movedHome) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001372 if ((launchFlags &
1373 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1374 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1375 // Caller wants to appear on home activity, so before starting
1376 // their own activity we will bring home to the front.
1377 r.mLaunchHomeTaskNext = true;
1378 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001379 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001380 } else if (sourceRecord != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001381 targetStack = sourceRecord.task.stack;
1382 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001383 if (!addingToTask &&
1384 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1385 // In this case, we are adding the activity to an existing
1386 // task, but the caller has asked to clear that task if the
1387 // activity is already running.
1388 ActivityRecord top = sourceRecord.task.performClearTaskLocked(r, launchFlags);
1389 keepCurTransition = true;
1390 if (top != null) {
1391 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1392 top.deliverNewIntentLocked(callingUid, r.intent);
1393 // For paranoia, make sure we have correctly
1394 // resumed the top activity.
1395 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001396 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001397 targetStack.resumeTopActivityLocked(null);
1398 }
1399 ActivityOptions.abort(options);
1400 return ActivityManager.START_DELIVERED_TO_TOP;
1401 }
1402 } else if (!addingToTask &&
1403 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1404 // In this case, we are launching an activity in our own task
1405 // that may already be running somewhere in the history, and
1406 // we want to shuffle it to the front of the stack if so.
1407 final ActivityRecord top =
1408 targetStack.findActivityInHistoryLocked(r, sourceRecord.task);
1409 if (top != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001410 final TaskRecord task = top.task;
1411 task.moveActivityToFrontLocked(top);
1412 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001413 top.updateOptionsLocked(options);
1414 top.deliverNewIntentLocked(callingUid, r.intent);
1415 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001416 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001417 targetStack.resumeTopActivityLocked(null);
1418 }
1419 return ActivityManager.START_DELIVERED_TO_TOP;
1420 }
1421 }
1422 // An existing activity is starting this new activity, so we want
1423 // to keep the new one in the same task as the one that is starting
1424 // it.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001425 r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001426 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1427 + " in existing task " + r.task);
1428
1429 } else {
1430 // This not being started from an existing activity, and not part
1431 // of a new task... just put it in the top task, though these days
1432 // this case should never happen.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001433 targetStack = getLastStack();
1434 moveHomeStack(targetStack.isHomeStack());
1435 ActivityRecord prev = targetStack.topActivity();
1436 r.setTask(prev != null ? prev.task
1437 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1438 null, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001439 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1440 + " in new guessed " + r.task);
1441 }
1442
1443 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1444 intent, r.getUriPermissionsLocked());
1445
1446 if (newTask) {
1447 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1448 }
1449 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001450 setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001451 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
1452 return ActivityManager.START_SUCCESS;
1453 }
1454
Craig Mautner8d341ef2013-03-26 09:03:27 -07001455 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
1456 // Just in case.
1457 final int numStacks = mStacks.size();
1458 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Craig Mautnere79d42682013-04-01 19:01:53 -07001459 mStacks.get(stackNdx).handleAppDiedLocked(app, restarting);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001460 }
1461 }
1462
1463 void closeSystemDialogsLocked() {
1464 final int numStacks = mStacks.size();
1465 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1466 final ActivityStack stack = mStacks.get(stackNdx);
1467 stack.closeSystemDialogsLocked();
1468 }
1469 }
1470
1471 /**
1472 * @return true if some activity was finished (or would have finished if doit were true).
1473 */
1474 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1475 boolean didSomething = false;
1476 final int numStacks = mStacks.size();
1477 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1478 final ActivityStack stack = mStacks.get(stackNdx);
1479 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1480 didSomething = true;
1481 }
1482 }
1483 return didSomething;
1484 }
1485
1486 void resumeTopActivityLocked() {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -07001487 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001488 mStacks.get(stackNdx).resumeTopActivityLocked(null);
1489 }
1490 }
1491
1492 void finishTopRunningActivityLocked(ProcessRecord app) {
1493 final int numStacks = mStacks.size();
1494 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1495 final ActivityStack stack = mStacks.get(stackNdx);
1496 stack.finishTopRunningActivityLocked(app);
1497 }
1498 }
1499
1500 void scheduleIdleLocked() {
1501 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1502 mStacks.get(stackNdx).scheduleIdleLocked();
1503 }
1504 }
1505
1506 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
1507 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1508 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
1509 return;
1510 }
1511 }
1512 }
1513
Craig Mautner967212c2013-04-13 21:10:58 -07001514 ActivityStack getStack(int stackId) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001515 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1516 final ActivityStack stack = mStacks.get(stackNdx);
1517 if (stack.getStackId() == stackId) {
1518 return stack;
1519 }
1520 }
1521 return null;
1522 }
1523
Craig Mautner967212c2013-04-13 21:10:58 -07001524 ArrayList<ActivityStack> getStacks() {
1525 return new ArrayList<ActivityStack>(mStacks);
1526 }
1527
1528 int createStack() {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001529 synchronized (this) {
1530 while (true) {
1531 if (++mLastStackId <= HOME_STACK_ID) {
1532 mLastStackId = HOME_STACK_ID + 1;
1533 }
1534 if (getStack(mLastStackId) == null) {
1535 break;
1536 }
1537 }
Craig Mautner2420ead2013-04-01 17:13:20 -07001538 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId, this,
1539 mCurrentUser));
Craig Mautner8d341ef2013-03-26 09:03:27 -07001540 return mLastStackId;
1541 }
1542 }
1543
1544 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
1545 final ActivityStack stack = getStack(stackId);
1546 if (stack == null) {
1547 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
1548 return;
1549 }
1550 stack.moveTask(taskId, toTop);
Craig Mautner967212c2013-04-13 21:10:58 -07001551 stack.resumeTopActivityLocked(null);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001552 }
1553
Craig Mautner8849a5e2013-04-02 16:41:03 -07001554 ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
1555 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1556 final ActivityRecord ar = mStacks.get(stackNdx).findTaskLocked(intent, info);
1557 if (ar != null) {
1558 return ar;
1559 }
1560 }
1561 return null;
1562 }
1563
1564 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
1565 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1566 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
1567 if (ar != null) {
1568 return ar;
1569 }
1570 }
1571 return null;
1572 }
1573
Craig Mautner8d341ef2013-03-26 09:03:27 -07001574 void goingToSleepLocked() {
1575 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1576 mStacks.get(stackNdx).stopIfSleepingLocked();
1577 }
1578 }
1579
1580 boolean shutdownLocked(int timeout) {
1581 boolean timedout = false;
1582 final int numStacks = mStacks.size();
1583 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1584 final ActivityStack stack = mStacks.get(stackNdx);
1585 if (stack.mResumedActivity != null) {
1586 stack.stopIfSleepingLocked();
1587 final long endTime = System.currentTimeMillis() + timeout;
1588 while (stack.mResumedActivity != null || stack.mPausingActivity != null) {
1589 long delay = endTime - System.currentTimeMillis();
1590 if (delay <= 0) {
1591 Slog.w(TAG, "Activity manager shutdown timed out");
1592 timedout = true;
1593 break;
1594 }
1595 try {
1596 mService.wait();
1597 } catch (InterruptedException e) {
1598 }
1599 }
1600 }
1601 }
1602 return timedout;
1603 }
1604
1605 void comeOutOfSleepIfNeededLocked() {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001606 final boolean homeIsBack = !homeIsInFront();
Craig Mautner8d341ef2013-03-26 09:03:27 -07001607 final int numStacks = mStacks.size();
1608 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1609 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001610 if (stack.isHomeStack() ^ homeIsBack) {
1611 stack.awakeFromSleepingLocked();
1612 stack.resumeTopActivityLocked(null);
1613 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001614 }
1615 }
1616
1617 void handleAppCrashLocked(ProcessRecord app) {
1618 final int numStacks = mStacks.size();
1619 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1620 final ActivityStack stack = mStacks.get(stackNdx);
1621 stack.handleAppCrashLocked(app);
1622 }
1623 }
1624
Craig Mautnerde4ef022013-04-07 19:01:33 -07001625 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
1626 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1627 mStacks.get(stackNdx).ensureActivitiesVisibleLocked(starting, configChanges);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001628 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001629 }
1630
1631 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
1632 final int numStacks = mStacks.size();
1633 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1634 final ActivityStack stack = mStacks.get(stackNdx);
1635 stack.scheduleDestroyActivities(app, false, reason);
1636 }
1637 }
1638
1639 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner2420ead2013-04-01 17:13:20 -07001640 mCurrentUser = userId;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001641 boolean homeInBack = !homeIsInFront();
Craig Mautner8d341ef2013-03-26 09:03:27 -07001642 boolean haveActivities = false;
1643 final int numStacks = mStacks.size();
1644 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1645 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001646 if (stack.isHomeStack() ^ homeInBack) {
1647 haveActivities |= stack.switchUserLocked(userId, uss);
1648 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001649 }
1650 return haveActivities;
Craig Mautner2219a1b2013-03-25 09:44:30 -07001651 }
1652
Craig Mautnerde4ef022013-04-07 19:01:33 -07001653 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
1654 int N = mStoppingActivities.size();
1655 if (N <= 0) return null;
1656
1657 ArrayList<ActivityRecord> stops = null;
1658
1659 final boolean nowVisible = allResumedActivitiesVisible();
1660 for (int i=0; i<N; i++) {
1661 ActivityRecord s = mStoppingActivities.get(i);
1662 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
1663 + nowVisible + " waitingVisible=" + s.waitingVisible
1664 + " finishing=" + s.finishing);
1665 if (s.waitingVisible && nowVisible) {
1666 mWaitingVisibleActivities.remove(s);
1667 s.waitingVisible = false;
1668 if (s.finishing) {
1669 // If this activity is finishing, it is sitting on top of
1670 // everyone else but we now know it is no longer needed...
1671 // so get rid of it. Otherwise, we need to go through the
1672 // normal flow and hide it once we determine that it is
1673 // hidden by the activities in front of it.
1674 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
1675 mService.mWindowManager.setAppVisibility(s.appToken, false);
1676 }
1677 }
1678 if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
1679 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
1680 if (stops == null) {
1681 stops = new ArrayList<ActivityRecord>();
1682 }
1683 stops.add(s);
1684 mStoppingActivities.remove(i);
1685 N--;
1686 i--;
1687 }
1688 }
1689
1690 return stops;
1691 }
1692
Craig Mautner27084302013-03-25 08:05:25 -07001693 public void dump(PrintWriter pw, String prefix) {
1694 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
1695 pw.println(mDismissKeyguardOnNextActivity);
1696 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001697
Craig Mautner20e72272013-04-01 13:45:53 -07001698 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001699 return getTopStack().getDumpActivitiesLocked(name);
Craig Mautner20e72272013-04-01 13:45:53 -07001700 }
1701
Craig Mautner8d341ef2013-03-26 09:03:27 -07001702 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
1703 boolean dumpClient, String dumpPackage) {
1704 final int numStacks = mStacks.size();
1705 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1706 final ActivityStack stack = mStacks.get(stackNdx);
1707 pw.print(" Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
1708 stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
1709 pw.println(" ");
1710 pw.println(" Running activities (most recent first):");
1711 dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false,
1712 dumpPackage);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001713 if (stack.mGoingToSleepActivities.size() > 0) {
1714 pw.println(" ");
1715 pw.println(" Activities waiting to sleep:");
1716 dumpHistoryList(fd, pw, stack.mGoingToSleepActivities, " ", "Sleep", false,
1717 !dumpAll, false, dumpPackage);
1718 }
1719 if (stack.mFinishingActivities.size() > 0) {
1720 pw.println(" ");
1721 pw.println(" Activities waiting to finish:");
1722 dumpHistoryList(fd, pw, stack.mFinishingActivities, " ", "Fin", false,
1723 !dumpAll, false, dumpPackage);
1724 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001725
Craig Mautner8d341ef2013-03-26 09:03:27 -07001726 pw.print(" Stack #"); pw.println(mStacks.indexOf(stack));
1727 if (stack.mPausingActivity != null) {
1728 pw.println(" mPausingActivity: " + stack.mPausingActivity);
1729 }
1730 pw.println(" mResumedActivity: " + stack.mResumedActivity);
1731 if (dumpAll) {
1732 pw.println(" mLastPausedActivity: " + stack.mLastPausedActivity);
1733 pw.println(" mSleepTimeout: " + stack.mSleepTimeout);
1734 }
1735 }
1736
Craig Mautnerde4ef022013-04-07 19:01:33 -07001737 if (mStoppingActivities.size() > 0) {
1738 pw.println(" ");
1739 pw.println(" Activities waiting to stop:");
1740 dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, false,
1741 dumpPackage);
1742 }
1743
1744 if (mWaitingVisibleActivities.size() > 0) {
1745 pw.println(" ");
1746 pw.println(" Activities waiting for another to become visible:");
1747 dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
1748 false, dumpPackage);
1749 }
1750
Craig Mautner8d341ef2013-03-26 09:03:27 -07001751 if (dumpAll) {
1752 pw.println(" ");
1753 pw.println(" mCurTaskId: " + mCurTaskId);
1754 }
1755 return true;
1756 }
1757
1758 static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
1759 String prefix, String label, boolean complete, boolean brief, boolean client,
1760 String dumpPackage) {
1761 TaskRecord lastTask = null;
1762 boolean needNL = false;
1763 final String innerPrefix = prefix + " ";
1764 final String[] args = new String[0];
1765 for (int i=list.size()-1; i>=0; i--) {
1766 final ActivityRecord r = list.get(i);
1767 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
1768 continue;
1769 }
1770 final boolean full = !brief && (complete || !r.isInHistory());
1771 if (needNL) {
1772 pw.println(" ");
1773 needNL = false;
1774 }
1775 if (lastTask != r.task) {
1776 lastTask = r.task;
1777 pw.print(prefix);
1778 pw.print(full ? "* " : " ");
1779 pw.println(lastTask);
1780 if (full) {
1781 lastTask.dump(pw, prefix + " ");
1782 } else if (complete) {
1783 // Complete + brief == give a summary. Isn't that obvious?!?
1784 if (lastTask.intent != null) {
1785 pw.print(prefix); pw.print(" ");
1786 pw.println(lastTask.intent.toInsecureStringWithClip());
1787 }
1788 }
1789 }
1790 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
1791 pw.print(" #"); pw.print(i); pw.print(": ");
1792 pw.println(r);
1793 if (full) {
1794 r.dump(pw, innerPrefix);
1795 } else if (complete) {
1796 // Complete + brief == give a summary. Isn't that obvious?!?
1797 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
1798 if (r.app != null) {
1799 pw.print(innerPrefix); pw.println(r.app);
1800 }
1801 }
1802 if (client && r.app != null && r.app.thread != null) {
1803 // flush anything that is already in the PrintWriter since the thread is going
1804 // to write to the file descriptor directly
1805 pw.flush();
1806 try {
1807 TransferPipe tp = new TransferPipe();
1808 try {
1809 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
1810 r.appToken, innerPrefix, args);
1811 // Short timeout, since blocking here can
1812 // deadlock with the application.
1813 tp.go(fd, 2000);
1814 } finally {
1815 tp.kill();
1816 }
1817 } catch (IOException e) {
1818 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
1819 } catch (RemoteException e) {
1820 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
1821 }
1822 needNL = true;
1823 }
1824 }
1825 }
Craig Mautner27084302013-03-25 08:05:25 -07001826}