blob: 89b0ff213f4afa640f7ca82711d3b764bcdf6869 [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;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070035import android.app.IActivityManager;
Craig Mautner23ac33b2013-04-01 16:26:35 -070036import android.app.IApplicationThread;
Craig Mautner20e72272013-04-01 13:45:53 -070037import android.app.IThumbnailReceiver;
Craig Mautner23ac33b2013-04-01 16:26:35 -070038import android.app.PendingIntent;
Craig Mautner20e72272013-04-01 13:45:53 -070039import android.app.ActivityManager.RunningTaskInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070040import android.app.IActivityManager.WaitResult;
Craig Mautner2420ead2013-04-01 17:13:20 -070041import android.app.ResultInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070042import android.content.ComponentName;
Craig Mautner2219a1b2013-03-25 09:44:30 -070043import android.content.Context;
Craig Mautner23ac33b2013-04-01 16:26:35 -070044import android.content.IIntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070045import android.content.Intent;
Craig Mautner23ac33b2013-04-01 16:26:35 -070046import android.content.IntentSender;
Craig Mautner2219a1b2013-03-25 09:44:30 -070047import android.content.pm.ActivityInfo;
Craig Mautner23ac33b2013-04-01 16:26:35 -070048import android.content.pm.ApplicationInfo;
49import android.content.pm.PackageManager;
50import android.content.pm.ResolveInfo;
51import android.content.res.Configuration;
52import android.os.Binder;
Craig Mautner8d341ef2013-03-26 09:03:27 -070053import android.os.Bundle;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070054import android.os.Handler;
Craig Mautner23ac33b2013-04-01 16:26:35 -070055import android.os.IBinder;
Craig Mautner2219a1b2013-03-25 09:44:30 -070056import android.os.Looper;
Craig Mautner2420ead2013-04-01 17:13:20 -070057import android.os.Message;
Craig Mautner23ac33b2013-04-01 16:26:35 -070058import android.os.ParcelFileDescriptor;
Craig Mautner8d341ef2013-03-26 09:03:27 -070059import android.os.RemoteException;
Craig Mautner23ac33b2013-04-01 16:26:35 -070060import android.os.SystemClock;
Craig Mautner6170f732013-04-02 13:05:23 -070061import android.os.UserHandle;
Craig Mautner2420ead2013-04-01 17:13:20 -070062import android.util.EventLog;
Craig Mautner8d341ef2013-03-26 09:03:27 -070063import android.util.Slog;
Craig Mautner2219a1b2013-03-25 09:44:30 -070064
Craig Mautner23ac33b2013-04-01 16:26:35 -070065import com.android.internal.app.HeavyWeightSwitcherActivity;
Craig Mautner6170f732013-04-02 13:05:23 -070066import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
Craig Mautner2420ead2013-04-01 17:13:20 -070067import com.android.server.am.ActivityStack.ActivityState;
Craig Mautnerde4ef022013-04-07 19:01:33 -070068import com.android.server.wm.StackBox;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070069import com.android.server.wm.WindowManagerService;
Craig Mautner23ac33b2013-04-01 16:26:35 -070070
Craig Mautner8d341ef2013-03-26 09:03:27 -070071import java.io.FileDescriptor;
72import java.io.IOException;
Craig Mautner27084302013-03-25 08:05:25 -070073import java.io.PrintWriter;
Craig Mautner2219a1b2013-03-25 09:44:30 -070074import java.util.ArrayList;
Craig Mautner8d341ef2013-03-26 09:03:27 -070075import java.util.List;
Craig Mautner27084302013-03-25 08:05:25 -070076
77public class ActivityStackSupervisor {
Craig Mautnera9a3fb12013-04-18 10:01:00 -070078 static final boolean DEBUG_STACK = ActivityManagerService.DEBUG_STACK;
79
Craig Mautnerde4ef022013-04-07 19:01:33 -070080 static final boolean DEBUG = ActivityManagerService.DEBUG || false;
81 static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
82 static final boolean DEBUG_APP = DEBUG || false;
83 static final boolean DEBUG_SAVED_STATE = DEBUG || false;
84 static final boolean DEBUG_STATES = DEBUG || false;
Craig Mautner2420ead2013-04-01 17:13:20 -070085
Craig Mautner2219a1b2013-03-25 09:44:30 -070086 public static final int HOME_STACK_ID = 0;
Craig Mautner27084302013-03-25 08:05:25 -070087
Craig Mautnerf3333272013-04-22 10:55:53 -070088 /** How long we wait until giving up on the last activity telling us it is idle. */
89 static final int IDLE_TIMEOUT = 10*1000;
90
91 static final int IDLE_TIMEOUT_MSG = ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
92 static final int IDLE_NOW_MSG = ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG + 1;
93
Craig Mautner27084302013-03-25 08:05:25 -070094 final ActivityManagerService mService;
Craig Mautner2219a1b2013-03-25 09:44:30 -070095 final Context mContext;
96 final Looper mLooper;
Craig Mautner27084302013-03-25 08:05:25 -070097
Craig Mautnerce5f3cb2013-04-22 08:58:54 -070098 final ActivityStackSupervisorHandler mHandler;
99
100 /** Short cut */
101 WindowManagerService mWindowManager;
102
Craig Mautner27084302013-03-25 08:05:25 -0700103 /** Dismiss the keyguard after the next activity is displayed? */
104 private boolean mDismissKeyguardOnNextActivity = false;
105
Craig Mautner8d341ef2013-03-26 09:03:27 -0700106 /** Identifier counter for all ActivityStacks */
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700107 private int mLastStackId = HOME_STACK_ID;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700108
109 /** Task identifier that activities are currently being started in. Incremented each time a
110 * new task is created. */
111 private int mCurTaskId = 0;
112
Craig Mautner2420ead2013-04-01 17:13:20 -0700113 /** The current user */
114 private int mCurrentUser;
115
Craig Mautner8d341ef2013-03-26 09:03:27 -0700116 /** The stack containing the launcher app */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700117 private ActivityStack mHomeStack;
Craig Mautner20e72272013-04-01 13:45:53 -0700118
Craig Mautnerde4ef022013-04-07 19:01:33 -0700119 /** The non-home stack currently receiving input or launching the next activity. If home is
Craig Mautner29219d92013-04-16 20:19:12 -0700120 * in front then mHomeStack overrides mFocusedStack. */
121 private ActivityStack mFocusedStack;
Craig Mautner8d341ef2013-03-26 09:03:27 -0700122
123 /** All the non-launcher stacks */
Craig Mautner2219a1b2013-03-25 09:44:30 -0700124 private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
125
Craig Mautnerde4ef022013-04-07 19:01:33 -0700126 private static final int STACK_STATE_HOME_IN_FRONT = 0;
127 private static final int STACK_STATE_HOME_TO_BACK = 1;
128 private static final int STACK_STATE_HOME_IN_BACK = 2;
129 private static final int STACK_STATE_HOME_TO_FRONT = 3;
130 private int mStackState = STACK_STATE_HOME_IN_FRONT;
131
132 /** List of activities that are waiting for a new activity to become visible before completing
133 * whatever operation they are supposed to do. */
134 final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();
135
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700136 /** List of processes waiting to find out about the next visible activity. */
137 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible =
138 new ArrayList<IActivityManager.WaitResult>();
139
140 /** List of processes waiting to find out about the next launched activity. */
141 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched =
142 new ArrayList<IActivityManager.WaitResult>();
143
Craig Mautnerde4ef022013-04-07 19:01:33 -0700144 /** List of activities that are ready to be stopped, but waiting for the next activity to
145 * settle down before doing so. */
146 final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();
147
Craig Mautnerf3333272013-04-22 10:55:53 -0700148 /** List of activities that are ready to be finished, but waiting for the previous activity to
149 * settle down before doing so. It contains ActivityRecord objects. */
150 final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<ActivityRecord>();
151
152 /** List of ActivityRecord objects that have been finished and must still report back to a
153 * pending thumbnail receiver. */
154 final ArrayList<ActivityRecord> mCancelledThumbnails = new ArrayList<ActivityRecord>();
155
156 /** Used on user changes */
157 final ArrayList<UserStartedState> mStartingUsers = new ArrayList<UserStartedState>();
158
Craig Mautnerde4ef022013-04-07 19:01:33 -0700159 /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity
160 * is being brought in front of us. */
161 boolean mUserLeaving = false;
162
Craig Mautner2219a1b2013-03-25 09:44:30 -0700163 public ActivityStackSupervisor(ActivityManagerService service, Context context,
164 Looper looper) {
Craig Mautner27084302013-03-25 08:05:25 -0700165 mService = service;
Craig Mautner2219a1b2013-03-25 09:44:30 -0700166 mContext = context;
167 mLooper = looper;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700168 mHandler = new ActivityStackSupervisorHandler(looper);
Craig Mautner2219a1b2013-03-25 09:44:30 -0700169 }
170
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700171 void setWindowManager(WindowManagerService wm) {
172 mWindowManager = wm;
173 mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700174 mStacks.add(mHomeStack);
Craig Mautner27084302013-03-25 08:05:25 -0700175 }
176
177 void dismissKeyguard() {
178 if (mDismissKeyguardOnNextActivity) {
179 mDismissKeyguardOnNextActivity = false;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700180 mWindowManager.dismissKeyguard();
Craig Mautner27084302013-03-25 08:05:25 -0700181 }
182 }
183
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700184 ActivityStack getFocusedStack() {
Craig Mautnerf88c50f2013-04-18 19:25:12 -0700185 if (mFocusedStack == null) {
186 return mHomeStack;
187 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700188 switch (mStackState) {
189 case STACK_STATE_HOME_IN_FRONT:
190 case STACK_STATE_HOME_TO_FRONT:
191 return mHomeStack;
192 case STACK_STATE_HOME_IN_BACK:
193 case STACK_STATE_HOME_TO_BACK:
194 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700195 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700196 }
Craig Mautner20e72272013-04-01 13:45:53 -0700197 }
198
Craig Mautnerde4ef022013-04-07 19:01:33 -0700199 ActivityStack getLastStack() {
200 switch (mStackState) {
201 case STACK_STATE_HOME_IN_FRONT:
202 case STACK_STATE_HOME_TO_BACK:
203 return mHomeStack;
204 case STACK_STATE_HOME_TO_FRONT:
205 case STACK_STATE_HOME_IN_BACK:
206 default:
Craig Mautner29219d92013-04-16 20:19:12 -0700207 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700208 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700209 }
210
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700211 boolean isFocusedStack(ActivityStack stack) {
212 return getFocusedStack() == stack;
213 }
214
Craig Mautnerde4ef022013-04-07 19:01:33 -0700215 boolean isFrontStack(ActivityStack stack) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700216 return !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
Craig Mautner20e72272013-04-01 13:45:53 -0700217 }
218
Craig Mautnerde4ef022013-04-07 19:01:33 -0700219 void moveHomeStack(boolean toFront) {
220 final boolean homeInFront = isFrontStack(mHomeStack);
221 if (homeInFront ^ toFront) {
222 mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
223 }
224 }
225
Craig Mautner69ada552013-04-18 13:51:51 -0700226 boolean resumeHomeActivity(ActivityRecord prev) {
227 moveHomeStack(true);
228 if (prev != null) {
229 prev.mLaunchHomeTaskNext = false;
230 }
231 if (mHomeStack.topRunningActivityLocked(null) != null) {
232 return mHomeStack.resumeTopActivityLocked(prev);
233 }
234 return mService.startHomeActivityLocked(mCurrentUser);
235 }
236
Craig Mautnerde4ef022013-04-07 19:01:33 -0700237 final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r,
238 ActivityStack stack) {
239 if (stack == mHomeStack) {
240 return;
241 }
242 if ((sourceRecord == null && getLastStack() == mHomeStack) ||
243 (sourceRecord != null && sourceRecord.isHomeActivity)) {
244 if (r == null) {
245 r = stack.topRunningActivityLocked(null);
246 }
247 if (r != null && !r.isHomeActivity && r.isRootActivity()) {
248 r.mLaunchHomeTaskNext = true;
249 }
250 }
Craig Mautner2219a1b2013-03-25 09:44:30 -0700251 }
252
Craig Mautner27084302013-03-25 08:05:25 -0700253 void setDismissKeyguard(boolean dismiss) {
254 mDismissKeyguardOnNextActivity = dismiss;
255 }
256
Craig Mautner8d341ef2013-03-26 09:03:27 -0700257 TaskRecord anyTaskForIdLocked(int id) {
258 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
259 ActivityStack stack = mStacks.get(stackNdx);
260 TaskRecord task = stack.taskForIdLocked(id);
261 if (task != null) {
262 return task;
263 }
264 }
265 return null;
266 }
267
Craig Mautner6170f732013-04-02 13:05:23 -0700268 ActivityRecord isInAnyStackLocked(IBinder token) {
269 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
270 final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
271 if (r != null) {
272 return r;
273 }
274 }
275 return null;
276 }
277
Craig Mautner8d341ef2013-03-26 09:03:27 -0700278 int getNextTaskId() {
279 do {
280 mCurTaskId++;
281 if (mCurTaskId <= 0) {
282 mCurTaskId = 1;
283 }
284 } while (anyTaskForIdLocked(mCurTaskId) != null);
285 return mCurTaskId;
286 }
287
Craig Mautnerde4ef022013-04-07 19:01:33 -0700288 void removeTask(TaskRecord task) {
289 final ActivityStack stack = task.stack;
290 if (stack.removeTask(task) && !stack.isHomeStack()) {
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700291 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700292 mStacks.remove(stack);
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700293 final int stackId = stack.mStackId;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700294 final int nextStackId = mWindowManager.removeStack(stackId);
Craig Mautnera9a3fb12013-04-18 10:01:00 -0700295 // TODO: Perhaps we need to let the ActivityManager determine the next focus...
Craig Mautner29219d92013-04-16 20:19:12 -0700296 if (mFocusedStack.mStackId == stackId) {
297 mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700298 }
299 }
300 }
301
302 ActivityRecord resumedAppLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700303 ActivityStack stack = getFocusedStack();
304 if (stack == null) {
305 return null;
306 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700307 ActivityRecord resumedActivity = stack.mResumedActivity;
308 if (resumedActivity == null || resumedActivity.app == null) {
309 resumedActivity = stack.mPausingActivity;
310 if (resumedActivity == null || resumedActivity.app == null) {
311 resumedActivity = stack.topRunningActivityLocked(null);
312 }
313 }
314 return resumedActivity;
315 }
316
Craig Mautner20e72272013-04-01 13:45:53 -0700317 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
318 boolean didSomething = false;
319 final String processName = app.processName;
320 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
321 final ActivityStack stack = mStacks.get(stackNdx);
322 ActivityRecord hr = stack.topRunningActivityLocked(null);
323 if (hr != null) {
324 if (hr.app == null && app.uid == hr.info.applicationInfo.uid
325 && processName.equals(hr.processName)) {
326 try {
327 if (headless) {
328 Slog.e(TAG, "Starting activities not supported on headless device: "
329 + hr);
Craig Mautner2420ead2013-04-01 17:13:20 -0700330 } else if (realStartActivityLocked(hr, app, true, true)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700331 didSomething = true;
332 }
333 } catch (Exception e) {
334 Slog.w(TAG, "Exception in new application when starting activity "
335 + hr.intent.getComponent().flattenToShortString(), e);
336 throw e;
337 }
338 } else {
339 stack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
340 }
341 }
342 }
343 return didSomething;
344 }
345
346 boolean allResumedActivitiesIdle() {
347 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -0700348 final ActivityRecord resumedActivity = mStacks.get(stackNdx).mResumedActivity;
349 if (resumedActivity == null || !resumedActivity.idle) {
Craig Mautner20e72272013-04-01 13:45:53 -0700350 return false;
351 }
352 }
353 return true;
354 }
355
Craig Mautnerde4ef022013-04-07 19:01:33 -0700356 boolean allResumedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700357 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
358 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner967212c2013-04-13 21:10:58 -0700359 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700360 final ActivityRecord r = stack.mResumedActivity;
361 if (r != null && r.state != ActivityState.RESUMED) {
362 return false;
363 }
364 }
365 }
366 // TODO: Not sure if this should check if all Paused are complete too.
367 switch (mStackState) {
368 case STACK_STATE_HOME_TO_BACK:
369 mStackState = STACK_STATE_HOME_IN_BACK;
370 break;
371 case STACK_STATE_HOME_TO_FRONT:
372 mStackState = STACK_STATE_HOME_IN_FRONT;
373 break;
374 }
375 return true;
376 }
377
378 boolean allResumedActivitiesVisible() {
379 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
380 final ActivityStack stack = mStacks.get(stackNdx);
381 final ActivityRecord r = stack.mResumedActivity;
382 if (r != null && (!r.nowVisible || r.waitingVisible)) {
383 return false;
384 }
385 }
386 return true;
387 }
388
Craig Mautnercf910b02013-04-23 11:23:27 -0700389 boolean pauseBackStacks(boolean userLeaving) {
390 boolean someActivityPaused = false;
391 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
392 final ActivityStack stack = mStacks.get(stackNdx);
393 if (!isFrontStack(stack) && stack.mResumedActivity != null) {
394 stack.startPausingLocked(userLeaving, false);
395 someActivityPaused = true;
396 }
397 }
398 return someActivityPaused;
399 }
400
Craig Mautnerde4ef022013-04-07 19:01:33 -0700401 boolean allPausedActivitiesComplete() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700402 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
403 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautner69ada552013-04-18 13:51:51 -0700404 final ActivityRecord r = stack.mPausingActivity;
405 if (r != null && r.state != ActivityState.PAUSED
406 && r.state != ActivityState.STOPPED
407 && r.state != ActivityState.STOPPING) {
408 return false;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700409 }
410 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700411 return true;
412 }
413
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700414 void reportActivityVisibleLocked(ActivityRecord r) {
415 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
416 WaitResult w = mWaitingActivityVisible.get(i);
417 w.timeout = false;
418 if (r != null) {
419 w.who = new ComponentName(r.info.packageName, r.info.name);
420 }
421 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
422 w.thisTime = w.totalTime;
423 }
424 mService.notifyAll();
425 dismissKeyguard();
426 }
427
428 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
429 long thisTime, long totalTime) {
430 for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
431 WaitResult w = mWaitingActivityLaunched.get(i);
432 w.timeout = timeout;
433 if (r != null) {
434 w.who = new ComponentName(r.info.packageName, r.info.name);
435 }
436 w.thisTime = thisTime;
437 w.totalTime = totalTime;
438 }
439 mService.notifyAll();
440 }
441
Craig Mautner29219d92013-04-16 20:19:12 -0700442 ActivityRecord topRunningActivityLocked() {
443 ActivityRecord r = null;
444 if (mFocusedStack != null) {
445 r = mFocusedStack.topRunningActivityLocked(null);
446 if (r != null) {
447 return r;
448 }
449 }
450 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
451 final ActivityStack stack = mStacks.get(stackNdx);
452 if (stack != mFocusedStack && isFrontStack(stack)) {
453 r = stack.topRunningActivityLocked(null);
454 if (r != null) {
455 return r;
456 }
457 }
458 }
459 return null;
460 }
461
Craig Mautner20e72272013-04-01 13:45:53 -0700462 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
463 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
464 ActivityRecord r = null;
465 final int numStacks = mStacks.size();
466 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
467 final ActivityStack stack = mStacks.get(stackNdx);
468 final ActivityRecord ar =
469 stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700470 if (isFrontStack(stack)) {
Craig Mautner20e72272013-04-01 13:45:53 -0700471 r = ar;
472 }
473 }
474 return r;
475 }
476
Craig Mautner23ac33b2013-04-01 16:26:35 -0700477 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
478 String profileFile, ParcelFileDescriptor profileFd, int userId) {
479 // Collect information about the target of the Intent.
480 ActivityInfo aInfo;
481 try {
482 ResolveInfo rInfo =
483 AppGlobals.getPackageManager().resolveIntent(
484 intent, resolvedType,
485 PackageManager.MATCH_DEFAULT_ONLY
486 | ActivityManagerService.STOCK_PM_FLAGS, userId);
487 aInfo = rInfo != null ? rInfo.activityInfo : null;
488 } catch (RemoteException e) {
489 aInfo = null;
490 }
491
492 if (aInfo != null) {
493 // Store the found target back into the intent, because now that
494 // we have it we never want to do this again. For example, if the
495 // user navigates back to this point in the history, we should
496 // always restart the exact same activity.
497 intent.setComponent(new ComponentName(
498 aInfo.applicationInfo.packageName, aInfo.name));
499
500 // Don't debug things in the system process
501 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
502 if (!aInfo.processName.equals("system")) {
503 mService.setDebugApp(aInfo.processName, true, false);
504 }
505 }
506
507 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
508 if (!aInfo.processName.equals("system")) {
509 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
510 }
511 }
512
513 if (profileFile != null) {
514 if (!aInfo.processName.equals("system")) {
515 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
516 profileFile, profileFd,
517 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
518 }
519 }
520 }
521 return aInfo;
522 }
523
Craig Mautner2219a1b2013-03-25 09:44:30 -0700524 void startHomeActivity(Intent intent, ActivityInfo aInfo) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700525 moveHomeStack(true);
Craig Mautner6170f732013-04-02 13:05:23 -0700526 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
Craig Mautner2219a1b2013-03-25 09:44:30 -0700527 null, false, null);
Craig Mautner8d341ef2013-03-26 09:03:27 -0700528 }
529
Craig Mautner23ac33b2013-04-01 16:26:35 -0700530 final int startActivityMayWait(IApplicationThread caller, int callingUid,
531 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
532 String resultWho, int requestCode, int startFlags, String profileFile,
533 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
534 Bundle options, int userId) {
535 // Refuse possible leaked file descriptors
536 if (intent != null && intent.hasFileDescriptors()) {
537 throw new IllegalArgumentException("File descriptors passed in Intent");
538 }
539 boolean componentSpecified = intent.getComponent() != null;
540
541 // Don't modify the client's object!
542 intent = new Intent(intent);
543
544 // Collect information about the target of the Intent.
545 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
546 profileFile, profileFd, userId);
547
548 synchronized (mService) {
549 int callingPid;
550 if (callingUid >= 0) {
551 callingPid = -1;
552 } else if (caller == null) {
553 callingPid = Binder.getCallingPid();
554 callingUid = Binder.getCallingUid();
555 } else {
556 callingPid = callingUid = -1;
557 }
558
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700559 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -0700560 stack.mConfigWillChange = config != null
Craig Mautner23ac33b2013-04-01 16:26:35 -0700561 && mService.mConfiguration.diff(config) != 0;
562 if (DEBUG_CONFIGURATION) Slog.v(TAG,
Craig Mautnerde4ef022013-04-07 19:01:33 -0700563 "Starting activity when config will change = " + stack.mConfigWillChange);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700564
565 final long origId = Binder.clearCallingIdentity();
566
567 if (aInfo != null &&
568 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
569 // This may be a heavy-weight process! Check to see if we already
570 // have another, different heavy-weight process running.
571 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
572 if (mService.mHeavyWeightProcess != null &&
573 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
574 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
575 int realCallingPid = callingPid;
576 int realCallingUid = callingUid;
577 if (caller != null) {
578 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
579 if (callerApp != null) {
580 realCallingPid = callerApp.pid;
581 realCallingUid = callerApp.info.uid;
582 } else {
583 Slog.w(TAG, "Unable to find app for caller " + caller
584 + " (pid=" + realCallingPid + ") when starting: "
585 + intent.toString());
586 ActivityOptions.abort(options);
587 return ActivityManager.START_PERMISSION_DENIED;
588 }
589 }
590
591 IIntentSender target = mService.getIntentSenderLocked(
592 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
593 realCallingUid, userId, null, null, 0, new Intent[] { intent },
594 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
595 | PendingIntent.FLAG_ONE_SHOT, null);
596
597 Intent newIntent = new Intent();
598 if (requestCode >= 0) {
599 // Caller is requesting a result.
600 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
601 }
602 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
603 new IntentSender(target));
604 if (mService.mHeavyWeightProcess.activities.size() > 0) {
605 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
606 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
607 hist.packageName);
608 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
609 hist.task.taskId);
610 }
611 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
612 aInfo.packageName);
613 newIntent.setFlags(intent.getFlags());
614 newIntent.setClassName("android",
615 HeavyWeightSwitcherActivity.class.getName());
616 intent = newIntent;
617 resolvedType = null;
618 caller = null;
619 callingUid = Binder.getCallingUid();
620 callingPid = Binder.getCallingPid();
621 componentSpecified = true;
622 try {
623 ResolveInfo rInfo =
624 AppGlobals.getPackageManager().resolveIntent(
625 intent, null,
626 PackageManager.MATCH_DEFAULT_ONLY
627 | ActivityManagerService.STOCK_PM_FLAGS, userId);
628 aInfo = rInfo != null ? rInfo.activityInfo : null;
629 aInfo = mService.getActivityInfoForUser(aInfo, userId);
630 } catch (RemoteException e) {
631 aInfo = null;
632 }
633 }
634 }
635 }
636
Craig Mautner6170f732013-04-02 13:05:23 -0700637 int res = startActivityLocked(caller, intent, resolvedType,
Craig Mautner23ac33b2013-04-01 16:26:35 -0700638 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
639 callingPackage, startFlags, options, componentSpecified, null);
640
Craig Mautnerde4ef022013-04-07 19:01:33 -0700641 if (stack.mConfigWillChange) {
Craig Mautner23ac33b2013-04-01 16:26:35 -0700642 // If the caller also wants to switch to a new configuration,
643 // do so now. This allows a clean switch, as we are waiting
644 // for the current activity to pause (so we will not destroy
645 // it), and have not yet started the next activity.
646 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
647 "updateConfiguration()");
Craig Mautnerde4ef022013-04-07 19:01:33 -0700648 stack.mConfigWillChange = false;
Craig Mautner23ac33b2013-04-01 16:26:35 -0700649 if (DEBUG_CONFIGURATION) Slog.v(TAG,
650 "Updating to new configuration after starting activity.");
651 mService.updateConfigurationLocked(config, null, false, false);
652 }
653
654 Binder.restoreCallingIdentity(origId);
655
656 if (outResult != null) {
657 outResult.result = res;
658 if (res == ActivityManager.START_SUCCESS) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700659 mWaitingActivityLaunched.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700660 do {
661 try {
662 mService.wait();
663 } catch (InterruptedException e) {
664 }
665 } while (!outResult.timeout && outResult.who == null);
666 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700667 ActivityRecord r = stack.topRunningActivityLocked(null);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700668 if (r.nowVisible) {
669 outResult.timeout = false;
670 outResult.who = new ComponentName(r.info.packageName, r.info.name);
671 outResult.totalTime = 0;
672 outResult.thisTime = 0;
673 } else {
674 outResult.thisTime = SystemClock.uptimeMillis();
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700675 mWaitingActivityVisible.add(outResult);
Craig Mautner23ac33b2013-04-01 16:26:35 -0700676 do {
677 try {
678 mService.wait();
679 } catch (InterruptedException e) {
680 }
681 } while (!outResult.timeout && outResult.who == null);
682 }
683 }
684 }
685
686 return res;
687 }
688 }
689
690 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
691 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
692 Bundle options, int userId) {
693 if (intents == null) {
694 throw new NullPointerException("intents is null");
695 }
696 if (resolvedTypes == null) {
697 throw new NullPointerException("resolvedTypes is null");
698 }
699 if (intents.length != resolvedTypes.length) {
700 throw new IllegalArgumentException("intents are length different than resolvedTypes");
701 }
702
703 ActivityRecord[] outActivity = new ActivityRecord[1];
704
705 int callingPid;
706 if (callingUid >= 0) {
707 callingPid = -1;
708 } else if (caller == null) {
709 callingPid = Binder.getCallingPid();
710 callingUid = Binder.getCallingUid();
711 } else {
712 callingPid = callingUid = -1;
713 }
714 final long origId = Binder.clearCallingIdentity();
715 try {
716 synchronized (mService) {
717
718 for (int i=0; i<intents.length; i++) {
719 Intent intent = intents[i];
720 if (intent == null) {
721 continue;
722 }
723
724 // Refuse possible leaked file descriptors
725 if (intent != null && intent.hasFileDescriptors()) {
726 throw new IllegalArgumentException("File descriptors passed in Intent");
727 }
728
729 boolean componentSpecified = intent.getComponent() != null;
730
731 // Don't modify the client's object!
732 intent = new Intent(intent);
733
734 // Collect information about the target of the Intent.
735 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
736 0, null, null, userId);
737 // TODO: New, check if this is correct
738 aInfo = mService.getActivityInfoForUser(aInfo, userId);
739
740 if (aInfo != null &&
741 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
742 != 0) {
743 throw new IllegalArgumentException(
744 "FLAG_CANT_SAVE_STATE not supported here");
745 }
746
747 Bundle theseOptions;
748 if (options != null && i == intents.length-1) {
749 theseOptions = options;
750 } else {
751 theseOptions = null;
752 }
Craig Mautner6170f732013-04-02 13:05:23 -0700753 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Craig Mautner23ac33b2013-04-01 16:26:35 -0700754 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
755 0, theseOptions, componentSpecified, outActivity);
756 if (res < 0) {
757 return res;
758 }
759
760 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
761 }
762 }
763 } finally {
764 Binder.restoreCallingIdentity(origId);
765 }
766
767 return ActivityManager.START_SUCCESS;
768 }
769
Craig Mautner2420ead2013-04-01 17:13:20 -0700770 final boolean realStartActivityLocked(ActivityRecord r,
771 ProcessRecord app, boolean andResume, boolean checkConfig)
772 throws RemoteException {
773
774 r.startFreezingScreenLocked(app, 0);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700775 mWindowManager.setAppVisibility(r.appToken, true);
Craig Mautner2420ead2013-04-01 17:13:20 -0700776
777 // schedule launch ticks to collect information about slow apps.
778 r.startLaunchTickingLocked();
779
780 // Have the window manager re-evaluate the orientation of
781 // the screen based on the new activity order. Note that
782 // as a result of this, it can call back into the activity
783 // manager with a new orientation. We don't care about that,
784 // because the activity is not currently running so we are
785 // just restarting it anyway.
786 if (checkConfig) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -0700787 Configuration config = mWindowManager.updateOrientationFromAppTokens(
Craig Mautner2420ead2013-04-01 17:13:20 -0700788 mService.mConfiguration,
789 r.mayFreezeScreenLocked(app) ? r.appToken : null);
790 mService.updateConfigurationLocked(config, r, false, false);
791 }
792
793 r.app = app;
794 app.waitingToKill = null;
795 r.launchCount++;
796 r.lastLaunchTime = SystemClock.uptimeMillis();
797
798 if (localLOGV) Slog.v(TAG, "Launching: " + r);
799
800 int idx = app.activities.indexOf(r);
801 if (idx < 0) {
802 app.activities.add(r);
803 }
804 mService.updateLruProcessLocked(app, true);
805
806 final ActivityStack stack = r.task.stack;
807 try {
808 if (app.thread == null) {
809 throw new RemoteException();
810 }
811 List<ResultInfo> results = null;
812 List<Intent> newIntents = null;
813 if (andResume) {
814 results = r.results;
815 newIntents = r.newIntents;
816 }
817 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
818 + " icicle=" + r.icicle
819 + " with results=" + results + " newIntents=" + newIntents
820 + " andResume=" + andResume);
821 if (andResume) {
822 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
823 r.userId, System.identityHashCode(r),
824 r.task.taskId, r.shortComponentName);
825 }
826 if (r.isHomeActivity) {
827 mService.mHomeProcess = app;
828 }
829 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
830 r.sleeping = false;
831 r.forceNewConfig = false;
832 mService.showAskCompatModeDialogLocked(r);
833 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
834 String profileFile = null;
835 ParcelFileDescriptor profileFd = null;
836 boolean profileAutoStop = false;
837 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
838 if (mService.mProfileProc == null || mService.mProfileProc == app) {
839 mService.mProfileProc = app;
840 profileFile = mService.mProfileFile;
841 profileFd = mService.mProfileFd;
842 profileAutoStop = mService.mAutoStopProfiler;
843 }
844 }
845 app.hasShownUi = true;
846 app.pendingUiClean = true;
847 if (profileFd != null) {
848 try {
849 profileFd = profileFd.dup();
850 } catch (IOException e) {
851 if (profileFd != null) {
852 try {
853 profileFd.close();
854 } catch (IOException o) {
855 }
856 profileFd = null;
857 }
858 }
859 }
860 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
861 System.identityHashCode(r), r.info,
862 new Configuration(mService.mConfiguration),
863 r.compat, r.icicle, results, newIntents, !andResume,
864 mService.isNextTransitionForward(), profileFile, profileFd,
865 profileAutoStop);
866
867 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
868 // This may be a heavy-weight process! Note that the package
869 // manager will ensure that only activity can run in the main
870 // process of the .apk, which is the only thing that will be
871 // considered heavy-weight.
872 if (app.processName.equals(app.info.packageName)) {
873 if (mService.mHeavyWeightProcess != null
874 && mService.mHeavyWeightProcess != app) {
875 Slog.w(TAG, "Starting new heavy weight process " + app
876 + " when already running "
877 + mService.mHeavyWeightProcess);
878 }
879 mService.mHeavyWeightProcess = app;
880 Message msg = mService.mHandler.obtainMessage(
881 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
882 msg.obj = r;
883 mService.mHandler.sendMessage(msg);
884 }
885 }
886
887 } catch (RemoteException e) {
888 if (r.launchFailed) {
889 // This is the second time we failed -- finish activity
890 // and give up.
891 Slog.e(TAG, "Second failure launching "
892 + r.intent.getComponent().flattenToShortString()
893 + ", giving up", e);
894 mService.appDiedLocked(app, app.pid, app.thread);
895 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
896 "2nd-crash", false);
897 return false;
898 }
899
900 // This is the first time we failed -- restart process and
901 // retry.
902 app.activities.remove(r);
903 throw e;
904 }
905
906 r.launchFailed = false;
907 if (stack.updateLRUListLocked(r)) {
908 Slog.w(TAG, "Activity " + r
909 + " being launched, but already in LRU list");
910 }
911
912 if (andResume) {
913 // As part of the process of launching, ActivityThread also performs
914 // a resume.
915 stack.minimalResumeActivityLocked(r);
916 } else {
917 // This activity is not starting in the resumed state... which
918 // should look like we asked it to pause+stop (but remain visible),
919 // and it has done so and reported back the current icicle and
920 // other state.
921 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
922 + " (starting in stopped state)");
923 r.state = ActivityState.STOPPED;
924 r.stopped = true;
925 }
926
927 // Launch the new version setup screen if needed. We do this -after-
928 // launching the initial activity (that is, home), so that it can have
929 // a chance to initialize itself while in the background, making the
930 // switch back to it faster and look better.
Craig Mautnerde4ef022013-04-07 19:01:33 -0700931 if (isFrontStack(stack)) {
Craig Mautner2420ead2013-04-01 17:13:20 -0700932 mService.startSetupActivityLocked();
933 }
934
935 return true;
936 }
937
Craig Mautnere79d42682013-04-01 19:01:53 -0700938 void startSpecificActivityLocked(ActivityRecord r,
939 boolean andResume, boolean checkConfig) {
940 // Is this activity's application already running?
941 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
942 r.info.applicationInfo.uid);
943
944 r.task.stack.setLaunchTime(r);
945
946 if (app != null && app.thread != null) {
947 try {
948 app.addPackage(r.info.packageName);
949 realStartActivityLocked(r, app, andResume, checkConfig);
950 return;
951 } catch (RemoteException e) {
952 Slog.w(TAG, "Exception when starting activity "
953 + r.intent.getComponent().flattenToShortString(), e);
954 }
955
956 // If a dead object exception was thrown -- fall through to
957 // restart the application.
958 }
959
960 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
961 "activity", r.intent.getComponent(), false, false);
962 }
963
Craig Mautner6170f732013-04-02 13:05:23 -0700964 final int startActivityLocked(IApplicationThread caller,
965 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
966 String resultWho, int requestCode,
967 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
968 boolean componentSpecified, ActivityRecord[] outActivity) {
969 int err = ActivityManager.START_SUCCESS;
970
971 ProcessRecord callerApp = null;
972 if (caller != null) {
973 callerApp = mService.getRecordForAppLocked(caller);
974 if (callerApp != null) {
975 callingPid = callerApp.pid;
976 callingUid = callerApp.info.uid;
977 } else {
978 Slog.w(TAG, "Unable to find app for caller " + caller
979 + " (pid=" + callingPid + ") when starting: "
980 + intent.toString());
981 err = ActivityManager.START_PERMISSION_DENIED;
982 }
983 }
984
985 if (err == ActivityManager.START_SUCCESS) {
986 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
987 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
988 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
989 }
990
991 ActivityRecord sourceRecord = null;
992 ActivityRecord resultRecord = null;
993 if (resultTo != null) {
994 sourceRecord = isInAnyStackLocked(resultTo);
995 if (DEBUG_RESULTS) Slog.v(
996 TAG, "Will send result to " + resultTo + " " + sourceRecord);
997 if (sourceRecord != null) {
998 if (requestCode >= 0 && !sourceRecord.finishing) {
999 resultRecord = sourceRecord;
1000 }
1001 }
1002 }
1003 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
1004
1005 int launchFlags = intent.getFlags();
1006
1007 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
1008 && sourceRecord != null) {
1009 // Transfer the result target from the source activity to the new
1010 // one being started, including any failures.
1011 if (requestCode >= 0) {
1012 ActivityOptions.abort(options);
1013 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
1014 }
1015 resultRecord = sourceRecord.resultTo;
1016 resultWho = sourceRecord.resultWho;
1017 requestCode = sourceRecord.requestCode;
1018 sourceRecord.resultTo = null;
1019 if (resultRecord != null) {
1020 resultRecord.removeResultsLocked(
1021 sourceRecord, resultWho, requestCode);
1022 }
1023 }
1024
1025 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
1026 // We couldn't find a class that can handle the given Intent.
1027 // That's the end of that!
1028 err = ActivityManager.START_INTENT_NOT_RESOLVED;
1029 }
1030
1031 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
1032 // We couldn't find the specific class specified in the Intent.
1033 // Also the end of the line.
1034 err = ActivityManager.START_CLASS_NOT_FOUND;
1035 }
1036
1037 if (err != ActivityManager.START_SUCCESS) {
1038 if (resultRecord != null) {
1039 resultStack.sendActivityResultLocked(-1,
1040 resultRecord, resultWho, requestCode,
1041 Activity.RESULT_CANCELED, null);
1042 }
1043 setDismissKeyguard(false);
1044 ActivityOptions.abort(options);
1045 return err;
1046 }
1047
1048 final int startAnyPerm = mService.checkPermission(
1049 START_ANY_ACTIVITY, callingPid, callingUid);
1050 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
1051 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
1052 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
1053 if (resultRecord != null) {
1054 resultStack.sendActivityResultLocked(-1,
1055 resultRecord, resultWho, requestCode,
1056 Activity.RESULT_CANCELED, null);
1057 }
1058 setDismissKeyguard(false);
1059 String msg;
1060 if (!aInfo.exported) {
1061 msg = "Permission Denial: starting " + intent.toString()
1062 + " from " + callerApp + " (pid=" + callingPid
1063 + ", uid=" + callingUid + ")"
1064 + " not exported from uid " + aInfo.applicationInfo.uid;
1065 } else {
1066 msg = "Permission Denial: starting " + intent.toString()
1067 + " from " + callerApp + " (pid=" + callingPid
1068 + ", uid=" + callingUid + ")"
1069 + " requires " + aInfo.permission;
1070 }
1071 Slog.w(TAG, msg);
1072 throw new SecurityException(msg);
1073 }
1074
Ben Gruver6617c3c2013-04-03 18:45:22 -07001075 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
Ben Gruver7b879f42013-04-08 14:56:55 -07001076 callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo);
Ben Gruver5e207332013-04-03 17:41:37 -07001077
Craig Mautner6170f732013-04-02 13:05:23 -07001078 if (mService.mController != null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001079 try {
1080 // The Intent we give to the watcher has the extra data
1081 // stripped off, since it can contain private information.
1082 Intent watchIntent = intent.cloneFilter();
Ben Gruver5e207332013-04-03 17:41:37 -07001083 abort |= !mService.mController.activityStarting(watchIntent,
Craig Mautner6170f732013-04-02 13:05:23 -07001084 aInfo.applicationInfo.packageName);
1085 } catch (RemoteException e) {
1086 mService.mController = null;
1087 }
Ben Gruver5e207332013-04-03 17:41:37 -07001088 }
Craig Mautner6170f732013-04-02 13:05:23 -07001089
Ben Gruver5e207332013-04-03 17:41:37 -07001090 if (abort) {
1091 if (resultRecord != null) {
1092 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Craig Mautner6170f732013-04-02 13:05:23 -07001093 Activity.RESULT_CANCELED, null);
Craig Mautner6170f732013-04-02 13:05:23 -07001094 }
Ben Gruver5e207332013-04-03 17:41:37 -07001095 // We pretend to the caller that it was really started, but
1096 // they will just get a cancel result.
1097 setDismissKeyguard(false);
1098 ActivityOptions.abort(options);
1099 return ActivityManager.START_SUCCESS;
Craig Mautner6170f732013-04-02 13:05:23 -07001100 }
1101
1102 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1103 intent, resolvedType, aInfo, mService.mConfiguration,
Craig Mautnerde4ef022013-04-07 19:01:33 -07001104 resultRecord, resultWho, requestCode, componentSpecified, this);
Craig Mautner6170f732013-04-02 13:05:23 -07001105 if (outActivity != null) {
1106 outActivity[0] = r;
1107 }
1108
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001109 final ActivityStack stack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001110 if (stack.mResumedActivity == null
1111 || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
Craig Mautner6170f732013-04-02 13:05:23 -07001112 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1113 PendingActivityLaunch pal =
Craig Mautnerde4ef022013-04-07 19:01:33 -07001114 new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
Craig Mautner6170f732013-04-02 13:05:23 -07001115 mService.mPendingActivityLaunches.add(pal);
1116 setDismissKeyguard(false);
1117 ActivityOptions.abort(options);
1118 return ActivityManager.START_SWITCHES_CANCELED;
1119 }
1120 }
1121
1122 if (mService.mDidAppSwitch) {
1123 // This is the second allowed switch since we stopped switches,
1124 // so now just generally allow switches. Use case: user presses
1125 // home (switches disabled, switch to home, mDidAppSwitch now true);
1126 // user taps a home icon (coming from home so allowed, we hit here
1127 // and now allow anyone to switch again).
1128 mService.mAppSwitchesAllowedTime = 0;
1129 } else {
1130 mService.mDidAppSwitch = true;
1131 }
1132
1133 mService.doPendingActivityLaunchesLocked(false);
1134
Craig Mautner8849a5e2013-04-02 16:41:03 -07001135 err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001136 if (stack.mPausingActivity == null) {
Craig Mautner6170f732013-04-02 13:05:23 -07001137 // Someone asked to have the keyguard dismissed on the next
1138 // activity start, but we are not actually doing an activity
1139 // switch... just dismiss the keyguard now, because we
1140 // probably want to see whatever is behind it.
1141 dismissKeyguard();
1142 }
1143 return err;
1144 }
1145
Craig Mautnerde4ef022013-04-07 19:01:33 -07001146 ActivityStack getCorrectStack(ActivityRecord r) {
1147 if (!r.isHomeActivity) {
1148 if (mStacks.size() == 1) {
1149 // Time to create the first app stack.
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001150 int stackId = mService.createStack(-1, HOME_STACK_ID,
1151 StackBox.TASK_STACK_GOES_OVER, 1.0f);
Craig Mautner29219d92013-04-16 20:19:12 -07001152 mFocusedStack = getStack(stackId);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001153 }
Craig Mautner29219d92013-04-16 20:19:12 -07001154 return mFocusedStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001155 }
1156 return mHomeStack;
1157 }
1158
Craig Mautner29219d92013-04-16 20:19:12 -07001159 void setFocusedStack(ActivityRecord r) {
1160 if (r == null) {
1161 return;
1162 }
1163 if (r.isHomeActivity) {
1164 if (mStackState != STACK_STATE_HOME_IN_FRONT) {
1165 mStackState = STACK_STATE_HOME_TO_FRONT;
1166 }
1167 } else {
1168 mFocusedStack = r.task.stack;
1169 if (mStackState != STACK_STATE_HOME_IN_BACK) {
1170 mStackState = STACK_STATE_HOME_TO_BACK;
1171 }
1172 }
1173 }
1174
Craig Mautner8849a5e2013-04-02 16:41:03 -07001175 final int startActivityUncheckedLocked(ActivityRecord r,
1176 ActivityRecord sourceRecord, int startFlags, boolean doResume,
1177 Bundle options) {
1178 final Intent intent = r.intent;
1179 final int callingUid = r.launchedFromUid;
1180
1181 int launchFlags = intent.getFlags();
1182
Craig Mautner8849a5e2013-04-02 16:41:03 -07001183 // We'll invoke onUserLeaving before onPause only if the launching
1184 // activity did not explicitly state that this is an automated launch.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001185 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1186 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001187
1188 // If the caller has asked not to resume at this point, we make note
1189 // of this in the record so that we can skip it when trying to find
1190 // the top running activity.
1191 if (!doResume) {
1192 r.delayedResume = true;
1193 }
1194
1195 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1196
1197 // If the onlyIfNeeded flag is set, then we can do this if the activity
1198 // being launched is the same as the one making the call... or, as
1199 // a special case, if we do not know the caller then we count the
1200 // current top activity as the caller.
1201 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1202 ActivityRecord checkedCaller = sourceRecord;
1203 if (checkedCaller == null) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001204 checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001205 }
1206 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1207 // Caller is not the same as launcher, so always needed.
1208 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1209 }
1210 }
1211
1212 if (sourceRecord == null) {
1213 // This activity is not being started from another... in this
1214 // case we -always- start a new task.
1215 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Craig Mautner29219d92013-04-16 20:19:12 -07001216 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1217 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001218 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1219 }
1220 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1221 // The original activity who is starting us is running as a single
1222 // instance... this new activity it is starting must go on its
1223 // own task.
1224 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1225 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1226 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1227 // The activity being started is a single instance... it always
1228 // gets launched into its own task.
1229 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1230 }
1231
Craig Mautnerde4ef022013-04-07 19:01:33 -07001232 final ActivityStack sourceStack;
1233 final TaskRecord sourceTask;
1234 if (sourceRecord != null) {
1235 sourceTask = sourceRecord.task;
1236 sourceStack = sourceTask.stack;
1237 } else {
1238 sourceTask = null;
1239 sourceStack = null;
1240 }
1241
Craig Mautner8849a5e2013-04-02 16:41:03 -07001242 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1243 // For whatever reason this activity is being launched into a new
1244 // task... yet the caller has requested a result back. Well, that
1245 // is pretty messed up, so instead immediately send back a cancel
1246 // and let the new task continue launched as normal without a
1247 // dependency on its originator.
1248 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1249 r.resultTo.task.stack.sendActivityResultLocked(-1,
1250 r.resultTo, r.resultWho, r.requestCode,
1251 Activity.RESULT_CANCELED, null);
1252 r.resultTo = null;
1253 }
1254
1255 boolean addingToTask = false;
1256 boolean movedHome = false;
1257 TaskRecord reuseTask = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001258 ActivityStack targetStack;
Craig Mautner8849a5e2013-04-02 16:41:03 -07001259 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1260 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1261 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1262 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1263 // If bring to front is requested, and no result is requested, and
1264 // we can find a task that was started with this same
1265 // component, then instead of launching bring that one to the front.
1266 if (r.resultTo == null) {
1267 // See if there is a task to bring to the front. If this is
1268 // a SINGLE_INSTANCE activity, there can be one and only one
1269 // instance of it in the history, and it is always in its own
1270 // unique task, so we do a special search.
1271 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
1272 ? findTaskLocked(intent, r.info)
1273 : findActivityLocked(intent, r.info);
1274 if (intentActivity != null) {
Craig Mautner29219d92013-04-16 20:19:12 -07001275 if (r.task == null) {
1276 r.task = intentActivity.task;
1277 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001278 targetStack = intentActivity.task.stack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001279 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001280 if (intentActivity.task.intent == null) {
1281 // This task was started because of movement of
1282 // the activity based on affinity... now that we
1283 // are actually launching it, we can assign the
1284 // base intent.
1285 intentActivity.task.setIntent(intent, r.info);
1286 }
1287 // If the target task is not in the front, then we need
1288 // to bring it to the front... except... well, with
1289 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
1290 // to have the same behavior as if a new instance was
1291 // being started, which means not bringing it to the front
1292 // if the caller is not itself in the front.
Craig Mautner165640b2013-04-20 10:34:33 -07001293 final ActivityStack lastStack = getLastStack();
1294 ActivityRecord curTop = lastStack == null?
1295 null : lastStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001296 if (curTop != null && curTop.task != intentActivity.task) {
1297 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001298 if (sourceRecord == null || sourceStack.topActivity() == sourceRecord) {
Craig Mautner8849a5e2013-04-02 16:41:03 -07001299 // We really do want to push this one into the
1300 // user's face, right now.
1301 movedHome = true;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001302 if ((launchFlags &
Craig Mautner29219d92013-04-16 20:19:12 -07001303 (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1304 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001305 // Caller wants to appear on home activity, so before starting
1306 // their own activity we will bring home to the front.
1307 r.mLaunchHomeTaskNext = true;
1308 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001309 targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1310 options = null;
1311 }
1312 }
1313 // If the caller has requested that the target task be
1314 // reset, then do so.
1315 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1316 intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1317 }
1318 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1319 // We don't need to start a new activity, and
1320 // the client said not to do anything if that
1321 // is the case, so this is it! And for paranoia, make
1322 // sure we have correctly resumed the top activity.
1323 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001324 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001325 targetStack.resumeTopActivityLocked(null, options);
1326 } else {
1327 ActivityOptions.abort(options);
1328 }
Craig Mautner29219d92013-04-16 20:19:12 -07001329 if (r.task == null) Slog.v(TAG,
1330 "startActivityUncheckedLocked: task left null",
1331 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001332 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1333 }
1334 if ((launchFlags &
1335 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1336 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1337 // The caller has requested to completely replace any
1338 // existing task with its new activity. Well that should
1339 // not be too hard...
1340 reuseTask = intentActivity.task;
1341 reuseTask.performClearTaskLocked();
1342 reuseTask.setIntent(r.intent, r.info);
1343 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1344 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1345 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1346 // In this situation we want to remove all activities
1347 // from the task up to the one being started. In most
1348 // cases this means we are resetting the task to its
1349 // initial state.
1350 ActivityRecord top =
1351 intentActivity.task.performClearTaskLocked(r, launchFlags);
1352 if (top != null) {
1353 if (top.frontOfTask) {
1354 // Activity aliases may mean we use different
1355 // intents for the top activity, so make sure
1356 // the task now has the identity of the new
1357 // intent.
1358 top.task.setIntent(r.intent, r.info);
1359 }
1360 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1361 r, top.task);
1362 top.deliverNewIntentLocked(callingUid, r.intent);
1363 } else {
1364 // A special case: we need to
1365 // start the activity because it is not currently
1366 // running, and the caller has asked to clear the
1367 // current task to have this activity at the top.
1368 addingToTask = true;
1369 // Now pretend like this activity is being started
1370 // by the top of its task, so it is put in the
1371 // right place.
1372 sourceRecord = intentActivity;
1373 }
1374 } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1375 // In this case the top activity on the task is the
1376 // same as the one being launched, so we take that
1377 // as a request to bring the task to the foreground.
1378 // If the top activity in the task is the root
1379 // activity, deliver this new intent to it if it
1380 // desires.
1381 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1382 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1383 && intentActivity.realActivity.equals(r.realActivity)) {
1384 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1385 intentActivity.task);
1386 if (intentActivity.frontOfTask) {
1387 intentActivity.task.setIntent(r.intent, r.info);
1388 }
1389 intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1390 } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1391 // In this case we are launching the root activity
1392 // of the task, but with a different intent. We
1393 // should start a new instance on top.
1394 addingToTask = true;
1395 sourceRecord = intentActivity;
1396 }
1397 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1398 // In this case an activity is being launched in to an
1399 // existing task, without resetting that task. This
1400 // is typically the situation of launching an activity
1401 // from a notification or shortcut. We want to place
1402 // the new activity on top of the current task.
1403 addingToTask = true;
1404 sourceRecord = intentActivity;
1405 } else if (!intentActivity.task.rootWasReset) {
1406 // In this case we are launching in to an existing task
1407 // that has not yet been started from its front door.
1408 // The current task has been brought to the front.
1409 // Ideally, we'd probably like to place this new task
1410 // at the bottom of its stack, but that's a little hard
1411 // to do with the current organization of the code so
1412 // for now we'll just drop it.
1413 intentActivity.task.setIntent(r.intent, r.info);
1414 }
1415 if (!addingToTask && reuseTask == null) {
1416 // We didn't do anything... but it was needed (a.k.a., client
1417 // don't use that intent!) And for paranoia, make
1418 // sure we have correctly resumed the top activity.
1419 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001420 setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1421 targetStack.resumeTopActivityLocked(null, options);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001422 } else {
1423 ActivityOptions.abort(options);
1424 }
Craig Mautner29219d92013-04-16 20:19:12 -07001425 if (r.task == null) Slog.v(TAG,
1426 "startActivityUncheckedLocked: task left null",
1427 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001428 return ActivityManager.START_TASK_TO_FRONT;
1429 }
1430 }
1431 }
1432 }
1433
1434 //String uri = r.intent.toURI();
1435 //Intent intent2 = new Intent(uri);
1436 //Slog.i(TAG, "Given intent: " + r.intent);
1437 //Slog.i(TAG, "URI is: " + uri);
1438 //Slog.i(TAG, "To intent: " + intent2);
1439
1440 if (r.packageName != null) {
1441 // If the activity being launched is the same as the one currently
1442 // at the top, then we need to check if it should only be launched
1443 // once.
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001444 ActivityStack topStack = getFocusedStack();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001445 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001446 if (top != null && r.resultTo == null) {
1447 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1448 if (top.app != null && top.app.thread != null) {
1449 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1450 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1451 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1452 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1453 top.task);
1454 // For paranoia, make sure we have correctly
1455 // resumed the top activity.
1456 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001457 setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
1458 topStack.resumeTopActivityLocked(null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001459 }
1460 ActivityOptions.abort(options);
1461 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1462 // We don't need to start a new activity, and
1463 // the client said not to do anything if that
1464 // is the case, so this is it!
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_RETURN_INTENT_TO_CALLER;
1469 }
1470 top.deliverNewIntentLocked(callingUid, r.intent);
Craig Mautner29219d92013-04-16 20:19:12 -07001471 if (r.task == null) Slog.v(TAG,
1472 "startActivityUncheckedLocked: task left null",
1473 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001474 return ActivityManager.START_DELIVERED_TO_TOP;
1475 }
1476 }
1477 }
1478 }
1479
1480 } else {
1481 if (r.resultTo != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001482 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1483 r.requestCode, Activity.RESULT_CANCELED, null);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001484 }
1485 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001486 if (r.task == null) Slog.v(TAG,
1487 "startActivityUncheckedLocked: task left null",
1488 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001489 return ActivityManager.START_CLASS_NOT_FOUND;
1490 }
1491
1492 boolean newTask = false;
1493 boolean keepCurTransition = false;
1494
1495 // Should this be considered a new task?
1496 if (r.resultTo == null && !addingToTask
1497 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001498 targetStack = getCorrectStack(r);
1499 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001500 if (reuseTask == null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001501 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1502 null, true);
1503 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1504 r.task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001505 } else {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001506 r.setTask(reuseTask, reuseTask, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001507 }
1508 newTask = true;
1509 if (!movedHome) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001510 if ((launchFlags &
1511 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1512 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1513 // Caller wants to appear on home activity, so before starting
1514 // their own activity we will bring home to the front.
1515 r.mLaunchHomeTaskNext = true;
1516 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001517 }
Craig Mautner8849a5e2013-04-02 16:41:03 -07001518 } else if (sourceRecord != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001519 targetStack = sourceRecord.task.stack;
1520 moveHomeStack(targetStack.isHomeStack());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001521 if (!addingToTask &&
1522 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1523 // In this case, we are adding the activity to an existing
1524 // task, but the caller has asked to clear that task if the
1525 // activity is already running.
1526 ActivityRecord top = sourceRecord.task.performClearTaskLocked(r, launchFlags);
1527 keepCurTransition = true;
1528 if (top != null) {
1529 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1530 top.deliverNewIntentLocked(callingUid, r.intent);
1531 // For paranoia, make sure we have correctly
1532 // resumed the top activity.
1533 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001534 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001535 targetStack.resumeTopActivityLocked(null);
1536 }
1537 ActivityOptions.abort(options);
Craig Mautner29219d92013-04-16 20:19:12 -07001538 if (r.task == null) Slog.v(TAG,
1539 "startActivityUncheckedLocked: task left null",
1540 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001541 return ActivityManager.START_DELIVERED_TO_TOP;
1542 }
1543 } else if (!addingToTask &&
1544 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1545 // In this case, we are launching an activity in our own task
1546 // that may already be running somewhere in the history, and
1547 // we want to shuffle it to the front of the stack if so.
1548 final ActivityRecord top =
1549 targetStack.findActivityInHistoryLocked(r, sourceRecord.task);
1550 if (top != null) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001551 final TaskRecord task = top.task;
1552 task.moveActivityToFrontLocked(top);
1553 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001554 top.updateOptionsLocked(options);
1555 top.deliverNewIntentLocked(callingUid, r.intent);
1556 if (doResume) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001557 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001558 targetStack.resumeTopActivityLocked(null);
1559 }
Craig Mautner29219d92013-04-16 20:19:12 -07001560 if (r.task == null) Slog.v(TAG,
1561 "startActivityUncheckedLocked: task left null",
1562 new RuntimeException("here").fillInStackTrace());
Craig Mautner8849a5e2013-04-02 16:41:03 -07001563 return ActivityManager.START_DELIVERED_TO_TOP;
1564 }
1565 }
1566 // An existing activity is starting this new activity, so we want
1567 // to keep the new one in the same task as the one that is starting
1568 // it.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001569 r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001570 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1571 + " in existing task " + r.task);
1572
1573 } else {
1574 // This not being started from an existing activity, and not part
1575 // of a new task... just put it in the top task, though these days
1576 // this case should never happen.
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001577 ActivityStack lastStack = getLastStack();
1578 targetStack = lastStack != null ? lastStack : mHomeStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -07001579 moveHomeStack(targetStack.isHomeStack());
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001580 ActivityRecord prev = lastStack == null ? null : targetStack.topActivity();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001581 r.setTask(prev != null ? prev.task
1582 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1583 null, true);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001584 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1585 + " in new guessed " + r.task);
1586 }
1587
1588 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1589 intent, r.getUriPermissionsLocked());
1590
1591 if (newTask) {
1592 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1593 }
1594 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001595 setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
Craig Mautner8849a5e2013-04-02 16:41:03 -07001596 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
1597 return ActivityManager.START_SUCCESS;
1598 }
1599
Craig Mautnerf3333272013-04-22 10:55:53 -07001600 // Checked.
1601 final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
1602 Configuration config) {
1603 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
1604
1605 ActivityRecord res = null;
1606
1607 ArrayList<ActivityRecord> stops = null;
1608 ArrayList<ActivityRecord> finishes = null;
1609 ArrayList<UserStartedState> startingUsers = null;
1610 int NS = 0;
1611 int NF = 0;
1612 IApplicationThread sendThumbnail = null;
1613 boolean booting = false;
1614 boolean enableScreen = false;
1615 boolean activityRemoved = false;
1616
1617 ActivityRecord r = ActivityRecord.forToken(token);
1618 if (r != null) {
1619 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
1620 r.finishLaunchTickingLocked();
1621 res = r.task.stack.activityIdleInternalLocked(token, fromTimeout, config);
1622 if (res != null) {
1623 if (fromTimeout) {
1624 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
1625 }
1626
1627 // This is a hack to semi-deal with a race condition
1628 // in the client where it can be constructed with a
1629 // newer configuration from when we asked it to launch.
1630 // We'll update with whatever configuration it now says
1631 // it used to launch.
1632 if (config != null) {
1633 r.configuration = config;
1634 }
1635
1636 // We are now idle. If someone is waiting for a thumbnail from
1637 // us, we can now deliver.
1638 r.idle = true;
1639 if (allResumedActivitiesIdle()) {
1640 mService.scheduleAppGcsLocked();
1641 }
1642 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
1643 sendThumbnail = r.app.thread;
1644 r.thumbnailNeeded = false;
1645 }
1646
1647 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
1648 if (!mService.mBooted && isFrontStack(r.task.stack)) {
1649 mService.mBooted = true;
1650 enableScreen = true;
1651 }
1652 } else if (fromTimeout) {
1653 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
1654 }
1655 }
1656
1657 // Atomically retrieve all of the other things to do.
1658 stops = processStoppingActivitiesLocked(true);
1659 NS = stops != null ? stops.size() : 0;
1660 if ((NF=mFinishingActivities.size()) > 0) {
1661 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
1662 mFinishingActivities.clear();
1663 }
1664
1665 final ArrayList<ActivityRecord> thumbnails;
1666 final int NT = mCancelledThumbnails.size();
1667 if (NT > 0) {
1668 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
1669 mCancelledThumbnails.clear();
1670 } else {
1671 thumbnails = null;
1672 }
1673
1674 if (isFrontStack(mHomeStack)) {
1675 booting = mService.mBooting;
1676 mService.mBooting = false;
1677 }
1678
1679 if (mStartingUsers.size() > 0) {
1680 startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
1681 mStartingUsers.clear();
1682 }
1683
1684 // Perform the following actions from unsynchronized state.
1685 final IApplicationThread thumbnailThread = sendThumbnail;
1686 mHandler.post(new Runnable() {
1687 @Override
1688 public void run() {
1689 if (thumbnailThread != null) {
1690 try {
1691 thumbnailThread.requestThumbnail(token);
1692 } catch (Exception e) {
1693 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
1694 mService.sendPendingThumbnail(null, token, null, null, true);
1695 }
1696 }
1697
1698 // Report back to any thumbnail receivers.
1699 for (int i = 0; i < NT; i++) {
1700 ActivityRecord r = thumbnails.get(i);
1701 mService.sendPendingThumbnail(r, null, null, null, true);
1702 }
1703 }
1704 });
1705
1706 // Stop any activities that are scheduled to do so but have been
1707 // waiting for the next one to start.
1708 for (int i = 0; i < NS; i++) {
1709 r = stops.get(i);
1710 final ActivityStack stack = r.task.stack;
1711 if (r.finishing) {
1712 stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
1713 } else {
1714 stack.stopActivityLocked(r);
1715 }
1716 }
1717
1718 // Finish any activities that are scheduled to do so but have been
1719 // waiting for the next one to start.
1720 for (int i = 0; i < NF; i++) {
1721 r = finishes.get(i);
1722 activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle");
1723 }
1724
1725 if (booting) {
1726 mService.finishBooting();
1727 } else if (startingUsers != null) {
1728 for (int i = 0; i < startingUsers.size(); i++) {
1729 mService.finishUserSwitch(startingUsers.get(i));
1730 }
1731 }
1732
1733 mService.trimApplications();
1734 //dump();
1735 //mWindowManager.dump();
1736
1737 if (enableScreen) {
1738 mService.enableScreenAfterBoot();
1739 }
1740
1741 if (activityRemoved) {
1742 getFocusedStack().resumeTopActivityLocked(null);
1743 }
1744
1745 return res;
1746 }
1747
Craig Mautner8d341ef2013-03-26 09:03:27 -07001748 void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
1749 // Just in case.
1750 final int numStacks = mStacks.size();
1751 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Craig Mautnere79d42682013-04-01 19:01:53 -07001752 mStacks.get(stackNdx).handleAppDiedLocked(app, restarting);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001753 }
1754 }
1755
1756 void closeSystemDialogsLocked() {
1757 final int numStacks = mStacks.size();
1758 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1759 final ActivityStack stack = mStacks.get(stackNdx);
1760 stack.closeSystemDialogsLocked();
1761 }
1762 }
1763
1764 /**
1765 * @return true if some activity was finished (or would have finished if doit were true).
1766 */
1767 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1768 boolean didSomething = false;
1769 final int numStacks = mStacks.size();
1770 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1771 final ActivityStack stack = mStacks.get(stackNdx);
1772 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1773 didSomething = true;
1774 }
1775 }
1776 return didSomething;
1777 }
1778
1779 void resumeTopActivityLocked() {
Craig Mautnerdbcb31f2013-04-02 12:32:53 -07001780 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautnerf88c50f2013-04-18 19:25:12 -07001781 final ActivityStack stack = mStacks.get(stackNdx);
1782 if (isFrontStack(stack)) {
1783 stack.resumeTopActivityLocked(null);
1784 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001785 }
1786 }
1787
1788 void finishTopRunningActivityLocked(ProcessRecord app) {
1789 final int numStacks = mStacks.size();
1790 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1791 final ActivityStack stack = mStacks.get(stackNdx);
1792 stack.finishTopRunningActivityLocked(app);
1793 }
1794 }
1795
Craig Mautner8d341ef2013-03-26 09:03:27 -07001796 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
1797 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1798 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
1799 return;
1800 }
1801 }
1802 }
1803
Craig Mautner967212c2013-04-13 21:10:58 -07001804 ActivityStack getStack(int stackId) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001805 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1806 final ActivityStack stack = mStacks.get(stackNdx);
1807 if (stack.getStackId() == stackId) {
1808 return stack;
1809 }
1810 }
1811 return null;
1812 }
1813
Craig Mautner967212c2013-04-13 21:10:58 -07001814 ArrayList<ActivityStack> getStacks() {
1815 return new ArrayList<ActivityStack>(mStacks);
1816 }
1817
1818 int createStack() {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001819 synchronized (this) {
1820 while (true) {
1821 if (++mLastStackId <= HOME_STACK_ID) {
1822 mLastStackId = HOME_STACK_ID + 1;
1823 }
1824 if (getStack(mLastStackId) == null) {
1825 break;
1826 }
1827 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001828 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
Craig Mautner8d341ef2013-03-26 09:03:27 -07001829 return mLastStackId;
1830 }
1831 }
1832
1833 void moveTaskToStack(int taskId, int stackId, boolean toTop) {
1834 final ActivityStack stack = getStack(stackId);
1835 if (stack == null) {
1836 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
1837 return;
1838 }
1839 stack.moveTask(taskId, toTop);
Craig Mautner967212c2013-04-13 21:10:58 -07001840 stack.resumeTopActivityLocked(null);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001841 }
1842
Craig Mautner8849a5e2013-04-02 16:41:03 -07001843 ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
1844 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1845 final ActivityRecord ar = mStacks.get(stackNdx).findTaskLocked(intent, info);
1846 if (ar != null) {
1847 return ar;
1848 }
1849 }
1850 return null;
1851 }
1852
1853 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
1854 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1855 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
1856 if (ar != null) {
1857 return ar;
1858 }
1859 }
1860 return null;
1861 }
1862
Craig Mautner8d341ef2013-03-26 09:03:27 -07001863 void goingToSleepLocked() {
1864 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1865 mStacks.get(stackNdx).stopIfSleepingLocked();
1866 }
1867 }
1868
1869 boolean shutdownLocked(int timeout) {
1870 boolean timedout = false;
1871 final int numStacks = mStacks.size();
1872 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1873 final ActivityStack stack = mStacks.get(stackNdx);
1874 if (stack.mResumedActivity != null) {
1875 stack.stopIfSleepingLocked();
1876 final long endTime = System.currentTimeMillis() + timeout;
1877 while (stack.mResumedActivity != null || stack.mPausingActivity != null) {
1878 long delay = endTime - System.currentTimeMillis();
1879 if (delay <= 0) {
1880 Slog.w(TAG, "Activity manager shutdown timed out");
1881 timedout = true;
1882 break;
1883 }
1884 try {
1885 mService.wait();
1886 } catch (InterruptedException e) {
1887 }
1888 }
1889 }
1890 }
1891 return timedout;
1892 }
1893
1894 void comeOutOfSleepIfNeededLocked() {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001895 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
Craig Mautner8d341ef2013-03-26 09:03:27 -07001896 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001897 stack.awakeFromSleepingLocked();
1898 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001899 stack.resumeTopActivityLocked(null);
1900 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001901 }
1902 }
1903
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001904 boolean reportResumedActivityLocked(ActivityRecord r) {
1905 final ActivityStack stack = r.task.stack;
1906 if (isFrontStack(stack)) {
1907 mService.reportResumedActivityLocked(r);
1908 mService.setFocusedActivityLocked(r);
1909 }
1910 if (allResumedActivitiesComplete()) {
1911 ensureActivitiesVisibleLocked(null, 0);
1912 mWindowManager.executeAppTransition();
1913 return true;
1914 }
1915 return false;
1916 }
1917
Craig Mautner8d341ef2013-03-26 09:03:27 -07001918 void handleAppCrashLocked(ProcessRecord app) {
1919 final int numStacks = mStacks.size();
1920 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1921 final ActivityStack stack = mStacks.get(stackNdx);
1922 stack.handleAppCrashLocked(app);
1923 }
1924 }
1925
Craig Mautnerde4ef022013-04-07 19:01:33 -07001926 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
1927 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1928 mStacks.get(stackNdx).ensureActivitiesVisibleLocked(starting, configChanges);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001929 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001930 }
1931
1932 void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
1933 final int numStacks = mStacks.size();
1934 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1935 final ActivityStack stack = mStacks.get(stackNdx);
1936 stack.scheduleDestroyActivities(app, false, reason);
1937 }
1938 }
1939
1940 boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner2420ead2013-04-01 17:13:20 -07001941 mCurrentUser = userId;
Craig Mautnerf3333272013-04-22 10:55:53 -07001942 mStartingUsers.add(uss);
Craig Mautner8d341ef2013-03-26 09:03:27 -07001943 boolean haveActivities = false;
1944 final int numStacks = mStacks.size();
1945 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1946 final ActivityStack stack = mStacks.get(stackNdx);
Craig Mautnerf3333272013-04-22 10:55:53 -07001947 if (isFrontStack(stack)) {
Craig Mautnerde4ef022013-04-07 19:01:33 -07001948 haveActivities |= stack.switchUserLocked(userId, uss);
1949 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07001950 }
1951 return haveActivities;
Craig Mautner2219a1b2013-03-25 09:44:30 -07001952 }
1953
Craig Mautnerde4ef022013-04-07 19:01:33 -07001954 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
1955 int N = mStoppingActivities.size();
1956 if (N <= 0) return null;
1957
1958 ArrayList<ActivityRecord> stops = null;
1959
1960 final boolean nowVisible = allResumedActivitiesVisible();
1961 for (int i=0; i<N; i++) {
1962 ActivityRecord s = mStoppingActivities.get(i);
1963 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
1964 + nowVisible + " waitingVisible=" + s.waitingVisible
1965 + " finishing=" + s.finishing);
1966 if (s.waitingVisible && nowVisible) {
1967 mWaitingVisibleActivities.remove(s);
1968 s.waitingVisible = false;
1969 if (s.finishing) {
1970 // If this activity is finishing, it is sitting on top of
1971 // everyone else but we now know it is no longer needed...
1972 // so get rid of it. Otherwise, we need to go through the
1973 // normal flow and hide it once we determine that it is
1974 // hidden by the activities in front of it.
1975 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07001976 mWindowManager.setAppVisibility(s.appToken, false);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001977 }
1978 }
1979 if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
1980 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
1981 if (stops == null) {
1982 stops = new ArrayList<ActivityRecord>();
1983 }
1984 stops.add(s);
1985 mStoppingActivities.remove(i);
1986 N--;
1987 i--;
1988 }
1989 }
1990
1991 return stops;
1992 }
1993
Craig Mautnercf910b02013-04-23 11:23:27 -07001994 void validateTopActivitiesLocked() {
1995 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1996 final ActivityStack stack = mStacks.get(stackNdx);
1997 final ActivityRecord r = stack.topRunningActivityLocked(null);
1998 if (isFrontStack(stack)) {
1999 if (r == null) {
2000 Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
2001 } else {
2002 if (stack.mPausingActivity != null) {
2003 Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
2004 " state=" + r.state);
2005 }
2006 if (r.state != ActivityState.INITIALIZING &&
2007 r.state != ActivityState.RESUMED) {
2008 Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
2009 " state=" + r.state);
2010 }
2011 }
2012 } else {
2013 if (stack.mResumedActivity != null) {
2014 Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
2015 " state=" + r.state);
2016 }
2017 if (r != null && (r.state == ActivityState.INITIALIZING
2018 || r.state == ActivityState.RESUMED)) {
2019 Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
2020 " state=" + r.state);
2021 }
2022 }
2023 }
2024 }
2025
Craig Mautner27084302013-03-25 08:05:25 -07002026 public void dump(PrintWriter pw, String prefix) {
2027 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
2028 pw.println(mDismissKeyguardOnNextActivity);
2029 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002030
Craig Mautner20e72272013-04-01 13:45:53 -07002031 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002032 return getFocusedStack().getDumpActivitiesLocked(name);
Craig Mautner20e72272013-04-01 13:45:53 -07002033 }
2034
Craig Mautner8d341ef2013-03-26 09:03:27 -07002035 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
2036 boolean dumpClient, String dumpPackage) {
2037 final int numStacks = mStacks.size();
2038 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2039 final ActivityStack stack = mStacks.get(stackNdx);
2040 pw.print(" Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
2041 stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
2042 pw.println(" ");
2043 pw.println(" Running activities (most recent first):");
2044 dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false,
2045 dumpPackage);
Craig Mautner8d341ef2013-03-26 09:03:27 -07002046 if (stack.mGoingToSleepActivities.size() > 0) {
2047 pw.println(" ");
2048 pw.println(" Activities waiting to sleep:");
2049 dumpHistoryList(fd, pw, stack.mGoingToSleepActivities, " ", "Sleep", false,
2050 !dumpAll, false, dumpPackage);
2051 }
Craig Mautner8d341ef2013-03-26 09:03:27 -07002052
Craig Mautner8d341ef2013-03-26 09:03:27 -07002053 pw.print(" Stack #"); pw.println(mStacks.indexOf(stack));
2054 if (stack.mPausingActivity != null) {
2055 pw.println(" mPausingActivity: " + stack.mPausingActivity);
2056 }
2057 pw.println(" mResumedActivity: " + stack.mResumedActivity);
2058 if (dumpAll) {
2059 pw.println(" mLastPausedActivity: " + stack.mLastPausedActivity);
2060 pw.println(" mSleepTimeout: " + stack.mSleepTimeout);
2061 }
2062 }
2063
Craig Mautnerf3333272013-04-22 10:55:53 -07002064 if (mFinishingActivities.size() > 0) {
2065 pw.println(" ");
2066 pw.println(" Activities waiting to finish:");
2067 dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll, false,
2068 dumpPackage);
2069 }
2070
Craig Mautnerde4ef022013-04-07 19:01:33 -07002071 if (mStoppingActivities.size() > 0) {
2072 pw.println(" ");
2073 pw.println(" Activities waiting to stop:");
2074 dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, false,
2075 dumpPackage);
2076 }
2077
2078 if (mWaitingVisibleActivities.size() > 0) {
2079 pw.println(" ");
2080 pw.println(" Activities waiting for another to become visible:");
2081 dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
2082 false, dumpPackage);
2083 }
2084
Craig Mautner8d341ef2013-03-26 09:03:27 -07002085 if (dumpAll) {
2086 pw.println(" ");
2087 pw.println(" mCurTaskId: " + mCurTaskId);
2088 }
2089 return true;
2090 }
2091
2092 static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
2093 String prefix, String label, boolean complete, boolean brief, boolean client,
2094 String dumpPackage) {
2095 TaskRecord lastTask = null;
2096 boolean needNL = false;
2097 final String innerPrefix = prefix + " ";
2098 final String[] args = new String[0];
2099 for (int i=list.size()-1; i>=0; i--) {
2100 final ActivityRecord r = list.get(i);
2101 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
2102 continue;
2103 }
2104 final boolean full = !brief && (complete || !r.isInHistory());
2105 if (needNL) {
2106 pw.println(" ");
2107 needNL = false;
2108 }
2109 if (lastTask != r.task) {
2110 lastTask = r.task;
2111 pw.print(prefix);
2112 pw.print(full ? "* " : " ");
2113 pw.println(lastTask);
2114 if (full) {
2115 lastTask.dump(pw, prefix + " ");
2116 } else if (complete) {
2117 // Complete + brief == give a summary. Isn't that obvious?!?
2118 if (lastTask.intent != null) {
2119 pw.print(prefix); pw.print(" ");
2120 pw.println(lastTask.intent.toInsecureStringWithClip());
2121 }
2122 }
2123 }
2124 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
2125 pw.print(" #"); pw.print(i); pw.print(": ");
2126 pw.println(r);
2127 if (full) {
2128 r.dump(pw, innerPrefix);
2129 } else if (complete) {
2130 // Complete + brief == give a summary. Isn't that obvious?!?
2131 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
2132 if (r.app != null) {
2133 pw.print(innerPrefix); pw.println(r.app);
2134 }
2135 }
2136 if (client && r.app != null && r.app.thread != null) {
2137 // flush anything that is already in the PrintWriter since the thread is going
2138 // to write to the file descriptor directly
2139 pw.flush();
2140 try {
2141 TransferPipe tp = new TransferPipe();
2142 try {
2143 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
2144 r.appToken, innerPrefix, args);
2145 // Short timeout, since blocking here can
2146 // deadlock with the application.
2147 tp.go(fd, 2000);
2148 } finally {
2149 tp.kill();
2150 }
2151 } catch (IOException e) {
2152 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
2153 } catch (RemoteException e) {
2154 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
2155 }
2156 needNL = true;
2157 }
2158 }
2159 }
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002160
Craig Mautnerf3333272013-04-22 10:55:53 -07002161 void scheduleIdleTimeoutLocked(ActivityRecord next) {
2162 mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next).sendToTarget();
2163 }
2164
2165 final void scheduleIdleLocked() {
2166 mHandler.obtainMessage(IDLE_NOW_MSG).sendToTarget();
2167 }
2168
2169 void removeTimeoutsForActivityLocked(ActivityRecord r) {
2170 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
2171 }
2172
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002173 private final class ActivityStackSupervisorHandler extends Handler {
Craig Mautnerf3333272013-04-22 10:55:53 -07002174
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002175 public ActivityStackSupervisorHandler(Looper looper) {
2176 super(looper);
2177 }
2178
Craig Mautnerf3333272013-04-22 10:55:53 -07002179 void activityIdleInternal(ActivityRecord r) {
2180 synchronized (mService) {
2181 activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
2182 }
2183 }
2184
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002185 @Override
2186 public void handleMessage(Message msg) {
2187 switch (msg.what) {
Craig Mautnerf3333272013-04-22 10:55:53 -07002188 case IDLE_TIMEOUT_MSG: {
2189 if (mService.mDidDexOpt) {
2190 mService.mDidDexOpt = false;
2191 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2192 nmsg.obj = msg.obj;
2193 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
2194 return;
2195 }
2196 // We don't at this point know if the activity is fullscreen,
2197 // so we need to be conservative and assume it isn't.
2198 activityIdleInternal((ActivityRecord)msg.obj);
2199 } break;
2200 case IDLE_NOW_MSG: {
2201 activityIdleInternal((ActivityRecord)msg.obj);
2202 } break;
Craig Mautnerce5f3cb2013-04-22 08:58:54 -07002203 }
2204 }
2205 }
Craig Mautner27084302013-03-25 08:05:25 -07002206}