blob: b5e952e74b5037743cbf16c9e9183e745c90d05f [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() {
150 switch (mStackState) {
151 case STACK_STATE_HOME_IN_FRONT:
152 case STACK_STATE_HOME_TO_FRONT:
153 return mHomeStack;
154 case STACK_STATE_HOME_IN_BACK:
155 case STACK_STATE_HOME_TO_BACK:
156 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700157 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700158 }
Craig Mautner20e72272013-04-01 13:45:53 -0700159 }
160
Craig Mautnerde4ef022013-04-07 19:01:33 -0700161 ActivityStack getLastStack() {
162 switch (mStackState) {
163 case STACK_STATE_HOME_IN_FRONT:
164 case STACK_STATE_HOME_TO_BACK:
165 return mHomeStack;
166 case STACK_STATE_HOME_TO_FRONT:
167 case STACK_STATE_HOME_IN_BACK:
168 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700169 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700170 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700171 }
172
Craig Mautnerde4ef022013-04-07 19:01:33 -0700173 boolean isFrontStack(ActivityStack stack) {
Craig Mautner967212c2013-04-13 21:10:58 -0700174 return !(stack.isHomeStack() ^ getTopStack().isHomeStack());
Craig Mautner20e72272013-04-01 13:45:53 -0700175 }
176
Craig Mautnerde4ef022013-04-07 19:01:33 -0700177 boolean homeIsInFront() {
178 return isFrontStack(mHomeStack);
179 }
180
181 void moveHomeStack(boolean toFront) {
182 final boolean homeInFront = isFrontStack(mHomeStack);
183 if (homeInFront ^ toFront) {
184 mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
185 }
186 }
187
Craig Mautner69ada552013-04-18 13:51:51 -0700188 boolean resumeHomeActivity(ActivityRecord prev) {
189 moveHomeStack(true);
190 if (prev != null) {
191 prev.mLaunchHomeTaskNext = false;
192 }
193 if (mHomeStack.topRunningActivityLocked(null) != null) {
194 return mHomeStack.resumeTopActivityLocked(prev);
195 }
196 return mService.startHomeActivityLocked(mCurrentUser);
197 }
198
Craig Mautnerde4ef022013-04-07 19:01:33 -0700199 final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r,
200 ActivityStack stack) {
201 if (stack == mHomeStack) {
202 return;
203 }
204 if ((sourceRecord == null && getLastStack() == mHomeStack) ||
205 (sourceRecord != null && sourceRecord.isHomeActivity)) {
206 if (r == null) {
207 r = stack.topRunningActivityLocked(null);
208 }
209 if (r != null && !r.isHomeActivity && r.isRootActivity()) {
210 r.mLaunchHomeTaskNext = true;
211 }
212 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700213 }
214
Craig Mautner27084302013-03-25 08:05:25 -0700215 void setDismissKeyguard(boolean dismiss) {
216 mDismissKeyguardOnNextActivity = dismiss;
217 }
218
Craig Mautner8d341ef2013-03-26 09:03:27 -0700219 TaskRecord anyTaskForIdLocked(int id) {
220 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
221 ActivityStack stack = mStacks.get(stackNdx);
222 TaskRecord task = stack.taskForIdLocked(id);
223 if (task != null) {
224 return task;
225 }
226 }
227 return null;
228 }
229
Craig Mautner6170f732013-04-02 13:05:23 -0700230 ActivityRecord isInAnyStackLocked(IBinder token) {
231 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
232 final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
233 if (r != null) {
234 return r;
235 }
236 }
237 return null;
238 }
239
Craig Mautner8d341ef2013-03-26 09:03:27 -0700240 int getNextTaskId() {
241 do {
242 mCurTaskId++;
243 if (mCurTaskId <= 0) {
244 mCurTaskId = 1;
245 }
246 } while (anyTaskForIdLocked(mCurTaskId) != null);
247 return mCurTaskId;
248 }
249
Craig Mautnerde4ef022013-04-07 19:01:33 -0700250 void removeTask(TaskRecord task) {
251 final ActivityStack stack = task.stack;
252 if (stack.removeTask(task) && !stack.isHomeStack()) {
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700253 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700254 mStacks.remove(stack);
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700255 final int stackId = stack.mStackId;
256 final int nextStackId = mService.mWindowManager.removeStack(stackId);
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700257 // TODO: Perhaps we need to let the ActivityManager determine the next focus...
Craig Mautner29219d92013-04-16 20:19:12 -0700258 if (mFocusedStack.mStackId == stackId) {
259 mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700260 }
261 }
262 }
263
264 ActivityRecord resumedAppLocked() {
265 ActivityStack stack = getTopStack();
266 ActivityRecord resumedActivity = stack.mResumedActivity;
267 if (resumedActivity == null || resumedActivity.app == null) {
268 resumedActivity = stack.mPausingActivity;
269 if (resumedActivity == null || resumedActivity.app == null) {
270 resumedActivity = stack.topRunningActivityLocked(null);
271 }
272 }
273 return resumedActivity;
274 }
275
Craig Mautner20e72272013-04-01 13:45:53 -0700276 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
277 boolean didSomething = false;
278 final String processName = app.processName;
279 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
280 final ActivityStack stack = mStacks.get(stackNdx);
281 ActivityRecord hr = stack.topRunningActivityLocked(null);
282 if (hr != null) {
283 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
284 && processName.equals(hr.processName)) {
285 try {
286 if (headless) {
287 Slog.e(TAG, "Starting activities not supported on headless device: "
288 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700289 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700290 didSomething = true;
291 }
292 } catch (Exception e) {
293 Slog.w(TAG, "Exception in new application when starting activity "
294 + hr.intent.getComponent().flattenToShortString(), e);
295 throw e;
296 }
297 } else {
298 stack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
299 }
300 }
301 }
302 return didSomething;
303 }
304
305 boolean allResumedActivitiesIdle() {
306 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700307 final ActivityRecord resumedActivity = mStacks.get(stackNdx).mResumedActivity;
308 if (resumedActivity == null || !resumedActivity.idle) {
Craig Mautner20e72272013-04-01 13:45:53 -0700309 return false;
310 }
311 }
312 return true;
313 }
314
Craig Mautnerde4ef022013-04-07 19:01:33 -0700315 boolean allResumedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700316 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
317 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner967212c2013-04-13 21:10:58 -0700318 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700319 final ActivityRecord r = stack.mResumedActivity;
320 if (r != null && r.state != ActivityState.RESUMED) {
321 return false;
322 }
323 }
324 }
325 // TODO: Not sure if this should check if all Paused are complete too.
326 switch (mStackState) {
327 case STACK_STATE_HOME_TO_BACK:
328 mStackState = STACK_STATE_HOME_IN_BACK;
329 break;
330 case STACK_STATE_HOME_TO_FRONT:
331 mStackState = STACK_STATE_HOME_IN_FRONT;
332 break;
333 }
334 return true;
335 }
336
337 boolean allResumedActivitiesVisible() {
338 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
339 final ActivityStack stack = mStacks.get(stackNdx);
340 final ActivityRecord r = stack.mResumedActivity;
341 if (r != null && (!r.nowVisible || r.waitingVisible)) {
342 return false;
343 }
344 }
345 return true;
346 }
347
348 boolean allPausedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700349 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
350 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner69ada552013-04-18 13:51:51 -0700351 final ActivityRecord r = stack.mPausingActivity;
352 if (r != null && r.state != ActivityState.PAUSED
353 && r.state != ActivityState.STOPPED
354 && r.state != ActivityState.STOPPING) {
355 return false;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700356 }
357 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700358 return true;
359 }
360
Craig Mautner29219d92013-04-16 20:19:12 -0700361 ActivityRecord topRunningActivityLocked() {
362 ActivityRecord r = null;
363 if (mFocusedStack != null) {
364 r = mFocusedStack.topRunningActivityLocked(null);
365 if (r != null) {
366 return r;
367 }
368 }
369 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
370 final ActivityStack stack = mStacks.get(stackNdx);
371 if (stack != mFocusedStack && isFrontStack(stack)) {
372 r = stack.topRunningActivityLocked(null);
373 if (r != null) {
374 return r;
375 }
376 }
377 }
378 return null;
379 }
380
381 void resumeTopActivitiesLocked() {
382 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
383 final ActivityStack stack = mStacks.get(stackNdx);
384 if (isFrontStack(stack)) {
385 stack.resumeTopActivityLocked(null);
386 }
387 }
388 }
389
Craig Mautner20e72272013-04-01 13:45:53 -0700390 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
391 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
392 ActivityRecord r = null;
393 final int numStacks = mStacks.size();
394 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
395 final ActivityStack stack = mStacks.get(stackNdx);
396 final ActivityRecord ar =
397 stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700398 if (isFrontStack(stack)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700399 r = ar;
400 }
401 }
402 return r;
403 }
404
Craig Mautner23ac33b2013-04-01 16:26:35 -0700405 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
406 String profileFile, ParcelFileDescriptor profileFd, int userId) {
407 // Collect information about the target of the Intent.
408 ActivityInfo aInfo;
409 try {
410 ResolveInfo rInfo =
411 AppGlobals.getPackageManager().resolveIntent(
412 intent, resolvedType,
413 PackageManager.MATCH_DEFAULT_ONLY
414 | ActivityManagerService.STOCK_PM_FLAGS, userId);
415 aInfo = rInfo != null ? rInfo.activityInfo : null;
416 } catch (RemoteException e) {
417 aInfo = null;
418 }
419
420 if (aInfo != null) {
421 // Store the found target back into the intent, because now that
422 // we have it we never want to do this again. For example, if the
423 // user navigates back to this point in the history, we should
424 // always restart the exact same activity.
425 intent.setComponent(new ComponentName(
426 aInfo.applicationInfo.packageName, aInfo.name));
427
428 // Don't debug things in the system process
429 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
430 if (!aInfo.processName.equals("system")) {
431 mService.setDebugApp(aInfo.processName, true, false);
432 }
433 }
434
435 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
436 if (!aInfo.processName.equals("system")) {
437 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
438 }
439 }
440
441 if (profileFile != null) {
442 if (!aInfo.processName.equals("system")) {
443 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
444 profileFile, profileFd,
445 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
446 }
447 }
448 }
449 return aInfo;
450 }
451
Craig Mautner2219a1b2013-03-25 09:44:30 -0700452 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700453 moveHomeStack(true);
Craig Mautner6170f732013-04-02 13:05:23 -0700454 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
Craig Mautner2219a1b2013-03-25 09:44:30 -0700455 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700456 }
457
Craig Mautner23ac33b2013-04-01 16:26:35 -0700458 final int startActivityMayWait(IApplicationThread caller, int callingUid,
459 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
460 String resultWho, int requestCode, int startFlags, String profileFile,
461 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
462 Bundle options, int userId) {
463 // Refuse possible leaked file descriptors
464 if (intent != null && intent.hasFileDescriptors()) {
465 throw new IllegalArgumentException("File descriptors passed in Intent");
466 }
467 boolean componentSpecified = intent.getComponent() != null;
468
469 // Don't modify the client's object!
470 intent = new Intent(intent);
471
472 // Collect information about the target of the Intent.
473 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
474 profileFile, profileFd, userId);
475
476 synchronized (mService) {
477 int callingPid;
478 if (callingUid >= 0) {
479 callingPid = -1;
480 } else if (caller == null) {
481 callingPid = Binder.getCallingPid();
482 callingUid = Binder.getCallingUid();
483 } else {
484 callingPid = callingUid = -1;
485 }
486
Craig Mautnerde4ef022013-04-07 19:01:33 -0700487 final ActivityStack stack = getTopStack();
488 stack.mConfigWillChange = config != null
Craig Mautner23ac33b2013-04-01 16:26:35 -0700489 && mService.mConfiguration.diff(config) != 0;
490 if (DEBUG_CONFIGURATION) Slog.v(TAG,
Craig Mautnerde4ef022013-04-07 19:01:33 -0700491 "Starting activity when config will change = " + stack.mConfigWillChange);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700492
493 final long origId = Binder.clearCallingIdentity();
494
495 if (aInfo != null &&
496 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
497 // This may be a heavy-weight process! Check to see if we already
498 // have another, different heavy-weight process running.
499 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
500 if (mService.mHeavyWeightProcess != null &&
501 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
502 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
503 int realCallingPid = callingPid;
504 int realCallingUid = callingUid;
505 if (caller != null) {
506 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
507 if (callerApp != null) {
508 realCallingPid = callerApp.pid;
509 realCallingUid = callerApp.info.uid;
510 } else {
511 Slog.w(TAG, "Unable to find app for caller " + caller
512 + " (pid=" + realCallingPid + ") when starting: "
513 + intent.toString());
514 ActivityOptions.abort(options);
515 return ActivityManager.START_PERMISSION_DENIED;
516 }
517 }
518
519 IIntentSender target = mService.getIntentSenderLocked(
520 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
521 realCallingUid, userId, null, null, 0, new Intent[] { intent },
522 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
523 | PendingIntent.FLAG_ONE_SHOT, null);
524
525 Intent newIntent = new Intent();
526 if (requestCode >= 0) {
527 // Caller is requesting a result.
528 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
529 }
530 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
531 new IntentSender(target));
532 if (mService.mHeavyWeightProcess.activities.size() > 0) {
533 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
534 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
535 hist.packageName);
536 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
537 hist.task.taskId);
538 }
539 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
540 aInfo.packageName);
541 newIntent.setFlags(intent.getFlags());
542 newIntent.setClassName("android",
543 HeavyWeightSwitcherActivity.class.getName());
544 intent = newIntent;
545 resolvedType = null;
546 caller = null;
547 callingUid = Binder.getCallingUid();
548 callingPid = Binder.getCallingPid();
549 componentSpecified = true;
550 try {
551 ResolveInfo rInfo =
552 AppGlobals.getPackageManager().resolveIntent(
553 intent, null,
554 PackageManager.MATCH_DEFAULT_ONLY
555 | ActivityManagerService.STOCK_PM_FLAGS, userId);
556 aInfo = rInfo != null ? rInfo.activityInfo : null;
557 aInfo = mService.getActivityInfoForUser(aInfo, userId);
558 } catch (RemoteException e) {
559 aInfo = null;
560 }
561 }
562 }
563 }
564
Craig Mautner6170f732013-04-02 13:05:23 -0700565 int res = startActivityLocked(caller, intent, resolvedType,
Craig Mautner23ac33b2013-04-01 16:26:35 -0700566 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
567 callingPackage, startFlags, options, componentSpecified, null);
568
Craig Mautnerde4ef022013-04-07 19:01:33 -0700569 if (stack.mConfigWillChange) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700570 // If the caller also wants to switch to a new configuration,
571 // do so now. This allows a clean switch, as we are waiting
572 // for the current activity to pause (so we will not destroy
573 // it), and have not yet started the next activity.
574 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
575 "updateConfiguration()");
Craig Mautnerde4ef022013-04-07 19:01:33 -0700576 stack.mConfigWillChange = false;
Craig Mautner23ac33b2013-04-01 16:26:35 -0700577 if (DEBUG_CONFIGURATION) Slog.v(TAG,
578 "Updating to new configuration after starting activity.");
579 mService.updateConfigurationLocked(config, null, false, false);
580 }
581
582 Binder.restoreCallingIdentity(origId);
583
584 if (outResult != null) {
585 outResult.result = res;
586 if (res == ActivityManager.START_SUCCESS) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700587 stack.mWaitingActivityLaunched.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700588 do {
589 try {
590 mService.wait();
591 } catch (InterruptedException e) {
592 }
593 } while (!outResult.timeout && outResult.who == null);
594 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700595 ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700596 if (r.nowVisible) {
597 outResult.timeout = false;
598 outResult.who = new ComponentName(r.info.packageName, r.info.name);
599 outResult.totalTime = 0;
600 outResult.thisTime = 0;
601 } else {
602 outResult.thisTime = SystemClock.uptimeMillis();
Craig Mautnerde4ef022013-04-07 19:01:33 -0700603 stack.mWaitingActivityVisible.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700604 do {
605 try {
606 mService.wait();
607 } catch (InterruptedException e) {
608 }
609 } while (!outResult.timeout && outResult.who == null);
610 }
611 }
612 }
613
614 return res;
615 }
616 }
617
618 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
619 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
620 Bundle options, int userId) {
621 if (intents == null) {
622 throw new NullPointerException("intents is null");
623 }
624 if (resolvedTypes == null) {
625 throw new NullPointerException("resolvedTypes is null");
626 }
627 if (intents.length != resolvedTypes.length) {
628 throw new IllegalArgumentException("intents are length different than resolvedTypes");
629 }
630
631 ActivityRecord[] outActivity = new ActivityRecord[1];
632
633 int callingPid;
634 if (callingUid >= 0) {
635 callingPid = -1;
636 } else if (caller == null) {
637 callingPid = Binder.getCallingPid();
638 callingUid = Binder.getCallingUid();
639 } else {
640 callingPid = callingUid = -1;
641 }
642 final long origId = Binder.clearCallingIdentity();
643 try {
644 synchronized (mService) {
645
646 for (int i=0; i<intents.length; i++) {
647 Intent intent = intents[i];
648 if (intent == null) {
649 continue;
650 }
651
652 // Refuse possible leaked file descriptors
653 if (intent != null && intent.hasFileDescriptors()) {
654 throw new IllegalArgumentException("File descriptors passed in Intent");
655 }
656
657 boolean componentSpecified = intent.getComponent() != null;
658
659 // Don't modify the client's object!
660 intent = new Intent(intent);
661
662 // Collect information about the target of the Intent.
663 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
664 0, null, null, userId);
665 // TODO: New, check if this is correct
666 aInfo = mService.getActivityInfoForUser(aInfo, userId);
667
668 if (aInfo != null &&
669 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
670 != 0) {
671 throw new IllegalArgumentException(
672 "FLAG_CANT_SAVE_STATE not supported here");
673 }
674
675 Bundle theseOptions;
676 if (options != null && i == intents.length-1) {
677 theseOptions = options;
678 } else {
679 theseOptions = null;
680 }
Craig Mautner6170f732013-04-02 13:05:23 -0700681 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Craig Mautner23ac33b2013-04-01 16:26:35 -0700682 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
683 0, theseOptions, componentSpecified, outActivity);
684 if (res < 0) {
685 return res;
686 }
687
688 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
689 }
690 }
691 } finally {
692 Binder.restoreCallingIdentity(origId);
693 }
694
695 return ActivityManager.START_SUCCESS;
696 }
697
Craig Mautner2420ead2013-04-01 17:13:20 -0700698 final boolean realStartActivityLocked(ActivityRecord r,
699 ProcessRecord app, boolean andResume, boolean checkConfig)
700 throws RemoteException {
701
702 r.startFreezingScreenLocked(app, 0);
703 mService.mWindowManager.setAppVisibility(r.appToken, true);
704
705 // schedule launch ticks to collect information about slow apps.
706 r.startLaunchTickingLocked();
707
708 // Have the window manager re-evaluate the orientation of
709 // the screen based on the new activity order. Note that
710 // as a result of this, it can call back into the activity
711 // manager with a new orientation. We don't care about that,
712 // because the activity is not currently running so we are
713 // just restarting it anyway.
714 if (checkConfig) {
715 Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
716 mService.mConfiguration,
717 r.mayFreezeScreenLocked(app) ? r.appToken : null);
718 mService.updateConfigurationLocked(config, r, false, false);
719 }
720
721 r.app = app;
722 app.waitingToKill = null;
723 r.launchCount++;
724 r.lastLaunchTime = SystemClock.uptimeMillis();
725
726 if (localLOGV) Slog.v(TAG, "Launching: " + r);
727
728 int idx = app.activities.indexOf(r);
729 if (idx < 0) {
730 app.activities.add(r);
731 }
732 mService.updateLruProcessLocked(app, true);
733
734 final ActivityStack stack = r.task.stack;
735 try {
736 if (app.thread == null) {
737 throw new RemoteException();
738 }
739 List<ResultInfo> results = null;
740 List<Intent> newIntents = null;
741 if (andResume) {
742 results = r.results;
743 newIntents = r.newIntents;
744 }
745 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
746 + " icicle=" + r.icicle
747 + " with results=" + results + " newIntents=" + newIntents
748 + " andResume=" + andResume);
749 if (andResume) {
750 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
751 r.userId, System.identityHashCode(r),
752 r.task.taskId, r.shortComponentName);
753 }
754 if (r.isHomeActivity) {
755 mService.mHomeProcess = app;
756 }
757 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
758 r.sleeping = false;
759 r.forceNewConfig = false;
760 mService.showAskCompatModeDialogLocked(r);
761 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
762 String profileFile = null;
763 ParcelFileDescriptor profileFd = null;
764 boolean profileAutoStop = false;
765 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
766 if (mService.mProfileProc == null || mService.mProfileProc == app) {
767 mService.mProfileProc = app;
768 profileFile = mService.mProfileFile;
769 profileFd = mService.mProfileFd;
770 profileAutoStop = mService.mAutoStopProfiler;
771 }
772 }
773 app.hasShownUi = true;
774 app.pendingUiClean = true;
775 if (profileFd != null) {
776 try {
777 profileFd = profileFd.dup();
778 } catch (IOException e) {
779 if (profileFd != null) {
780 try {
781 profileFd.close();
782 } catch (IOException o) {
783 }
784 profileFd = null;
785 }
786 }
787 }
788 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
789 System.identityHashCode(r), r.info,
790 new Configuration(mService.mConfiguration),
791 r.compat, r.icicle, results, newIntents, !andResume,
792 mService.isNextTransitionForward(), profileFile, profileFd,
793 profileAutoStop);
794
795 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
796 // This may be a heavy-weight process! Note that the package
797 // manager will ensure that only activity can run in the main
798 // process of the .apk, which is the only thing that will be
799 // considered heavy-weight.
800 if (app.processName.equals(app.info.packageName)) {
801 if (mService.mHeavyWeightProcess != null
802 && mService.mHeavyWeightProcess != app) {
803 Slog.w(TAG, "Starting new heavy weight process " + app
804 + " when already running "
805 + mService.mHeavyWeightProcess);
806 }
807 mService.mHeavyWeightProcess = app;
808 Message msg = mService.mHandler.obtainMessage(
809 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
810 msg.obj = r;
811 mService.mHandler.sendMessage(msg);
812 }
813 }
814
815 } catch (RemoteException e) {
816 if (r.launchFailed) {
817 // This is the second time we failed -- finish activity
818 // and give up.
819 Slog.e(TAG, "Second failure launching "
820 + r.intent.getComponent().flattenToShortString()
821 + ", giving up", e);
822 mService.appDiedLocked(app, app.pid, app.thread);
823 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
824 "2nd-crash", false);
825 return false;
826 }
827
828 // This is the first time we failed -- restart process and
829 // retry.
830 app.activities.remove(r);
831 throw e;
832 }
833
834 r.launchFailed = false;
835 if (stack.updateLRUListLocked(r)) {
836 Slog.w(TAG, "Activity " + r
837 + " being launched, but already in LRU list");
838 }
839
840 if (andResume) {
841 // As part of the process of launching, ActivityThread also performs
842 // a resume.
843 stack.minimalResumeActivityLocked(r);
844 } else {
845 // This activity is not starting in the resumed state... which
846 // should look like we asked it to pause+stop (but remain visible),
847 // and it has done so and reported back the current icicle and
848 // other state.
849 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
850 + " (starting in stopped state)");
851 r.state = ActivityState.STOPPED;
852 r.stopped = true;
853 }
854
855 // Launch the new version setup screen if needed. We do this -after-
856 // launching the initial activity (that is, home), so that it can have
857 // a chance to initialize itself while in the background, making the
858 // switch back to it faster and look better.
Craig Mautnerde4ef022013-04-07 19:01:33 -0700859 if (isFrontStack(stack)) {
Craig Mautner2420ead2013-04-01 17:13:20 -0700860 mService.startSetupActivityLocked();
861 }
862
863 return true;
864 }
865
Craig Mautnere79d42682013-04-01 19:01:53 -0700866 void startSpecificActivityLocked(ActivityRecord r,
867 boolean andResume, boolean checkConfig) {
868 // Is this activity's application already running?
869 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
870 r.info.applicationInfo.uid);
871
872 r.task.stack.setLaunchTime(r);
873
874 if (app != null && app.thread != null) {
875 try {
876 app.addPackage(r.info.packageName);
877 realStartActivityLocked(r, app, andResume, checkConfig);
878 return;
879 } catch (RemoteException e) {
880 Slog.w(TAG, "Exception when starting activity "
881 + r.intent.getComponent().flattenToShortString(), e);
882 }
883
884 // If a dead object exception was thrown -- fall through to
885 // restart the application.
886 }
887
888 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
889 "activity", r.intent.getComponent(), false, false);
890 }
891
Craig Mautner6170f732013-04-02 13:05:23 -0700892 final int startActivityLocked(IApplicationThread caller,
893 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
894 String resultWho, int requestCode,
895 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
896 boolean componentSpecified, ActivityRecord[] outActivity) {
897 int err = ActivityManager.START_SUCCESS;
898
899 ProcessRecord callerApp = null;
900 if (caller != null) {
901 callerApp = mService.getRecordForAppLocked(caller);
902 if (callerApp != null) {
903 callingPid = callerApp.pid;
904 callingUid = callerApp.info.uid;
905 } else {
906 Slog.w(TAG, "Unable to find app for caller " + caller
907 + " (pid=" + callingPid + ") when starting: "
908 + intent.toString());
909 err = ActivityManager.START_PERMISSION_DENIED;
910 }
911 }
912
913 if (err == ActivityManager.START_SUCCESS) {
914 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
915 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
916 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
917 }
918
919 ActivityRecord sourceRecord = null;
920 ActivityRecord resultRecord = null;
921 if (resultTo != null) {
922 sourceRecord = isInAnyStackLocked(resultTo);
923 if (DEBUG_RESULTS) Slog.v(
924 TAG, "Will send result to " + resultTo + " " + sourceRecord);
925 if (sourceRecord != null) {
926 if (requestCode >= 0 && !sourceRecord.finishing) {
927 resultRecord = sourceRecord;
928 }
929 }
930 }
931 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
932
933 int launchFlags = intent.getFlags();
934
935 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
936 && sourceRecord != null) {
937 // Transfer the result target from the source activity to the new
938 // one being started, including any failures.
939 if (requestCode >= 0) {
940 ActivityOptions.abort(options);
941 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
942 }
943 resultRecord = sourceRecord.resultTo;
944 resultWho = sourceRecord.resultWho;
945 requestCode = sourceRecord.requestCode;
946 sourceRecord.resultTo = null;
947 if (resultRecord != null) {
948 resultRecord.removeResultsLocked(
949 sourceRecord, resultWho, requestCode);
950 }
951 }
952
953 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
954 // We couldn't find a class that can handle the given Intent.
955 // That's the end of that!
956 err = ActivityManager.START_INTENT_NOT_RESOLVED;
957 }
958
959 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
960 // We couldn't find the specific class specified in the Intent.
961 // Also the end of the line.
962 err = ActivityManager.START_CLASS_NOT_FOUND;
963 }
964
965 if (err != ActivityManager.START_SUCCESS) {
966 if (resultRecord != null) {
967 resultStack.sendActivityResultLocked(-1,
968 resultRecord, resultWho, requestCode,
969 Activity.RESULT_CANCELED, null);
970 }
971 setDismissKeyguard(false);
972 ActivityOptions.abort(options);
973 return err;
974 }
975
976 final int startAnyPerm = mService.checkPermission(
977 START_ANY_ACTIVITY, callingPid, callingUid);
978 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
979 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
980 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
981 if (resultRecord != null) {
982 resultStack.sendActivityResultLocked(-1,
983 resultRecord, resultWho, requestCode,
984 Activity.RESULT_CANCELED, null);
985 }
986 setDismissKeyguard(false);
987 String msg;
988 if (!aInfo.exported) {
989 msg = "Permission Denial: starting " + intent.toString()
990 + " from " + callerApp + " (pid=" + callingPid
991 + ", uid=" + callingUid + ")"
992 + " not exported from uid " + aInfo.applicationInfo.uid;
993 } else {
994 msg = "Permission Denial: starting " + intent.toString()
995 + " from " + callerApp + " (pid=" + callingPid
996 + ", uid=" + callingUid + ")"
997 + " requires " + aInfo.permission;
998 }
999 Slog.w(TAG, msg);
1000 throw new SecurityException(msg);
1001 }
1002
Ben Gruver6617c3c2013-04-03 18:45:22 -07001003 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
Ben Gruver7b879f42013-04-08 14:56:55 -07001004 callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo);
Ben Gruver5e207332013-04-03 17:41:37 -07001005
Craig Mautner6170f732013-04-02 13:05:23 -07001006 if (mService.mController != null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001007 try {
1008 // The Intent we give to the watcher has the extra data
1009 // stripped off, since it can contain private information.
1010 Intent watchIntent = intent.cloneFilter();
Ben Gruver5e207332013-04-03 17:41:37 -07001011 abort |= !mService.mController.activityStarting(watchIntent,
Craig Mautner6170f732013-04-02 13:05:23 -07001012 aInfo.applicationInfo.packageName);
1013 } catch (RemoteException e) {
1014 mService.mController = null;
1015 }
Ben Gruver5e207332013-04-03 17:41:37 -07001016 }
Craig Mautner6170f732013-04-02 13:05:23 -07001017
Ben Gruver5e207332013-04-03 17:41:37 -07001018 if (abort) {
1019 if (resultRecord != null) {
1020 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Craig Mautner6170f732013-04-02 13:05:23 -07001021 Activity.RESULT_CANCELED, null);
Craig Mautner6170f732013-04-02 13:05:23 -07001022 }
Ben Gruver5e207332013-04-03 17:41:37 -07001023 // We pretend to the caller that it was really started, but
1024 // they will just get a cancel result.
1025 setDismissKeyguard(false);
1026 ActivityOptions.abort(options);
1027 return ActivityManager.START_SUCCESS;
Craig Mautner6170f732013-04-02 13:05:23 -07001028 }
1029
1030 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1031 intent, resolvedType, aInfo, mService.mConfiguration,
Craig Mautnerde4ef022013-04-07 19:01:33 -07001032 resultRecord, resultWho, requestCode, componentSpecified, this);
Craig Mautner6170f732013-04-02 13:05:23 -07001033 if (outActivity != null) {
1034 outActivity[0] = r;
1035 }
1036
Craig Mautnerde4ef022013-04-07 19:01:33 -07001037 final ActivityStack stack = getTopStack();
1038 if (stack.mResumedActivity == null
1039 || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
Craig Mautner6170f732013-04-02 13:05:23 -07001040 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1041 PendingActivityLaunch pal =
Craig Mautnerde4ef022013-04-07 19:01:33 -07001042 new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
Craig Mautner6170f732013-04-02 13:05:23 -07001043 mService.mPendingActivityLaunches.add(pal);
1044 setDismissKeyguard(false);
1045 ActivityOptions.abort(options);
1046 return ActivityManager.START_SWITCHES_CANCELED;
1047 }
1048 }
1049
1050 if (mService.mDidAppSwitch) {
1051 // This is the second allowed switch since we stopped switches,
1052 // so now just generally allow switches. Use case: user presses
1053 // home (switches disabled, switch to home, mDidAppSwitch now true);
1054 // user taps a home icon (coming from home so allowed, we hit here
1055 // and now allow anyone to switch again).
1056 mService.mAppSwitchesAllowedTime = 0;
1057 } else {
1058 mService.mDidAppSwitch = true;
1059 }
1060
1061 mService.doPendingActivityLaunchesLocked(false);
1062
Craig Mautner8849a5e2013-04-02 16:41:03 -07001063 err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001064 if (stack.mPausingActivity == null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001065 // Someone asked to have the keyguard dismissed on the next
1066 // activity start, but we are not actually doing an activity
1067 // switch... just dismiss the keyguard now, because we
1068 // probably want to see whatever is behind it.
1069 dismissKeyguard();
1070 }
1071 return err;
1072 }
1073
Craig Mautnerde4ef022013-04-07 19:01:33 -07001074 ActivityStack getCorrectStack(ActivityRecord r) {
1075 if (!r.isHomeActivity) {
1076 if (mStacks.size() == 1) {
1077 // Time to create the first app stack.
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001078 int stackId = mService.createStack(-1, HOME_STACK_ID,
1079 StackBox.TASK_STACK_GOES_OVER, 1.0f);
Craig Mautner29219d92013-04-16 20:19:12 -07001080 mFocusedStack = getStack(stackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001081 }
Craig Mautner29219d92013-04-16 20:19:12 -07001082 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001083 }
1084 return mHomeStack;
1085 }
1086
Craig Mautner29219d92013-04-16 20:19:12 -07001087 void setFocusedStack(ActivityRecord r) {
1088 if (r == null) {
1089 return;
1090 }
1091 if (r.isHomeActivity) {
1092 if (mStackState != STACK_STATE_HOME_IN_FRONT) {
1093 mStackState = STACK_STATE_HOME_TO_FRONT;
1094 }
1095 } else {
1096 mFocusedStack = r.task.stack;
1097 if (mStackState != STACK_STATE_HOME_IN_BACK) {
1098 mStackState = STACK_STATE_HOME_TO_BACK;
1099 }
1100 }
1101 }
1102
Craig Mautner8849a5e2013-04-02 16:41:03 -07001103 final int startActivityUncheckedLocked(ActivityRecord r,
1104 ActivityRecord sourceRecord, int startFlags, boolean doResume,
1105 Bundle options) {
1106 final Intent intent = r.intent;
1107 final int callingUid = r.launchedFromUid;
1108
1109 int launchFlags = intent.getFlags();
1110
Craig Mautner8849a5e2013-04-02 16:41:03 -07001111 // We'll invoke onUserLeaving before onPause only if the launching
1112 // activity did not explicitly state that this is an automated launch.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001113 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1114 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001115
1116 // If the caller has asked not to resume at this point, we make note
1117 // of this in the record so that we can skip it when trying to find
1118 // the top running activity.
1119 if (!doResume) {
1120 r.delayedResume = true;
1121 }
1122
1123 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1124
1125 // If the onlyIfNeeded flag is set, then we can do this if the activity
1126 // being launched is the same as the one making the call... or, as
1127 // a special case, if we do not know the caller then we count the
1128 // current top activity as the caller.
1129 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1130 ActivityRecord checkedCaller = sourceRecord;
1131 if (checkedCaller == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001132 checkedCaller = getTopStack().topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001133 }
1134 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1135 // Caller is not the same as launcher, so always needed.
1136 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1137 }
1138 }
1139
1140 if (sourceRecord == null) {
1141 // This activity is not being started from another... in this
1142 // case we -always- start a new task.
1143 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Craig Mautner29219d92013-04-16 20:19:12 -07001144 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1145 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001146 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1147 }
1148 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1149 // The original activity who is starting us is running as a single
1150 // instance... this new activity it is starting must go on its
1151 // own task.
1152 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1153 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1154 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1155 // The activity being started is a single instance... it always
1156 // gets launched into its own task.
1157 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1158 }
1159
Craig Mautnerde4ef022013-04-07 19:01:33 -07001160 final ActivityStack sourceStack;
1161 final TaskRecord sourceTask;
1162 if (sourceRecord != null) {
1163 sourceTask = sourceRecord.task;
1164 sourceStack = sourceTask.stack;
1165 } else {
1166 sourceTask = null;
1167 sourceStack = null;
1168 }
1169
Craig Mautner8849a5e2013-04-02 16:41:03 -07001170 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1171 // For whatever reason this activity is being launched into a new
1172 // task... yet the caller has requested a result back. Well, that
1173 // is pretty messed up, so instead immediately send back a cancel
1174 // and let the new task continue launched as normal without a
1175 // dependency on its originator.
1176 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1177 r.resultTo.task.stack.sendActivityResultLocked(-1,
1178 r.resultTo, r.resultWho, r.requestCode,
1179 Activity.RESULT_CANCELED, null);
1180 r.resultTo = null;
1181 }
1182
1183 boolean addingToTask = false;
1184 boolean movedHome = false;
1185 TaskRecord reuseTask = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001186 ActivityStack targetStack;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001187 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1188 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1189 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1190 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1191 // If bring to front is requested, and no result is requested, and
1192 // we can find a task that was started with this same
1193 // component, then instead of launching bring that one to the front.
1194 if (r.resultTo == null) {
1195 // See if there is a task to bring to the front. If this is
1196 // a SINGLE_INSTANCE activity, there can be one and only one
1197 // instance of it in the history, and it is always in its own
1198 // unique task, so we do a special search.
1199 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
1200 ? findTaskLocked(intent, r.info)
1201 : findActivityLocked(intent, r.info);
1202 if (intentActivity != null) {
Craig Mautner29219d92013-04-16 20:19:12 -07001203 if (r.task == null) {
1204 r.task = intentActivity.task;
1205 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001206 targetStack = intentActivity.task.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001207 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001208 if (intentActivity.task.intent == null) {
1209 // This task was started because of movement of
1210 // the activity based on affinity... now that we
1211 // are actually launching it, we can assign the
1212 // base intent.
1213 intentActivity.task.setIntent(intent, r.info);
1214 }
1215 // If the target task is not in the front, then we need
1216 // to bring it to the front... except... well, with
1217 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
1218 // to have the same behavior as if a new instance was
1219 // being started, which means not bringing it to the front
1220 // if the caller is not itself in the front.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001221 ActivityRecord curTop =
1222 targetStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001223 if (curTop != null && curTop.task != intentActivity.task) {
1224 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001225 if (sourceRecord == null || sourceStack.topActivity() == sourceRecord) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001226 // We really do want to push this one into the
1227 // user's face, right now.
1228 movedHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001229 if ((launchFlags &
Craig Mautner29219d92013-04-16 20:19:12 -07001230 (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1231 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001232 // Caller wants to appear on home activity, so before starting
1233 // their own activity we will bring home to the front.
1234 r.mLaunchHomeTaskNext = true;
1235 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001236 targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1237 options = null;
1238 }
1239 }
1240 // If the caller has requested that the target task be
1241 // reset, then do so.
1242 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1243 intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1244 }
1245 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1246 // We don't need to start a new activity, and
1247 // the client said not to do anything if that
1248 // is the case, so this is it! And for paranoia, make
1249 // sure we have correctly resumed the top activity.
1250 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001251 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001252 targetStack.resumeTopActivityLocked(null, options);
1253 } else {
1254 ActivityOptions.abort(options);
1255 }
Craig Mautner29219d92013-04-16 20:19:12 -07001256 if (r.task == null) Slog.v(TAG,
1257 "startActivityUncheckedLocked: task left null",
1258 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001259 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1260 }
1261 if ((launchFlags &
1262 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1263 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1264 // The caller has requested to completely replace any
1265 // existing task with its new activity. Well that should
1266 // not be too hard...
1267 reuseTask = intentActivity.task;
1268 reuseTask.performClearTaskLocked();
1269 reuseTask.setIntent(r.intent, r.info);
1270 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1271 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1272 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1273 // In this situation we want to remove all activities
1274 // from the task up to the one being started. In most
1275 // cases this means we are resetting the task to its
1276 // initial state.
1277 ActivityRecord top =
1278 intentActivity.task.performClearTaskLocked(r, launchFlags);
1279 if (top != null) {
1280 if (top.frontOfTask) {
1281 // Activity aliases may mean we use different
1282 // intents for the top activity, so make sure
1283 // the task now has the identity of the new
1284 // intent.
1285 top.task.setIntent(r.intent, r.info);
1286 }
1287 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1288 r, top.task);
1289 top.deliverNewIntentLocked(callingUid, r.intent);
1290 } else {
1291 // A special case: we need to
1292 // start the activity because it is not currently
1293 // running, and the caller has asked to clear the
1294 // current task to have this activity at the top.
1295 addingToTask = true;
1296 // Now pretend like this activity is being started
1297 // by the top of its task, so it is put in the
1298 // right place.
1299 sourceRecord = intentActivity;
1300 }
1301 } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1302 // In this case the top activity on the task is the
1303 // same as the one being launched, so we take that
1304 // as a request to bring the task to the foreground.
1305 // If the top activity in the task is the root
1306 // activity, deliver this new intent to it if it
1307 // desires.
1308 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1309 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1310 && intentActivity.realActivity.equals(r.realActivity)) {
1311 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1312 intentActivity.task);
1313 if (intentActivity.frontOfTask) {
1314 intentActivity.task.setIntent(r.intent, r.info);
1315 }
1316 intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1317 } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1318 // In this case we are launching the root activity
1319 // of the task, but with a different intent. We
1320 // should start a new instance on top.
1321 addingToTask = true;
1322 sourceRecord = intentActivity;
1323 }
1324 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1325 // In this case an activity is being launched in to an
1326 // existing task, without resetting that task. This
1327 // is typically the situation of launching an activity
1328 // from a notification or shortcut. We want to place
1329 // the new activity on top of the current task.
1330 addingToTask = true;
1331 sourceRecord = intentActivity;
1332 } else if (!intentActivity.task.rootWasReset) {
1333 // In this case we are launching in to an existing task
1334 // that has not yet been started from its front door.
1335 // The current task has been brought to the front.
1336 // Ideally, we'd probably like to place this new task
1337 // at the bottom of its stack, but that's a little hard
1338 // to do with the current organization of the code so
1339 // for now we'll just drop it.
1340 intentActivity.task.setIntent(r.intent, r.info);
1341 }
1342 if (!addingToTask && reuseTask == null) {
1343 // We didn't do anything... but it was needed (a.k.a., client
1344 // don't use that intent!) And for paranoia, make
1345 // sure we have correctly resumed the top activity.
1346 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001347 setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1348 targetStack.resumeTopActivityLocked(null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001349 } else {
1350 ActivityOptions.abort(options);
1351 }
Craig Mautner29219d92013-04-16 20:19:12 -07001352 if (r.task == null) Slog.v(TAG,
1353 "startActivityUncheckedLocked: task left null",
1354 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001355 return ActivityManager.START_TASK_TO_FRONT;
1356 }
1357 }
1358 }
1359 }
1360
1361 //String uri = r.intent.toURI();
1362 //Intent intent2 = new Intent(uri);
1363 //Slog.i(TAG, "Given intent: " + r.intent);
1364 //Slog.i(TAG, "URI is: " + uri);
1365 //Slog.i(TAG, "To intent: " + intent2);
1366
1367 if (r.packageName != null) {
1368 // If the activity being launched is the same as the one currently
1369 // at the top, then we need to check if it should only be launched
1370 // once.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001371 ActivityStack topStack = getTopStack();
1372 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001373 if (top != null && r.resultTo == null) {
1374 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1375 if (top.app != null && top.app.thread != null) {
1376 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1377 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1378 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1379 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1380 top.task);
1381 // For paranoia, make sure we have correctly
1382 // resumed the top activity.
1383 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001384 setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
1385 topStack.resumeTopActivityLocked(null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001386 }
1387 ActivityOptions.abort(options);
1388 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1389 // We don't need to start a new activity, and
1390 // the client said not to do anything if that
1391 // is the case, so this is it!
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_RETURN_INTENT_TO_CALLER;
1396 }
1397 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner29219d92013-04-16 20:19:12 -07001398 if (r.task == null) Slog.v(TAG,
1399 "startActivityUncheckedLocked: task left null",
1400 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001401 return ActivityManager.START_DELIVERED_TO_TOP;
1402 }
1403 }
1404 }
1405 }
1406
1407 } else {
1408 if (r.resultTo != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001409 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1410 r.requestCode, Activity.RESULT_CANCELED, null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001411 }
1412 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001413 if (r.task == null) Slog.v(TAG,
1414 "startActivityUncheckedLocked: task left null",
1415 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001416 return ActivityManager.START_CLASS_NOT_FOUND;
1417 }
1418
1419 boolean newTask = false;
1420 boolean keepCurTransition = false;
1421
1422 // Should this be considered a new task?
1423 if (r.resultTo == null && !addingToTask
1424 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001425 targetStack = getCorrectStack(r);
1426 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001427 if (reuseTask == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001428 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1429 null, true);
1430 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1431 r.task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001432 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001433 r.setTask(reuseTask, reuseTask, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001434 }
1435 newTask = true;
1436 if (!movedHome) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001437 if ((launchFlags &
1438 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1439 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1440 // Caller wants to appear on home activity, so before starting
1441 // their own activity we will bring home to the front.
1442 r.mLaunchHomeTaskNext = true;
1443 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001444 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001445 } else if (sourceRecord != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001446 targetStack = sourceRecord.task.stack;
1447 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001448 if (!addingToTask &&
1449 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1450 // In this case, we are adding the activity to an existing
1451 // task, but the caller has asked to clear that task if the
1452 // activity is already running.
1453 ActivityRecord top = sourceRecord.task.performClearTaskLocked(r, launchFlags);
1454 keepCurTransition = true;
1455 if (top != null) {
1456 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1457 top.deliverNewIntentLocked(callingUid, r.intent);
1458 // For paranoia, make sure we have correctly
1459 // resumed the top activity.
1460 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001461 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001462 targetStack.resumeTopActivityLocked(null);
1463 }
1464 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001465 if (r.task == null) Slog.v(TAG,
1466 "startActivityUncheckedLocked: task left null",
1467 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001468 return ActivityManager.START_DELIVERED_TO_TOP;
1469 }
1470 } else if (!addingToTask &&
1471 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1472 // In this case, we are launching an activity in our own task
1473 // that may already be running somewhere in the history, and
1474 // we want to shuffle it to the front of the stack if so.
1475 final ActivityRecord top =
1476 targetStack.findActivityInHistoryLocked(r, sourceRecord.task);
1477 if (top != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001478 final TaskRecord task = top.task;
1479 task.moveActivityToFrontLocked(top);
1480 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001481 top.updateOptionsLocked(options);
1482 top.deliverNewIntentLocked(callingUid, r.intent);
1483 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001484 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001485 targetStack.resumeTopActivityLocked(null);
1486 }
Craig Mautner29219d92013-04-16 20:19:12 -07001487 if (r.task == null) Slog.v(TAG,
1488 "startActivityUncheckedLocked: task left null",
1489 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001490 return ActivityManager.START_DELIVERED_TO_TOP;
1491 }
1492 }
1493 // An existing activity is starting this new activity, so we want
1494 // to keep the new one in the same task as the one that is starting
1495 // it.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001496 r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001497 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1498 + " in existing task " + r.task);
1499
1500 } else {
1501 // This not being started from an existing activity, and not part
1502 // of a new task... just put it in the top task, though these days
1503 // this case should never happen.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001504 targetStack = getLastStack();
1505 moveHomeStack(targetStack.isHomeStack());
1506 ActivityRecord prev = targetStack.topActivity();
1507 r.setTask(prev != null ? prev.task
1508 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1509 null, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001510 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1511 + " in new guessed " + r.task);
1512 }
1513
1514 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1515 intent, r.getUriPermissionsLocked());
1516
1517 if (newTask) {
1518 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1519 }
1520 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001521 setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001522 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
1523 return ActivityManager.START_SUCCESS;
1524 }
1525
Craig Mautner8d341ef2013-03-26 09:03:27 -07001526 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
1527 // Just in case.
1528 final int numStacks = mStacks.size();
1529 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Craig Mautnere79d42682013-04-01 19:01:53 -07001530 mStacks.get(stackNdx).handleAppDiedLocked(app, restarting);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001531 }
1532 }
1533
1534 void closeSystemDialogsLocked() {
1535 final int numStacks = mStacks.size();
1536 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1537 final ActivityStack stack = mStacks.get(stackNdx);
1538 stack.closeSystemDialogsLocked();
1539 }
1540 }
1541
1542 /**
1543 * @return true if some activity was finished (or would have finished if doit were true).
1544 */
1545 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1546 boolean didSomething = false;
1547 final int numStacks = mStacks.size();
1548 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1549 final ActivityStack stack = mStacks.get(stackNdx);
1550 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1551 didSomething = true;
1552 }
1553 }
1554 return didSomething;
1555 }
1556
1557 void resumeTopActivityLocked() {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -07001558 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001559 mStacks.get(stackNdx).resumeTopActivityLocked(null);
1560 }
1561 }
1562
1563 void finishTopRunningActivityLocked(ProcessRecord app) {
1564 final int numStacks = mStacks.size();
1565 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1566 final ActivityStack stack = mStacks.get(stackNdx);
1567 stack.finishTopRunningActivityLocked(app);
1568 }
1569 }
1570
1571 void scheduleIdleLocked() {
1572 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1573 mStacks.get(stackNdx).scheduleIdleLocked();
1574 }
1575 }
1576
1577 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
1578 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1579 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
1580 return;
1581 }
1582 }
1583 }
1584
Craig Mautner967212c2013-04-13 21:10:58 -07001585 ActivityStack getStack(int stackId) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001586 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1587 final ActivityStack stack = mStacks.get(stackNdx);
1588 if (stack.getStackId() == stackId) {
1589 return stack;
1590 }
1591 }
1592 return null;
1593 }
1594
Craig Mautner967212c2013-04-13 21:10:58 -07001595 ArrayList<ActivityStack> getStacks() {
1596 return new ArrayList<ActivityStack>(mStacks);
1597 }
1598
1599 int createStack() {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001600 synchronized (this) {
1601 while (true) {
1602 if (++mLastStackId <= HOME_STACK_ID) {
1603 mLastStackId = HOME_STACK_ID + 1;
1604 }
1605 if (getStack(mLastStackId) == null) {
1606 break;
1607 }
1608 }
Craig Mautner2420ead2013-04-01 17:13:20 -07001609 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId, this,
1610 mCurrentUser));
Craig Mautner8d341ef2013-03-26 09:03:27 -07001611 return mLastStackId;
1612 }
1613 }
1614
1615 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
1616 final ActivityStack stack = getStack(stackId);
1617 if (stack == null) {
1618 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
1619 return;
1620 }
1621 stack.moveTask(taskId, toTop);
Craig Mautner967212c2013-04-13 21:10:58 -07001622 stack.resumeTopActivityLocked(null);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001623 }
1624
Craig Mautner8849a5e2013-04-02 16:41:03 -07001625 ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
1626 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1627 final ActivityRecord ar = mStacks.get(stackNdx).findTaskLocked(intent, info);
1628 if (ar != null) {
1629 return ar;
1630 }
1631 }
1632 return null;
1633 }
1634
1635 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
1636 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1637 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
1638 if (ar != null) {
1639 return ar;
1640 }
1641 }
1642 return null;
1643 }
1644
Craig Mautner8d341ef2013-03-26 09:03:27 -07001645 void goingToSleepLocked() {
1646 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1647 mStacks.get(stackNdx).stopIfSleepingLocked();
1648 }
1649 }
1650
1651 boolean shutdownLocked(int timeout) {
1652 boolean timedout = false;
1653 final int numStacks = mStacks.size();
1654 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1655 final ActivityStack stack = mStacks.get(stackNdx);
1656 if (stack.mResumedActivity != null) {
1657 stack.stopIfSleepingLocked();
1658 final long endTime = System.currentTimeMillis() + timeout;
1659 while (stack.mResumedActivity != null || stack.mPausingActivity != null) {
1660 long delay = endTime - System.currentTimeMillis();
1661 if (delay <= 0) {
1662 Slog.w(TAG, "Activity manager shutdown timed out");
1663 timedout = true;
1664 break;
1665 }
1666 try {
1667 mService.wait();
1668 } catch (InterruptedException e) {
1669 }
1670 }
1671 }
1672 }
1673 return timedout;
1674 }
1675
1676 void comeOutOfSleepIfNeededLocked() {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001677 final boolean homeIsBack = !homeIsInFront();
Craig Mautner8d341ef2013-03-26 09:03:27 -07001678 final int numStacks = mStacks.size();
1679 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1680 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001681 if (stack.isHomeStack() ^ homeIsBack) {
1682 stack.awakeFromSleepingLocked();
1683 stack.resumeTopActivityLocked(null);
1684 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001685 }
1686 }
1687
1688 void handleAppCrashLocked(ProcessRecord app) {
1689 final int numStacks = mStacks.size();
1690 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1691 final ActivityStack stack = mStacks.get(stackNdx);
1692 stack.handleAppCrashLocked(app);
1693 }
1694 }
1695
Craig Mautnerde4ef022013-04-07 19:01:33 -07001696 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
1697 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1698 mStacks.get(stackNdx).ensureActivitiesVisibleLocked(starting, configChanges);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001699 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001700 }
1701
1702 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
1703 final int numStacks = mStacks.size();
1704 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1705 final ActivityStack stack = mStacks.get(stackNdx);
1706 stack.scheduleDestroyActivities(app, false, reason);
1707 }
1708 }
1709
1710 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner2420ead2013-04-01 17:13:20 -07001711 mCurrentUser = userId;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001712 boolean homeInBack = !homeIsInFront();
Craig Mautner8d341ef2013-03-26 09:03:27 -07001713 boolean haveActivities = false;
1714 final int numStacks = mStacks.size();
1715 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1716 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001717 if (stack.isHomeStack() ^ homeInBack) {
1718 haveActivities |= stack.switchUserLocked(userId, uss);
1719 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001720 }
1721 return haveActivities;
Craig Mautner2219a1b2013-03-25 09:44:30 -07001722 }
1723
Craig Mautnerde4ef022013-04-07 19:01:33 -07001724 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
1725 int N = mStoppingActivities.size();
1726 if (N <= 0) return null;
1727
1728 ArrayList<ActivityRecord> stops = null;
1729
1730 final boolean nowVisible = allResumedActivitiesVisible();
1731 for (int i=0; i<N; i++) {
1732 ActivityRecord s = mStoppingActivities.get(i);
1733 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
1734 + nowVisible + " waitingVisible=" + s.waitingVisible
1735 + " finishing=" + s.finishing);
1736 if (s.waitingVisible && nowVisible) {
1737 mWaitingVisibleActivities.remove(s);
1738 s.waitingVisible = false;
1739 if (s.finishing) {
1740 // If this activity is finishing, it is sitting on top of
1741 // everyone else but we now know it is no longer needed...
1742 // so get rid of it. Otherwise, we need to go through the
1743 // normal flow and hide it once we determine that it is
1744 // hidden by the activities in front of it.
1745 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
1746 mService.mWindowManager.setAppVisibility(s.appToken, false);
1747 }
1748 }
1749 if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
1750 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
1751 if (stops == null) {
1752 stops = new ArrayList<ActivityRecord>();
1753 }
1754 stops.add(s);
1755 mStoppingActivities.remove(i);
1756 N--;
1757 i--;
1758 }
1759 }
1760
1761 return stops;
1762 }
1763
Craig Mautner27084302013-03-25 08:05:25 -07001764 public void dump(PrintWriter pw, String prefix) {
1765 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
1766 pw.println(mDismissKeyguardOnNextActivity);
1767 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001768
Craig Mautner20e72272013-04-01 13:45:53 -07001769 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001770 return getTopStack().getDumpActivitiesLocked(name);
Craig Mautner20e72272013-04-01 13:45:53 -07001771 }
1772
Craig Mautner8d341ef2013-03-26 09:03:27 -07001773 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
1774 boolean dumpClient, String dumpPackage) {
1775 final int numStacks = mStacks.size();
1776 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1777 final ActivityStack stack = mStacks.get(stackNdx);
1778 pw.print(" Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
1779 stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
1780 pw.println(" ");
1781 pw.println(" Running activities (most recent first):");
1782 dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false,
1783 dumpPackage);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001784 if (stack.mGoingToSleepActivities.size() > 0) {
1785 pw.println(" ");
1786 pw.println(" Activities waiting to sleep:");
1787 dumpHistoryList(fd, pw, stack.mGoingToSleepActivities, " ", "Sleep", false,
1788 !dumpAll, false, dumpPackage);
1789 }
1790 if (stack.mFinishingActivities.size() > 0) {
1791 pw.println(" ");
1792 pw.println(" Activities waiting to finish:");
1793 dumpHistoryList(fd, pw, stack.mFinishingActivities, " ", "Fin", false,
1794 !dumpAll, false, dumpPackage);
1795 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001796
Craig Mautner8d341ef2013-03-26 09:03:27 -07001797 pw.print(" Stack #"); pw.println(mStacks.indexOf(stack));
1798 if (stack.mPausingActivity != null) {
1799 pw.println(" mPausingActivity: " + stack.mPausingActivity);
1800 }
1801 pw.println(" mResumedActivity: " + stack.mResumedActivity);
1802 if (dumpAll) {
1803 pw.println(" mLastPausedActivity: " + stack.mLastPausedActivity);
1804 pw.println(" mSleepTimeout: " + stack.mSleepTimeout);
1805 }
1806 }
1807
Craig Mautnerde4ef022013-04-07 19:01:33 -07001808 if (mStoppingActivities.size() > 0) {
1809 pw.println(" ");
1810 pw.println(" Activities waiting to stop:");
1811 dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, false,
1812 dumpPackage);
1813 }
1814
1815 if (mWaitingVisibleActivities.size() > 0) {
1816 pw.println(" ");
1817 pw.println(" Activities waiting for another to become visible:");
1818 dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
1819 false, dumpPackage);
1820 }
1821
Craig Mautner8d341ef2013-03-26 09:03:27 -07001822 if (dumpAll) {
1823 pw.println(" ");
1824 pw.println(" mCurTaskId: " + mCurTaskId);
1825 }
1826 return true;
1827 }
1828
1829 static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
1830 String prefix, String label, boolean complete, boolean brief, boolean client,
1831 String dumpPackage) {
1832 TaskRecord lastTask = null;
1833 boolean needNL = false;
1834 final String innerPrefix = prefix + " ";
1835 final String[] args = new String[0];
1836 for (int i=list.size()-1; i>=0; i--) {
1837 final ActivityRecord r = list.get(i);
1838 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
1839 continue;
1840 }
1841 final boolean full = !brief && (complete || !r.isInHistory());
1842 if (needNL) {
1843 pw.println(" ");
1844 needNL = false;
1845 }
1846 if (lastTask != r.task) {
1847 lastTask = r.task;
1848 pw.print(prefix);
1849 pw.print(full ? "* " : " ");
1850 pw.println(lastTask);
1851 if (full) {
1852 lastTask.dump(pw, prefix + " ");
1853 } else if (complete) {
1854 // Complete + brief == give a summary. Isn't that obvious?!?
1855 if (lastTask.intent != null) {
1856 pw.print(prefix); pw.print(" ");
1857 pw.println(lastTask.intent.toInsecureStringWithClip());
1858 }
1859 }
1860 }
1861 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
1862 pw.print(" #"); pw.print(i); pw.print(": ");
1863 pw.println(r);
1864 if (full) {
1865 r.dump(pw, innerPrefix);
1866 } else if (complete) {
1867 // Complete + brief == give a summary. Isn't that obvious?!?
1868 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
1869 if (r.app != null) {
1870 pw.print(innerPrefix); pw.println(r.app);
1871 }
1872 }
1873 if (client && r.app != null && r.app.thread != null) {
1874 // flush anything that is already in the PrintWriter since the thread is going
1875 // to write to the file descriptor directly
1876 pw.flush();
1877 try {
1878 TransferPipe tp = new TransferPipe();
1879 try {
1880 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
1881 r.appToken, innerPrefix, args);
1882 // Short timeout, since blocking here can
1883 // deadlock with the application.
1884 tp.go(fd, 2000);
1885 } finally {
1886 tp.kill();
1887 }
1888 } catch (IOException e) {
1889 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
1890 } catch (RemoteException e) {
1891 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
1892 }
1893 needNL = true;
1894 }
1895 }
1896 }
Craig Mautner27084302013-03-25 08:05:25 -07001897}