blob: 2880b8d1c8310c8b0ef29ee1651e8548629dfea8 [file] [log] [blame]
Craig Mautner27084302013-03-25 08:05:25 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Craig Mautner6170f732013-04-02 13:05:23 -070019import static android.Manifest.permission.START_ANY_ACTIVITY;
Craig Mautner29219d92013-04-16 20:19:12 -070020import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
21import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Craig Mautner6170f732013-04-02 13:05:23 -070022import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Craig Mautner2420ead2013-04-01 17:13:20 -070023import static com.android.server.am.ActivityManagerService.localLOGV;
Craig Mautner23ac33b2013-04-01 16:26:35 -070024import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION;
Craig Mautner6170f732013-04-02 13:05:23 -070025import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
Craig Mautner2420ead2013-04-01 17:13:20 -070026import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
Craig Mautner8849a5e2013-04-02 16:41:03 -070027import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
28import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
Craig Mautner8d341ef2013-03-26 09:03:27 -070029import static com.android.server.am.ActivityManagerService.TAG;
30
Craig Mautner2420ead2013-04-01 17:13:20 -070031import android.app.Activity;
Craig Mautner23ac33b2013-04-01 16:26:35 -070032import android.app.ActivityManager;
33import android.app.ActivityOptions;
34import android.app.AppGlobals;
35import android.app.IApplicationThread;
Craig Mautner20e72272013-04-01 13:45:53 -070036import android.app.IThumbnailReceiver;
Craig Mautner23ac33b2013-04-01 16:26:35 -070037import android.app.PendingIntent;
Craig Mautner20e72272013-04-01 13:45:53 -070038import android.app.ActivityManager.RunningTaskInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070039import android.app.IActivityManager.WaitResult;
Craig Mautner2420ead2013-04-01 17:13:20 -070040import android.app.ResultInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070041import android.content.ComponentName;
Craig Mautner2219a1b2013-03-25 09:44:30 -070042import android.content.Context;
Craig Mautner23ac33b2013-04-01 16:26:35 -070043import android.content.IIntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070044import android.content.Intent;
Craig Mautner23ac33b2013-04-01 16:26:35 -070045import android.content.IntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070046import android.content.pm.ActivityInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070047import android.content.pm.ApplicationInfo;
48import android.content.pm.PackageManager;
49import android.content.pm.ResolveInfo;
50import android.content.res.Configuration;
51import android.os.Binder;
Craig Mautner8d341ef2013-03-26 09:03:27 -070052import android.os.Bundle;
Craig Mautner23ac33b2013-04-01 16:26:35 -070053import android.os.IBinder;
Craig Mautner2219a1b2013-03-25 09:44:30 -070054import android.os.Looper;
Craig Mautner2420ead2013-04-01 17:13:20 -070055import android.os.Message;
Craig Mautner23ac33b2013-04-01 16:26:35 -070056import android.os.ParcelFileDescriptor;
Craig Mautner8d341ef2013-03-26 09:03:27 -070057import android.os.RemoteException;
Craig Mautner23ac33b2013-04-01 16:26:35 -070058import android.os.SystemClock;
Craig Mautner6170f732013-04-02 13:05:23 -070059import android.os.UserHandle;
Craig Mautner2420ead2013-04-01 17:13:20 -070060import android.util.EventLog;
Craig Mautner8d341ef2013-03-26 09:03:27 -070061import android.util.Slog;
Craig Mautner2219a1b2013-03-25 09:44:30 -070062
Craig Mautner23ac33b2013-04-01 16:26:35 -070063import com.android.internal.app.HeavyWeightSwitcherActivity;
Craig Mautner6170f732013-04-02 13:05:23 -070064import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
Craig Mautner2420ead2013-04-01 17:13:20 -070065import com.android.server.am.ActivityStack.ActivityState;
Craig Mautnerde4ef022013-04-07 19:01:33 -070066import com.android.server.wm.StackBox;
Craig Mautner23ac33b2013-04-01 16:26:35 -070067
Craig Mautner8d341ef2013-03-26 09:03:27 -070068import java.io.FileDescriptor;
69import java.io.IOException;
Craig Mautner27084302013-03-25 08:05:25 -070070import java.io.PrintWriter;
Craig Mautner2219a1b2013-03-25 09:44:30 -070071import java.util.ArrayList;
Craig Mautner8d341ef2013-03-26 09:03:27 -070072import java.util.List;
Craig Mautner27084302013-03-25 08:05:25 -070073
74public class ActivityStackSupervisor {
Craig Mautnera9a3fb12013-04-18 10:01:00 -070075 static final boolean DEBUG_STACK = ActivityManagerService.DEBUG_STACK;
76
Craig Mautnerde4ef022013-04-07 19:01:33 -070077 static final boolean DEBUG = ActivityManagerService.DEBUG || false;
78 static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
79 static final boolean DEBUG_APP = DEBUG || false;
80 static final boolean DEBUG_SAVED_STATE = DEBUG || false;
81 static final boolean DEBUG_STATES = DEBUG || false;
Craig Mautner2420ead2013-04-01 17:13:20 -070082
Craig Mautner2219a1b2013-03-25 09:44:30 -070083 public static final int HOME_STACK_ID = 0;
Craig Mautner27084302013-03-25 08:05:25 -070084
85 final ActivityManagerService mService;
Craig Mautner2219a1b2013-03-25 09:44:30 -070086 final Context mContext;
87 final Looper mLooper;
Craig Mautner27084302013-03-25 08:05:25 -070088
89 /** Dismiss the keyguard after the next activity is displayed? */
90 private boolean mDismissKeyguardOnNextActivity = false;
91
Craig Mautner8d341ef2013-03-26 09:03:27 -070092 /** Identifier counter for all ActivityStacks */
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -070093 private int mLastStackId = HOME_STACK_ID;
Craig Mautner8d341ef2013-03-26 09:03:27 -070094
95 /** Task identifier that activities are currently being started in. Incremented each time a
96 * new task is created. */
97 private int mCurTaskId = 0;
98
Craig Mautner2420ead2013-04-01 17:13:20 -070099 /** The current user */
100 private int mCurrentUser;
101
Craig Mautner8d341ef2013-03-26 09:03:27 -0700102 /** The stack containing the launcher app */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700103 private ActivityStack mHomeStack;
Craig Mautner20e72272013-04-01 13:45:53 -0700104
Craig Mautnerde4ef022013-04-07 19:01:33 -0700105 /** The non-home stack currently receiving input or launching the next activity. If home is
Craig Mautner29219d92013-04-16 20:19:12 -0700106 * in front then mHomeStack overrides mFocusedStack. */
107 private ActivityStack mFocusedStack;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700108
109 /** All the non-launcher stacks */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700110 private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
111
Craig Mautnerde4ef022013-04-07 19:01:33 -0700112 private static final int STACK_STATE_HOME_IN_FRONT = 0;
113 private static final int STACK_STATE_HOME_TO_BACK = 1;
114 private static final int STACK_STATE_HOME_IN_BACK = 2;
115 private static final int STACK_STATE_HOME_TO_FRONT = 3;
116 private int mStackState = STACK_STATE_HOME_IN_FRONT;
117
118 /** List of activities that are waiting for a new activity to become visible before completing
119 * whatever operation they are supposed to do. */
120 final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();
121
122 /** List of activities that are ready to be stopped, but waiting for the next activity to
123 * settle down before doing so. */
124 final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();
125
126 /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity
127 * is being brought in front of us. */
128 boolean mUserLeaving = false;
129
Craig Mautner2219a1b2013-03-25 09:44:30 -0700130 public ActivityStackSupervisor(ActivityManagerService service, Context context,
131 Looper looper) {
Craig Mautner27084302013-03-25 08:05:25 -0700132 mService = service;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700133 mContext = context;
134 mLooper = looper;
135 }
136
Craig Mautner2420ead2013-04-01 17:13:20 -0700137 void init(int userId) {
138 mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID, this, userId);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700139 mStacks.add(mHomeStack);
Craig Mautner27084302013-03-25 08:05:25 -0700140 }
141
142 void dismissKeyguard() {
143 if (mDismissKeyguardOnNextActivity) {
144 mDismissKeyguardOnNextActivity = false;
145 mService.mWindowManager.dismissKeyguard();
146 }
147 }
148
Craig Mautnerde4ef022013-04-07 19:01:33 -0700149 ActivityStack getTopStack() {
Craig Mautnerf88c50f2013-04-18 19:25:12 -0700150 if (mFocusedStack == null) {
151 return mHomeStack;
152 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700153 switch (mStackState) {
154 case STACK_STATE_HOME_IN_FRONT:
155 case STACK_STATE_HOME_TO_FRONT:
156 return mHomeStack;
157 case STACK_STATE_HOME_IN_BACK:
158 case STACK_STATE_HOME_TO_BACK:
159 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700160 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700161 }
Craig Mautner20e72272013-04-01 13:45:53 -0700162 }
163
Craig Mautnerde4ef022013-04-07 19:01:33 -0700164 ActivityStack getLastStack() {
165 switch (mStackState) {
166 case STACK_STATE_HOME_IN_FRONT:
167 case STACK_STATE_HOME_TO_BACK:
168 return mHomeStack;
169 case STACK_STATE_HOME_TO_FRONT:
170 case STACK_STATE_HOME_IN_BACK:
171 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700172 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700173 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700174 }
175
Craig Mautnerde4ef022013-04-07 19:01:33 -0700176 boolean isFrontStack(ActivityStack stack) {
Craig Mautner967212c2013-04-13 21:10:58 -0700177 return !(stack.isHomeStack() ^ getTopStack().isHomeStack());
Craig Mautner20e72272013-04-01 13:45:53 -0700178 }
179
Craig Mautnerde4ef022013-04-07 19:01:33 -0700180 boolean homeIsInFront() {
181 return isFrontStack(mHomeStack);
182 }
183
184 void moveHomeStack(boolean toFront) {
185 final boolean homeInFront = isFrontStack(mHomeStack);
186 if (homeInFront ^ toFront) {
187 mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
188 }
189 }
190
Craig Mautner69ada552013-04-18 13:51:51 -0700191 boolean resumeHomeActivity(ActivityRecord prev) {
192 moveHomeStack(true);
193 if (prev != null) {
194 prev.mLaunchHomeTaskNext = false;
195 }
196 if (mHomeStack.topRunningActivityLocked(null) != null) {
197 return mHomeStack.resumeTopActivityLocked(prev);
198 }
199 return mService.startHomeActivityLocked(mCurrentUser);
200 }
201
Craig Mautnerde4ef022013-04-07 19:01:33 -0700202 final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r,
203 ActivityStack stack) {
204 if (stack == mHomeStack) {
205 return;
206 }
207 if ((sourceRecord == null && getLastStack() == mHomeStack) ||
208 (sourceRecord != null && sourceRecord.isHomeActivity)) {
209 if (r == null) {
210 r = stack.topRunningActivityLocked(null);
211 }
212 if (r != null && !r.isHomeActivity && r.isRootActivity()) {
213 r.mLaunchHomeTaskNext = true;
214 }
215 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700216 }
217
Craig Mautner27084302013-03-25 08:05:25 -0700218 void setDismissKeyguard(boolean dismiss) {
219 mDismissKeyguardOnNextActivity = dismiss;
220 }
221
Craig Mautner8d341ef2013-03-26 09:03:27 -0700222 TaskRecord anyTaskForIdLocked(int id) {
223 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
224 ActivityStack stack = mStacks.get(stackNdx);
225 TaskRecord task = stack.taskForIdLocked(id);
226 if (task != null) {
227 return task;
228 }
229 }
230 return null;
231 }
232
Craig Mautner6170f732013-04-02 13:05:23 -0700233 ActivityRecord isInAnyStackLocked(IBinder token) {
234 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
235 final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
236 if (r != null) {
237 return r;
238 }
239 }
240 return null;
241 }
242
Craig Mautner8d341ef2013-03-26 09:03:27 -0700243 int getNextTaskId() {
244 do {
245 mCurTaskId++;
246 if (mCurTaskId <= 0) {
247 mCurTaskId = 1;
248 }
249 } while (anyTaskForIdLocked(mCurTaskId) != null);
250 return mCurTaskId;
251 }
252
Craig Mautnerde4ef022013-04-07 19:01:33 -0700253 void removeTask(TaskRecord task) {
254 final ActivityStack stack = task.stack;
255 if (stack.removeTask(task) && !stack.isHomeStack()) {
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700256 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700257 mStacks.remove(stack);
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700258 final int stackId = stack.mStackId;
259 final int nextStackId = mService.mWindowManager.removeStack(stackId);
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700260 // TODO: Perhaps we need to let the ActivityManager determine the next focus...
Craig Mautner29219d92013-04-16 20:19:12 -0700261 if (mFocusedStack.mStackId == stackId) {
262 mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700263 }
264 }
265 }
266
267 ActivityRecord resumedAppLocked() {
268 ActivityStack stack = getTopStack();
269 ActivityRecord resumedActivity = stack.mResumedActivity;
270 if (resumedActivity == null || resumedActivity.app == null) {
271 resumedActivity = stack.mPausingActivity;
272 if (resumedActivity == null || resumedActivity.app == null) {
273 resumedActivity = stack.topRunningActivityLocked(null);
274 }
275 }
276 return resumedActivity;
277 }
278
Craig Mautner20e72272013-04-01 13:45:53 -0700279 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
280 boolean didSomething = false;
281 final String processName = app.processName;
282 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
283 final ActivityStack stack = mStacks.get(stackNdx);
284 ActivityRecord hr = stack.topRunningActivityLocked(null);
285 if (hr != null) {
286 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
287 && processName.equals(hr.processName)) {
288 try {
289 if (headless) {
290 Slog.e(TAG, "Starting activities not supported on headless device: "
291 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700292 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700293 didSomething = true;
294 }
295 } catch (Exception e) {
296 Slog.w(TAG, "Exception in new application when starting activity "
297 + hr.intent.getComponent().flattenToShortString(), e);
298 throw e;
299 }
300 } else {
301 stack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
302 }
303 }
304 }
305 return didSomething;
306 }
307
308 boolean allResumedActivitiesIdle() {
309 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700310 final ActivityRecord resumedActivity = mStacks.get(stackNdx).mResumedActivity;
311 if (resumedActivity == null || !resumedActivity.idle) {
Craig Mautner20e72272013-04-01 13:45:53 -0700312 return false;
313 }
314 }
315 return true;
316 }
317
Craig Mautnerde4ef022013-04-07 19:01:33 -0700318 boolean allResumedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700319 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
320 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner967212c2013-04-13 21:10:58 -0700321 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700322 final ActivityRecord r = stack.mResumedActivity;
323 if (r != null && r.state != ActivityState.RESUMED) {
324 return false;
325 }
326 }
327 }
328 // TODO: Not sure if this should check if all Paused are complete too.
329 switch (mStackState) {
330 case STACK_STATE_HOME_TO_BACK:
331 mStackState = STACK_STATE_HOME_IN_BACK;
332 break;
333 case STACK_STATE_HOME_TO_FRONT:
334 mStackState = STACK_STATE_HOME_IN_FRONT;
335 break;
336 }
337 return true;
338 }
339
340 boolean allResumedActivitiesVisible() {
341 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
342 final ActivityStack stack = mStacks.get(stackNdx);
343 final ActivityRecord r = stack.mResumedActivity;
344 if (r != null && (!r.nowVisible || r.waitingVisible)) {
345 return false;
346 }
347 }
348 return true;
349 }
350
351 boolean allPausedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700352 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
353 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner69ada552013-04-18 13:51:51 -0700354 final ActivityRecord r = stack.mPausingActivity;
355 if (r != null && r.state != ActivityState.PAUSED
356 && r.state != ActivityState.STOPPED
357 && r.state != ActivityState.STOPPING) {
358 return false;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700359 }
360 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700361 return true;
362 }
363
Craig Mautner29219d92013-04-16 20:19:12 -0700364 ActivityRecord topRunningActivityLocked() {
365 ActivityRecord r = null;
366 if (mFocusedStack != null) {
367 r = mFocusedStack.topRunningActivityLocked(null);
368 if (r != null) {
369 return r;
370 }
371 }
372 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
373 final ActivityStack stack = mStacks.get(stackNdx);
374 if (stack != mFocusedStack && isFrontStack(stack)) {
375 r = stack.topRunningActivityLocked(null);
376 if (r != null) {
377 return r;
378 }
379 }
380 }
381 return null;
382 }
383
Craig Mautner20e72272013-04-01 13:45:53 -0700384 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
385 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
386 ActivityRecord r = null;
387 final int numStacks = mStacks.size();
388 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
389 final ActivityStack stack = mStacks.get(stackNdx);
390 final ActivityRecord ar =
391 stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700392 if (isFrontStack(stack)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700393 r = ar;
394 }
395 }
396 return r;
397 }
398
Craig Mautner23ac33b2013-04-01 16:26:35 -0700399 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
400 String profileFile, ParcelFileDescriptor profileFd, int userId) {
401 // Collect information about the target of the Intent.
402 ActivityInfo aInfo;
403 try {
404 ResolveInfo rInfo =
405 AppGlobals.getPackageManager().resolveIntent(
406 intent, resolvedType,
407 PackageManager.MATCH_DEFAULT_ONLY
408 | ActivityManagerService.STOCK_PM_FLAGS, userId);
409 aInfo = rInfo != null ? rInfo.activityInfo : null;
410 } catch (RemoteException e) {
411 aInfo = null;
412 }
413
414 if (aInfo != null) {
415 // Store the found target back into the intent, because now that
416 // we have it we never want to do this again. For example, if the
417 // user navigates back to this point in the history, we should
418 // always restart the exact same activity.
419 intent.setComponent(new ComponentName(
420 aInfo.applicationInfo.packageName, aInfo.name));
421
422 // Don't debug things in the system process
423 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
424 if (!aInfo.processName.equals("system")) {
425 mService.setDebugApp(aInfo.processName, true, false);
426 }
427 }
428
429 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
430 if (!aInfo.processName.equals("system")) {
431 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
432 }
433 }
434
435 if (profileFile != null) {
436 if (!aInfo.processName.equals("system")) {
437 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
438 profileFile, profileFd,
439 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
440 }
441 }
442 }
443 return aInfo;
444 }
445
Craig Mautner2219a1b2013-03-25 09:44:30 -0700446 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700447 moveHomeStack(true);
Craig Mautner6170f732013-04-02 13:05:23 -0700448 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
Craig Mautner2219a1b2013-03-25 09:44:30 -0700449 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700450 }
451
Craig Mautner23ac33b2013-04-01 16:26:35 -0700452 final int startActivityMayWait(IApplicationThread caller, int callingUid,
453 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
454 String resultWho, int requestCode, int startFlags, String profileFile,
455 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
456 Bundle options, int userId) {
457 // Refuse possible leaked file descriptors
458 if (intent != null && intent.hasFileDescriptors()) {
459 throw new IllegalArgumentException("File descriptors passed in Intent");
460 }
461 boolean componentSpecified = intent.getComponent() != null;
462
463 // Don't modify the client's object!
464 intent = new Intent(intent);
465
466 // Collect information about the target of the Intent.
467 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
468 profileFile, profileFd, userId);
469
470 synchronized (mService) {
471 int callingPid;
472 if (callingUid >= 0) {
473 callingPid = -1;
474 } else if (caller == null) {
475 callingPid = Binder.getCallingPid();
476 callingUid = Binder.getCallingUid();
477 } else {
478 callingPid = callingUid = -1;
479 }
480
Craig Mautnerde4ef022013-04-07 19:01:33 -0700481 final ActivityStack stack = getTopStack();
482 stack.mConfigWillChange = config != null
Craig Mautner23ac33b2013-04-01 16:26:35 -0700483 && mService.mConfiguration.diff(config) != 0;
484 if (DEBUG_CONFIGURATION) Slog.v(TAG,
Craig Mautnerde4ef022013-04-07 19:01:33 -0700485 "Starting activity when config will change = " + stack.mConfigWillChange);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700486
487 final long origId = Binder.clearCallingIdentity();
488
489 if (aInfo != null &&
490 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
491 // This may be a heavy-weight process! Check to see if we already
492 // have another, different heavy-weight process running.
493 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
494 if (mService.mHeavyWeightProcess != null &&
495 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
496 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
497 int realCallingPid = callingPid;
498 int realCallingUid = callingUid;
499 if (caller != null) {
500 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
501 if (callerApp != null) {
502 realCallingPid = callerApp.pid;
503 realCallingUid = callerApp.info.uid;
504 } else {
505 Slog.w(TAG, "Unable to find app for caller " + caller
506 + " (pid=" + realCallingPid + ") when starting: "
507 + intent.toString());
508 ActivityOptions.abort(options);
509 return ActivityManager.START_PERMISSION_DENIED;
510 }
511 }
512
513 IIntentSender target = mService.getIntentSenderLocked(
514 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
515 realCallingUid, userId, null, null, 0, new Intent[] { intent },
516 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
517 | PendingIntent.FLAG_ONE_SHOT, null);
518
519 Intent newIntent = new Intent();
520 if (requestCode >= 0) {
521 // Caller is requesting a result.
522 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
523 }
524 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
525 new IntentSender(target));
526 if (mService.mHeavyWeightProcess.activities.size() > 0) {
527 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
528 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
529 hist.packageName);
530 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
531 hist.task.taskId);
532 }
533 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
534 aInfo.packageName);
535 newIntent.setFlags(intent.getFlags());
536 newIntent.setClassName("android",
537 HeavyWeightSwitcherActivity.class.getName());
538 intent = newIntent;
539 resolvedType = null;
540 caller = null;
541 callingUid = Binder.getCallingUid();
542 callingPid = Binder.getCallingPid();
543 componentSpecified = true;
544 try {
545 ResolveInfo rInfo =
546 AppGlobals.getPackageManager().resolveIntent(
547 intent, null,
548 PackageManager.MATCH_DEFAULT_ONLY
549 | ActivityManagerService.STOCK_PM_FLAGS, userId);
550 aInfo = rInfo != null ? rInfo.activityInfo : null;
551 aInfo = mService.getActivityInfoForUser(aInfo, userId);
552 } catch (RemoteException e) {
553 aInfo = null;
554 }
555 }
556 }
557 }
558
Craig Mautner6170f732013-04-02 13:05:23 -0700559 int res = startActivityLocked(caller, intent, resolvedType,
Craig Mautner23ac33b2013-04-01 16:26:35 -0700560 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
561 callingPackage, startFlags, options, componentSpecified, null);
562
Craig Mautnerde4ef022013-04-07 19:01:33 -0700563 if (stack.mConfigWillChange) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700564 // If the caller also wants to switch to a new configuration,
565 // do so now. This allows a clean switch, as we are waiting
566 // for the current activity to pause (so we will not destroy
567 // it), and have not yet started the next activity.
568 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
569 "updateConfiguration()");
Craig Mautnerde4ef022013-04-07 19:01:33 -0700570 stack.mConfigWillChange = false;
Craig Mautner23ac33b2013-04-01 16:26:35 -0700571 if (DEBUG_CONFIGURATION) Slog.v(TAG,
572 "Updating to new configuration after starting activity.");
573 mService.updateConfigurationLocked(config, null, false, false);
574 }
575
576 Binder.restoreCallingIdentity(origId);
577
578 if (outResult != null) {
579 outResult.result = res;
580 if (res == ActivityManager.START_SUCCESS) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700581 stack.mWaitingActivityLaunched.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700582 do {
583 try {
584 mService.wait();
585 } catch (InterruptedException e) {
586 }
587 } while (!outResult.timeout && outResult.who == null);
588 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700589 ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700590 if (r.nowVisible) {
591 outResult.timeout = false;
592 outResult.who = new ComponentName(r.info.packageName, r.info.name);
593 outResult.totalTime = 0;
594 outResult.thisTime = 0;
595 } else {
596 outResult.thisTime = SystemClock.uptimeMillis();
Craig Mautnerde4ef022013-04-07 19:01:33 -0700597 stack.mWaitingActivityVisible.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700598 do {
599 try {
600 mService.wait();
601 } catch (InterruptedException e) {
602 }
603 } while (!outResult.timeout && outResult.who == null);
604 }
605 }
606 }
607
608 return res;
609 }
610 }
611
612 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
613 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
614 Bundle options, int userId) {
615 if (intents == null) {
616 throw new NullPointerException("intents is null");
617 }
618 if (resolvedTypes == null) {
619 throw new NullPointerException("resolvedTypes is null");
620 }
621 if (intents.length != resolvedTypes.length) {
622 throw new IllegalArgumentException("intents are length different than resolvedTypes");
623 }
624
625 ActivityRecord[] outActivity = new ActivityRecord[1];
626
627 int callingPid;
628 if (callingUid >= 0) {
629 callingPid = -1;
630 } else if (caller == null) {
631 callingPid = Binder.getCallingPid();
632 callingUid = Binder.getCallingUid();
633 } else {
634 callingPid = callingUid = -1;
635 }
636 final long origId = Binder.clearCallingIdentity();
637 try {
638 synchronized (mService) {
639
640 for (int i=0; i<intents.length; i++) {
641 Intent intent = intents[i];
642 if (intent == null) {
643 continue;
644 }
645
646 // Refuse possible leaked file descriptors
647 if (intent != null && intent.hasFileDescriptors()) {
648 throw new IllegalArgumentException("File descriptors passed in Intent");
649 }
650
651 boolean componentSpecified = intent.getComponent() != null;
652
653 // Don't modify the client's object!
654 intent = new Intent(intent);
655
656 // Collect information about the target of the Intent.
657 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
658 0, null, null, userId);
659 // TODO: New, check if this is correct
660 aInfo = mService.getActivityInfoForUser(aInfo, userId);
661
662 if (aInfo != null &&
663 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
664 != 0) {
665 throw new IllegalArgumentException(
666 "FLAG_CANT_SAVE_STATE not supported here");
667 }
668
669 Bundle theseOptions;
670 if (options != null && i == intents.length-1) {
671 theseOptions = options;
672 } else {
673 theseOptions = null;
674 }
Craig Mautner6170f732013-04-02 13:05:23 -0700675 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Craig Mautner23ac33b2013-04-01 16:26:35 -0700676 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
677 0, theseOptions, componentSpecified, outActivity);
678 if (res < 0) {
679 return res;
680 }
681
682 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
683 }
684 }
685 } finally {
686 Binder.restoreCallingIdentity(origId);
687 }
688
689 return ActivityManager.START_SUCCESS;
690 }
691
Craig Mautner2420ead2013-04-01 17:13:20 -0700692 final boolean realStartActivityLocked(ActivityRecord r,
693 ProcessRecord app, boolean andResume, boolean checkConfig)
694 throws RemoteException {
695
696 r.startFreezingScreenLocked(app, 0);
697 mService.mWindowManager.setAppVisibility(r.appToken, true);
698
699 // schedule launch ticks to collect information about slow apps.
700 r.startLaunchTickingLocked();
701
702 // Have the window manager re-evaluate the orientation of
703 // the screen based on the new activity order. Note that
704 // as a result of this, it can call back into the activity
705 // manager with a new orientation. We don't care about that,
706 // because the activity is not currently running so we are
707 // just restarting it anyway.
708 if (checkConfig) {
709 Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
710 mService.mConfiguration,
711 r.mayFreezeScreenLocked(app) ? r.appToken : null);
712 mService.updateConfigurationLocked(config, r, false, false);
713 }
714
715 r.app = app;
716 app.waitingToKill = null;
717 r.launchCount++;
718 r.lastLaunchTime = SystemClock.uptimeMillis();
719
720 if (localLOGV) Slog.v(TAG, "Launching: " + r);
721
722 int idx = app.activities.indexOf(r);
723 if (idx < 0) {
724 app.activities.add(r);
725 }
726 mService.updateLruProcessLocked(app, true);
727
728 final ActivityStack stack = r.task.stack;
729 try {
730 if (app.thread == null) {
731 throw new RemoteException();
732 }
733 List<ResultInfo> results = null;
734 List<Intent> newIntents = null;
735 if (andResume) {
736 results = r.results;
737 newIntents = r.newIntents;
738 }
739 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
740 + " icicle=" + r.icicle
741 + " with results=" + results + " newIntents=" + newIntents
742 + " andResume=" + andResume);
743 if (andResume) {
744 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
745 r.userId, System.identityHashCode(r),
746 r.task.taskId, r.shortComponentName);
747 }
748 if (r.isHomeActivity) {
749 mService.mHomeProcess = app;
750 }
751 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
752 r.sleeping = false;
753 r.forceNewConfig = false;
754 mService.showAskCompatModeDialogLocked(r);
755 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
756 String profileFile = null;
757 ParcelFileDescriptor profileFd = null;
758 boolean profileAutoStop = false;
759 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
760 if (mService.mProfileProc == null || mService.mProfileProc == app) {
761 mService.mProfileProc = app;
762 profileFile = mService.mProfileFile;
763 profileFd = mService.mProfileFd;
764 profileAutoStop = mService.mAutoStopProfiler;
765 }
766 }
767 app.hasShownUi = true;
768 app.pendingUiClean = true;
769 if (profileFd != null) {
770 try {
771 profileFd = profileFd.dup();
772 } catch (IOException e) {
773 if (profileFd != null) {
774 try {
775 profileFd.close();
776 } catch (IOException o) {
777 }
778 profileFd = null;
779 }
780 }
781 }
782 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
783 System.identityHashCode(r), r.info,
784 new Configuration(mService.mConfiguration),
785 r.compat, r.icicle, results, newIntents, !andResume,
786 mService.isNextTransitionForward(), profileFile, profileFd,
787 profileAutoStop);
788
789 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
790 // This may be a heavy-weight process! Note that the package
791 // manager will ensure that only activity can run in the main
792 // process of the .apk, which is the only thing that will be
793 // considered heavy-weight.
794 if (app.processName.equals(app.info.packageName)) {
795 if (mService.mHeavyWeightProcess != null
796 && mService.mHeavyWeightProcess != app) {
797 Slog.w(TAG, "Starting new heavy weight process " + app
798 + " when already running "
799 + mService.mHeavyWeightProcess);
800 }
801 mService.mHeavyWeightProcess = app;
802 Message msg = mService.mHandler.obtainMessage(
803 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
804 msg.obj = r;
805 mService.mHandler.sendMessage(msg);
806 }
807 }
808
809 } catch (RemoteException e) {
810 if (r.launchFailed) {
811 // This is the second time we failed -- finish activity
812 // and give up.
813 Slog.e(TAG, "Second failure launching "
814 + r.intent.getComponent().flattenToShortString()
815 + ", giving up", e);
816 mService.appDiedLocked(app, app.pid, app.thread);
817 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
818 "2nd-crash", false);
819 return false;
820 }
821
822 // This is the first time we failed -- restart process and
823 // retry.
824 app.activities.remove(r);
825 throw e;
826 }
827
828 r.launchFailed = false;
829 if (stack.updateLRUListLocked(r)) {
830 Slog.w(TAG, "Activity " + r
831 + " being launched, but already in LRU list");
832 }
833
834 if (andResume) {
835 // As part of the process of launching, ActivityThread also performs
836 // a resume.
837 stack.minimalResumeActivityLocked(r);
838 } else {
839 // This activity is not starting in the resumed state... which
840 // should look like we asked it to pause+stop (but remain visible),
841 // and it has done so and reported back the current icicle and
842 // other state.
843 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
844 + " (starting in stopped state)");
845 r.state = ActivityState.STOPPED;
846 r.stopped = true;
847 }
848
849 // Launch the new version setup screen if needed. We do this -after-
850 // launching the initial activity (that is, home), so that it can have
851 // a chance to initialize itself while in the background, making the
852 // switch back to it faster and look better.
Craig Mautnerde4ef022013-04-07 19:01:33 -0700853 if (isFrontStack(stack)) {
Craig Mautner2420ead2013-04-01 17:13:20 -0700854 mService.startSetupActivityLocked();
855 }
856
857 return true;
858 }
859
Craig Mautnere79d42682013-04-01 19:01:53 -0700860 void startSpecificActivityLocked(ActivityRecord r,
861 boolean andResume, boolean checkConfig) {
862 // Is this activity's application already running?
863 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
864 r.info.applicationInfo.uid);
865
866 r.task.stack.setLaunchTime(r);
867
868 if (app != null && app.thread != null) {
869 try {
870 app.addPackage(r.info.packageName);
871 realStartActivityLocked(r, app, andResume, checkConfig);
872 return;
873 } catch (RemoteException e) {
874 Slog.w(TAG, "Exception when starting activity "
875 + r.intent.getComponent().flattenToShortString(), e);
876 }
877
878 // If a dead object exception was thrown -- fall through to
879 // restart the application.
880 }
881
882 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
883 "activity", r.intent.getComponent(), false, false);
884 }
885
Craig Mautner6170f732013-04-02 13:05:23 -0700886 final int startActivityLocked(IApplicationThread caller,
887 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
888 String resultWho, int requestCode,
889 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
890 boolean componentSpecified, ActivityRecord[] outActivity) {
891 int err = ActivityManager.START_SUCCESS;
892
893 ProcessRecord callerApp = null;
894 if (caller != null) {
895 callerApp = mService.getRecordForAppLocked(caller);
896 if (callerApp != null) {
897 callingPid = callerApp.pid;
898 callingUid = callerApp.info.uid;
899 } else {
900 Slog.w(TAG, "Unable to find app for caller " + caller
901 + " (pid=" + callingPid + ") when starting: "
902 + intent.toString());
903 err = ActivityManager.START_PERMISSION_DENIED;
904 }
905 }
906
907 if (err == ActivityManager.START_SUCCESS) {
908 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
909 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
910 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
911 }
912
913 ActivityRecord sourceRecord = null;
914 ActivityRecord resultRecord = null;
915 if (resultTo != null) {
916 sourceRecord = isInAnyStackLocked(resultTo);
917 if (DEBUG_RESULTS) Slog.v(
918 TAG, "Will send result to " + resultTo + " " + sourceRecord);
919 if (sourceRecord != null) {
920 if (requestCode >= 0 && !sourceRecord.finishing) {
921 resultRecord = sourceRecord;
922 }
923 }
924 }
925 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
926
927 int launchFlags = intent.getFlags();
928
929 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
930 && sourceRecord != null) {
931 // Transfer the result target from the source activity to the new
932 // one being started, including any failures.
933 if (requestCode >= 0) {
934 ActivityOptions.abort(options);
935 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
936 }
937 resultRecord = sourceRecord.resultTo;
938 resultWho = sourceRecord.resultWho;
939 requestCode = sourceRecord.requestCode;
940 sourceRecord.resultTo = null;
941 if (resultRecord != null) {
942 resultRecord.removeResultsLocked(
943 sourceRecord, resultWho, requestCode);
944 }
945 }
946
947 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
948 // We couldn't find a class that can handle the given Intent.
949 // That's the end of that!
950 err = ActivityManager.START_INTENT_NOT_RESOLVED;
951 }
952
953 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
954 // We couldn't find the specific class specified in the Intent.
955 // Also the end of the line.
956 err = ActivityManager.START_CLASS_NOT_FOUND;
957 }
958
959 if (err != ActivityManager.START_SUCCESS) {
960 if (resultRecord != null) {
961 resultStack.sendActivityResultLocked(-1,
962 resultRecord, resultWho, requestCode,
963 Activity.RESULT_CANCELED, null);
964 }
965 setDismissKeyguard(false);
966 ActivityOptions.abort(options);
967 return err;
968 }
969
970 final int startAnyPerm = mService.checkPermission(
971 START_ANY_ACTIVITY, callingPid, callingUid);
972 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
973 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
974 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
975 if (resultRecord != null) {
976 resultStack.sendActivityResultLocked(-1,
977 resultRecord, resultWho, requestCode,
978 Activity.RESULT_CANCELED, null);
979 }
980 setDismissKeyguard(false);
981 String msg;
982 if (!aInfo.exported) {
983 msg = "Permission Denial: starting " + intent.toString()
984 + " from " + callerApp + " (pid=" + callingPid
985 + ", uid=" + callingUid + ")"
986 + " not exported from uid " + aInfo.applicationInfo.uid;
987 } else {
988 msg = "Permission Denial: starting " + intent.toString()
989 + " from " + callerApp + " (pid=" + callingPid
990 + ", uid=" + callingUid + ")"
991 + " requires " + aInfo.permission;
992 }
993 Slog.w(TAG, msg);
994 throw new SecurityException(msg);
995 }
996
Ben Gruver6617c3c2013-04-03 18:45:22 -0700997 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
Ben Gruver7b879f42013-04-08 14:56:55 -0700998 callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo);
Ben Gruver5e207332013-04-03 17:41:37 -0700999
Craig Mautner6170f732013-04-02 13:05:23 -07001000 if (mService.mController != null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001001 try {
1002 // The Intent we give to the watcher has the extra data
1003 // stripped off, since it can contain private information.
1004 Intent watchIntent = intent.cloneFilter();
Ben Gruver5e207332013-04-03 17:41:37 -07001005 abort |= !mService.mController.activityStarting(watchIntent,
Craig Mautner6170f732013-04-02 13:05:23 -07001006 aInfo.applicationInfo.packageName);
1007 } catch (RemoteException e) {
1008 mService.mController = null;
1009 }
Ben Gruver5e207332013-04-03 17:41:37 -07001010 }
Craig Mautner6170f732013-04-02 13:05:23 -07001011
Ben Gruver5e207332013-04-03 17:41:37 -07001012 if (abort) {
1013 if (resultRecord != null) {
1014 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Craig Mautner6170f732013-04-02 13:05:23 -07001015 Activity.RESULT_CANCELED, null);
Craig Mautner6170f732013-04-02 13:05:23 -07001016 }
Ben Gruver5e207332013-04-03 17:41:37 -07001017 // We pretend to the caller that it was really started, but
1018 // they will just get a cancel result.
1019 setDismissKeyguard(false);
1020 ActivityOptions.abort(options);
1021 return ActivityManager.START_SUCCESS;
Craig Mautner6170f732013-04-02 13:05:23 -07001022 }
1023
1024 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1025 intent, resolvedType, aInfo, mService.mConfiguration,
Craig Mautnerde4ef022013-04-07 19:01:33 -07001026 resultRecord, resultWho, requestCode, componentSpecified, this);
Craig Mautner6170f732013-04-02 13:05:23 -07001027 if (outActivity != null) {
1028 outActivity[0] = r;
1029 }
1030
Craig Mautnerde4ef022013-04-07 19:01:33 -07001031 final ActivityStack stack = getTopStack();
1032 if (stack.mResumedActivity == null
1033 || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
Craig Mautner6170f732013-04-02 13:05:23 -07001034 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1035 PendingActivityLaunch pal =
Craig Mautnerde4ef022013-04-07 19:01:33 -07001036 new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
Craig Mautner6170f732013-04-02 13:05:23 -07001037 mService.mPendingActivityLaunches.add(pal);
1038 setDismissKeyguard(false);
1039 ActivityOptions.abort(options);
1040 return ActivityManager.START_SWITCHES_CANCELED;
1041 }
1042 }
1043
1044 if (mService.mDidAppSwitch) {
1045 // This is the second allowed switch since we stopped switches,
1046 // so now just generally allow switches. Use case: user presses
1047 // home (switches disabled, switch to home, mDidAppSwitch now true);
1048 // user taps a home icon (coming from home so allowed, we hit here
1049 // and now allow anyone to switch again).
1050 mService.mAppSwitchesAllowedTime = 0;
1051 } else {
1052 mService.mDidAppSwitch = true;
1053 }
1054
1055 mService.doPendingActivityLaunchesLocked(false);
1056
Craig Mautner8849a5e2013-04-02 16:41:03 -07001057 err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001058 if (stack.mPausingActivity == null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001059 // Someone asked to have the keyguard dismissed on the next
1060 // activity start, but we are not actually doing an activity
1061 // switch... just dismiss the keyguard now, because we
1062 // probably want to see whatever is behind it.
1063 dismissKeyguard();
1064 }
1065 return err;
1066 }
1067
Craig Mautnerde4ef022013-04-07 19:01:33 -07001068 ActivityStack getCorrectStack(ActivityRecord r) {
1069 if (!r.isHomeActivity) {
1070 if (mStacks.size() == 1) {
1071 // Time to create the first app stack.
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001072 int stackId = mService.createStack(-1, HOME_STACK_ID,
1073 StackBox.TASK_STACK_GOES_OVER, 1.0f);
Craig Mautner29219d92013-04-16 20:19:12 -07001074 mFocusedStack = getStack(stackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001075 }
Craig Mautner29219d92013-04-16 20:19:12 -07001076 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001077 }
1078 return mHomeStack;
1079 }
1080
Craig Mautner29219d92013-04-16 20:19:12 -07001081 void setFocusedStack(ActivityRecord r) {
1082 if (r == null) {
1083 return;
1084 }
1085 if (r.isHomeActivity) {
1086 if (mStackState != STACK_STATE_HOME_IN_FRONT) {
1087 mStackState = STACK_STATE_HOME_TO_FRONT;
1088 }
1089 } else {
1090 mFocusedStack = r.task.stack;
1091 if (mStackState != STACK_STATE_HOME_IN_BACK) {
1092 mStackState = STACK_STATE_HOME_TO_BACK;
1093 }
1094 }
1095 }
1096
Craig Mautner8849a5e2013-04-02 16:41:03 -07001097 final int startActivityUncheckedLocked(ActivityRecord r,
1098 ActivityRecord sourceRecord, int startFlags, boolean doResume,
1099 Bundle options) {
1100 final Intent intent = r.intent;
1101 final int callingUid = r.launchedFromUid;
1102
1103 int launchFlags = intent.getFlags();
1104
Craig Mautner8849a5e2013-04-02 16:41:03 -07001105 // We'll invoke onUserLeaving before onPause only if the launching
1106 // activity did not explicitly state that this is an automated launch.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001107 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1108 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001109
1110 // If the caller has asked not to resume at this point, we make note
1111 // of this in the record so that we can skip it when trying to find
1112 // the top running activity.
1113 if (!doResume) {
1114 r.delayedResume = true;
1115 }
1116
1117 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1118
1119 // If the onlyIfNeeded flag is set, then we can do this if the activity
1120 // being launched is the same as the one making the call... or, as
1121 // a special case, if we do not know the caller then we count the
1122 // current top activity as the caller.
1123 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1124 ActivityRecord checkedCaller = sourceRecord;
1125 if (checkedCaller == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001126 checkedCaller = getTopStack().topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001127 }
1128 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1129 // Caller is not the same as launcher, so always needed.
1130 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1131 }
1132 }
1133
1134 if (sourceRecord == null) {
1135 // This activity is not being started from another... in this
1136 // case we -always- start a new task.
1137 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Craig Mautner29219d92013-04-16 20:19:12 -07001138 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1139 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001140 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1141 }
1142 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1143 // The original activity who is starting us is running as a single
1144 // instance... this new activity it is starting must go on its
1145 // own task.
1146 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1147 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1148 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1149 // The activity being started is a single instance... it always
1150 // gets launched into its own task.
1151 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1152 }
1153
Craig Mautnerde4ef022013-04-07 19:01:33 -07001154 final ActivityStack sourceStack;
1155 final TaskRecord sourceTask;
1156 if (sourceRecord != null) {
1157 sourceTask = sourceRecord.task;
1158 sourceStack = sourceTask.stack;
1159 } else {
1160 sourceTask = null;
1161 sourceStack = null;
1162 }
1163
Craig Mautner8849a5e2013-04-02 16:41:03 -07001164 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1165 // For whatever reason this activity is being launched into a new
1166 // task... yet the caller has requested a result back. Well, that
1167 // is pretty messed up, so instead immediately send back a cancel
1168 // and let the new task continue launched as normal without a
1169 // dependency on its originator.
1170 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1171 r.resultTo.task.stack.sendActivityResultLocked(-1,
1172 r.resultTo, r.resultWho, r.requestCode,
1173 Activity.RESULT_CANCELED, null);
1174 r.resultTo = null;
1175 }
1176
1177 boolean addingToTask = false;
1178 boolean movedHome = false;
1179 TaskRecord reuseTask = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001180 ActivityStack targetStack;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001181 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1182 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1183 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1184 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1185 // If bring to front is requested, and no result is requested, and
1186 // we can find a task that was started with this same
1187 // component, then instead of launching bring that one to the front.
1188 if (r.resultTo == null) {
1189 // See if there is a task to bring to the front. If this is
1190 // a SINGLE_INSTANCE activity, there can be one and only one
1191 // instance of it in the history, and it is always in its own
1192 // unique task, so we do a special search.
1193 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
1194 ? findTaskLocked(intent, r.info)
1195 : findActivityLocked(intent, r.info);
1196 if (intentActivity != null) {
Craig Mautner29219d92013-04-16 20:19:12 -07001197 if (r.task == null) {
1198 r.task = intentActivity.task;
1199 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001200 targetStack = intentActivity.task.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001201 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001202 if (intentActivity.task.intent == null) {
1203 // This task was started because of movement of
1204 // the activity based on affinity... now that we
1205 // are actually launching it, we can assign the
1206 // base intent.
1207 intentActivity.task.setIntent(intent, r.info);
1208 }
1209 // If the target task is not in the front, then we need
1210 // to bring it to the front... except... well, with
1211 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
1212 // to have the same behavior as if a new instance was
1213 // being started, which means not bringing it to the front
1214 // if the caller is not itself in the front.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001215 ActivityRecord curTop =
1216 targetStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001217 if (curTop != null && curTop.task != intentActivity.task) {
1218 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001219 if (sourceRecord == null || sourceStack.topActivity() == sourceRecord) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001220 // We really do want to push this one into the
1221 // user's face, right now.
1222 movedHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001223 if ((launchFlags &
Craig Mautner29219d92013-04-16 20:19:12 -07001224 (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1225 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001226 // Caller wants to appear on home activity, so before starting
1227 // their own activity we will bring home to the front.
1228 r.mLaunchHomeTaskNext = true;
1229 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001230 targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1231 options = null;
1232 }
1233 }
1234 // If the caller has requested that the target task be
1235 // reset, then do so.
1236 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1237 intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1238 }
1239 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1240 // We don't need to start a new activity, and
1241 // the client said not to do anything if that
1242 // is the case, so this is it! And for paranoia, make
1243 // sure we have correctly resumed the top activity.
1244 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001245 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001246 targetStack.resumeTopActivityLocked(null, options);
1247 } else {
1248 ActivityOptions.abort(options);
1249 }
Craig Mautner29219d92013-04-16 20:19:12 -07001250 if (r.task == null) Slog.v(TAG,
1251 "startActivityUncheckedLocked: task left null",
1252 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001253 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1254 }
1255 if ((launchFlags &
1256 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1257 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1258 // The caller has requested to completely replace any
1259 // existing task with its new activity. Well that should
1260 // not be too hard...
1261 reuseTask = intentActivity.task;
1262 reuseTask.performClearTaskLocked();
1263 reuseTask.setIntent(r.intent, r.info);
1264 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1265 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1266 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1267 // In this situation we want to remove all activities
1268 // from the task up to the one being started. In most
1269 // cases this means we are resetting the task to its
1270 // initial state.
1271 ActivityRecord top =
1272 intentActivity.task.performClearTaskLocked(r, launchFlags);
1273 if (top != null) {
1274 if (top.frontOfTask) {
1275 // Activity aliases may mean we use different
1276 // intents for the top activity, so make sure
1277 // the task now has the identity of the new
1278 // intent.
1279 top.task.setIntent(r.intent, r.info);
1280 }
1281 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1282 r, top.task);
1283 top.deliverNewIntentLocked(callingUid, r.intent);
1284 } else {
1285 // A special case: we need to
1286 // start the activity because it is not currently
1287 // running, and the caller has asked to clear the
1288 // current task to have this activity at the top.
1289 addingToTask = true;
1290 // Now pretend like this activity is being started
1291 // by the top of its task, so it is put in the
1292 // right place.
1293 sourceRecord = intentActivity;
1294 }
1295 } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1296 // In this case the top activity on the task is the
1297 // same as the one being launched, so we take that
1298 // as a request to bring the task to the foreground.
1299 // If the top activity in the task is the root
1300 // activity, deliver this new intent to it if it
1301 // desires.
1302 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1303 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1304 && intentActivity.realActivity.equals(r.realActivity)) {
1305 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1306 intentActivity.task);
1307 if (intentActivity.frontOfTask) {
1308 intentActivity.task.setIntent(r.intent, r.info);
1309 }
1310 intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1311 } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1312 // In this case we are launching the root activity
1313 // of the task, but with a different intent. We
1314 // should start a new instance on top.
1315 addingToTask = true;
1316 sourceRecord = intentActivity;
1317 }
1318 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1319 // In this case an activity is being launched in to an
1320 // existing task, without resetting that task. This
1321 // is typically the situation of launching an activity
1322 // from a notification or shortcut. We want to place
1323 // the new activity on top of the current task.
1324 addingToTask = true;
1325 sourceRecord = intentActivity;
1326 } else if (!intentActivity.task.rootWasReset) {
1327 // In this case we are launching in to an existing task
1328 // that has not yet been started from its front door.
1329 // The current task has been brought to the front.
1330 // Ideally, we'd probably like to place this new task
1331 // at the bottom of its stack, but that's a little hard
1332 // to do with the current organization of the code so
1333 // for now we'll just drop it.
1334 intentActivity.task.setIntent(r.intent, r.info);
1335 }
1336 if (!addingToTask && reuseTask == null) {
1337 // We didn't do anything... but it was needed (a.k.a., client
1338 // don't use that intent!) And for paranoia, make
1339 // sure we have correctly resumed the top activity.
1340 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001341 setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1342 targetStack.resumeTopActivityLocked(null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001343 } else {
1344 ActivityOptions.abort(options);
1345 }
Craig Mautner29219d92013-04-16 20:19:12 -07001346 if (r.task == null) Slog.v(TAG,
1347 "startActivityUncheckedLocked: task left null",
1348 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001349 return ActivityManager.START_TASK_TO_FRONT;
1350 }
1351 }
1352 }
1353 }
1354
1355 //String uri = r.intent.toURI();
1356 //Intent intent2 = new Intent(uri);
1357 //Slog.i(TAG, "Given intent: " + r.intent);
1358 //Slog.i(TAG, "URI is: " + uri);
1359 //Slog.i(TAG, "To intent: " + intent2);
1360
1361 if (r.packageName != null) {
1362 // If the activity being launched is the same as the one currently
1363 // at the top, then we need to check if it should only be launched
1364 // once.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001365 ActivityStack topStack = getTopStack();
1366 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001367 if (top != null && r.resultTo == null) {
1368 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1369 if (top.app != null && top.app.thread != null) {
1370 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1371 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1372 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1373 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1374 top.task);
1375 // For paranoia, make sure we have correctly
1376 // resumed the top activity.
1377 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001378 setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
1379 topStack.resumeTopActivityLocked(null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001380 }
1381 ActivityOptions.abort(options);
1382 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1383 // We don't need to start a new activity, and
1384 // the client said not to do anything if that
1385 // is the case, so this is it!
Craig Mautner29219d92013-04-16 20:19:12 -07001386 if (r.task == null) Slog.v(TAG,
1387 "startActivityUncheckedLocked: task left null",
1388 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001389 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1390 }
1391 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner29219d92013-04-16 20:19:12 -07001392 if (r.task == null) Slog.v(TAG,
1393 "startActivityUncheckedLocked: task left null",
1394 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001395 return ActivityManager.START_DELIVERED_TO_TOP;
1396 }
1397 }
1398 }
1399 }
1400
1401 } else {
1402 if (r.resultTo != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001403 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1404 r.requestCode, Activity.RESULT_CANCELED, null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001405 }
1406 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001407 if (r.task == null) Slog.v(TAG,
1408 "startActivityUncheckedLocked: task left null",
1409 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001410 return ActivityManager.START_CLASS_NOT_FOUND;
1411 }
1412
1413 boolean newTask = false;
1414 boolean keepCurTransition = false;
1415
1416 // Should this be considered a new task?
1417 if (r.resultTo == null && !addingToTask
1418 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001419 targetStack = getCorrectStack(r);
1420 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001421 if (reuseTask == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001422 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1423 null, true);
1424 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1425 r.task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001426 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001427 r.setTask(reuseTask, reuseTask, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001428 }
1429 newTask = true;
1430 if (!movedHome) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001431 if ((launchFlags &
1432 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1433 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1434 // Caller wants to appear on home activity, so before starting
1435 // their own activity we will bring home to the front.
1436 r.mLaunchHomeTaskNext = true;
1437 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001438 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001439 } else if (sourceRecord != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001440 targetStack = sourceRecord.task.stack;
1441 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001442 if (!addingToTask &&
1443 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1444 // In this case, we are adding the activity to an existing
1445 // task, but the caller has asked to clear that task if the
1446 // activity is already running.
1447 ActivityRecord top = sourceRecord.task.performClearTaskLocked(r, launchFlags);
1448 keepCurTransition = true;
1449 if (top != null) {
1450 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1451 top.deliverNewIntentLocked(callingUid, r.intent);
1452 // For paranoia, make sure we have correctly
1453 // resumed the top activity.
1454 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001455 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001456 targetStack.resumeTopActivityLocked(null);
1457 }
1458 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001459 if (r.task == null) Slog.v(TAG,
1460 "startActivityUncheckedLocked: task left null",
1461 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001462 return ActivityManager.START_DELIVERED_TO_TOP;
1463 }
1464 } else if (!addingToTask &&
1465 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1466 // In this case, we are launching an activity in our own task
1467 // that may already be running somewhere in the history, and
1468 // we want to shuffle it to the front of the stack if so.
1469 final ActivityRecord top =
1470 targetStack.findActivityInHistoryLocked(r, sourceRecord.task);
1471 if (top != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001472 final TaskRecord task = top.task;
1473 task.moveActivityToFrontLocked(top);
1474 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001475 top.updateOptionsLocked(options);
1476 top.deliverNewIntentLocked(callingUid, r.intent);
1477 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001478 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001479 targetStack.resumeTopActivityLocked(null);
1480 }
Craig Mautner29219d92013-04-16 20:19:12 -07001481 if (r.task == null) Slog.v(TAG,
1482 "startActivityUncheckedLocked: task left null",
1483 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001484 return ActivityManager.START_DELIVERED_TO_TOP;
1485 }
1486 }
1487 // An existing activity is starting this new activity, so we want
1488 // to keep the new one in the same task as the one that is starting
1489 // it.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001490 r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001491 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1492 + " in existing task " + r.task);
1493
1494 } else {
1495 // This not being started from an existing activity, and not part
1496 // of a new task... just put it in the top task, though these days
1497 // this case should never happen.
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001498 ActivityStack lastStack = getLastStack();
1499 targetStack = lastStack != null ? lastStack : mHomeStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001500 moveHomeStack(targetStack.isHomeStack());
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001501 ActivityRecord prev = lastStack == null ? null : targetStack.topActivity();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001502 r.setTask(prev != null ? prev.task
1503 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1504 null, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001505 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1506 + " in new guessed " + r.task);
1507 }
1508
1509 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1510 intent, r.getUriPermissionsLocked());
1511
1512 if (newTask) {
1513 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1514 }
1515 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001516 setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001517 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
1518 return ActivityManager.START_SUCCESS;
1519 }
1520
Craig Mautner8d341ef2013-03-26 09:03:27 -07001521 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
1522 // Just in case.
1523 final int numStacks = mStacks.size();
1524 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Craig Mautnere79d42682013-04-01 19:01:53 -07001525 mStacks.get(stackNdx).handleAppDiedLocked(app, restarting);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001526 }
1527 }
1528
1529 void closeSystemDialogsLocked() {
1530 final int numStacks = mStacks.size();
1531 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1532 final ActivityStack stack = mStacks.get(stackNdx);
1533 stack.closeSystemDialogsLocked();
1534 }
1535 }
1536
1537 /**
1538 * @return true if some activity was finished (or would have finished if doit were true).
1539 */
1540 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1541 boolean didSomething = false;
1542 final int numStacks = mStacks.size();
1543 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1544 final ActivityStack stack = mStacks.get(stackNdx);
1545 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1546 didSomething = true;
1547 }
1548 }
1549 return didSomething;
1550 }
1551
1552 void resumeTopActivityLocked() {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -07001553 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001554 final ActivityStack stack = mStacks.get(stackNdx);
1555 if (isFrontStack(stack)) {
1556 stack.resumeTopActivityLocked(null);
1557 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001558 }
1559 }
1560
1561 void finishTopRunningActivityLocked(ProcessRecord app) {
1562 final int numStacks = mStacks.size();
1563 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1564 final ActivityStack stack = mStacks.get(stackNdx);
1565 stack.finishTopRunningActivityLocked(app);
1566 }
1567 }
1568
1569 void scheduleIdleLocked() {
1570 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1571 mStacks.get(stackNdx).scheduleIdleLocked();
1572 }
1573 }
1574
1575 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
1576 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1577 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
1578 return;
1579 }
1580 }
1581 }
1582
Craig Mautner967212c2013-04-13 21:10:58 -07001583 ActivityStack getStack(int stackId) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001584 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1585 final ActivityStack stack = mStacks.get(stackNdx);
1586 if (stack.getStackId() == stackId) {
1587 return stack;
1588 }
1589 }
1590 return null;
1591 }
1592
Craig Mautner967212c2013-04-13 21:10:58 -07001593 ArrayList<ActivityStack> getStacks() {
1594 return new ArrayList<ActivityStack>(mStacks);
1595 }
1596
1597 int createStack() {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001598 synchronized (this) {
1599 while (true) {
1600 if (++mLastStackId <= HOME_STACK_ID) {
1601 mLastStackId = HOME_STACK_ID + 1;
1602 }
1603 if (getStack(mLastStackId) == null) {
1604 break;
1605 }
1606 }
Craig Mautner2420ead2013-04-01 17:13:20 -07001607 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId, this,
1608 mCurrentUser));
Craig Mautner8d341ef2013-03-26 09:03:27 -07001609 return mLastStackId;
1610 }
1611 }
1612
1613 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
1614 final ActivityStack stack = getStack(stackId);
1615 if (stack == null) {
1616 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
1617 return;
1618 }
1619 stack.moveTask(taskId, toTop);
Craig Mautner967212c2013-04-13 21:10:58 -07001620 stack.resumeTopActivityLocked(null);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001621 }
1622
Craig Mautner8849a5e2013-04-02 16:41:03 -07001623 ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
1624 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1625 final ActivityRecord ar = mStacks.get(stackNdx).findTaskLocked(intent, info);
1626 if (ar != null) {
1627 return ar;
1628 }
1629 }
1630 return null;
1631 }
1632
1633 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
1634 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1635 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
1636 if (ar != null) {
1637 return ar;
1638 }
1639 }
1640 return null;
1641 }
1642
Craig Mautner8d341ef2013-03-26 09:03:27 -07001643 void goingToSleepLocked() {
1644 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1645 mStacks.get(stackNdx).stopIfSleepingLocked();
1646 }
1647 }
1648
1649 boolean shutdownLocked(int timeout) {
1650 boolean timedout = false;
1651 final int numStacks = mStacks.size();
1652 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1653 final ActivityStack stack = mStacks.get(stackNdx);
1654 if (stack.mResumedActivity != null) {
1655 stack.stopIfSleepingLocked();
1656 final long endTime = System.currentTimeMillis() + timeout;
1657 while (stack.mResumedActivity != null || stack.mPausingActivity != null) {
1658 long delay = endTime - System.currentTimeMillis();
1659 if (delay <= 0) {
1660 Slog.w(TAG, "Activity manager shutdown timed out");
1661 timedout = true;
1662 break;
1663 }
1664 try {
1665 mService.wait();
1666 } catch (InterruptedException e) {
1667 }
1668 }
1669 }
1670 }
1671 return timedout;
1672 }
1673
1674 void comeOutOfSleepIfNeededLocked() {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001675 final boolean homeIsBack = !homeIsInFront();
Craig Mautner8d341ef2013-03-26 09:03:27 -07001676 final int numStacks = mStacks.size();
1677 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1678 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001679 if (stack.isHomeStack() ^ homeIsBack) {
1680 stack.awakeFromSleepingLocked();
1681 stack.resumeTopActivityLocked(null);
1682 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001683 }
1684 }
1685
1686 void handleAppCrashLocked(ProcessRecord app) {
1687 final int numStacks = mStacks.size();
1688 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1689 final ActivityStack stack = mStacks.get(stackNdx);
1690 stack.handleAppCrashLocked(app);
1691 }
1692 }
1693
Craig Mautnerde4ef022013-04-07 19:01:33 -07001694 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
1695 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1696 mStacks.get(stackNdx).ensureActivitiesVisibleLocked(starting, configChanges);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001697 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001698 }
1699
1700 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
1701 final int numStacks = mStacks.size();
1702 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1703 final ActivityStack stack = mStacks.get(stackNdx);
1704 stack.scheduleDestroyActivities(app, false, reason);
1705 }
1706 }
1707
1708 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner2420ead2013-04-01 17:13:20 -07001709 mCurrentUser = userId;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001710 boolean homeInBack = !homeIsInFront();
Craig Mautner8d341ef2013-03-26 09:03:27 -07001711 boolean haveActivities = false;
1712 final int numStacks = mStacks.size();
1713 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1714 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001715 if (stack.isHomeStack() ^ homeInBack) {
1716 haveActivities |= stack.switchUserLocked(userId, uss);
1717 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001718 }
1719 return haveActivities;
Craig Mautner2219a1b2013-03-25 09:44:30 -07001720 }
1721
Craig Mautnerde4ef022013-04-07 19:01:33 -07001722 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
1723 int N = mStoppingActivities.size();
1724 if (N <= 0) return null;
1725
1726 ArrayList<ActivityRecord> stops = null;
1727
1728 final boolean nowVisible = allResumedActivitiesVisible();
1729 for (int i=0; i<N; i++) {
1730 ActivityRecord s = mStoppingActivities.get(i);
1731 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
1732 + nowVisible + " waitingVisible=" + s.waitingVisible
1733 + " finishing=" + s.finishing);
1734 if (s.waitingVisible && nowVisible) {
1735 mWaitingVisibleActivities.remove(s);
1736 s.waitingVisible = false;
1737 if (s.finishing) {
1738 // If this activity is finishing, it is sitting on top of
1739 // everyone else but we now know it is no longer needed...
1740 // so get rid of it. Otherwise, we need to go through the
1741 // normal flow and hide it once we determine that it is
1742 // hidden by the activities in front of it.
1743 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
1744 mService.mWindowManager.setAppVisibility(s.appToken, false);
1745 }
1746 }
1747 if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
1748 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
1749 if (stops == null) {
1750 stops = new ArrayList<ActivityRecord>();
1751 }
1752 stops.add(s);
1753 mStoppingActivities.remove(i);
1754 N--;
1755 i--;
1756 }
1757 }
1758
1759 return stops;
1760 }
1761
Craig Mautner27084302013-03-25 08:05:25 -07001762 public void dump(PrintWriter pw, String prefix) {
1763 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
1764 pw.println(mDismissKeyguardOnNextActivity);
1765 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001766
Craig Mautner20e72272013-04-01 13:45:53 -07001767 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001768 return getTopStack().getDumpActivitiesLocked(name);
Craig Mautner20e72272013-04-01 13:45:53 -07001769 }
1770
Craig Mautner8d341ef2013-03-26 09:03:27 -07001771 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
1772 boolean dumpClient, String dumpPackage) {
1773 final int numStacks = mStacks.size();
1774 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1775 final ActivityStack stack = mStacks.get(stackNdx);
1776 pw.print(" Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
1777 stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
1778 pw.println(" ");
1779 pw.println(" Running activities (most recent first):");
1780 dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false,
1781 dumpPackage);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001782 if (stack.mGoingToSleepActivities.size() > 0) {
1783 pw.println(" ");
1784 pw.println(" Activities waiting to sleep:");
1785 dumpHistoryList(fd, pw, stack.mGoingToSleepActivities, " ", "Sleep", false,
1786 !dumpAll, false, dumpPackage);
1787 }
1788 if (stack.mFinishingActivities.size() > 0) {
1789 pw.println(" ");
1790 pw.println(" Activities waiting to finish:");
1791 dumpHistoryList(fd, pw, stack.mFinishingActivities, " ", "Fin", false,
1792 !dumpAll, false, dumpPackage);
1793 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001794
Craig Mautner8d341ef2013-03-26 09:03:27 -07001795 pw.print(" Stack #"); pw.println(mStacks.indexOf(stack));
1796 if (stack.mPausingActivity != null) {
1797 pw.println(" mPausingActivity: " + stack.mPausingActivity);
1798 }
1799 pw.println(" mResumedActivity: " + stack.mResumedActivity);
1800 if (dumpAll) {
1801 pw.println(" mLastPausedActivity: " + stack.mLastPausedActivity);
1802 pw.println(" mSleepTimeout: " + stack.mSleepTimeout);
1803 }
1804 }
1805
Craig Mautnerde4ef022013-04-07 19:01:33 -07001806 if (mStoppingActivities.size() > 0) {
1807 pw.println(" ");
1808 pw.println(" Activities waiting to stop:");
1809 dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, false,
1810 dumpPackage);
1811 }
1812
1813 if (mWaitingVisibleActivities.size() > 0) {
1814 pw.println(" ");
1815 pw.println(" Activities waiting for another to become visible:");
1816 dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
1817 false, dumpPackage);
1818 }
1819
Craig Mautner8d341ef2013-03-26 09:03:27 -07001820 if (dumpAll) {
1821 pw.println(" ");
1822 pw.println(" mCurTaskId: " + mCurTaskId);
1823 }
1824 return true;
1825 }
1826
1827 static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
1828 String prefix, String label, boolean complete, boolean brief, boolean client,
1829 String dumpPackage) {
1830 TaskRecord lastTask = null;
1831 boolean needNL = false;
1832 final String innerPrefix = prefix + " ";
1833 final String[] args = new String[0];
1834 for (int i=list.size()-1; i>=0; i--) {
1835 final ActivityRecord r = list.get(i);
1836 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
1837 continue;
1838 }
1839 final boolean full = !brief && (complete || !r.isInHistory());
1840 if (needNL) {
1841 pw.println(" ");
1842 needNL = false;
1843 }
1844 if (lastTask != r.task) {
1845 lastTask = r.task;
1846 pw.print(prefix);
1847 pw.print(full ? "* " : " ");
1848 pw.println(lastTask);
1849 if (full) {
1850 lastTask.dump(pw, prefix + " ");
1851 } else if (complete) {
1852 // Complete + brief == give a summary. Isn't that obvious?!?
1853 if (lastTask.intent != null) {
1854 pw.print(prefix); pw.print(" ");
1855 pw.println(lastTask.intent.toInsecureStringWithClip());
1856 }
1857 }
1858 }
1859 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
1860 pw.print(" #"); pw.print(i); pw.print(": ");
1861 pw.println(r);
1862 if (full) {
1863 r.dump(pw, innerPrefix);
1864 } else if (complete) {
1865 // Complete + brief == give a summary. Isn't that obvious?!?
1866 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
1867 if (r.app != null) {
1868 pw.print(innerPrefix); pw.println(r.app);
1869 }
1870 }
1871 if (client && r.app != null && r.app.thread != null) {
1872 // flush anything that is already in the PrintWriter since the thread is going
1873 // to write to the file descriptor directly
1874 pw.flush();
1875 try {
1876 TransferPipe tp = new TransferPipe();
1877 try {
1878 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
1879 r.appToken, innerPrefix, args);
1880 // Short timeout, since blocking here can
1881 // deadlock with the application.
1882 tp.go(fd, 2000);
1883 } finally {
1884 tp.kill();
1885 }
1886 } catch (IOException e) {
1887 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
1888 } catch (RemoteException e) {
1889 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
1890 }
1891 needNL = true;
1892 }
1893 }
1894 }
Craig Mautner27084302013-03-25 08:05:25 -07001895}