blob: e0b80150fe306bde3e2c5ceb0c3bb701299b2f51 [file] [log] [blame]
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001/*
2 * Copyright (C) 2010 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
Jeff Sharkey35be7562012-04-18 19:16:15 -070019import static android.Manifest.permission.START_ANY_ACTIVITY;
20import static android.content.pm.PackageManager.PERMISSION_GRANTED;
21
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070022import com.android.internal.app.HeavyWeightSwitcherActivity;
23import com.android.internal.os.BatteryStatsImpl;
Craig Mautnercae015f2013-02-08 14:31:27 -080024import com.android.server.am.ActivityManagerService.ItemMatcher;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070025import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
Craig Mautner4b71aa12012-12-27 17:20:01 -080026import com.android.server.wm.AppTransition;
Craig Mautner05d6272ba2013-02-11 09:39:27 -080027import com.android.server.wm.TaskGroup;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070028
29import android.app.Activity;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070030import android.app.ActivityManager;
Dianne Hackborn7a2195c2012-03-19 17:38:00 -070031import android.app.ActivityOptions;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070032import android.app.AppGlobals;
Craig Mautner05d6272ba2013-02-11 09:39:27 -080033import android.app.IActivityController;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070034import android.app.IActivityManager;
Craig Mautnercae015f2013-02-08 14:31:27 -080035import android.app.IThumbnailReceiver;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070036import android.app.IThumbnailRetriever;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070037import android.app.IApplicationThread;
38import android.app.PendingIntent;
39import android.app.ResultInfo;
Craig Mautnercae015f2013-02-08 14:31:27 -080040import android.app.ActivityManager.RunningTaskInfo;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070041import android.app.IActivityManager.WaitResult;
42import android.content.ComponentName;
43import android.content.Context;
44import android.content.IIntentSender;
45import android.content.Intent;
46import android.content.IntentSender;
47import android.content.pm.ActivityInfo;
48import android.content.pm.ApplicationInfo;
49import android.content.pm.PackageManager;
50import android.content.pm.ResolveInfo;
51import android.content.res.Configuration;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080052import android.content.res.Resources;
53import android.graphics.Bitmap;
Craig Mautnerb12428a2012-12-20 16:07:06 -080054import android.graphics.Bitmap.Config;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070055import android.os.Binder;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070056import android.os.Bundle;
Craig Mautner5d9c7be2013-02-15 14:02:56 -080057import android.os.Debug;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070058import android.os.Handler;
59import android.os.IBinder;
Zoran Marcetaf958b322012-08-09 20:27:12 +090060import android.os.Looper;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070061import android.os.Message;
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070062import android.os.ParcelFileDescriptor;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070063import android.os.PowerManager;
64import android.os.RemoteException;
65import android.os.SystemClock;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070066import android.os.UserHandle;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070067import android.util.EventLog;
68import android.util.Log;
69import android.util.Slog;
Craig Mautner5d9c7be2013-02-15 14:02:56 -080070import android.util.SparseArray;
Craig Mautner59c00972012-07-30 12:10:24 -070071import android.view.Display;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070072
Craig Mautnercae015f2013-02-08 14:31:27 -080073import java.io.FileDescriptor;
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070074import java.io.IOException;
Craig Mautnercae015f2013-02-08 14:31:27 -080075import java.io.PrintWriter;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070076import java.lang.ref.WeakReference;
77import java.util.ArrayList;
78import java.util.Iterator;
79import java.util.List;
80
81/**
82 * State and management of a single stack of activities.
83 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070084final class ActivityStack {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070085 static final String TAG = ActivityManagerService.TAG;
Dianne Hackbornb961cd22011-06-21 12:13:37 -070086 static final boolean localLOGV = ActivityManagerService.localLOGV;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070087 static final boolean DEBUG_SWITCH = ActivityManagerService.DEBUG_SWITCH;
88 static final boolean DEBUG_PAUSE = ActivityManagerService.DEBUG_PAUSE;
89 static final boolean DEBUG_VISBILITY = ActivityManagerService.DEBUG_VISBILITY;
90 static final boolean DEBUG_USER_LEAVING = ActivityManagerService.DEBUG_USER_LEAVING;
91 static final boolean DEBUG_TRANSITION = ActivityManagerService.DEBUG_TRANSITION;
92 static final boolean DEBUG_RESULTS = ActivityManagerService.DEBUG_RESULTS;
93 static final boolean DEBUG_CONFIGURATION = ActivityManagerService.DEBUG_CONFIGURATION;
94 static final boolean DEBUG_TASKS = ActivityManagerService.DEBUG_TASKS;
Dianne Hackborncc5a0552012-10-01 16:32:39 -070095 static final boolean DEBUG_CLEANUP = ActivityManagerService.DEBUG_CLEANUP;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070096
Dianne Hackbornce86ba82011-07-13 19:33:41 -070097 static final boolean DEBUG_STATES = false;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070098 static final boolean DEBUG_ADD_REMOVE = false;
99 static final boolean DEBUG_SAVED_STATE = false;
Dianne Hackborn07981492013-01-28 11:36:23 -0800100 static final boolean DEBUG_APP = false;
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700101
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700102 static final boolean VALIDATE_TOKENS = ActivityManagerService.VALIDATE_TOKENS;
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800103 static final boolean VALIDATE_TASK_REPLACE = true;
104
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700105 // How long we wait until giving up on the last activity telling us it
106 // is idle.
107 static final int IDLE_TIMEOUT = 10*1000;
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -0700108
109 // Ticks during which we check progress while waiting for an app to launch.
110 static final int LAUNCH_TICK = 500;
111
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700112 // How long we wait until giving up on the last activity to pause. This
113 // is short because it directly impacts the responsiveness of starting the
114 // next activity.
115 static final int PAUSE_TIMEOUT = 500;
116
Dianne Hackborn162bc0e2012-04-09 14:06:16 -0700117 // How long we wait for the activity to tell us it has stopped before
118 // giving up. This is a good amount of time because we really need this
119 // from the application in order to get its saved state.
120 static final int STOP_TIMEOUT = 10*1000;
121
Dianne Hackborn4eba96b2011-01-21 13:34:36 -0800122 // How long we can hold the sleep wake lock before giving up.
123 static final int SLEEP_TIMEOUT = 5*1000;
124
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700125 // How long we can hold the launch wake lock before giving up.
126 static final int LAUNCH_TIMEOUT = 10*1000;
127
128 // How long we wait until giving up on an activity telling us it has
129 // finished destroying itself.
130 static final int DESTROY_TIMEOUT = 10*1000;
131
132 // How long until we reset a task when the user returns to it. Currently
Dianne Hackborn621e17d2010-11-22 15:59:56 -0800133 // disabled.
134 static final long ACTIVITY_INACTIVE_RESET_TIME = 0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700135
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700136 // How long between activity launches that we consider safe to not warn
137 // the user about an unexpected activity being launched on top.
138 static final long START_WARN_TIME = 5*1000;
139
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700140 // Set to false to disable the preview that is shown while a new activity
141 // is being started.
142 static final boolean SHOW_APP_STARTING_PREVIEW = true;
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800143
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700144 enum ActivityState {
145 INITIALIZING,
146 RESUMED,
147 PAUSING,
148 PAUSED,
149 STOPPING,
150 STOPPED,
151 FINISHING,
152 DESTROYING,
153 DESTROYED
154 }
155
156 final ActivityManagerService mService;
157 final boolean mMainStack;
158
159 final Context mContext;
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800160
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700161 /**
162 * The back history of all previous (and possibly still
Craig Mautnercae015f2013-02-08 14:31:27 -0800163 * running) activities. It contains #ActivityRecord objects.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700164 */
Craig Mautnercae015f2013-02-08 14:31:27 -0800165 private final ArrayList<ActivityRecord> mHistory = new ArrayList<ActivityRecord>();
Dianne Hackbornbe707852011-11-11 14:32:10 -0800166
167 /**
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800168 * The back history of all previous (and possibly still
169 * running) activities. It contains #TaskRecord objects.
170 */
171 private ArrayList<TaskRecord> mTaskHistory = new ArrayList<TaskRecord>();
172
173 /**
174 * Mapping from taskId to TaskRecord
175 */
176 private SparseArray<TaskRecord> mTaskIdToTaskRecord = new SparseArray<TaskRecord>();
177
178 /**
Dianne Hackbornbe707852011-11-11 14:32:10 -0800179 * Used for validating app tokens with window manager.
180 */
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800181 final ArrayList<TaskGroup> mValidateAppTokens = new ArrayList<TaskGroup>();
Dianne Hackbornbe707852011-11-11 14:32:10 -0800182
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700183 /**
184 * List of running activities, sorted by recent usage.
185 * The first entry in the list is the least recently used.
186 * It contains HistoryRecord objects.
187 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700188 final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<ActivityRecord>();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700189
190 /**
191 * List of activities that are waiting for a new activity
192 * to become visible before completing whatever operation they are
193 * supposed to do.
194 */
195 final ArrayList<ActivityRecord> mWaitingVisibleActivities
196 = new ArrayList<ActivityRecord>();
197
198 /**
199 * List of activities that are ready to be stopped, but waiting
200 * for the next activity to settle down before doing so. It contains
201 * HistoryRecord objects.
202 */
203 final ArrayList<ActivityRecord> mStoppingActivities
204 = new ArrayList<ActivityRecord>();
205
206 /**
Dianne Hackborn4eba96b2011-01-21 13:34:36 -0800207 * List of activities that are in the process of going to sleep.
208 */
209 final ArrayList<ActivityRecord> mGoingToSleepActivities
210 = new ArrayList<ActivityRecord>();
211
212 /**
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700213 * Animations that for the current transition have requested not to
214 * be considered for the transition animation.
215 */
216 final ArrayList<ActivityRecord> mNoAnimActivities
217 = new ArrayList<ActivityRecord>();
218
219 /**
220 * List of activities that are ready to be finished, but waiting
221 * for the previous activity to settle down before doing so. It contains
222 * HistoryRecord objects.
223 */
224 final ArrayList<ActivityRecord> mFinishingActivities
225 = new ArrayList<ActivityRecord>();
226
227 /**
228 * List of people waiting to find out about the next launched activity.
229 */
230 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
231 = new ArrayList<IActivityManager.WaitResult>();
232
233 /**
234 * List of people waiting to find out about the next visible activity.
235 */
236 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
237 = new ArrayList<IActivityManager.WaitResult>();
Dianne Hackborn80a4af22012-08-27 19:18:31 -0700238
239 final ArrayList<UserStartedState> mStartingUsers
240 = new ArrayList<UserStartedState>();
241
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700242 /**
243 * Set when the system is going to sleep, until we have
244 * successfully paused the current activity and released our wake lock.
245 * At that point the system is allowed to actually sleep.
246 */
247 final PowerManager.WakeLock mGoingToSleep;
248
249 /**
250 * We don't want to allow the device to go to sleep while in the process
251 * of launching an activity. This is primarily to allow alarm intent
252 * receivers to launch an activity and get that to run before the device
253 * goes back to sleep.
254 */
255 final PowerManager.WakeLock mLaunchingActivity;
256
257 /**
258 * When we are in the process of pausing an activity, before starting the
259 * next one, this variable holds the activity that is currently being paused.
260 */
Dianne Hackborn621e2fe2012-02-16 17:07:33 -0800261 ActivityRecord mPausingActivity = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700262
263 /**
264 * This is the last activity that we put into the paused state. This is
265 * used to determine if we need to do an activity transition while sleeping,
266 * when we normally hold the top activity paused.
267 */
268 ActivityRecord mLastPausedActivity = null;
269
270 /**
271 * Current activity that is resumed, or null if there is none.
272 */
273 ActivityRecord mResumedActivity = null;
274
275 /**
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700276 * This is the last activity that has been started. It is only used to
277 * identify when multiple activities are started at once so that the user
278 * can be warned they may not be in the activity they think they are.
279 */
280 ActivityRecord mLastStartedActivity = null;
281
282 /**
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700283 * Set when we know we are going to be calling updateConfiguration()
284 * soon, so want to skip intermediate config checks.
285 */
286 boolean mConfigWillChange;
287
288 /**
289 * Set to indicate whether to issue an onUserLeaving callback when a
290 * newly launched activity is being brought in front of us.
291 */
292 boolean mUserLeaving = false;
293
294 long mInitialStartTime = 0;
295
Dianne Hackborn4eba96b2011-01-21 13:34:36 -0800296 /**
297 * Set when we have taken too long waiting to go to sleep.
298 */
299 boolean mSleepTimeout = false;
300
Dianne Hackborn90c52de2011-09-23 12:57:44 -0700301 /**
302 * Dismiss the keyguard after the next activity is displayed?
303 */
304 boolean mDismissKeyguardOnNextActivity = false;
305
Craig Mautnerb12428a2012-12-20 16:07:06 -0800306 /**
307 * Save the most recent screenshot for reuse. This keeps Recents from taking two identical
308 * screenshots, one for the Recents thumbnail and one for the pauseActivity thumbnail.
309 */
310 private ActivityRecord mLastScreenshotActivity = null;
311 private Bitmap mLastScreenshotBitmap = null;
312
Craig Mautnercae015f2013-02-08 14:31:27 -0800313 /**
314 * List of ActivityRecord objects that have been finished and must
315 * still report back to a pending thumbnail receiver.
316 */
317 private final ArrayList<ActivityRecord> mCancelledThumbnails = new ArrayList<ActivityRecord>();
318
Dianne Hackborn0aae2d42010-12-07 23:51:29 -0800319 int mThumbnailWidth = -1;
320 int mThumbnailHeight = -1;
321
Amith Yamasani742a6712011-05-04 14:49:28 -0700322 private int mCurrentUser;
323
Dianne Hackborn40c8db52012-02-10 18:59:48 -0800324 static final int SLEEP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG;
325 static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
326 static final int IDLE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
327 static final int IDLE_NOW_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
328 static final int LAUNCH_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 4;
329 static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 5;
330 static final int RESUME_TOP_ACTIVITY_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6;
Dianne Hackborn29ba7e62012-03-16 15:03:36 -0700331 static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 7;
Dianne Hackborn162bc0e2012-04-09 14:06:16 -0700332 static final int STOP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 8;
Dianne Hackborn755c8bf2012-05-07 15:06:09 -0700333 static final int DESTROY_ACTIVITIES_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 9;
334
335 static class ScheduleDestroyArgs {
336 final ProcessRecord mOwner;
337 final boolean mOomAdj;
338 final String mReason;
339 ScheduleDestroyArgs(ProcessRecord owner, boolean oomAdj, String reason) {
340 mOwner = owner;
341 mOomAdj = oomAdj;
342 mReason = reason;
343 }
344 }
345
Zoran Marcetaf958b322012-08-09 20:27:12 +0900346 final Handler mHandler;
347
Craig Mautner11bf9a52013-02-19 14:08:51 -0800348 String mLastHistoryModifier;
349
Zoran Marcetaf958b322012-08-09 20:27:12 +0900350 final class ActivityStackHandler extends Handler {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700351 //public Handler() {
352 // if (localLOGV) Slog.v(TAG, "Handler started!");
353 //}
Zoran Marcetaf958b322012-08-09 20:27:12 +0900354 public ActivityStackHandler(Looper looper) {
355 super(looper);
356 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700357
Zoran Marcetaf958b322012-08-09 20:27:12 +0900358 @Override
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700359 public void handleMessage(Message msg) {
360 switch (msg.what) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -0800361 case SLEEP_TIMEOUT_MSG: {
Dianne Hackborn8e8d65f2011-08-11 19:36:18 -0700362 synchronized (mService) {
363 if (mService.isSleeping()) {
364 Slog.w(TAG, "Sleep timeout! Sleeping now.");
365 mSleepTimeout = true;
366 checkReadyForSleepLocked();
367 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -0800368 }
369 } break;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700370 case PAUSE_TIMEOUT_MSG: {
Dianne Hackbornbe707852011-11-11 14:32:10 -0800371 ActivityRecord r = (ActivityRecord)msg.obj;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700372 // We don't at this point know if the activity is fullscreen,
373 // so we need to be conservative and assume it isn't.
Dianne Hackbornbe707852011-11-11 14:32:10 -0800374 Slog.w(TAG, "Activity pause timeout for " + r);
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -0700375 synchronized (mService) {
376 if (r.app != null) {
377 mService.logAppTooSlow(r.app, r.pauseTime,
378 "pausing " + r);
379 }
380 }
381
Dianne Hackbornbe707852011-11-11 14:32:10 -0800382 activityPaused(r != null ? r.appToken : null, true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700383 } break;
384 case IDLE_TIMEOUT_MSG: {
385 if (mService.mDidDexOpt) {
386 mService.mDidDexOpt = false;
387 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
388 nmsg.obj = msg.obj;
389 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
390 return;
391 }
392 // We don't at this point know if the activity is fullscreen,
393 // so we need to be conservative and assume it isn't.
Dianne Hackbornbe707852011-11-11 14:32:10 -0800394 ActivityRecord r = (ActivityRecord)msg.obj;
395 Slog.w(TAG, "Activity idle timeout for " + r);
396 activityIdleInternal(r != null ? r.appToken : null, true, null);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700397 } break;
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -0700398 case LAUNCH_TICK_MSG: {
399 ActivityRecord r = (ActivityRecord)msg.obj;
400 synchronized (mService) {
401 if (r.continueLaunchTickingLocked()) {
402 mService.logAppTooSlow(r.app, r.launchTickTime,
403 "launching " + r);
404 }
405 }
406 } break;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700407 case DESTROY_TIMEOUT_MSG: {
Dianne Hackbornbe707852011-11-11 14:32:10 -0800408 ActivityRecord r = (ActivityRecord)msg.obj;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700409 // We don't at this point know if the activity is fullscreen,
410 // so we need to be conservative and assume it isn't.
Dianne Hackbornbe707852011-11-11 14:32:10 -0800411 Slog.w(TAG, "Activity destroy timeout for " + r);
412 activityDestroyed(r != null ? r.appToken : null);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700413 } break;
414 case IDLE_NOW_MSG: {
Dianne Hackbornbe707852011-11-11 14:32:10 -0800415 ActivityRecord r = (ActivityRecord)msg.obj;
416 activityIdleInternal(r != null ? r.appToken : null, false, null);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700417 } break;
418 case LAUNCH_TIMEOUT_MSG: {
419 if (mService.mDidDexOpt) {
420 mService.mDidDexOpt = false;
421 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
422 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
423 return;
424 }
425 synchronized (mService) {
426 if (mLaunchingActivity.isHeld()) {
427 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
428 mLaunchingActivity.release();
429 }
430 }
431 } break;
432 case RESUME_TOP_ACTIVITY_MSG: {
433 synchronized (mService) {
434 resumeTopActivityLocked(null);
435 }
436 } break;
Dianne Hackborn162bc0e2012-04-09 14:06:16 -0700437 case STOP_TIMEOUT_MSG: {
438 ActivityRecord r = (ActivityRecord)msg.obj;
439 // We don't at this point know if the activity is fullscreen,
440 // so we need to be conservative and assume it isn't.
441 Slog.w(TAG, "Activity stop timeout for " + r);
442 synchronized (mService) {
443 if (r.isInHistory()) {
444 activityStoppedLocked(r, null, null, null);
445 }
446 }
447 } break;
Dianne Hackborn755c8bf2012-05-07 15:06:09 -0700448 case DESTROY_ACTIVITIES_MSG: {
449 ScheduleDestroyArgs args = (ScheduleDestroyArgs)msg.obj;
450 synchronized (mService) {
451 destroyActivitiesLocked(args.mOwner, args.mOomAdj, args.mReason);
452 }
453 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700454 }
455 }
Craig Mautner4b71aa12012-12-27 17:20:01 -0800456 }
457
Zoran Marcetaf958b322012-08-09 20:27:12 +0900458 ActivityStack(ActivityManagerService service, Context context, boolean mainStack, Looper looper) {
459 mHandler = new ActivityStackHandler(looper);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700460 mService = service;
461 mContext = context;
462 mMainStack = mainStack;
463 PowerManager pm =
464 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
465 mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
466 mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
467 mLaunchingActivity.setReferenceCounted(false);
468 }
Craig Mautner5962b122012-10-05 14:45:52 -0700469
470 private boolean okToShow(ActivityRecord r) {
471 return r.userId == mCurrentUser
472 || (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0;
473 }
474
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700475 final ActivityRecord topRunningActivityLocked(ActivityRecord notTop) {
Craig Mautner11bf9a52013-02-19 14:08:51 -0800476 ActivityRecord newAr = newTopRunningActivityLocked(notTop);
477
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700478 int i = mHistory.size()-1;
479 while (i >= 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700480 ActivityRecord r = mHistory.get(i);
Craig Mautner5962b122012-10-05 14:45:52 -0700481 if (!r.finishing && r != notTop && okToShow(r)) {
Craig Mautner11bf9a52013-02-19 14:08:51 -0800482 if (VALIDATE_TASK_REPLACE && newAr != r) logHistories(
483 "topRunningActivityLocked", true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700484 return r;
485 }
486 i--;
487 }
Craig Mautner11bf9a52013-02-19 14:08:51 -0800488 if (VALIDATE_TASK_REPLACE && newAr != null) Slog.w(TAG,
489 "topRunningActivityLocked: mismatch: newAr!=null");
490 return null;
491 }
492
493 final ActivityRecord newTopRunningActivityLocked(ActivityRecord notTop) {
494 for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
495 final TaskRecord task = mTaskHistory.get(i);
496 final ArrayList<ActivityRecord> activities = task.mActivities;
497 for (int j = activities.size() - 1; j >= 0; --j) {
498 ActivityRecord r = activities.get(j);
499 if (!r.finishing && r != notTop && okToShow(r)) {
500 return r;
501 }
502 }
503 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700504 return null;
505 }
506
507 final ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
Craig Mautner11bf9a52013-02-19 14:08:51 -0800508 ActivityRecord newAr = newTopRunningNonDelayedActivityLocked(notTop);
509
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700510 int i = mHistory.size()-1;
511 while (i >= 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700512 ActivityRecord r = mHistory.get(i);
Craig Mautner5962b122012-10-05 14:45:52 -0700513 if (!r.finishing && !r.delayedResume && r != notTop && okToShow(r)) {
Craig Mautner11bf9a52013-02-19 14:08:51 -0800514 if (VALIDATE_TASK_REPLACE && newAr != r) Slog.w(TAG,
515 "topRunningNonDelayedActivityLocked: mismatch: newAr=" + newAr + " r=" + r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700516 return r;
517 }
518 i--;
519 }
Craig Mautner11bf9a52013-02-19 14:08:51 -0800520 if (VALIDATE_TASK_REPLACE && newAr != null) Slog.w(TAG,
521 "topRunningNonDelayedActivityLocked: mismatch: newAr!=null");
522 return null;
523 }
524
525 final ActivityRecord newTopRunningNonDelayedActivityLocked(ActivityRecord notTop) {
526 for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
527 final TaskRecord task = mTaskHistory.get(i);
528 final ArrayList<ActivityRecord> activities = task.mActivities;
529 for (int j = activities.size() - 1; j >= 0; --j) {
530 ActivityRecord r = activities.get(j);
531 if (!r.finishing && !r.delayedResume && r != notTop && okToShow(r)) {
532 return r;
533 }
534 }
535 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700536 return null;
537 }
538
539 /**
540 * This is a simplified version of topRunningActivityLocked that provides a number of
541 * optional skip-over modes. It is intended for use with the ActivityController hook only.
542 *
543 * @param token If non-null, any history records matching this token will be skipped.
544 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
545 *
546 * @return Returns the HistoryRecord of the next activity on the stack.
547 */
548 final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) {
Craig Mautner11bf9a52013-02-19 14:08:51 -0800549 ActivityRecord newAr = newTopRunningActivityLocked(token, taskId);
550
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700551 int i = mHistory.size()-1;
552 while (i >= 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700553 ActivityRecord r = mHistory.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700554 // Note: the taskId check depends on real taskId fields being non-zero
Amith Yamasani259d5e52012-08-31 15:11:01 -0700555 if (!r.finishing && (token != r.appToken) && (taskId != r.task.taskId)
Craig Mautner5962b122012-10-05 14:45:52 -0700556 && okToShow(r)) {
Craig Mautner11bf9a52013-02-19 14:08:51 -0800557 if (VALIDATE_TASK_REPLACE && newAr != r) Slog.w(TAG,
558 "topRunningActivityLocked(token): mismatch: newAr=" + newAr + " r=" + r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700559 return r;
560 }
561 i--;
562 }
Craig Mautner11bf9a52013-02-19 14:08:51 -0800563 if (VALIDATE_TASK_REPLACE && newAr != null) Slog.w(TAG,
564 "topRunningActivityLocked(token): mismatch: newAr!=null");
565 return null;
566 }
567
568 final ActivityRecord newTopRunningActivityLocked(IBinder token, int taskId) {
569 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
570 TaskRecord task = mTaskHistory.get(taskNdx);
571 if (task.taskId == taskId) {
572 continue;
573 }
574 ArrayList<ActivityRecord> activities = task.mActivities;
575 for (int i = activities.size() - 1; i >= 0; --i) {
576 final ActivityRecord r = activities.get(i);
577 // Note: the taskId check depends on real taskId fields being non-zero
578 if (!r.finishing && (token != r.appToken) && okToShow(r)) {
579 return r;
580 }
581 }
582 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700583 return null;
584 }
585
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800586 private final int indexOfTokenLocked(IBinder token) {
Dianne Hackbornbe707852011-11-11 14:32:10 -0800587 return mHistory.indexOf(ActivityRecord.forToken(token));
588 }
589
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700590 final ActivityRecord isInStackLocked(IBinder token) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800591 ActivityRecord newAr = newIsInStackLocked(token);
592
Dianne Hackbornbe707852011-11-11 14:32:10 -0800593 ActivityRecord r = ActivityRecord.forToken(token);
594 if (mHistory.contains(r)) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800595 if (VALIDATE_TASK_REPLACE && newAr != r) Slog.w(TAG,
596 "isInStackLocked: mismatch: newAr=" + newAr + " r=" + r);
Dianne Hackbornbe707852011-11-11 14:32:10 -0800597 return r;
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700598 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800599 if (VALIDATE_TASK_REPLACE && newAr != null) Slog.w(TAG,
600 "isInStackLocked: mismatch: newAr!=null");
601 return null;
602 }
603
604 final ActivityRecord newIsInStackLocked(IBinder token) {
605 final ActivityRecord r = ActivityRecord.forToken(token);
606 if (r != null) {
607 final TaskRecord task = r.task;
608 if (mTaskHistory.contains(task) && task.mActivities.contains(r)) {
609 return r;
610 }
611 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700612 return null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700613 }
614
Craig Mautnercae015f2013-02-08 14:31:27 -0800615 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800616 int newTaskId = newGetTaskForActivityLocked(token, onlyRoot);
617
Craig Mautnercae015f2013-02-08 14:31:27 -0800618 TaskRecord lastTask = null;
619 final int N = mHistory.size();
620 for (int i = 0; i < N; i++) {
621 ActivityRecord r = mHistory.get(i);
622 if (r.appToken == token) {
623 if (!onlyRoot || lastTask != r.task) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800624 if (VALIDATE_TASK_REPLACE && newTaskId != r.task.taskId) Slog.w(TAG,
625 "getTaskForActivityLocked: mismatch: new=" + newTaskId
626 + " taskId=" + r.task.taskId);
Craig Mautnercae015f2013-02-08 14:31:27 -0800627 return r.task.taskId;
628 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800629 if (VALIDATE_TASK_REPLACE && newTaskId != -1) Slog.w(TAG,
630 "getTaskForActivityLocked: mismatch: newTaskId=" + newTaskId + " not -1.");
Craig Mautnercae015f2013-02-08 14:31:27 -0800631 return -1;
632 }
633 lastTask = r.task;
634 }
635
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800636 if (VALIDATE_TASK_REPLACE && newTaskId != -1) Slog.w(TAG,
637 "getTaskForActivityLocked: mismatch at end: newTaskId=" + newTaskId + " not -1.");
Craig Mautnercae015f2013-02-08 14:31:27 -0800638 return -1;
639 }
640
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800641 int newGetTaskForActivityLocked(IBinder token, boolean onlyRoot) {
642 final ActivityRecord r = ActivityRecord.forToken(token);
643 if (r == null) {
644 return -1;
645 }
646 final TaskRecord task = r.task;
647 switch (task.mActivities.indexOf(r)) {
648 case -1: return -1;
649 case 0: return task.taskId;
650 default: return onlyRoot ? -1 : task.taskId;
651 }
652 }
653
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700654 private final boolean updateLRUListLocked(ActivityRecord r) {
655 final boolean hadit = mLRUActivities.remove(r);
656 mLRUActivities.add(r);
657 return hadit;
658 }
659
660 /**
661 * Returns the top activity in any existing task matching the given
662 * Intent. Returns null if no such task is found.
663 */
664 private ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
665 ComponentName cls = intent.getComponent();
666 if (info.targetActivity != null) {
667 cls = new ComponentName(info.packageName, info.targetActivity);
668 }
669
670 TaskRecord cp = null;
671
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700672 final int userId = UserHandle.getUserId(info.applicationInfo.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700673 final int N = mHistory.size();
674 for (int i=(N-1); i>=0; i--) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700675 ActivityRecord r = mHistory.get(i);
Amith Yamasani742a6712011-05-04 14:49:28 -0700676 if (!r.finishing && r.task != cp && r.userId == userId
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700677 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
678 cp = r.task;
679 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
680 // + "/aff=" + r.task.affinity + " to new cls="
681 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
682 if (r.task.affinity != null) {
683 if (r.task.affinity.equals(info.taskAffinity)) {
684 //Slog.i(TAG, "Found matching affinity!");
685 return r;
686 }
687 } else if (r.task.intent != null
688 && r.task.intent.getComponent().equals(cls)) {
689 //Slog.i(TAG, "Found matching class!");
690 //dump();
691 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
692 return r;
693 } else if (r.task.affinityIntent != null
694 && r.task.affinityIntent.getComponent().equals(cls)) {
695 //Slog.i(TAG, "Found matching class!");
696 //dump();
697 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
698 return r;
699 }
700 }
701 }
702
703 return null;
704 }
705
706 /**
707 * Returns the first activity (starting from the top of the stack) that
708 * is the same as the given activity. Returns null if no such activity
709 * is found.
710 */
711 private ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
712 ComponentName cls = intent.getComponent();
713 if (info.targetActivity != null) {
714 cls = new ComponentName(info.packageName, info.targetActivity);
715 }
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700716 final int userId = UserHandle.getUserId(info.applicationInfo.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700717
718 final int N = mHistory.size();
719 for (int i=(N-1); i>=0; i--) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700720 ActivityRecord r = mHistory.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700721 if (!r.finishing) {
Amith Yamasani742a6712011-05-04 14:49:28 -0700722 if (r.intent.getComponent().equals(cls) && r.userId == userId) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700723 //Slog.i(TAG, "Found matching class!");
724 //dump();
725 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
726 return r;
727 }
728 }
729 }
730
731 return null;
732 }
733
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700734 final void showAskCompatModeDialogLocked(ActivityRecord r) {
735 Message msg = Message.obtain();
736 msg.what = ActivityManagerService.SHOW_COMPAT_MODE_DIALOG_MSG;
737 msg.obj = r.task.askedCompatMode ? null : r;
738 mService.mHandler.sendMessage(msg);
739 }
740
Amith Yamasani742a6712011-05-04 14:49:28 -0700741 /*
742 * Move the activities around in the stack to bring a user to the foreground.
743 * @return whether there are any activities for the specified user.
744 */
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700745 final boolean switchUserLocked(int userId, UserStartedState uss) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800746 if (VALIDATE_TOKENS) {
747 validateAppTokensLocked();
748 }
749 final boolean newResult = newSwitchUserLocked(userId, uss);
750
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700751 mCurrentUser = userId;
752 mStartingUsers.add(uss);
Amith Yamasani742a6712011-05-04 14:49:28 -0700753
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700754 // Only one activity? Nothing to do...
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800755 if (mHistory.size() < 2) {
756 if (VALIDATE_TASK_REPLACE && newResult) Slog.w(TAG,
757 "switchUserLocked: mismatch: " + newResult + " " + false);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700758 return false;
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800759 }
Amith Yamasani742a6712011-05-04 14:49:28 -0700760
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700761 boolean haveActivities = false;
762 // Check if the top activity is from the new user.
763 ActivityRecord top = mHistory.get(mHistory.size() - 1);
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800764 if (top.userId == userId) {
765 if (VALIDATE_TASK_REPLACE && !newResult) Slog.w(TAG,
766 "switchUserLocked: mismatch: " + newResult + " " + true);
767 return true;
768 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700769 // Otherwise, move the user's activities to the top.
770 int N = mHistory.size();
771 int i = 0;
772 while (i < N) {
773 ActivityRecord r = mHistory.get(i);
774 if (r.userId == userId) {
775 ActivityRecord moveToTop = mHistory.remove(i);
776 mHistory.add(moveToTop);
777 // No need to check the top one now
778 N--;
779 haveActivities = true;
780 } else {
781 i++;
Amith Yamasani742a6712011-05-04 14:49:28 -0700782 }
Amith Yamasani742a6712011-05-04 14:49:28 -0700783 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700784 // Transition from the old top to the new top
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800785 if (VALIDATE_TASK_REPLACE) Slog.w(TAG,
786 "switchUserLocked: calling resumeTopActivity " + top);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700787 resumeTopActivityLocked(top);
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800788 if (VALIDATE_TASK_REPLACE && (newResult != haveActivities)) Slog.w(TAG,
789 "switchUserLocked: mismatch: " + newResult + " " + haveActivities);
790 return haveActivities;
791 }
792
793 /*
794 * Move the activities around in the stack to bring a user to the foreground.
795 * @return whether there are any activities for the specified user.
796 */
797 final boolean newSwitchUserLocked(int userId, UserStartedState uss) {
798// mStartingUsers.add(uss);
799 if (mCurrentUser == userId) {
800 return true;
801 }
802 mCurrentUser = userId;
803
804 // Move userId's tasks to the top.
805 boolean haveActivities = false;
806 TaskRecord task = null;
807 int index = mTaskHistory.size();
808 for (int i = 0; i < index; ++i) {
809 task = mTaskHistory.get(i);
810 if (task.userId == userId) {
811 haveActivities = true;
812 mTaskHistory.remove(i);
813 mTaskHistory.add(task);
814 --index;
815 }
816 }
817
818 // task is now the original topmost TaskRecord. Transition from the old top to the new top.
819 ActivityRecord top = task != null ? task.getTopActivity() : null;
820 if (VALIDATE_TASK_REPLACE) Slog.w(TAG,
821 "newSwitchUserLocked: would call resumeTopActivity " + top);
822// resumeTopActivityLocked(top);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700823 return haveActivities;
Amith Yamasani742a6712011-05-04 14:49:28 -0700824 }
825
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700826 final boolean realStartActivityLocked(ActivityRecord r,
827 ProcessRecord app, boolean andResume, boolean checkConfig)
828 throws RemoteException {
829
830 r.startFreezingScreenLocked(app, 0);
Dianne Hackbornbe707852011-11-11 14:32:10 -0800831 mService.mWindowManager.setAppVisibility(r.appToken, true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700832
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -0700833 // schedule launch ticks to collect information about slow apps.
834 r.startLaunchTickingLocked();
835
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700836 // Have the window manager re-evaluate the orientation of
837 // the screen based on the new activity order. Note that
838 // as a result of this, it can call back into the activity
839 // manager with a new orientation. We don't care about that,
840 // because the activity is not currently running so we are
841 // just restarting it anyway.
842 if (checkConfig) {
843 Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
844 mService.mConfiguration,
Dianne Hackbornbe707852011-11-11 14:32:10 -0800845 r.mayFreezeScreenLocked(app) ? r.appToken : null);
Dianne Hackborn813075a62011-11-14 17:45:19 -0800846 mService.updateConfigurationLocked(config, r, false, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700847 }
848
849 r.app = app;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700850 app.waitingToKill = null;
Dianne Hackborn07981492013-01-28 11:36:23 -0800851 r.launchCount++;
852 r.lastLaunchTime = SystemClock.uptimeMillis();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700853
854 if (localLOGV) Slog.v(TAG, "Launching: " + r);
855
856 int idx = app.activities.indexOf(r);
857 if (idx < 0) {
858 app.activities.add(r);
859 }
Dianne Hackbornb12e1352012-09-26 11:39:20 -0700860 mService.updateLruProcessLocked(app, true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700861
862 try {
863 if (app.thread == null) {
864 throw new RemoteException();
865 }
866 List<ResultInfo> results = null;
867 List<Intent> newIntents = null;
868 if (andResume) {
869 results = r.results;
870 newIntents = r.newIntents;
871 }
872 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
873 + " icicle=" + r.icicle
874 + " with results=" + results + " newIntents=" + newIntents
875 + " andResume=" + andResume);
876 if (andResume) {
877 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
Dianne Hackbornb12e1352012-09-26 11:39:20 -0700878 r.userId, System.identityHashCode(r),
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700879 r.task.taskId, r.shortComponentName);
880 }
881 if (r.isHomeActivity) {
882 mService.mHomeProcess = app;
883 }
884 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
Dianne Hackborn4eba96b2011-01-21 13:34:36 -0800885 r.sleeping = false;
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400886 r.forceNewConfig = false;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700887 showAskCompatModeDialogLocked(r);
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -0700888 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
Dianne Hackborn62f20ec2011-08-15 17:40:28 -0700889 String profileFile = null;
890 ParcelFileDescriptor profileFd = null;
891 boolean profileAutoStop = false;
892 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
893 if (mService.mProfileProc == null || mService.mProfileProc == app) {
894 mService.mProfileProc = app;
895 profileFile = mService.mProfileFile;
896 profileFd = mService.mProfileFd;
897 profileAutoStop = mService.mAutoStopProfiler;
898 }
899 }
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -0700900 app.hasShownUi = true;
Dianne Hackbornc68c9132011-07-29 01:25:18 -0700901 app.pendingUiClean = true;
Dianne Hackborn62f20ec2011-08-15 17:40:28 -0700902 if (profileFd != null) {
903 try {
904 profileFd = profileFd.dup();
905 } catch (IOException e) {
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800906 if (profileFd != null) {
907 try {
908 profileFd.close();
909 } catch (IOException o) {
910 }
911 profileFd = null;
912 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -0700913 }
914 }
Dianne Hackbornbe707852011-11-11 14:32:10 -0800915 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
Dianne Hackborn813075a62011-11-14 17:45:19 -0800916 System.identityHashCode(r), r.info,
917 new Configuration(mService.mConfiguration),
Dianne Hackborn58f42a52011-10-10 13:46:34 -0700918 r.compat, r.icicle, results, newIntents, !andResume,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -0700919 mService.isNextTransitionForward(), profileFile, profileFd,
920 profileAutoStop);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700921
Dianne Hackborn54e570f2010-10-04 18:32:32 -0700922 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700923 // This may be a heavy-weight process! Note that the package
924 // manager will ensure that only activity can run in the main
925 // process of the .apk, which is the only thing that will be
926 // considered heavy-weight.
927 if (app.processName.equals(app.info.packageName)) {
928 if (mService.mHeavyWeightProcess != null
929 && mService.mHeavyWeightProcess != app) {
930 Log.w(TAG, "Starting new heavy weight process " + app
931 + " when already running "
932 + mService.mHeavyWeightProcess);
933 }
934 mService.mHeavyWeightProcess = app;
935 Message msg = mService.mHandler.obtainMessage(
936 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
937 msg.obj = r;
938 mService.mHandler.sendMessage(msg);
939 }
940 }
941
942 } catch (RemoteException e) {
943 if (r.launchFailed) {
944 // This is the second time we failed -- finish activity
945 // and give up.
946 Slog.e(TAG, "Second failure launching "
947 + r.intent.getComponent().flattenToShortString()
948 + ", giving up", e);
949 mService.appDiedLocked(app, app.pid, app.thread);
Dianne Hackbornbe707852011-11-11 14:32:10 -0800950 requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -0700951 "2nd-crash", false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700952 return false;
953 }
954
955 // This is the first time we failed -- restart process and
956 // retry.
957 app.activities.remove(r);
958 throw e;
959 }
960
961 r.launchFailed = false;
962 if (updateLRUListLocked(r)) {
963 Slog.w(TAG, "Activity " + r
964 + " being launched, but already in LRU list");
965 }
966
967 if (andResume) {
968 // As part of the process of launching, ActivityThread also performs
969 // a resume.
970 r.state = ActivityState.RESUMED;
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700971 if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + r
972 + " (starting new instance)");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700973 r.stopped = false;
974 mResumedActivity = r;
975 r.task.touchActiveTime();
Dianne Hackborn88819b22010-12-21 18:18:02 -0800976 if (mMainStack) {
977 mService.addRecentTaskLocked(r.task);
978 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700979 completeResumeLocked(r);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -0800980 checkReadyForSleepLocked();
Dianne Hackborn98cfebc2011-10-18 13:17:33 -0700981 if (DEBUG_SAVED_STATE) Slog.i(TAG, "Launch completed; removing icicle of " + r.icicle);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700982 } else {
983 // This activity is not starting in the resumed state... which
984 // should look like we asked it to pause+stop (but remain visible),
985 // and it has done so and reported back the current icicle and
986 // other state.
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700987 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
988 + " (starting in stopped state)");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700989 r.state = ActivityState.STOPPED;
990 r.stopped = true;
991 }
992
993 // Launch the new version setup screen if needed. We do this -after-
994 // launching the initial activity (that is, home), so that it can have
995 // a chance to initialize itself while in the background, making the
996 // switch back to it faster and look better.
997 if (mMainStack) {
998 mService.startSetupActivityLocked();
999 }
1000
1001 return true;
1002 }
1003
1004 private final void startSpecificActivityLocked(ActivityRecord r,
1005 boolean andResume, boolean checkConfig) {
1006 // Is this activity's application already running?
1007 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
1008 r.info.applicationInfo.uid);
Dianne Hackborn07981492013-01-28 11:36:23 -08001009
Dianne Hackborn0dad3642010-09-09 21:25:35 -07001010 if (r.launchTime == 0) {
1011 r.launchTime = SystemClock.uptimeMillis();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001012 if (mInitialStartTime == 0) {
Dianne Hackborn0dad3642010-09-09 21:25:35 -07001013 mInitialStartTime = r.launchTime;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001014 }
1015 } else if (mInitialStartTime == 0) {
1016 mInitialStartTime = SystemClock.uptimeMillis();
1017 }
1018
1019 if (app != null && app.thread != null) {
1020 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001021 app.addPackage(r.info.packageName);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001022 realStartActivityLocked(r, app, andResume, checkConfig);
1023 return;
1024 } catch (RemoteException e) {
1025 Slog.w(TAG, "Exception when starting activity "
1026 + r.intent.getComponent().flattenToShortString(), e);
1027 }
1028
1029 // If a dead object exception was thrown -- fall through to
1030 // restart the application.
1031 }
1032
1033 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborna0c283e2012-02-09 10:47:01 -08001034 "activity", r.intent.getComponent(), false, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001035 }
1036
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001037 void stopIfSleepingLocked() {
1038 if (mService.isSleeping()) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001039 if (!mGoingToSleep.isHeld()) {
1040 mGoingToSleep.acquire();
1041 if (mLaunchingActivity.isHeld()) {
1042 mLaunchingActivity.release();
1043 mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
1044 }
1045 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001046 mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
1047 Message msg = mHandler.obtainMessage(SLEEP_TIMEOUT_MSG);
1048 mHandler.sendMessageDelayed(msg, SLEEP_TIMEOUT);
1049 checkReadyForSleepLocked();
1050 }
1051 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001052
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001053 void awakeFromSleepingLocked() {
1054 mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
1055 mSleepTimeout = false;
1056 if (mGoingToSleep.isHeld()) {
1057 mGoingToSleep.release();
1058 }
1059 // Ensure activities are no longer sleeping.
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001060 if (VALIDATE_TASK_REPLACE) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08001061 verifyActivityRecords(true);
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001062 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001063 for (int i=mHistory.size()-1; i>=0; i--) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07001064 ActivityRecord r = mHistory.get(i);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001065 r.setSleeping(false);
1066 }
1067 mGoingToSleepActivities.clear();
1068 }
1069
1070 void activitySleptLocked(ActivityRecord r) {
1071 mGoingToSleepActivities.remove(r);
1072 checkReadyForSleepLocked();
1073 }
1074
1075 void checkReadyForSleepLocked() {
1076 if (!mService.isSleeping()) {
1077 // Do not care.
1078 return;
1079 }
1080
1081 if (!mSleepTimeout) {
1082 if (mResumedActivity != null) {
1083 // Still have something resumed; can't sleep until it is paused.
1084 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause " + mResumedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001085 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
1086 startPausingLocked(false, true);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001087 return;
1088 }
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001089 if (mPausingActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001090 // Still waiting for something to pause; can't sleep yet.
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001091 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still waiting to pause " + mPausingActivity);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001092 return;
1093 }
1094
1095 if (mStoppingActivities.size() > 0) {
1096 // Still need to tell some activities to stop; can't sleep yet.
1097 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
1098 + mStoppingActivities.size() + " activities");
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07001099 scheduleIdleLocked();
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001100 return;
1101 }
1102
1103 ensureActivitiesVisibleLocked(null, 0);
1104
1105 // Make sure any stopped but visible activities are now sleeping.
1106 // This ensures that the activity's onStop() is called.
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001107 if (VALIDATE_TASK_REPLACE) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08001108 verifyActivityRecords(true);
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001109 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001110 for (int i=mHistory.size()-1; i>=0; i--) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07001111 ActivityRecord r = mHistory.get(i);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001112 if (r.state == ActivityState.STOPPING || r.state == ActivityState.STOPPED) {
1113 r.setSleeping(true);
1114 }
1115 }
1116
1117 if (mGoingToSleepActivities.size() > 0) {
1118 // Still need to tell some activities to sleep; can't sleep yet.
1119 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
1120 + mGoingToSleepActivities.size() + " activities");
1121 return;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001122 }
1123 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001124
1125 mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
1126
1127 if (mGoingToSleep.isHeld()) {
1128 mGoingToSleep.release();
1129 }
1130 if (mService.mShuttingDown) {
1131 mService.notifyAll();
1132 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001133 }
Craig Mautner59c00972012-07-30 12:10:24 -07001134
Dianne Hackbornd2835932010-12-13 16:28:46 -08001135 public final Bitmap screenshotActivities(ActivityRecord who) {
Dianne Hackbornff801ec2011-01-22 18:05:38 -08001136 if (who.noDisplay) {
1137 return null;
1138 }
1139
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08001140 Resources res = mService.mContext.getResources();
1141 int w = mThumbnailWidth;
1142 int h = mThumbnailHeight;
1143 if (w < 0) {
1144 mThumbnailWidth = w =
1145 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
1146 mThumbnailHeight = h =
1147 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
1148 }
1149
1150 if (w > 0) {
Craig Mautnerb12428a2012-12-20 16:07:06 -08001151 if (who != mLastScreenshotActivity || mLastScreenshotBitmap == null
1152 || mLastScreenshotBitmap.getWidth() != w
1153 || mLastScreenshotBitmap.getHeight() != h) {
1154 mLastScreenshotActivity = who;
1155 mLastScreenshotBitmap = mService.mWindowManager.screenshotApplications(
1156 who.appToken, Display.DEFAULT_DISPLAY, w, h);
1157 }
1158 if (mLastScreenshotBitmap != null) {
1159 return mLastScreenshotBitmap.copy(Config.ARGB_8888, true);
1160 }
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08001161 }
1162 return null;
1163 }
1164
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001165 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001166 if (mPausingActivity != null) {
1167 RuntimeException e = new RuntimeException();
1168 Slog.e(TAG, "Trying to pause when pause is already pending for "
1169 + mPausingActivity, e);
1170 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001171 ActivityRecord prev = mResumedActivity;
1172 if (prev == null) {
1173 RuntimeException e = new RuntimeException();
1174 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
1175 resumeTopActivityLocked(null);
1176 return;
1177 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07001178 if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev);
1179 else if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001180 mResumedActivity = null;
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001181 mPausingActivity = prev;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001182 mLastPausedActivity = prev;
1183 prev.state = ActivityState.PAUSING;
1184 prev.task.touchActiveTime();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07001185 prev.updateThumbnail(screenshotActivities(prev), null);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001186
1187 mService.updateCpuStats();
1188
1189 if (prev.app != null && prev.app.thread != null) {
1190 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
1191 try {
1192 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
Dianne Hackbornb12e1352012-09-26 11:39:20 -07001193 prev.userId, System.identityHashCode(prev),
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001194 prev.shortComponentName);
Dianne Hackbornbe707852011-11-11 14:32:10 -08001195 prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
1196 userLeaving, prev.configChangeFlags);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001197 if (mMainStack) {
1198 mService.updateUsageStats(prev, false);
1199 }
1200 } catch (Exception e) {
1201 // Ignore exception, if process died other code will cleanup.
1202 Slog.w(TAG, "Exception thrown during pause", e);
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001203 mPausingActivity = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001204 mLastPausedActivity = null;
1205 }
1206 } else {
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001207 mPausingActivity = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001208 mLastPausedActivity = null;
1209 }
1210
1211 // If we are not going to sleep, we want to ensure the device is
1212 // awake until the next activity is started.
1213 if (!mService.mSleeping && !mService.mShuttingDown) {
1214 mLaunchingActivity.acquire();
1215 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
1216 // To be safe, don't allow the wake lock to be held for too long.
1217 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1218 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
1219 }
1220 }
1221
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001222
1223 if (mPausingActivity != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001224 // Have the window manager pause its key dispatching until the new
1225 // activity has started. If we're pausing the activity just because
1226 // the screen is being turned off and the UI is sleeping, don't interrupt
1227 // key dispatch; the same activity will pick it up again on wakeup.
1228 if (!uiSleeping) {
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001229 prev.pauseKeyDispatchingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001230 } else {
1231 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
1232 }
1233
1234 // Schedule a pause timeout in case the app doesn't respond.
1235 // We don't give it much time because this directly impacts the
1236 // responsiveness seen by the user.
1237 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
1238 msg.obj = prev;
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07001239 prev.pauseTime = SystemClock.uptimeMillis();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001240 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
1241 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
1242 } else {
1243 // This activity failed to schedule the
1244 // pause, so just treat it as being paused now.
1245 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001246 resumeTopActivityLocked(null);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001247 }
1248 }
Dianne Hackbornad9b32112012-09-17 15:35:01 -07001249
1250 final void activityResumed(IBinder token) {
1251 ActivityRecord r = null;
1252
1253 synchronized (mService) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001254 if (VALIDATE_TASK_REPLACE) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08001255 verifyActivityRecords(true);
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001256 }
Dianne Hackbornad9b32112012-09-17 15:35:01 -07001257 int index = indexOfTokenLocked(token);
1258 if (index >= 0) {
1259 r = mHistory.get(index);
1260 if (DEBUG_SAVED_STATE) Slog.i(TAG, "Resumed activity; dropping state of: " + r);
1261 r.icicle = null;
1262 r.haveState = false;
1263 }
1264 }
1265 }
1266
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08001267 final void activityPaused(IBinder token, boolean timeout) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001268 if (DEBUG_PAUSE) Slog.v(
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08001269 TAG, "Activity paused: token=" + token + ", timeout=" + timeout);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001270
1271 ActivityRecord r = null;
1272
1273 synchronized (mService) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001274 if (VALIDATE_TASK_REPLACE) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08001275 verifyActivityRecords(true);
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001276 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001277 int index = indexOfTokenLocked(token);
1278 if (index >= 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07001279 r = mHistory.get(index);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001280 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001281 if (mPausingActivity == r) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07001282 if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r
1283 + (timeout ? " (due to timeout)" : " (pause complete)"));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001284 r.state = ActivityState.PAUSED;
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001285 completePauseLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001286 } else {
1287 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
Dianne Hackbornb12e1352012-09-26 11:39:20 -07001288 r.userId, System.identityHashCode(r), r.shortComponentName,
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001289 mPausingActivity != null
1290 ? mPausingActivity.shortComponentName : "(none)");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001291 }
1292 }
1293 }
1294 }
1295
Dianne Hackbornce86ba82011-07-13 19:33:41 -07001296 final void activityStoppedLocked(ActivityRecord r, Bundle icicle, Bitmap thumbnail,
1297 CharSequence description) {
Dianne Hackbornb61a0262012-05-14 17:19:18 -07001298 if (r.state != ActivityState.STOPPING) {
1299 Slog.i(TAG, "Activity reported stop, but no longer stopping: " + r);
1300 mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
1301 return;
1302 }
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07001303 if (DEBUG_SAVED_STATE) Slog.i(TAG, "Saving icicle of " + r + ": " + icicle);
Dianne Hackborn162bc0e2012-04-09 14:06:16 -07001304 if (icicle != null) {
1305 // If icicle is null, this is happening due to a timeout, so we
1306 // haven't really saved the state.
1307 r.icicle = icicle;
1308 r.haveState = true;
Dianne Hackborn07981492013-01-28 11:36:23 -08001309 r.launchCount = 0;
Dianne Hackborn162bc0e2012-04-09 14:06:16 -07001310 r.updateThumbnail(thumbnail, description);
1311 }
1312 if (!r.stopped) {
1313 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r + " (stop complete)");
1314 mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
1315 r.stopped = true;
1316 r.state = ActivityState.STOPPED;
Dianne Hackborn6e3d6da2012-06-15 12:05:27 -07001317 if (r.finishing) {
1318 r.clearOptionsLocked();
1319 } else {
Dianne Hackborn162bc0e2012-04-09 14:06:16 -07001320 if (r.configDestroy) {
1321 destroyActivityLocked(r, true, false, "stop-config");
1322 resumeTopActivityLocked(null);
1323 } else {
1324 // Now that this process has stopped, we may want to consider
1325 // it to be the previous app to try to keep around in case
1326 // the user wants to return to it.
1327 ProcessRecord fgApp = null;
1328 if (mResumedActivity != null) {
1329 fgApp = mResumedActivity.app;
1330 } else if (mPausingActivity != null) {
1331 fgApp = mPausingActivity.app;
1332 }
1333 if (r.app != null && fgApp != null && r.app != fgApp
1334 && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
1335 && r.app != mService.mHomeProcess) {
1336 mService.mPreviousProcess = r.app;
1337 mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
1338 }
Dianne Hackborn50685602011-12-01 12:23:37 -08001339 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07001340 }
1341 }
1342 }
1343
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001344 private final void completePauseLocked() {
1345 ActivityRecord prev = mPausingActivity;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001346 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
1347
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001348 if (prev != null) {
1349 if (prev.finishing) {
1350 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07001351 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false);
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001352 } else if (prev.app != null) {
1353 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
1354 if (prev.waitingVisible) {
1355 prev.waitingVisible = false;
1356 mWaitingVisibleActivities.remove(prev);
1357 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
1358 TAG, "Complete pause, no longer waiting: " + prev);
Dianne Hackborncbb722e2012-02-07 18:33:49 -08001359 }
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001360 if (prev.configDestroy) {
1361 // The previous is being paused because the configuration
1362 // is changing, which means it is actually stopping...
1363 // To juggle the fact that we are also starting a new
1364 // instance right now, we need to first completely stop
1365 // the current instance before starting the new one.
1366 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
1367 destroyActivityLocked(prev, true, false, "pause-config");
1368 } else {
1369 mStoppingActivities.add(prev);
1370 if (mStoppingActivities.size() > 3) {
1371 // If we already have a few activities waiting to stop,
1372 // then give up on things going idle and start clearing
1373 // them out.
1374 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
1375 scheduleIdleLocked();
1376 } else {
1377 checkReadyForSleepLocked();
1378 }
1379 }
1380 } else {
1381 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
1382 prev = null;
Dianne Hackborncbb722e2012-02-07 18:33:49 -08001383 }
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001384 mPausingActivity = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001385 }
Dianne Hackborncbb722e2012-02-07 18:33:49 -08001386
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001387 if (!mService.isSleeping()) {
1388 resumeTopActivityLocked(prev);
1389 } else {
Dianne Hackborncbb722e2012-02-07 18:33:49 -08001390 checkReadyForSleepLocked();
Dianne Hackborncc5a0552012-10-01 16:32:39 -07001391 ActivityRecord top = topRunningActivityLocked(null);
1392 if (top == null || (prev != null && top != prev)) {
1393 // If there are no more activities available to run,
1394 // do resume anyway to start something. Also if the top
1395 // activity on the stack is not the just paused activity,
1396 // we need to go ahead and resume it to ensure we complete
1397 // an in-flight app switch.
Dianne Hackborn42e620c2012-06-24 13:20:51 -07001398 resumeTopActivityLocked(null);
1399 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001400 }
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001401
1402 if (prev != null) {
1403 prev.resumeKeyDispatchingLocked();
1404 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001405
1406 if (prev.app != null && prev.cpuTimeAtResume > 0
1407 && mService.mBatteryStatsService.isOnBattery()) {
1408 long diff = 0;
1409 synchronized (mService.mProcessStatsThread) {
1410 diff = mService.mProcessStats.getCpuTimeForPid(prev.app.pid)
1411 - prev.cpuTimeAtResume;
1412 }
1413 if (diff > 0) {
1414 BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics();
1415 synchronized (bsi) {
1416 BatteryStatsImpl.Uid.Proc ps =
1417 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
1418 prev.info.packageName);
1419 if (ps != null) {
1420 ps.addForegroundTimeLocked(diff);
1421 }
1422 }
1423 }
1424 }
1425 prev.cpuTimeAtResume = 0; // reset it
1426 }
1427
1428 /**
1429 * Once we know that we have asked an application to put an activity in
1430 * the resumed state (either by launching it or explicitly telling it),
1431 * this function updates the rest of our state to match that fact.
1432 */
1433 private final void completeResumeLocked(ActivityRecord next) {
1434 next.idle = false;
1435 next.results = null;
1436 next.newIntents = null;
1437
1438 // schedule an idle timeout in case the app doesn't do it for us.
1439 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1440 msg.obj = next;
1441 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
1442
1443 if (false) {
1444 // The activity was never told to pause, so just keep
1445 // things going as-is. To maintain our own state,
1446 // we need to emulate it coming back and saying it is
1447 // idle.
1448 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
1449 msg.obj = next;
1450 mHandler.sendMessage(msg);
1451 }
1452
1453 if (mMainStack) {
1454 mService.reportResumedActivityLocked(next);
1455 }
Dianne Hackborn15491c62012-09-19 10:59:14 -07001456
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001457 if (mMainStack) {
1458 mService.setFocusedActivityLocked(next);
1459 }
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001460 next.resumeKeyDispatchingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001461 ensureActivitiesVisibleLocked(null, 0);
1462 mService.mWindowManager.executeAppTransition();
1463 mNoAnimActivities.clear();
1464
1465 // Mark the point when the activity is resuming
1466 // TODO: To be more accurate, the mark should be before the onCreate,
1467 // not after the onResume. But for subsequent starts, onResume is fine.
1468 if (next.app != null) {
1469 synchronized (mService.mProcessStatsThread) {
1470 next.cpuTimeAtResume = mService.mProcessStats.getCpuTimeForPid(next.app.pid);
1471 }
1472 } else {
1473 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
1474 }
1475 }
1476
1477 /**
1478 * Make sure that all activities that need to be visible (that is, they
1479 * currently can be seen by the user) actually are.
1480 */
1481 final void ensureActivitiesVisibleLocked(ActivityRecord top,
1482 ActivityRecord starting, String onlyThisProcess, int configChanges) {
1483 if (DEBUG_VISBILITY) Slog.v(
1484 TAG, "ensureActivitiesVisible behind " + top
1485 + " configChanges=0x" + Integer.toHexString(configChanges));
1486
1487 // If the top activity is not fullscreen, then we need to
1488 // make sure any activities under it are now visible.
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001489 if (VALIDATE_TASK_REPLACE) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08001490 verifyActivityRecords(true);
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001491 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001492 final int count = mHistory.size();
1493 int i = count-1;
1494 while (mHistory.get(i) != top) {
1495 i--;
1496 }
1497 ActivityRecord r;
1498 boolean behindFullscreen = false;
1499 for (; i>=0; i--) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07001500 r = mHistory.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001501 if (DEBUG_VISBILITY) Slog.v(
1502 TAG, "Make visible? " + r + " finishing=" + r.finishing
1503 + " state=" + r.state);
1504 if (r.finishing) {
1505 continue;
1506 }
1507
1508 final boolean doThisProcess = onlyThisProcess == null
1509 || onlyThisProcess.equals(r.processName);
1510
1511 // First: if this is not the current activity being started, make
1512 // sure it matches the current configuration.
1513 if (r != starting && doThisProcess) {
1514 ensureActivityConfigurationLocked(r, 0);
1515 }
1516
1517 if (r.app == null || r.app.thread == null) {
1518 if (onlyThisProcess == null
1519 || onlyThisProcess.equals(r.processName)) {
1520 // This activity needs to be visible, but isn't even
1521 // running... get it started, but don't resume it
1522 // at this point.
1523 if (DEBUG_VISBILITY) Slog.v(
1524 TAG, "Start and freeze screen for " + r);
1525 if (r != starting) {
1526 r.startFreezingScreenLocked(r.app, configChanges);
1527 }
1528 if (!r.visible) {
1529 if (DEBUG_VISBILITY) Slog.v(
1530 TAG, "Starting and making visible: " + r);
Dianne Hackbornbe707852011-11-11 14:32:10 -08001531 mService.mWindowManager.setAppVisibility(r.appToken, true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001532 }
1533 if (r != starting) {
1534 startSpecificActivityLocked(r, false, false);
1535 }
1536 }
1537
1538 } else if (r.visible) {
1539 // If this activity is already visible, then there is nothing
1540 // else to do here.
1541 if (DEBUG_VISBILITY) Slog.v(
1542 TAG, "Skipping: already visible at " + r);
1543 r.stopFreezingScreenLocked(false);
1544
1545 } else if (onlyThisProcess == null) {
1546 // This activity is not currently visible, but is running.
1547 // Tell it to become visible.
1548 r.visible = true;
1549 if (r.state != ActivityState.RESUMED && r != starting) {
1550 // If this activity is paused, tell it
1551 // to now show its window.
1552 if (DEBUG_VISBILITY) Slog.v(
1553 TAG, "Making visible and scheduling visibility: " + r);
1554 try {
Dianne Hackbornbe707852011-11-11 14:32:10 -08001555 mService.mWindowManager.setAppVisibility(r.appToken, true);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001556 r.sleeping = false;
Dianne Hackborn905577f2011-09-07 18:31:28 -07001557 r.app.pendingUiClean = true;
Dianne Hackbornbe707852011-11-11 14:32:10 -08001558 r.app.thread.scheduleWindowVisibility(r.appToken, true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001559 r.stopFreezingScreenLocked(false);
1560 } catch (Exception e) {
1561 // Just skip on any failure; we'll make it
1562 // visible when it next restarts.
1563 Slog.w(TAG, "Exception thrown making visibile: "
1564 + r.intent.getComponent(), e);
1565 }
1566 }
1567 }
1568
1569 // Aggregate current change flags.
1570 configChanges |= r.configChangeFlags;
1571
1572 if (r.fullscreen) {
1573 // At this point, nothing else needs to be shown
1574 if (DEBUG_VISBILITY) Slog.v(
1575 TAG, "Stopping: fullscreen at " + r);
1576 behindFullscreen = true;
1577 i--;
1578 break;
1579 }
1580 }
1581
1582 // Now for any activities that aren't visible to the user, make
1583 // sure they no longer are keeping the screen frozen.
1584 while (i >= 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07001585 r = mHistory.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001586 if (DEBUG_VISBILITY) Slog.v(
1587 TAG, "Make invisible? " + r + " finishing=" + r.finishing
1588 + " state=" + r.state
1589 + " behindFullscreen=" + behindFullscreen);
1590 if (!r.finishing) {
1591 if (behindFullscreen) {
1592 if (r.visible) {
1593 if (DEBUG_VISBILITY) Slog.v(
1594 TAG, "Making invisible: " + r);
1595 r.visible = false;
1596 try {
Dianne Hackbornbe707852011-11-11 14:32:10 -08001597 mService.mWindowManager.setAppVisibility(r.appToken, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001598 if ((r.state == ActivityState.STOPPING
1599 || r.state == ActivityState.STOPPED)
1600 && r.app != null && r.app.thread != null) {
1601 if (DEBUG_VISBILITY) Slog.v(
1602 TAG, "Scheduling invisibility: " + r);
Dianne Hackbornbe707852011-11-11 14:32:10 -08001603 r.app.thread.scheduleWindowVisibility(r.appToken, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001604 }
1605 } catch (Exception e) {
1606 // Just skip on any failure; we'll make it
1607 // visible when it next restarts.
1608 Slog.w(TAG, "Exception thrown making hidden: "
1609 + r.intent.getComponent(), e);
1610 }
1611 } else {
1612 if (DEBUG_VISBILITY) Slog.v(
1613 TAG, "Already invisible: " + r);
1614 }
1615 } else if (r.fullscreen) {
1616 if (DEBUG_VISBILITY) Slog.v(
1617 TAG, "Now behindFullscreen: " + r);
1618 behindFullscreen = true;
1619 }
1620 }
1621 i--;
1622 }
1623 }
1624
1625 /**
1626 * Version of ensureActivitiesVisible that can easily be called anywhere.
1627 */
1628 final void ensureActivitiesVisibleLocked(ActivityRecord starting,
1629 int configChanges) {
1630 ActivityRecord r = topRunningActivityLocked(null);
1631 if (r != null) {
1632 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
1633 }
1634 }
1635
1636 /**
1637 * Ensure that the top activity in the stack is resumed.
1638 *
1639 * @param prev The previously resumed activity, for when in the process
1640 * of pausing; can be null to call from elsewhere.
1641 *
1642 * @return Returns true if something is being resumed, or false if
1643 * nothing happened.
1644 */
1645 final boolean resumeTopActivityLocked(ActivityRecord prev) {
Dianne Hackborn84375872012-06-01 19:03:50 -07001646 return resumeTopActivityLocked(prev, null);
1647 }
1648
1649 final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001650 // Find the first activity that is not finishing.
1651 ActivityRecord next = topRunningActivityLocked(null);
1652
1653 // Remember how we'll process this pause/resume situation, and ensure
1654 // that the state is reset however we wind up proceeding.
1655 final boolean userLeaving = mUserLeaving;
1656 mUserLeaving = false;
1657
1658 if (next == null) {
1659 // There are no more activities! Let's just start up the
1660 // Launcher...
1661 if (mMainStack) {
Dianne Hackborn84375872012-06-01 19:03:50 -07001662 ActivityOptions.abort(options);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001663 return mService.startHomeActivityLocked(mCurrentUser);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001664 }
1665 }
1666
1667 next.delayedResume = false;
1668
1669 // If the top activity is the resumed one, nothing to do.
1670 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
1671 // Make sure we have executed any pending transitions, since there
1672 // should be nothing left to do at this point.
1673 mService.mWindowManager.executeAppTransition();
1674 mNoAnimActivities.clear();
Dianne Hackborn84375872012-06-01 19:03:50 -07001675 ActivityOptions.abort(options);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001676 return false;
1677 }
1678
1679 // If we are sleeping, and there is no resumed activity, and the top
1680 // activity is paused, well that is the state we want.
1681 if ((mService.mSleeping || mService.mShuttingDown)
p13451dbad2872012-04-18 11:39:23 +09001682 && mLastPausedActivity == next
1683 && (next.state == ActivityState.PAUSED
1684 || next.state == ActivityState.STOPPED
1685 || next.state == ActivityState.STOPPING)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001686 // Make sure we have executed any pending transitions, since there
1687 // should be nothing left to do at this point.
1688 mService.mWindowManager.executeAppTransition();
1689 mNoAnimActivities.clear();
Dianne Hackborn84375872012-06-01 19:03:50 -07001690 ActivityOptions.abort(options);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001691 return false;
1692 }
Dianne Hackborn80a4af22012-08-27 19:18:31 -07001693
1694 // Make sure that the user who owns this activity is started. If not,
1695 // we will just leave it as is because someone should be bringing
1696 // another user's activities to the top of the stack.
1697 if (mService.mStartedUsers.get(next.userId) == null) {
1698 Slog.w(TAG, "Skipping resume of top activity " + next
1699 + ": user " + next.userId + " is stopped");
1700 return false;
1701 }
1702
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001703 // The activity may be waiting for stop, but that is no longer
1704 // appropriate for it.
1705 mStoppingActivities.remove(next);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001706 mGoingToSleepActivities.remove(next);
1707 next.sleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001708 mWaitingVisibleActivities.remove(next);
1709
Dianne Hackborn84375872012-06-01 19:03:50 -07001710 next.updateOptionsLocked(options);
1711
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001712 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
1713
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001714 // If we are currently pausing an activity, then don't do anything
1715 // until that is done.
1716 if (mPausingActivity != null) {
Dianne Hackborncc5a0552012-10-01 16:32:39 -07001717 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG,
1718 "Skip resume: pausing=" + mPausingActivity);
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001719 return false;
1720 }
1721
Dianne Hackborn0dad3642010-09-09 21:25:35 -07001722 // Okay we are now going to start a switch, to 'next'. We may first
1723 // have to pause the current activity, but this is an important point
1724 // where we have decided to go to 'next' so keep track of that.
Dianne Hackborn034093a42010-09-20 22:24:38 -07001725 // XXX "App Redirected" dialog is getting too many false positives
1726 // at this point, so turn off for now.
1727 if (false) {
1728 if (mLastStartedActivity != null && !mLastStartedActivity.finishing) {
1729 long now = SystemClock.uptimeMillis();
1730 final boolean inTime = mLastStartedActivity.startTime != 0
1731 && (mLastStartedActivity.startTime + START_WARN_TIME) >= now;
1732 final int lastUid = mLastStartedActivity.info.applicationInfo.uid;
1733 final int nextUid = next.info.applicationInfo.uid;
1734 if (inTime && lastUid != nextUid
1735 && lastUid != next.launchedFromUid
1736 && mService.checkPermission(
1737 android.Manifest.permission.STOP_APP_SWITCHES,
1738 -1, next.launchedFromUid)
1739 != PackageManager.PERMISSION_GRANTED) {
1740 mService.showLaunchWarningLocked(mLastStartedActivity, next);
1741 } else {
1742 next.startTime = now;
1743 mLastStartedActivity = next;
1744 }
Dianne Hackborn0dad3642010-09-09 21:25:35 -07001745 } else {
Dianne Hackborn034093a42010-09-20 22:24:38 -07001746 next.startTime = SystemClock.uptimeMillis();
Dianne Hackborn0dad3642010-09-09 21:25:35 -07001747 mLastStartedActivity = next;
1748 }
Dianne Hackborn0dad3642010-09-09 21:25:35 -07001749 }
1750
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001751 // We need to start pausing the current activity so the top one
1752 // can be resumed...
1753 if (mResumedActivity != null) {
1754 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
Dianne Hackbornad9b32112012-09-17 15:35:01 -07001755 // At this point we want to put the upcoming activity's process
1756 // at the top of the LRU list, since we know we will be needing it
1757 // very soon and it would be a waste to let it get killed if it
1758 // happens to be sitting towards the end.
1759 if (next.app != null && next.app.thread != null) {
1760 // No reason to do full oom adj update here; we'll let that
1761 // happen whenever it needs to later.
Dianne Hackbornb12e1352012-09-26 11:39:20 -07001762 mService.updateLruProcessLocked(next.app, false);
Dianne Hackbornad9b32112012-09-17 15:35:01 -07001763 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001764 startPausingLocked(userLeaving, false);
1765 return true;
1766 }
1767
Christopher Tated3f175c2012-06-14 14:16:54 -07001768 // If the most recent activity was noHistory but was only stopped rather
1769 // than stopped+finished because the device went to sleep, we need to make
1770 // sure to finish it as we're making a new activity topmost.
1771 final ActivityRecord last = mLastPausedActivity;
1772 if (mService.mSleeping && last != null && !last.finishing) {
1773 if ((last.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
1774 || (last.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
1775 if (DEBUG_STATES) {
1776 Slog.d(TAG, "no-history finish of " + last + " on new resume");
1777 }
1778 requestFinishActivityLocked(last.appToken, Activity.RESULT_CANCELED, null,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07001779 "no-history", false);
Christopher Tated3f175c2012-06-14 14:16:54 -07001780 }
1781 }
1782
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001783 if (prev != null && prev != next) {
1784 if (!prev.waitingVisible && next != null && !next.nowVisible) {
1785 prev.waitingVisible = true;
1786 mWaitingVisibleActivities.add(prev);
1787 if (DEBUG_SWITCH) Slog.v(
1788 TAG, "Resuming top, waiting visible to hide: " + prev);
1789 } else {
1790 // The next activity is already visible, so hide the previous
1791 // activity's windows right now so we can show the new one ASAP.
1792 // We only do this if the previous is finishing, which should mean
1793 // it is on top of the one being resumed so hiding it quickly
1794 // is good. Otherwise, we want to do the normal route of allowing
1795 // the resumed activity to be shown so we can decide if the
1796 // previous should actually be hidden depending on whether the
1797 // new one is found to be full-screen or not.
1798 if (prev.finishing) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08001799 mService.mWindowManager.setAppVisibility(prev.appToken, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001800 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
1801 + prev + ", waitingVisible="
1802 + (prev != null ? prev.waitingVisible : null)
1803 + ", nowVisible=" + next.nowVisible);
1804 } else {
1805 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
1806 + prev + ", waitingVisible="
1807 + (prev != null ? prev.waitingVisible : null)
1808 + ", nowVisible=" + next.nowVisible);
1809 }
1810 }
1811 }
1812
Dianne Hackborne7f97212011-02-24 14:40:20 -08001813 // Launching this app's activity, make sure the app is no longer
1814 // considered stopped.
1815 try {
1816 AppGlobals.getPackageManager().setPackageStoppedState(
Amith Yamasani483f3b02012-03-13 16:08:00 -07001817 next.packageName, false, next.userId); /* TODO: Verify if correct userid */
Dianne Hackborne7f97212011-02-24 14:40:20 -08001818 } catch (RemoteException e1) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08001819 } catch (IllegalArgumentException e) {
1820 Slog.w(TAG, "Failed trying to unstop package "
1821 + next.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08001822 }
1823
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001824 // We are starting up the next activity, so tell the window manager
1825 // that the previous one will be hidden soon. This way it can know
1826 // to ignore it when computing the desired screen orientation.
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07001827 boolean noAnim = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001828 if (prev != null) {
1829 if (prev.finishing) {
1830 if (DEBUG_TRANSITION) Slog.v(TAG,
1831 "Prepare close transition: prev=" + prev);
1832 if (mNoAnimActivities.contains(prev)) {
Dianne Hackborn7da6ac32010-12-09 19:22:04 -08001833 mService.mWindowManager.prepareAppTransition(
Craig Mautner4b71aa12012-12-27 17:20:01 -08001834 AppTransition.TRANSIT_NONE, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001835 } else {
1836 mService.mWindowManager.prepareAppTransition(prev.task == next.task
Craig Mautner4b71aa12012-12-27 17:20:01 -08001837 ? AppTransition.TRANSIT_ACTIVITY_CLOSE
1838 : AppTransition.TRANSIT_TASK_CLOSE, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001839 }
Dianne Hackbornbe707852011-11-11 14:32:10 -08001840 mService.mWindowManager.setAppWillBeHidden(prev.appToken);
1841 mService.mWindowManager.setAppVisibility(prev.appToken, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001842 } else {
1843 if (DEBUG_TRANSITION) Slog.v(TAG,
1844 "Prepare open transition: prev=" + prev);
1845 if (mNoAnimActivities.contains(next)) {
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07001846 noAnim = true;
Dianne Hackborn7da6ac32010-12-09 19:22:04 -08001847 mService.mWindowManager.prepareAppTransition(
Craig Mautner4b71aa12012-12-27 17:20:01 -08001848 AppTransition.TRANSIT_NONE, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001849 } else {
1850 mService.mWindowManager.prepareAppTransition(prev.task == next.task
Craig Mautner4b71aa12012-12-27 17:20:01 -08001851 ? AppTransition.TRANSIT_ACTIVITY_OPEN
1852 : AppTransition.TRANSIT_TASK_OPEN, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001853 }
1854 }
1855 if (false) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08001856 mService.mWindowManager.setAppWillBeHidden(prev.appToken);
1857 mService.mWindowManager.setAppVisibility(prev.appToken, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001858 }
1859 } else if (mHistory.size() > 1) {
1860 if (DEBUG_TRANSITION) Slog.v(TAG,
1861 "Prepare open transition: no previous");
1862 if (mNoAnimActivities.contains(next)) {
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07001863 noAnim = true;
Dianne Hackborn7da6ac32010-12-09 19:22:04 -08001864 mService.mWindowManager.prepareAppTransition(
Craig Mautner4b71aa12012-12-27 17:20:01 -08001865 AppTransition.TRANSIT_NONE, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001866 } else {
Dianne Hackborn7da6ac32010-12-09 19:22:04 -08001867 mService.mWindowManager.prepareAppTransition(
Craig Mautner4b71aa12012-12-27 17:20:01 -08001868 AppTransition.TRANSIT_ACTIVITY_OPEN, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001869 }
1870 }
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07001871 if (!noAnim) {
1872 next.applyOptionsLocked();
1873 } else {
1874 next.clearOptionsLocked();
1875 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001876
1877 if (next.app != null && next.app.thread != null) {
1878 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
1879
1880 // This activity is now becoming visible.
Dianne Hackbornbe707852011-11-11 14:32:10 -08001881 mService.mWindowManager.setAppVisibility(next.appToken, true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001882
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07001883 // schedule launch ticks to collect information about slow apps.
1884 next.startLaunchTickingLocked();
1885
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001886 ActivityRecord lastResumedActivity = mResumedActivity;
1887 ActivityState lastState = next.state;
1888
1889 mService.updateCpuStats();
1890
Dianne Hackbornce86ba82011-07-13 19:33:41 -07001891 if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + next + " (in existing)");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001892 next.state = ActivityState.RESUMED;
1893 mResumedActivity = next;
1894 next.task.touchActiveTime();
Dianne Hackborn88819b22010-12-21 18:18:02 -08001895 if (mMainStack) {
1896 mService.addRecentTaskLocked(next.task);
1897 }
Dianne Hackbornb12e1352012-09-26 11:39:20 -07001898 mService.updateLruProcessLocked(next.app, true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001899 updateLRUListLocked(next);
1900
1901 // Have the window manager re-evaluate the orientation of
1902 // the screen based on the new activity order.
1903 boolean updated = false;
1904 if (mMainStack) {
1905 synchronized (mService) {
1906 Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
1907 mService.mConfiguration,
Dianne Hackbornbe707852011-11-11 14:32:10 -08001908 next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001909 if (config != null) {
1910 next.frozenBeforeDestroy = true;
1911 }
Dianne Hackborn813075a62011-11-14 17:45:19 -08001912 updated = mService.updateConfigurationLocked(config, next, false, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001913 }
1914 }
1915 if (!updated) {
1916 // The configuration update wasn't able to keep the existing
1917 // instance of the activity, and instead started a new one.
1918 // We should be all done, but let's just make sure our activity
1919 // is still at the top and schedule another run if something
1920 // weird happened.
1921 ActivityRecord nextNext = topRunningActivityLocked(null);
1922 if (DEBUG_SWITCH) Slog.i(TAG,
1923 "Activity config changed during resume: " + next
1924 + ", new next: " + nextNext);
1925 if (nextNext != next) {
1926 // Do over!
1927 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
1928 }
1929 if (mMainStack) {
1930 mService.setFocusedActivityLocked(next);
1931 }
1932 ensureActivitiesVisibleLocked(null, 0);
1933 mService.mWindowManager.executeAppTransition();
1934 mNoAnimActivities.clear();
1935 return true;
1936 }
1937
1938 try {
1939 // Deliver all pending results.
Craig Mautner05d6272ba2013-02-11 09:39:27 -08001940 ArrayList<ResultInfo> a = next.results;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001941 if (a != null) {
1942 final int N = a.size();
1943 if (!next.finishing && N > 0) {
1944 if (DEBUG_RESULTS) Slog.v(
1945 TAG, "Delivering results to " + next
1946 + ": " + a);
Dianne Hackbornbe707852011-11-11 14:32:10 -08001947 next.app.thread.scheduleSendResult(next.appToken, a);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001948 }
1949 }
1950
1951 if (next.newIntents != null) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08001952 next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001953 }
1954
1955 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
Dianne Hackbornb12e1352012-09-26 11:39:20 -07001956 next.userId, System.identityHashCode(next),
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001957 next.task.taskId, next.shortComponentName);
1958
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001959 next.sleeping = false;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001960 showAskCompatModeDialogLocked(next);
Dianne Hackborn905577f2011-09-07 18:31:28 -07001961 next.app.pendingUiClean = true;
Dianne Hackbornbe707852011-11-11 14:32:10 -08001962 next.app.thread.scheduleResumeActivity(next.appToken,
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001963 mService.isNextTransitionForward());
1964
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001965 checkReadyForSleepLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001966
1967 } catch (Exception e) {
1968 // Whoops, need to restart this activity!
Dianne Hackbornce86ba82011-07-13 19:33:41 -07001969 if (DEBUG_STATES) Slog.v(TAG, "Resume failed; resetting state to "
1970 + lastState + ": " + next);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001971 next.state = lastState;
1972 mResumedActivity = lastResumedActivity;
1973 Slog.i(TAG, "Restarting because process died: " + next);
1974 if (!next.hasBeenLaunched) {
1975 next.hasBeenLaunched = true;
1976 } else {
1977 if (SHOW_APP_STARTING_PREVIEW && mMainStack) {
1978 mService.mWindowManager.setAppStartingWindow(
Dianne Hackbornbe707852011-11-11 14:32:10 -08001979 next.appToken, next.packageName, next.theme,
Dianne Hackborn2f0b1752011-05-31 17:59:49 -07001980 mService.compatibilityInfoForPackageLocked(
1981 next.info.applicationInfo),
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001982 next.nonLocalizedLabel,
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001983 next.labelRes, next.icon, next.windowFlags,
1984 null, true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001985 }
1986 }
1987 startSpecificActivityLocked(next, true, false);
1988 return true;
1989 }
1990
1991 // From this point on, if something goes wrong there is no way
1992 // to recover the activity.
1993 try {
1994 next.visible = true;
1995 completeResumeLocked(next);
1996 } catch (Exception e) {
1997 // If any exception gets thrown, toss away this
1998 // activity and try the next one.
1999 Slog.w(TAG, "Exception thrown during resume of " + next, e);
Dianne Hackbornbe707852011-11-11 14:32:10 -08002000 requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07002001 "resume-exception", true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002002 return true;
2003 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002004 next.stopped = false;
2005
2006 } else {
2007 // Whoops, need to restart this activity!
2008 if (!next.hasBeenLaunched) {
2009 next.hasBeenLaunched = true;
2010 } else {
2011 if (SHOW_APP_STARTING_PREVIEW) {
2012 mService.mWindowManager.setAppStartingWindow(
Dianne Hackbornbe707852011-11-11 14:32:10 -08002013 next.appToken, next.packageName, next.theme,
Dianne Hackborn2f0b1752011-05-31 17:59:49 -07002014 mService.compatibilityInfoForPackageLocked(
2015 next.info.applicationInfo),
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002016 next.nonLocalizedLabel,
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08002017 next.labelRes, next.icon, next.windowFlags,
2018 null, true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002019 }
2020 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
2021 }
2022 startSpecificActivityLocked(next, true, true);
2023 }
2024
2025 return true;
2026 }
2027
Craig Mautner11bf9a52013-02-19 14:08:51 -08002028 /** Temporary until startActivityLocked is rewritten for tasks. */
2029 private int convertAddPos(int addPos) {
2030 final int taskId = mHistory.get(addPos).task.taskId;
2031 addPos--;
2032 int taskOffset = 0;
2033 while (addPos >= 0 && taskId == mHistory.get(addPos).task.taskId) {
2034 ++taskOffset;
2035 --addPos;
2036 }
2037 return taskOffset;
2038 }
2039
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002040 private final void startActivityLocked(ActivityRecord r, boolean newTask,
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07002041 boolean doResume, boolean keepCurTransition, Bundle options) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08002042 mLastHistoryModifier = "startActivityLocked";
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002043 final int NH = mHistory.size();
2044
2045 int addPos = -1;
2046
2047 if (!newTask) {
2048 // If starting in an existing task, find where that is...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002049 boolean startIt = true;
2050 for (int i = NH-1; i >= 0; i--) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002051 ActivityRecord p = mHistory.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002052 if (p.finishing) {
2053 continue;
2054 }
2055 if (p.task == r.task) {
2056 // Here it is! Now, if this is not yet visible to the
2057 // user, then just add it without starting; it will
2058 // get started when the user navigates back to it.
2059 addPos = i+1;
2060 if (!startIt) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07002061 if (DEBUG_ADD_REMOVE) {
2062 RuntimeException here = new RuntimeException("here");
2063 here.fillInStackTrace();
2064 Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos,
2065 here);
2066 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002067 r.task.addActivityToTop(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002068 mHistory.add(addPos, r);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002069 r.putInHistory();
Craig Mautner11bf9a52013-02-19 14:08:51 -08002070 mService.mWindowManager.addAppToken(convertAddPos(addPos), r.appToken,
2071 r.task.taskId, r.info.screenOrientation, r.fullscreen,
Craig Mautner5962b122012-10-05 14:45:52 -07002072 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002073 if (VALIDATE_TOKENS) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08002074 validateAppTokensLocked();
Craig Mautner11bf9a52013-02-19 14:08:51 -08002075 verifyActivityRecords(true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002076 }
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07002077 ActivityOptions.abort(options);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002078 return;
2079 }
2080 break;
2081 }
2082 if (p.fullscreen) {
2083 startIt = false;
2084 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002085 }
2086 }
2087
2088 // Place a new activity at top of stack, so it is next to interact
2089 // with the user.
2090 if (addPos < 0) {
Dianne Hackborn0dad3642010-09-09 21:25:35 -07002091 addPos = NH;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002092 }
2093
2094 // If we are not placing the new activity frontmost, we do not want
2095 // to deliver the onUserLeaving callback to the actual frontmost
2096 // activity
2097 if (addPos < NH) {
2098 mUserLeaving = false;
2099 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
2100 }
2101
2102 // Slot the activity into the history stack and proceed
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07002103 if (DEBUG_ADD_REMOVE) {
2104 RuntimeException here = new RuntimeException("here");
2105 here.fillInStackTrace();
2106 Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos, here);
2107 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002108 r.task.addActivityToTop(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002109 mHistory.add(addPos, r);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002110 r.putInHistory();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002111 r.frontOfTask = newTask;
Craig Mautner11bf9a52013-02-19 14:08:51 -08002112 if (VALIDATE_TASK_REPLACE) {
2113 if (verifyActivityRecords(false)) {
2114 Slog.w(TAG, "startActivityLocked: addPos=" + addPos);
2115 }
2116 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002117 if (NH > 0) {
2118 // We want to show the starting preview window if we are
2119 // switching to a new task, or the next activity's process is
2120 // not currently running.
2121 boolean showStartingIcon = newTask;
2122 ProcessRecord proc = r.app;
2123 if (proc == null) {
2124 proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2125 }
2126 if (proc == null || proc.thread == null) {
2127 showStartingIcon = true;
2128 }
2129 if (DEBUG_TRANSITION) Slog.v(TAG,
2130 "Prepare open transition: starting " + r);
2131 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
Dianne Hackborn7da6ac32010-12-09 19:22:04 -08002132 mService.mWindowManager.prepareAppTransition(
Craig Mautner4b71aa12012-12-27 17:20:01 -08002133 AppTransition.TRANSIT_NONE, keepCurTransition);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002134 mNoAnimActivities.add(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002135 } else {
2136 mService.mWindowManager.prepareAppTransition(newTask
Craig Mautner4b71aa12012-12-27 17:20:01 -08002137 ? AppTransition.TRANSIT_TASK_OPEN
2138 : AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002139 mNoAnimActivities.remove(r);
2140 }
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07002141 r.updateOptionsLocked(options);
Craig Mautner11bf9a52013-02-19 14:08:51 -08002142 mService.mWindowManager.addAppToken(convertAddPos(addPos),
2143 r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen,
Craig Mautner5962b122012-10-05 14:45:52 -07002144 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002145 boolean doShow = true;
2146 if (newTask) {
2147 // Even though this activity is starting fresh, we still need
2148 // to reset it to make sure we apply affinities to move any
2149 // existing activities from other tasks in to it.
2150 // If the caller has requested that the target task be
2151 // reset, then do so.
2152 if ((r.intent.getFlags()
2153 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2154 resetTaskIfNeededLocked(r, r);
2155 doShow = topRunningNonDelayedActivityLocked(null) == r;
2156 }
2157 }
2158 if (SHOW_APP_STARTING_PREVIEW && doShow) {
2159 // Figure out if we are transitioning from another activity that is
2160 // "has the same starting icon" as the next one. This allows the
2161 // window manager to keep the previous window it had previously
2162 // created, if it still had one.
2163 ActivityRecord prev = mResumedActivity;
2164 if (prev != null) {
2165 // We don't want to reuse the previous starting preview if:
2166 // (1) The current activity is in a different task.
2167 if (prev.task != r.task) prev = null;
2168 // (2) The current activity is already displayed.
2169 else if (prev.nowVisible) prev = null;
2170 }
2171 mService.mWindowManager.setAppStartingWindow(
Dianne Hackbornbe707852011-11-11 14:32:10 -08002172 r.appToken, r.packageName, r.theme,
Dianne Hackborn2f0b1752011-05-31 17:59:49 -07002173 mService.compatibilityInfoForPackageLocked(
2174 r.info.applicationInfo), r.nonLocalizedLabel,
Dianne Hackbornbe707852011-11-11 14:32:10 -08002175 r.labelRes, r.icon, r.windowFlags,
2176 prev != null ? prev.appToken : null, showStartingIcon);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002177 }
2178 } else {
2179 // If this is the first activity, don't do any fancy animations,
2180 // because there is nothing for it to animate on top of.
Craig Mautner11bf9a52013-02-19 14:08:51 -08002181 mService.mWindowManager.addAppToken(convertAddPos(addPos), r.appToken, r.task.taskId,
Craig Mautner5962b122012-10-05 14:45:52 -07002182 r.info.screenOrientation, r.fullscreen,
2183 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07002184 ActivityOptions.abort(options);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002185 }
2186 if (VALIDATE_TOKENS) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08002187 validateAppTokensLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002188 }
2189
2190 if (doResume) {
2191 resumeTopActivityLocked(null);
2192 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002193 if (VALIDATE_TASK_REPLACE) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08002194 if (verifyActivityRecords(true)) {
2195 Slog.w(TAG, "startActivityLocked: addPos=" + addPos);
2196 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002197 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002198 }
2199
Dianne Hackbornbe707852011-11-11 14:32:10 -08002200 final void validateAppTokensLocked() {
2201 mValidateAppTokens.clear();
2202 mValidateAppTokens.ensureCapacity(mHistory.size());
Craig Mautnerb1fd65c02013-02-05 13:34:57 -08002203 int taskId = Integer.MIN_VALUE;
2204 TaskGroup task = null;
Dianne Hackbornbe707852011-11-11 14:32:10 -08002205 for (int i=0; i<mHistory.size(); i++) {
Craig Mautnerb1fd65c02013-02-05 13:34:57 -08002206 final ActivityRecord r = mHistory.get(i);
2207 if (taskId != r.task.taskId) {
2208 taskId = r.task.taskId;
2209 task = new TaskGroup();
2210 task.taskId = taskId;
2211 mValidateAppTokens.add(task);
2212 }
2213 task.tokens.add(r.appToken);
Dianne Hackbornbe707852011-11-11 14:32:10 -08002214 }
2215 mService.mWindowManager.validateAppTokens(mValidateAppTokens);
2216 }
2217
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002218 /**
2219 * Perform a reset of the given task, if needed as part of launching it.
2220 * Returns the new HistoryRecord at the top of the task.
2221 */
2222 private final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
2223 ActivityRecord newActivity) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08002224 mLastHistoryModifier = "resetTaskIfNeededLocked";
2225
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002226 boolean forceReset = (newActivity.info.flags
2227 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002228 if (ACTIVITY_INACTIVE_RESET_TIME > 0
2229 && taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002230 if ((newActivity.info.flags
2231 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
2232 forceReset = true;
2233 }
2234 }
2235
2236 final TaskRecord task = taskTop.task;
2237
2238 // We are going to move through the history list so that we can look
2239 // at each activity 'target' with 'below' either the interesting
2240 // activity immediately below it in the stack or null.
2241 ActivityRecord target = null;
2242 int targetI = 0;
2243 int taskTopI = -1;
2244 int replyChainEnd = -1;
2245 int lastReparentPos = -1;
Dianne Hackborn9622ca42012-10-23 18:56:33 -07002246 ActivityOptions topOptions = null;
2247 boolean canMoveOptions = true;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002248 for (int i=mHistory.size()-1; i>=-1; i--) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002249 ActivityRecord below = i >= 0 ? mHistory.get(i) : null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002250
2251 if (below != null && below.finishing) {
2252 continue;
2253 }
Amith Yamasani04e0d262012-02-14 11:50:53 -08002254 // Don't check any lower in the stack if we're crossing a user boundary.
2255 if (below != null && below.userId != taskTop.userId) {
2256 break;
2257 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002258 if (target == null) {
2259 target = below;
2260 targetI = i;
2261 // If we were in the middle of a reply chain before this
2262 // task, it doesn't appear like the root of the chain wants
2263 // anything interesting, so drop it.
2264 replyChainEnd = -1;
2265 continue;
2266 }
2267
2268 final int flags = target.info.flags;
2269
2270 final boolean finishOnTaskLaunch =
2271 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
2272 final boolean allowTaskReparenting =
2273 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
2274
2275 if (target.task == task) {
2276 // We are inside of the task being reset... we'll either
2277 // finish this activity, push it out for another task,
2278 // or leave it as-is. We only do this
2279 // for activities that are not the root of the task (since
2280 // if we finish the root, we may no longer have the task!).
2281 if (taskTopI < 0) {
2282 taskTopI = targetI;
2283 }
2284 if (below != null && below.task == task) {
2285 final boolean clearWhenTaskReset =
2286 (target.intent.getFlags()
2287 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
2288 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
2289 // If this activity is sending a reply to a previous
2290 // activity, we can't do anything with it now until
2291 // we reach the start of the reply chain.
2292 // XXX note that we are assuming the result is always
2293 // to the previous activity, which is almost always
2294 // the case but we really shouldn't count on.
2295 if (replyChainEnd < 0) {
2296 replyChainEnd = targetI;
2297 }
2298 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
2299 && target.taskAffinity != null
2300 && !target.taskAffinity.equals(task.affinity)) {
2301 // If this activity has an affinity for another
2302 // task, then we need to move it out of here. We will
2303 // move it as far out of the way as possible, to the
2304 // bottom of the activity stack. This also keeps it
2305 // correctly ordered with any activities we previously
2306 // moved.
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002307 ActivityRecord p = mHistory.get(0);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002308 if (target.taskAffinity != null
2309 && target.taskAffinity.equals(p.task.affinity)) {
2310 // If the activity currently at the bottom has the
2311 // same task affinity as the one we are moving,
2312 // then merge it into the same task.
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002313 target.setTask(p.task, p.thumbHolder, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002314 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
2315 + " out to bottom task " + p.task);
2316 } else {
2317 mService.mCurTask++;
2318 if (mService.mCurTask <= 0) {
2319 mService.mCurTask = 1;
2320 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002321 target.setTask(createTaskRecord(mService.mCurTask, target.info, null,
2322 false), null, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002323 target.task.affinityIntent = target.intent;
2324 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
2325 + " out to new task " + target.task);
2326 }
Craig Mautner926f3832013-02-13 11:56:07 -08002327 mService.mWindowManager.setAppGroupId(target.appToken, target.task.taskId);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002328 if (replyChainEnd < 0) {
2329 replyChainEnd = targetI;
2330 }
2331 int dstPos = 0;
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002332 ThumbnailHolder curThumbHolder = target.thumbHolder;
Dianne Hackborn9622ca42012-10-23 18:56:33 -07002333 boolean gotOptions = !canMoveOptions;
Craig Mautner30e2d722013-02-12 11:30:16 -08002334 final int taskId = target.task.taskId;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002335 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002336 p = mHistory.get(srcPos);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002337 if (p.finishing) {
2338 continue;
2339 }
2340 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
2341 + " out to target's task " + target.task);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002342 p.setTask(target.task, curThumbHolder, false);
2343 curThumbHolder = p.thumbHolder;
Dianne Hackborn9622ca42012-10-23 18:56:33 -07002344 canMoveOptions = false;
2345 if (!gotOptions && topOptions == null) {
2346 topOptions = p.takeOptionsLocked();
2347 if (topOptions != null) {
2348 gotOptions = true;
2349 }
2350 }
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07002351 if (DEBUG_ADD_REMOVE) {
2352 RuntimeException here = new RuntimeException("here");
2353 here.fillInStackTrace();
2354 Slog.i(TAG, "Removing and adding activity " + p + " to stack at "
2355 + dstPos, here);
2356 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002357 mHistory.remove(srcPos);
2358 mHistory.add(dstPos, p);
Craig Mautner30e2d722013-02-12 11:30:16 -08002359 mService.mWindowManager.setAppGroupId(p.appToken, taskId);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002360 dstPos++;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002361 i++;
2362 }
Craig Mautner11bf9a52013-02-19 14:08:51 -08002363 rebuildTaskHistory();
Craig Mautner30e2d722013-02-12 11:30:16 -08002364 mService.mWindowManager.moveTaskToBottom(taskId);
2365 if (VALIDATE_TOKENS) {
2366 validateAppTokensLocked();
2367 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002368 if (taskTop == p) {
2369 taskTop = below;
2370 }
2371 if (taskTopI == replyChainEnd) {
2372 taskTopI = -1;
2373 }
2374 replyChainEnd = -1;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002375 } else if (forceReset || finishOnTaskLaunch
2376 || clearWhenTaskReset) {
2377 // If the activity should just be removed -- either
2378 // because it asks for it, or the task should be
2379 // cleared -- then finish it and anything that is
2380 // part of its reply chain.
2381 if (clearWhenTaskReset) {
2382 // In this case, we want to finish this activity
2383 // and everything above it, so be sneaky and pretend
2384 // like these are all in the reply chain.
2385 replyChainEnd = targetI+1;
2386 while (replyChainEnd < mHistory.size() &&
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002387 (mHistory.get(replyChainEnd)).task == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002388 replyChainEnd++;
2389 }
2390 replyChainEnd--;
2391 } else if (replyChainEnd < 0) {
2392 replyChainEnd = targetI;
2393 }
2394 ActivityRecord p = null;
Dianne Hackborn9622ca42012-10-23 18:56:33 -07002395 boolean gotOptions = !canMoveOptions;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002396 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002397 p = mHistory.get(srcPos);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002398 if (p.finishing) {
2399 continue;
2400 }
Dianne Hackborn9622ca42012-10-23 18:56:33 -07002401 canMoveOptions = false;
2402 if (!gotOptions && topOptions == null) {
2403 topOptions = p.takeOptionsLocked();
2404 if (topOptions != null) {
2405 gotOptions = true;
2406 }
2407 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002408 if (finishActivityLocked(p, srcPos,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07002409 Activity.RESULT_CANCELED, null, "reset", false)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002410 replyChainEnd--;
2411 srcPos--;
2412 }
2413 }
2414 if (taskTop == p) {
2415 taskTop = below;
2416 }
2417 if (taskTopI == replyChainEnd) {
2418 taskTopI = -1;
2419 }
2420 replyChainEnd = -1;
2421 } else {
2422 // If we were in the middle of a chain, well the
2423 // activity that started it all doesn't want anything
2424 // special, so leave it all as-is.
2425 replyChainEnd = -1;
2426 }
2427 } else {
2428 // Reached the bottom of the task -- any reply chain
2429 // should be left as-is.
2430 replyChainEnd = -1;
2431 }
Dianne Hackbornae0a0a82011-12-07 14:03:01 -08002432
2433 } else if (target.resultTo != null && (below == null
2434 || below.task == target.task)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002435 // If this activity is sending a reply to a previous
2436 // activity, we can't do anything with it now until
2437 // we reach the start of the reply chain.
2438 // XXX note that we are assuming the result is always
2439 // to the previous activity, which is almost always
2440 // the case but we really shouldn't count on.
2441 if (replyChainEnd < 0) {
2442 replyChainEnd = targetI;
2443 }
2444
2445 } else if (taskTopI >= 0 && allowTaskReparenting
2446 && task.affinity != null
2447 && task.affinity.equals(target.taskAffinity)) {
2448 // We are inside of another task... if this activity has
2449 // an affinity for our task, then either remove it if we are
2450 // clearing or move it over to our task. Note that
2451 // we currently punt on the case where we are resetting a
2452 // task that is not at the top but who has activities above
2453 // with an affinity to it... this is really not a normal
2454 // case, and we will need to later pull that task to the front
2455 // and usually at that point we will do the reset and pick
2456 // up those remaining activities. (This only happens if
2457 // someone starts an activity in a new task from an activity
2458 // in a task that is not currently on top.)
2459 if (forceReset || finishOnTaskLaunch) {
2460 if (replyChainEnd < 0) {
2461 replyChainEnd = targetI;
2462 }
2463 ActivityRecord p = null;
Dianne Hackbornae0a0a82011-12-07 14:03:01 -08002464 if (DEBUG_TASKS) Slog.v(TAG, "Finishing task at index "
2465 + targetI + " to " + replyChainEnd);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002466 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002467 p = mHistory.get(srcPos);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002468 if (p.finishing) {
2469 continue;
2470 }
2471 if (finishActivityLocked(p, srcPos,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07002472 Activity.RESULT_CANCELED, null, "reset", false)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002473 taskTopI--;
2474 lastReparentPos--;
2475 replyChainEnd--;
2476 srcPos--;
2477 }
2478 }
2479 replyChainEnd = -1;
2480 } else {
2481 if (replyChainEnd < 0) {
2482 replyChainEnd = targetI;
2483 }
Craig Mautner30e2d722013-02-12 11:30:16 -08002484 final int taskId = task.taskId;
Dianne Hackbornae0a0a82011-12-07 14:03:01 -08002485 if (DEBUG_TASKS) Slog.v(TAG, "Reparenting task at index "
2486 + targetI + " to " + replyChainEnd);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002487 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002488 ActivityRecord p = mHistory.get(srcPos);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002489 if (p.finishing) {
2490 continue;
2491 }
2492 if (lastReparentPos < 0) {
2493 lastReparentPos = taskTopI;
2494 taskTop = p;
2495 } else {
2496 lastReparentPos--;
2497 }
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07002498 if (DEBUG_ADD_REMOVE) {
2499 RuntimeException here = new RuntimeException("here");
2500 here.fillInStackTrace();
2501 Slog.i(TAG, "Removing and adding activity " + p + " to stack at "
2502 + lastReparentPos, here);
2503 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002504 mHistory.remove(srcPos);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002505 p.setTask(task, null, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002506 mHistory.add(lastReparentPos, p);
2507 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
Dianne Hackbornae0a0a82011-12-07 14:03:01 -08002508 + " from " + srcPos + " to " + lastReparentPos
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002509 + " in to resetting task " + task);
Craig Mautner30e2d722013-02-12 11:30:16 -08002510 mService.mWindowManager.setAppGroupId(p.appToken, taskId);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002511 }
Craig Mautner11bf9a52013-02-19 14:08:51 -08002512 rebuildTaskHistory();
Craig Mautner05d6272ba2013-02-11 09:39:27 -08002513 // TODO: This is wrong because it doesn't take lastReparentPos into account.
Craig Mautner30e2d722013-02-12 11:30:16 -08002514 mService.mWindowManager.moveTaskToTop(taskId);
2515 if (VALIDATE_TOKENS) {
2516 validateAppTokensLocked();
2517 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002518 replyChainEnd = -1;
2519
2520 // Now we've moved it in to place... but what if this is
2521 // a singleTop activity and we have put it on top of another
2522 // instance of the same activity? Then we drop the instance
2523 // below so it remains singleTop.
2524 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
2525 for (int j=lastReparentPos-1; j>=0; j--) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002526 ActivityRecord p = mHistory.get(j);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002527 if (p.finishing) {
2528 continue;
2529 }
2530 if (p.intent.getComponent().equals(target.intent.getComponent())) {
2531 if (finishActivityLocked(p, j,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07002532 Activity.RESULT_CANCELED, null, "replace", false)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002533 taskTopI--;
2534 lastReparentPos--;
2535 }
2536 }
2537 }
2538 }
2539 }
Dianne Hackbornae0a0a82011-12-07 14:03:01 -08002540
2541 } else if (below != null && below.task != target.task) {
2542 // We hit the botton of a task; the reply chain can't
2543 // pass through it.
2544 replyChainEnd = -1;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002545 }
2546
2547 target = below;
2548 targetI = i;
2549 }
Dianne Hackborn9622ca42012-10-23 18:56:33 -07002550
2551 if (topOptions != null) {
2552 // If we got some ActivityOptions from an activity on top that
2553 // was removed from the task, propagate them to the new real top.
2554 if (taskTop != null) {
2555 taskTop.updateOptionsLocked(topOptions);
2556 } else {
2557 topOptions.abort();
2558 }
2559 }
2560
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002561 if (VALIDATE_TASK_REPLACE) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08002562 verifyActivityRecords(true);
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002563 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002564 return taskTop;
2565 }
2566
2567 /**
2568 * Perform clear operation as requested by
2569 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2570 * stack to the given task, then look for
2571 * an instance of that activity in the stack and, if found, finish all
2572 * activities on top of it and return the instance.
2573 *
2574 * @param newR Description of the new activity being started.
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002575 * @return Returns the old activity that should be continued to be used,
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002576 * or null if none was found.
2577 */
2578 private final ActivityRecord performClearTaskLocked(int taskId,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002579 ActivityRecord newR, int launchFlags) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002580 int i = mHistory.size();
2581
2582 // First find the requested task.
2583 while (i > 0) {
2584 i--;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002585 ActivityRecord r = mHistory.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002586 if (r.task.taskId == taskId) {
2587 i++;
2588 break;
2589 }
2590 }
2591
2592 // Now clear it.
2593 while (i > 0) {
2594 i--;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002595 ActivityRecord r = mHistory.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002596 if (r.finishing) {
2597 continue;
2598 }
2599 if (r.task.taskId != taskId) {
2600 return null;
2601 }
2602 if (r.realActivity.equals(newR.realActivity)) {
2603 // Here it is! Now finish everything in front...
2604 ActivityRecord ret = r;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002605 while (i < (mHistory.size()-1)) {
2606 i++;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002607 r = mHistory.get(i);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002608 if (r.task.taskId != taskId) {
2609 break;
2610 }
2611 if (r.finishing) {
2612 continue;
2613 }
Dianne Hackborn9622ca42012-10-23 18:56:33 -07002614 ActivityOptions opts = r.takeOptionsLocked();
2615 if (opts != null) {
2616 ret.updateOptionsLocked(opts);
2617 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002618 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07002619 null, "clear", false)) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002620 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002621 }
2622 }
2623
2624 // Finally, if this is a normal launch mode (that is, not
2625 // expecting onNewIntent()), then we will finish the current
2626 // instance of the activity so a new fresh one can be started.
2627 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
2628 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
2629 if (!ret.finishing) {
Craig Mautner05d6272ba2013-02-11 09:39:27 -08002630 int index = mHistory.indexOf(ret);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002631 if (index >= 0) {
2632 finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07002633 null, "clear", false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002634 }
2635 return null;
2636 }
2637 }
2638
2639 return ret;
2640 }
2641 }
2642
2643 return null;
2644 }
2645
2646 /**
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002647 * Completely remove all activities associated with an existing
2648 * task starting at a specified index.
2649 */
2650 private final void performClearTaskAtIndexLocked(int taskId, int i) {
Dianne Hackborneabd3282011-10-13 16:26:49 -07002651 while (i < mHistory.size()) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002652 ActivityRecord r = mHistory.get(i);
2653 if (r.task.taskId != taskId) {
2654 // Whoops hit the end.
2655 return;
2656 }
2657 if (r.finishing) {
2658 i++;
2659 continue;
2660 }
2661 if (!finishActivityLocked(r, i, Activity.RESULT_CANCELED,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07002662 null, "clear", false)) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002663 i++;
2664 }
2665 }
2666 }
2667
2668 /**
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002669 * Completely remove all activities associated with an existing task.
2670 */
2671 private final void performClearTaskLocked(int taskId) {
2672 int i = mHistory.size();
2673
2674 // First find the requested task.
2675 while (i > 0) {
2676 i--;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002677 ActivityRecord r = mHistory.get(i);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002678 if (r.task.taskId == taskId) {
2679 i++;
2680 break;
2681 }
2682 }
2683
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002684 // Now find the start and clear it.
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002685 while (i > 0) {
2686 i--;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002687 ActivityRecord r = mHistory.get(i);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002688 if (r.finishing) {
2689 continue;
2690 }
2691 if (r.task.taskId != taskId) {
2692 // We hit the bottom. Now finish it all...
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002693 performClearTaskAtIndexLocked(taskId, i+1);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002694 return;
2695 }
2696 }
2697 }
2698
2699 /**
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002700 * Find the activity in the history stack within the given task. Returns
2701 * the index within the history at which it's found, or < 0 if not found.
2702 */
2703 private final int findActivityInHistoryLocked(ActivityRecord r, int task) {
2704 int i = mHistory.size();
2705 while (i > 0) {
2706 i--;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002707 ActivityRecord candidate = mHistory.get(i);
Dianne Hackborn45a25bc2012-06-28 13:49:17 -07002708 if (candidate.finishing) {
2709 continue;
2710 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002711 if (candidate.task.taskId != task) {
2712 break;
2713 }
2714 if (candidate.realActivity.equals(r.realActivity)) {
2715 return i;
2716 }
2717 }
2718
2719 return -1;
2720 }
2721
2722 /**
2723 * Reorder the history stack so that the activity at the given index is
2724 * brought to the front.
2725 */
2726 private final ActivityRecord moveActivityToFrontLocked(int where) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002727 ActivityRecord newTop = mHistory.remove(where);
Craig Mautner11bf9a52013-02-19 14:08:51 -08002728 newMoveActivityToFrontLocked(newTop);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002729 int top = mHistory.size();
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002730 ActivityRecord oldTop = mHistory.get(top-1);
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07002731 if (DEBUG_ADD_REMOVE) {
2732 RuntimeException here = new RuntimeException("here");
2733 here.fillInStackTrace();
2734 Slog.i(TAG, "Removing and adding activity " + newTop + " to stack at "
2735 + top, here);
2736 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002737 mHistory.add(top, newTop);
Craig Mautner11bf9a52013-02-19 14:08:51 -08002738 if (VALIDATE_TASK_REPLACE) {
2739 verifyActivityRecords(true);
2740 }
2741 return newTop;
2742 }
2743
2744 private final ActivityRecord newMoveActivityToFrontLocked(ActivityRecord newTop) {
2745 final TaskRecord task = newTop.task;
2746 ActivityRecord oldTop = task.getTopActivity();
2747 task.mActivities.remove(newTop);
2748 task.mActivities.add(newTop);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002749 oldTop.frontOfTask = false;
2750 newTop.frontOfTask = true;
2751 return newTop;
2752 }
2753
2754 final int startActivityLocked(IApplicationThread caller,
Dianne Hackborna4972e92012-03-14 10:38:05 -07002755 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002756 String resultWho, int requestCode,
Dianne Hackbornf265ea92013-01-31 15:00:51 -08002757 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002758 boolean componentSpecified, ActivityRecord[] outActivity) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08002759 mLastHistoryModifier = "startActivityLocked(IApplicationThread)";
Dianne Hackbornefb58102010-10-14 16:47:34 -07002760
Dianne Hackborna4972e92012-03-14 10:38:05 -07002761 int err = ActivityManager.START_SUCCESS;
Dianne Hackbornefb58102010-10-14 16:47:34 -07002762
2763 ProcessRecord callerApp = null;
2764 if (caller != null) {
2765 callerApp = mService.getRecordForAppLocked(caller);
2766 if (callerApp != null) {
2767 callingPid = callerApp.pid;
2768 callingUid = callerApp.info.uid;
2769 } else {
2770 Slog.w(TAG, "Unable to find app for caller " + caller
2771 + " (pid=" + callingPid + ") when starting: "
2772 + intent.toString());
Dianne Hackborna4972e92012-03-14 10:38:05 -07002773 err = ActivityManager.START_PERMISSION_DENIED;
Dianne Hackbornefb58102010-10-14 16:47:34 -07002774 }
2775 }
2776
Dianne Hackborna4972e92012-03-14 10:38:05 -07002777 if (err == ActivityManager.START_SUCCESS) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002778 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
Dianne Hackborn5fe7e2a2012-10-04 11:58:16 -07002779 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
2780 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
Dianne Hackbornefb58102010-10-14 16:47:34 -07002781 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002782
2783 ActivityRecord sourceRecord = null;
2784 ActivityRecord resultRecord = null;
2785 if (resultTo != null) {
2786 int index = indexOfTokenLocked(resultTo);
2787 if (DEBUG_RESULTS) Slog.v(
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07002788 TAG, "Will send result to " + resultTo + " (index " + index + ")");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002789 if (index >= 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002790 sourceRecord = mHistory.get(index);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002791 if (requestCode >= 0 && !sourceRecord.finishing) {
2792 resultRecord = sourceRecord;
2793 }
2794 }
2795 }
2796
2797 int launchFlags = intent.getFlags();
2798
2799 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
2800 && sourceRecord != null) {
2801 // Transfer the result target from the source activity to the new
2802 // one being started, including any failures.
2803 if (requestCode >= 0) {
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07002804 ActivityOptions.abort(options);
Dianne Hackborna4972e92012-03-14 10:38:05 -07002805 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002806 }
2807 resultRecord = sourceRecord.resultTo;
2808 resultWho = sourceRecord.resultWho;
2809 requestCode = sourceRecord.requestCode;
2810 sourceRecord.resultTo = null;
2811 if (resultRecord != null) {
2812 resultRecord.removeResultsLocked(
2813 sourceRecord, resultWho, requestCode);
2814 }
2815 }
2816
Dianne Hackborna4972e92012-03-14 10:38:05 -07002817 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002818 // We couldn't find a class that can handle the given Intent.
2819 // That's the end of that!
Dianne Hackborna4972e92012-03-14 10:38:05 -07002820 err = ActivityManager.START_INTENT_NOT_RESOLVED;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002821 }
2822
Dianne Hackborna4972e92012-03-14 10:38:05 -07002823 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002824 // We couldn't find the specific class specified in the Intent.
2825 // Also the end of the line.
Dianne Hackborna4972e92012-03-14 10:38:05 -07002826 err = ActivityManager.START_CLASS_NOT_FOUND;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002827 }
2828
Dianne Hackborna4972e92012-03-14 10:38:05 -07002829 if (err != ActivityManager.START_SUCCESS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002830 if (resultRecord != null) {
2831 sendActivityResultLocked(-1,
2832 resultRecord, resultWho, requestCode,
2833 Activity.RESULT_CANCELED, null);
2834 }
Dianne Hackborn90c52de2011-09-23 12:57:44 -07002835 mDismissKeyguardOnNextActivity = false;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07002836 ActivityOptions.abort(options);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002837 return err;
2838 }
2839
Jeff Sharkey35be7562012-04-18 19:16:15 -07002840 final int startAnyPerm = mService.checkPermission(
2841 START_ANY_ACTIVITY, callingPid, callingUid);
2842 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08002843 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
Jeff Sharkey35be7562012-04-18 19:16:15 -07002844 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002845 if (resultRecord != null) {
2846 sendActivityResultLocked(-1,
2847 resultRecord, resultWho, requestCode,
2848 Activity.RESULT_CANCELED, null);
2849 }
Dianne Hackborn90c52de2011-09-23 12:57:44 -07002850 mDismissKeyguardOnNextActivity = false;
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08002851 String msg;
2852 if (!aInfo.exported) {
2853 msg = "Permission Denial: starting " + intent.toString()
2854 + " from " + callerApp + " (pid=" + callingPid
2855 + ", uid=" + callingUid + ")"
2856 + " not exported from uid " + aInfo.applicationInfo.uid;
2857 } else {
2858 msg = "Permission Denial: starting " + intent.toString()
2859 + " from " + callerApp + " (pid=" + callingPid
2860 + ", uid=" + callingUid + ")"
2861 + " requires " + aInfo.permission;
2862 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002863 Slog.w(TAG, msg);
2864 throw new SecurityException(msg);
2865 }
2866
2867 if (mMainStack) {
2868 if (mService.mController != null) {
2869 boolean abort = false;
2870 try {
2871 // The Intent we give to the watcher has the extra data
2872 // stripped off, since it can contain private information.
2873 Intent watchIntent = intent.cloneFilter();
2874 abort = !mService.mController.activityStarting(watchIntent,
2875 aInfo.applicationInfo.packageName);
2876 } catch (RemoteException e) {
2877 mService.mController = null;
2878 }
2879
2880 if (abort) {
2881 if (resultRecord != null) {
2882 sendActivityResultLocked(-1,
2883 resultRecord, resultWho, requestCode,
2884 Activity.RESULT_CANCELED, null);
2885 }
2886 // We pretend to the caller that it was really started, but
2887 // they will just get a cancel result.
Dianne Hackborn90c52de2011-09-23 12:57:44 -07002888 mDismissKeyguardOnNextActivity = false;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07002889 ActivityOptions.abort(options);
Dianne Hackborna4972e92012-03-14 10:38:05 -07002890 return ActivityManager.START_SUCCESS;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002891 }
2892 }
2893 }
Amith Yamasani742a6712011-05-04 14:49:28 -07002894
Dianne Hackbornf265ea92013-01-31 15:00:51 -08002895 ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid, callingPackage,
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002896 intent, resolvedType, aInfo, mService.mConfiguration,
2897 resultRecord, resultWho, requestCode, componentSpecified);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002898 if (outActivity != null) {
2899 outActivity[0] = r;
2900 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002901
2902 if (mMainStack) {
2903 if (mResumedActivity == null
2904 || mResumedActivity.info.applicationInfo.uid != callingUid) {
2905 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
2906 PendingActivityLaunch pal = new PendingActivityLaunch();
2907 pal.r = r;
2908 pal.sourceRecord = sourceRecord;
Dianne Hackborna4972e92012-03-14 10:38:05 -07002909 pal.startFlags = startFlags;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002910 mService.mPendingActivityLaunches.add(pal);
Dianne Hackborn90c52de2011-09-23 12:57:44 -07002911 mDismissKeyguardOnNextActivity = false;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07002912 ActivityOptions.abort(options);
Dianne Hackborna4972e92012-03-14 10:38:05 -07002913 return ActivityManager.START_SWITCHES_CANCELED;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002914 }
2915 }
2916
2917 if (mService.mDidAppSwitch) {
2918 // This is the second allowed switch since we stopped switches,
2919 // so now just generally allow switches. Use case: user presses
2920 // home (switches disabled, switch to home, mDidAppSwitch now true);
2921 // user taps a home icon (coming from home so allowed, we hit here
2922 // and now allow anyone to switch again).
2923 mService.mAppSwitchesAllowedTime = 0;
2924 } else {
2925 mService.mDidAppSwitch = true;
2926 }
2927
2928 mService.doPendingActivityLaunchesLocked(false);
2929 }
2930
Dianne Hackborn90c52de2011-09-23 12:57:44 -07002931 err = startActivityUncheckedLocked(r, sourceRecord,
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07002932 startFlags, true, options);
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08002933 if (mDismissKeyguardOnNextActivity && mPausingActivity == null) {
Dianne Hackborn90c52de2011-09-23 12:57:44 -07002934 // Someone asked to have the keyguard dismissed on the next
2935 // activity start, but we are not actually doing an activity
2936 // switch... just dismiss the keyguard now, because we
2937 // probably want to see whatever is behind it.
2938 mDismissKeyguardOnNextActivity = false;
2939 mService.mWindowManager.dismissKeyguard();
2940 }
2941 return err;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002942 }
2943
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002944 final void moveHomeToFrontFromLaunchLocked(int launchFlags) {
2945 if ((launchFlags &
2946 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
2947 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
2948 // Caller wants to appear on home activity, so before starting
2949 // their own activity we will bring home to the front.
2950 moveHomeToFrontLocked();
2951 }
2952 }
2953
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002954 final int startActivityUncheckedLocked(ActivityRecord r,
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07002955 ActivityRecord sourceRecord, int startFlags, boolean doResume,
2956 Bundle options) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002957 final Intent intent = r.intent;
2958 final int callingUid = r.launchedFromUid;
Amith Yamasani742a6712011-05-04 14:49:28 -07002959
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002960 int launchFlags = intent.getFlags();
2961
2962 // We'll invoke onUserLeaving before onPause only if the launching
2963 // activity did not explicitly state that this is an automated launch.
2964 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
2965 if (DEBUG_USER_LEAVING) Slog.v(TAG,
2966 "startActivity() => mUserLeaving=" + mUserLeaving);
2967
2968 // If the caller has asked not to resume at this point, we make note
2969 // of this in the record so that we can skip it when trying to find
2970 // the top running activity.
2971 if (!doResume) {
2972 r.delayedResume = true;
2973 }
2974
2975 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
2976 != 0 ? r : null;
2977
2978 // If the onlyIfNeeded flag is set, then we can do this if the activity
2979 // being launched is the same as the one making the call... or, as
2980 // a special case, if we do not know the caller then we count the
2981 // current top activity as the caller.
Dianne Hackborna4972e92012-03-14 10:38:05 -07002982 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002983 ActivityRecord checkedCaller = sourceRecord;
2984 if (checkedCaller == null) {
2985 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
2986 }
2987 if (!checkedCaller.realActivity.equals(r.realActivity)) {
2988 // Caller is not the same as launcher, so always needed.
Dianne Hackborna4972e92012-03-14 10:38:05 -07002989 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002990 }
2991 }
2992
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002993 if (sourceRecord == null) {
2994 // This activity is not being started from another... in this
2995 // case we -always- start a new task.
2996 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
2997 Slog.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
2998 + intent);
2999 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3000 }
3001 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3002 // The original activity who is starting us is running as a single
3003 // instance... this new activity it is starting must go on its
3004 // own task.
3005 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3006 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3007 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3008 // The activity being started is a single instance... it always
3009 // gets launched into its own task.
3010 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3011 }
3012
3013 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3014 // For whatever reason this activity is being launched into a new
3015 // task... yet the caller has requested a result back. Well, that
3016 // is pretty messed up, so instead immediately send back a cancel
3017 // and let the new task continue launched as normal without a
3018 // dependency on its originator.
3019 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
3020 sendActivityResultLocked(-1,
3021 r.resultTo, r.resultWho, r.requestCode,
3022 Activity.RESULT_CANCELED, null);
3023 r.resultTo = null;
3024 }
3025
3026 boolean addingToTask = false;
Dianne Hackborn03fcc332012-05-15 12:49:40 -07003027 boolean movedHome = false;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003028 TaskRecord reuseTask = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003029 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3030 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3031 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3032 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3033 // If bring to front is requested, and no result is requested, and
3034 // we can find a task that was started with this same
3035 // component, then instead of launching bring that one to the front.
3036 if (r.resultTo == null) {
3037 // See if there is a task to bring to the front. If this is
3038 // a SINGLE_INSTANCE activity, there can be one and only one
3039 // instance of it in the history, and it is always in its own
3040 // unique task, so we do a special search.
3041 ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3042 ? findTaskLocked(intent, r.info)
3043 : findActivityLocked(intent, r.info);
3044 if (taskTop != null) {
3045 if (taskTop.task.intent == null) {
3046 // This task was started because of movement of
3047 // the activity based on affinity... now that we
3048 // are actually launching it, we can assign the
3049 // base intent.
3050 taskTop.task.setIntent(intent, r.info);
3051 }
3052 // If the target task is not in the front, then we need
3053 // to bring it to the front... except... well, with
3054 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3055 // to have the same behavior as if a new instance was
3056 // being started, which means not bringing it to the front
3057 // if the caller is not itself in the front.
3058 ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop);
Jean-Baptiste Queru66a5d692010-10-25 17:27:16 -07003059 if (curTop != null && curTop.task != taskTop.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003060 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3061 boolean callerAtFront = sourceRecord == null
3062 || curTop.task == sourceRecord.task;
3063 if (callerAtFront) {
3064 // We really do want to push this one into the
3065 // user's face, right now.
Dianne Hackborn03fcc332012-05-15 12:49:40 -07003066 movedHome = true;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003067 moveHomeToFrontFromLaunchLocked(launchFlags);
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003068 moveTaskToFrontLocked(taskTop.task, r, options);
Dianne Hackborn84375872012-06-01 19:03:50 -07003069 options = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003070 }
3071 }
3072 // If the caller has requested that the target task be
3073 // reset, then do so.
3074 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3075 taskTop = resetTaskIfNeededLocked(taskTop, r);
3076 }
Dianne Hackborna4972e92012-03-14 10:38:05 -07003077 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003078 // We don't need to start a new activity, and
3079 // the client said not to do anything if that
3080 // is the case, so this is it! And for paranoia, make
3081 // sure we have correctly resumed the top activity.
3082 if (doResume) {
Dianne Hackborn84375872012-06-01 19:03:50 -07003083 resumeTopActivityLocked(null, options);
3084 } else {
3085 ActivityOptions.abort(options);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003086 }
Dianne Hackborna4972e92012-03-14 10:38:05 -07003087 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003088 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003089 if ((launchFlags &
3090 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
3091 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
3092 // The caller has requested to completely replace any
Dianne Hackborn7da6ac32010-12-09 19:22:04 -08003093 // existing task with its new activity. Well that should
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003094 // not be too hard...
3095 reuseTask = taskTop.task;
3096 performClearTaskLocked(taskTop.task.taskId);
3097 reuseTask.setIntent(r.intent, r.info);
3098 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003099 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3100 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3101 // In this situation we want to remove all activities
3102 // from the task up to the one being started. In most
3103 // cases this means we are resetting the task to its
3104 // initial state.
3105 ActivityRecord top = performClearTaskLocked(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003106 taskTop.task.taskId, r, launchFlags);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003107 if (top != null) {
3108 if (top.frontOfTask) {
3109 // Activity aliases may mean we use different
3110 // intents for the top activity, so make sure
3111 // the task now has the identity of the new
3112 // intent.
3113 top.task.setIntent(r.intent, r.info);
3114 }
3115 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
Dianne Hackborn39792d22010-08-19 18:01:52 -07003116 top.deliverNewIntentLocked(callingUid, r.intent);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003117 } else {
3118 // A special case: we need to
3119 // start the activity because it is not currently
3120 // running, and the caller has asked to clear the
3121 // current task to have this activity at the top.
3122 addingToTask = true;
3123 // Now pretend like this activity is being started
3124 // by the top of its task, so it is put in the
3125 // right place.
3126 sourceRecord = taskTop;
3127 }
3128 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3129 // In this case the top activity on the task is the
3130 // same as the one being launched, so we take that
3131 // as a request to bring the task to the foreground.
3132 // If the top activity in the task is the root
3133 // activity, deliver this new intent to it if it
3134 // desires.
Johan Viktorssonf363dfd2012-02-16 17:05:16 +01003135 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3136 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003137 && taskTop.realActivity.equals(r.realActivity)) {
3138 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
3139 if (taskTop.frontOfTask) {
3140 taskTop.task.setIntent(r.intent, r.info);
3141 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07003142 taskTop.deliverNewIntentLocked(callingUid, r.intent);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003143 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3144 // In this case we are launching the root activity
3145 // of the task, but with a different intent. We
3146 // should start a new instance on top.
3147 addingToTask = true;
3148 sourceRecord = taskTop;
3149 }
3150 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3151 // In this case an activity is being launched in to an
3152 // existing task, without resetting that task. This
3153 // is typically the situation of launching an activity
3154 // from a notification or shortcut. We want to place
3155 // the new activity on top of the current task.
3156 addingToTask = true;
3157 sourceRecord = taskTop;
3158 } else if (!taskTop.task.rootWasReset) {
3159 // In this case we are launching in to an existing task
3160 // that has not yet been started from its front door.
3161 // The current task has been brought to the front.
3162 // Ideally, we'd probably like to place this new task
3163 // at the bottom of its stack, but that's a little hard
3164 // to do with the current organization of the code so
3165 // for now we'll just drop it.
3166 taskTop.task.setIntent(r.intent, r.info);
3167 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003168 if (!addingToTask && reuseTask == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003169 // We didn't do anything... but it was needed (a.k.a., client
3170 // don't use that intent!) And for paranoia, make
3171 // sure we have correctly resumed the top activity.
3172 if (doResume) {
Dianne Hackborn84375872012-06-01 19:03:50 -07003173 resumeTopActivityLocked(null, options);
3174 } else {
3175 ActivityOptions.abort(options);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003176 }
Dianne Hackborna4972e92012-03-14 10:38:05 -07003177 return ActivityManager.START_TASK_TO_FRONT;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003178 }
3179 }
3180 }
3181 }
3182
3183 //String uri = r.intent.toURI();
3184 //Intent intent2 = new Intent(uri);
3185 //Slog.i(TAG, "Given intent: " + r.intent);
3186 //Slog.i(TAG, "URI is: " + uri);
3187 //Slog.i(TAG, "To intent: " + intent2);
3188
3189 if (r.packageName != null) {
3190 // If the activity being launched is the same as the one currently
3191 // at the top, then we need to check if it should only be launched
3192 // once.
3193 ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);
3194 if (top != null && r.resultTo == null) {
Amith Yamasani742a6712011-05-04 14:49:28 -07003195 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003196 if (top.app != null && top.app.thread != null) {
3197 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3198 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3199 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3200 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
3201 // For paranoia, make sure we have correctly
3202 // resumed the top activity.
3203 if (doResume) {
3204 resumeTopActivityLocked(null);
3205 }
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003206 ActivityOptions.abort(options);
Dianne Hackborna4972e92012-03-14 10:38:05 -07003207 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003208 // We don't need to start a new activity, and
3209 // the client said not to do anything if that
3210 // is the case, so this is it!
Dianne Hackborna4972e92012-03-14 10:38:05 -07003211 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003212 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07003213 top.deliverNewIntentLocked(callingUid, r.intent);
Dianne Hackborna4972e92012-03-14 10:38:05 -07003214 return ActivityManager.START_DELIVERED_TO_TOP;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003215 }
3216 }
3217 }
3218 }
3219
3220 } else {
3221 if (r.resultTo != null) {
3222 sendActivityResultLocked(-1,
3223 r.resultTo, r.resultWho, r.requestCode,
3224 Activity.RESULT_CANCELED, null);
3225 }
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003226 ActivityOptions.abort(options);
Dianne Hackborna4972e92012-03-14 10:38:05 -07003227 return ActivityManager.START_CLASS_NOT_FOUND;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003228 }
3229
3230 boolean newTask = false;
Dianne Hackborn7da6ac32010-12-09 19:22:04 -08003231 boolean keepCurTransition = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003232
3233 // Should this be considered a new task?
3234 if (r.resultTo == null && !addingToTask
3235 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003236 if (reuseTask == null) {
3237 // todo: should do better management of integers.
3238 mService.mCurTask++;
3239 if (mService.mCurTask <= 0) {
3240 mService.mCurTask = 1;
3241 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08003242 r.setTask(createTaskRecord(mService.mCurTask, r.info, intent, true), null, true);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003243 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
3244 + " in new task " + r.task);
3245 } else {
Dianne Hackbornf26fd992011-04-08 18:14:09 -07003246 r.setTask(reuseTask, reuseTask, true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003247 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003248 newTask = true;
Dianne Hackborn03fcc332012-05-15 12:49:40 -07003249 if (!movedHome) {
3250 moveHomeToFrontFromLaunchLocked(launchFlags);
3251 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003252
3253 } else if (sourceRecord != null) {
3254 if (!addingToTask &&
3255 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3256 // In this case, we are adding the activity to an existing
3257 // task, but the caller has asked to clear that task if the
3258 // activity is already running.
3259 ActivityRecord top = performClearTaskLocked(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003260 sourceRecord.task.taskId, r, launchFlags);
Dianne Hackborn7da6ac32010-12-09 19:22:04 -08003261 keepCurTransition = true;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003262 if (top != null) {
3263 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
Dianne Hackborn39792d22010-08-19 18:01:52 -07003264 top.deliverNewIntentLocked(callingUid, r.intent);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003265 // For paranoia, make sure we have correctly
3266 // resumed the top activity.
3267 if (doResume) {
3268 resumeTopActivityLocked(null);
3269 }
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003270 ActivityOptions.abort(options);
Dianne Hackborna4972e92012-03-14 10:38:05 -07003271 return ActivityManager.START_DELIVERED_TO_TOP;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003272 }
3273 } else if (!addingToTask &&
3274 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3275 // In this case, we are launching an activity in our own task
3276 // that may already be running somewhere in the history, and
3277 // we want to shuffle it to the front of the stack if so.
3278 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3279 if (where >= 0) {
3280 ActivityRecord top = moveActivityToFrontLocked(where);
3281 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003282 top.updateOptionsLocked(options);
Dianne Hackborn39792d22010-08-19 18:01:52 -07003283 top.deliverNewIntentLocked(callingUid, r.intent);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003284 if (doResume) {
3285 resumeTopActivityLocked(null);
3286 }
Dianne Hackborna4972e92012-03-14 10:38:05 -07003287 return ActivityManager.START_DELIVERED_TO_TOP;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003288 }
3289 }
3290 // An existing activity is starting this new activity, so we want
3291 // to keep the new one in the same task as the one that is starting
3292 // it.
Dianne Hackbornf26fd992011-04-08 18:14:09 -07003293 r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003294 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
3295 + " in existing task " + r.task);
3296
3297 } else {
3298 // This not being started from an existing activity, and not part
3299 // of a new task... just put it in the top task, though these days
3300 // this case should never happen.
3301 final int N = mHistory.size();
3302 ActivityRecord prev =
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003303 N > 0 ? mHistory.get(N-1) : null;
Dianne Hackbornf26fd992011-04-08 18:14:09 -07003304 r.setTask(prev != null
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003305 ? prev.task
Craig Mautner5d9c7be2013-02-15 14:02:56 -08003306 : createTaskRecord(mService.mCurTask, r.info, intent, true), null, true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003307 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
3308 + " in new guessed " + r.task);
3309 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07003310
Dianne Hackborn39792d22010-08-19 18:01:52 -07003311 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
Dianne Hackborn7e269642010-08-25 19:50:20 -07003312 intent, r.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07003313
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003314 if (newTask) {
Dianne Hackbornb12e1352012-09-26 11:39:20 -07003315 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003316 }
3317 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003318 startActivityLocked(r, newTask, doResume, keepCurTransition, options);
Dianne Hackborna4972e92012-03-14 10:38:05 -07003319 return ActivityManager.START_SUCCESS;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003320 }
3321
Dianne Hackborna4972e92012-03-14 10:38:05 -07003322 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
Amith Yamasani483f3b02012-03-13 16:08:00 -07003323 String profileFile, ParcelFileDescriptor profileFd, int userId) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003324 // Collect information about the target of the Intent.
3325 ActivityInfo aInfo;
3326 try {
3327 ResolveInfo rInfo =
3328 AppGlobals.getPackageManager().resolveIntent(
3329 intent, resolvedType,
3330 PackageManager.MATCH_DEFAULT_ONLY
Amith Yamasani483f3b02012-03-13 16:08:00 -07003331 | ActivityManagerService.STOCK_PM_FLAGS, userId);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003332 aInfo = rInfo != null ? rInfo.activityInfo : null;
3333 } catch (RemoteException e) {
3334 aInfo = null;
3335 }
3336
3337 if (aInfo != null) {
3338 // Store the found target back into the intent, because now that
3339 // we have it we never want to do this again. For example, if the
3340 // user navigates back to this point in the history, we should
3341 // always restart the exact same activity.
3342 intent.setComponent(new ComponentName(
3343 aInfo.applicationInfo.packageName, aInfo.name));
3344
3345 // Don't debug things in the system process
Dianne Hackborna4972e92012-03-14 10:38:05 -07003346 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003347 if (!aInfo.processName.equals("system")) {
3348 mService.setDebugApp(aInfo.processName, true, false);
3349 }
3350 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003351
Dianne Hackborna4972e92012-03-14 10:38:05 -07003352 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
Siva Velusamy92a8b222012-03-09 16:24:04 -08003353 if (!aInfo.processName.equals("system")) {
3354 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
3355 }
3356 }
3357
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003358 if (profileFile != null) {
3359 if (!aInfo.processName.equals("system")) {
3360 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
Dianne Hackborna4972e92012-03-14 10:38:05 -07003361 profileFile, profileFd,
3362 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003363 }
3364 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003365 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003366 return aInfo;
3367 }
3368
3369 final int startActivityMayWait(IApplicationThread caller, int callingUid,
Dianne Hackbornf265ea92013-01-31 15:00:51 -08003370 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
Dianne Hackborna4972e92012-03-14 10:38:05 -07003371 String resultWho, int requestCode, int startFlags, String profileFile,
3372 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
3373 Bundle options, int userId) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003374 // Refuse possible leaked file descriptors
3375 if (intent != null && intent.hasFileDescriptors()) {
3376 throw new IllegalArgumentException("File descriptors passed in Intent");
3377 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003378 boolean componentSpecified = intent.getComponent() != null;
3379
3380 // Don't modify the client's object!
3381 intent = new Intent(intent);
3382
3383 // Collect information about the target of the Intent.
Dianne Hackborna4972e92012-03-14 10:38:05 -07003384 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
Amith Yamasani483f3b02012-03-13 16:08:00 -07003385 profileFile, profileFd, userId);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003386
3387 synchronized (mService) {
3388 int callingPid;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003389 if (callingUid >= 0) {
3390 callingPid = -1;
3391 } else if (caller == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003392 callingPid = Binder.getCallingPid();
3393 callingUid = Binder.getCallingUid();
3394 } else {
3395 callingPid = callingUid = -1;
3396 }
3397
3398 mConfigWillChange = config != null
3399 && mService.mConfiguration.diff(config) != 0;
3400 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3401 "Starting activity when config will change = " + mConfigWillChange);
3402
3403 final long origId = Binder.clearCallingIdentity();
3404
3405 if (mMainStack && aInfo != null &&
Dianne Hackborn54e570f2010-10-04 18:32:32 -07003406 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003407 // This may be a heavy-weight process! Check to see if we already
3408 // have another, different heavy-weight process running.
3409 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
3410 if (mService.mHeavyWeightProcess != null &&
3411 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
3412 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
3413 int realCallingPid = callingPid;
3414 int realCallingUid = callingUid;
3415 if (caller != null) {
3416 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
3417 if (callerApp != null) {
3418 realCallingPid = callerApp.pid;
3419 realCallingUid = callerApp.info.uid;
3420 } else {
3421 Slog.w(TAG, "Unable to find app for caller " + caller
3422 + " (pid=" + realCallingPid + ") when starting: "
3423 + intent.toString());
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003424 ActivityOptions.abort(options);
Dianne Hackborna4972e92012-03-14 10:38:05 -07003425 return ActivityManager.START_PERMISSION_DENIED;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003426 }
3427 }
3428
3429 IIntentSender target = mService.getIntentSenderLocked(
Dianne Hackborna4972e92012-03-14 10:38:05 -07003430 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
Dianne Hackborn41203752012-08-31 14:05:51 -07003431 realCallingUid, userId, null, null, 0, new Intent[] { intent },
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003432 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003433 | PendingIntent.FLAG_ONE_SHOT, null);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003434
3435 Intent newIntent = new Intent();
3436 if (requestCode >= 0) {
3437 // Caller is requesting a result.
3438 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
3439 }
3440 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
3441 new IntentSender(target));
3442 if (mService.mHeavyWeightProcess.activities.size() > 0) {
3443 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
3444 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
3445 hist.packageName);
3446 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
3447 hist.task.taskId);
3448 }
3449 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
3450 aInfo.packageName);
3451 newIntent.setFlags(intent.getFlags());
3452 newIntent.setClassName("android",
3453 HeavyWeightSwitcherActivity.class.getName());
3454 intent = newIntent;
3455 resolvedType = null;
3456 caller = null;
3457 callingUid = Binder.getCallingUid();
3458 callingPid = Binder.getCallingPid();
3459 componentSpecified = true;
3460 try {
3461 ResolveInfo rInfo =
3462 AppGlobals.getPackageManager().resolveIntent(
3463 intent, null,
3464 PackageManager.MATCH_DEFAULT_ONLY
Amith Yamasani483f3b02012-03-13 16:08:00 -07003465 | ActivityManagerService.STOCK_PM_FLAGS, userId);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003466 aInfo = rInfo != null ? rInfo.activityInfo : null;
Amith Yamasani742a6712011-05-04 14:49:28 -07003467 aInfo = mService.getActivityInfoForUser(aInfo, userId);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003468 } catch (RemoteException e) {
3469 aInfo = null;
3470 }
3471 }
3472 }
3473 }
3474
3475 int res = startActivityLocked(caller, intent, resolvedType,
Dianne Hackborna4972e92012-03-14 10:38:05 -07003476 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
Dianne Hackbornf265ea92013-01-31 15:00:51 -08003477 callingPackage, startFlags, options, componentSpecified, null);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003478
3479 if (mConfigWillChange && mMainStack) {
3480 // If the caller also wants to switch to a new configuration,
3481 // do so now. This allows a clean switch, as we are waiting
3482 // for the current activity to pause (so we will not destroy
3483 // it), and have not yet started the next activity.
3484 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3485 "updateConfiguration()");
3486 mConfigWillChange = false;
3487 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3488 "Updating to new configuration after starting activity.");
Dianne Hackborn813075a62011-11-14 17:45:19 -08003489 mService.updateConfigurationLocked(config, null, false, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003490 }
3491
3492 Binder.restoreCallingIdentity(origId);
3493
3494 if (outResult != null) {
3495 outResult.result = res;
Dianne Hackborna4972e92012-03-14 10:38:05 -07003496 if (res == ActivityManager.START_SUCCESS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003497 mWaitingActivityLaunched.add(outResult);
3498 do {
3499 try {
Dianne Hackbornba0492d2010-10-12 19:01:46 -07003500 mService.wait();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003501 } catch (InterruptedException e) {
3502 }
3503 } while (!outResult.timeout && outResult.who == null);
Dianne Hackborna4972e92012-03-14 10:38:05 -07003504 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003505 ActivityRecord r = this.topRunningActivityLocked(null);
3506 if (r.nowVisible) {
3507 outResult.timeout = false;
3508 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3509 outResult.totalTime = 0;
3510 outResult.thisTime = 0;
3511 } else {
3512 outResult.thisTime = SystemClock.uptimeMillis();
3513 mWaitingActivityVisible.add(outResult);
3514 do {
3515 try {
Dianne Hackbornba0492d2010-10-12 19:01:46 -07003516 mService.wait();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003517 } catch (InterruptedException e) {
3518 }
3519 } while (!outResult.timeout && outResult.who == null);
3520 }
3521 }
3522 }
3523
3524 return res;
3525 }
3526 }
3527
Dianne Hackbornf265ea92013-01-31 15:00:51 -08003528 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
Dianne Hackborna4972e92012-03-14 10:38:05 -07003529 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
3530 Bundle options, int userId) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003531 if (intents == null) {
3532 throw new NullPointerException("intents is null");
3533 }
3534 if (resolvedTypes == null) {
3535 throw new NullPointerException("resolvedTypes is null");
3536 }
3537 if (intents.length != resolvedTypes.length) {
3538 throw new IllegalArgumentException("intents are length different than resolvedTypes");
3539 }
3540
3541 ActivityRecord[] outActivity = new ActivityRecord[1];
3542
3543 int callingPid;
3544 if (callingUid >= 0) {
3545 callingPid = -1;
3546 } else if (caller == null) {
3547 callingPid = Binder.getCallingPid();
3548 callingUid = Binder.getCallingUid();
3549 } else {
3550 callingPid = callingUid = -1;
3551 }
3552 final long origId = Binder.clearCallingIdentity();
3553 try {
3554 synchronized (mService) {
3555
3556 for (int i=0; i<intents.length; i++) {
3557 Intent intent = intents[i];
3558 if (intent == null) {
3559 continue;
3560 }
3561
3562 // Refuse possible leaked file descriptors
3563 if (intent != null && intent.hasFileDescriptors()) {
3564 throw new IllegalArgumentException("File descriptors passed in Intent");
3565 }
3566
3567 boolean componentSpecified = intent.getComponent() != null;
3568
3569 // Don't modify the client's object!
3570 intent = new Intent(intent);
3571
3572 // Collect information about the target of the Intent.
Dianne Hackborna4972e92012-03-14 10:38:05 -07003573 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
Amith Yamasani483f3b02012-03-13 16:08:00 -07003574 0, null, null, userId);
Amith Yamasani742a6712011-05-04 14:49:28 -07003575 // TODO: New, check if this is correct
3576 aInfo = mService.getActivityInfoForUser(aInfo, userId);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003577
3578 if (mMainStack && aInfo != null && (aInfo.applicationInfo.flags
3579 & ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
3580 throw new IllegalArgumentException(
3581 "FLAG_CANT_SAVE_STATE not supported here");
3582 }
3583
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003584 Bundle theseOptions;
3585 if (options != null && i == intents.length-1) {
3586 theseOptions = options;
3587 } else {
3588 theseOptions = null;
3589 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003590 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Dianne Hackbornf265ea92013-01-31 15:00:51 -08003591 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003592 0, theseOptions, componentSpecified, outActivity);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003593 if (res < 0) {
3594 return res;
3595 }
3596
Dianne Hackbornbe707852011-11-11 14:32:10 -08003597 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003598 }
3599 }
3600 } finally {
3601 Binder.restoreCallingIdentity(origId);
3602 }
3603
Dianne Hackborna4972e92012-03-14 10:38:05 -07003604 return ActivityManager.START_SUCCESS;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003605 }
3606
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003607 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
3608 long thisTime, long totalTime) {
3609 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3610 WaitResult w = mWaitingActivityLaunched.get(i);
3611 w.timeout = timeout;
3612 if (r != null) {
3613 w.who = new ComponentName(r.info.packageName, r.info.name);
3614 }
3615 w.thisTime = thisTime;
3616 w.totalTime = totalTime;
3617 }
3618 mService.notifyAll();
3619 }
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08003620
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003621 void reportActivityVisibleLocked(ActivityRecord r) {
3622 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3623 WaitResult w = mWaitingActivityVisible.get(i);
3624 w.timeout = false;
3625 if (r != null) {
3626 w.who = new ComponentName(r.info.packageName, r.info.name);
3627 }
3628 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3629 w.thisTime = w.totalTime;
3630 }
3631 mService.notifyAll();
Dianne Hackborn90c52de2011-09-23 12:57:44 -07003632
3633 if (mDismissKeyguardOnNextActivity) {
3634 mDismissKeyguardOnNextActivity = false;
3635 mService.mWindowManager.dismissKeyguard();
3636 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003637 }
3638
3639 void sendActivityResultLocked(int callingUid, ActivityRecord r,
3640 String resultWho, int requestCode, int resultCode, Intent data) {
3641
3642 if (callingUid > 0) {
3643 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
Dianne Hackborn7e269642010-08-25 19:50:20 -07003644 data, r.getUriPermissionsLocked());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003645 }
3646
3647 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
3648 + " : who=" + resultWho + " req=" + requestCode
3649 + " res=" + resultCode + " data=" + data);
3650 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
3651 try {
3652 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
3653 list.add(new ResultInfo(resultWho, requestCode,
3654 resultCode, data));
Dianne Hackbornbe707852011-11-11 14:32:10 -08003655 r.app.thread.scheduleSendResult(r.appToken, list);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003656 return;
3657 } catch (Exception e) {
3658 Slog.w(TAG, "Exception thrown sending result to " + r, e);
3659 }
3660 }
3661
3662 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
3663 }
3664
3665 private final void stopActivityLocked(ActivityRecord r) {
3666 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
3667 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3668 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3669 if (!r.finishing) {
Christopher Tated3f175c2012-06-14 14:16:54 -07003670 if (!mService.mSleeping) {
3671 if (DEBUG_STATES) {
3672 Slog.d(TAG, "no-history finish of " + r);
3673 }
3674 requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07003675 "no-history", false);
Christopher Tated3f175c2012-06-14 14:16:54 -07003676 } else {
3677 if (DEBUG_STATES) Slog.d(TAG, "Not finishing noHistory " + r
3678 + " on stop because we're just sleeping");
3679 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003680 }
Christopher Tate5007ddd2012-06-12 13:08:18 -07003681 }
3682
3683 if (r.app != null && r.app.thread != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003684 if (mMainStack) {
3685 if (mService.mFocusedActivity == r) {
3686 mService.setFocusedActivityLocked(topRunningActivityLocked(null));
3687 }
3688 }
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08003689 r.resumeKeyDispatchingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003690 try {
3691 r.stopped = false;
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003692 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
3693 + " (stop requested)");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003694 r.state = ActivityState.STOPPING;
3695 if (DEBUG_VISBILITY) Slog.v(
3696 TAG, "Stopping visible=" + r.visible + " for " + r);
3697 if (!r.visible) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08003698 mService.mWindowManager.setAppVisibility(r.appToken, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003699 }
Dianne Hackbornbe707852011-11-11 14:32:10 -08003700 r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08003701 if (mService.isSleeping()) {
3702 r.setSleeping(true);
3703 }
Dianne Hackborn162bc0e2012-04-09 14:06:16 -07003704 Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG);
3705 msg.obj = r;
3706 mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003707 } catch (Exception e) {
3708 // Maybe just ignore exceptions here... if the process
3709 // has crashed, our death notification will clean things
3710 // up.
3711 Slog.w(TAG, "Exception thrown during pause", e);
3712 // Just in case, assume it to be stopped.
3713 r.stopped = true;
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003714 if (DEBUG_STATES) Slog.v(TAG, "Stop failed; moving to STOPPED: " + r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003715 r.state = ActivityState.STOPPED;
3716 if (r.configDestroy) {
Dianne Hackborn28695e02011-11-02 21:59:51 -07003717 destroyActivityLocked(r, true, false, "stop-except");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003718 }
3719 }
3720 }
3721 }
3722
3723 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(
3724 boolean remove) {
3725 int N = mStoppingActivities.size();
3726 if (N <= 0) return null;
3727
3728 ArrayList<ActivityRecord> stops = null;
3729
3730 final boolean nowVisible = mResumedActivity != null
3731 && mResumedActivity.nowVisible
3732 && !mResumedActivity.waitingVisible;
3733 for (int i=0; i<N; i++) {
3734 ActivityRecord s = mStoppingActivities.get(i);
3735 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
3736 + nowVisible + " waitingVisible=" + s.waitingVisible
3737 + " finishing=" + s.finishing);
3738 if (s.waitingVisible && nowVisible) {
3739 mWaitingVisibleActivities.remove(s);
3740 s.waitingVisible = false;
3741 if (s.finishing) {
3742 // If this activity is finishing, it is sitting on top of
3743 // everyone else but we now know it is no longer needed...
3744 // so get rid of it. Otherwise, we need to go through the
3745 // normal flow and hide it once we determine that it is
3746 // hidden by the activities in front of it.
3747 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
Dianne Hackbornbe707852011-11-11 14:32:10 -08003748 mService.mWindowManager.setAppVisibility(s.appToken, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003749 }
3750 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08003751 if ((!s.waitingVisible || mService.isSleeping()) && remove) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003752 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
3753 if (stops == null) {
3754 stops = new ArrayList<ActivityRecord>();
3755 }
3756 stops.add(s);
3757 mStoppingActivities.remove(i);
3758 N--;
3759 i--;
3760 }
3761 }
3762
3763 return stops;
3764 }
3765
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07003766 final void scheduleIdleLocked() {
3767 Message msg = Message.obtain();
3768 msg.what = IDLE_NOW_MSG;
3769 mHandler.sendMessage(msg);
3770 }
3771
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003772 final ActivityRecord activityIdleInternal(IBinder token, boolean fromTimeout,
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003773 Configuration config) {
3774 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
3775
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003776 ActivityRecord res = null;
3777
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003778 ArrayList<ActivityRecord> stops = null;
3779 ArrayList<ActivityRecord> finishes = null;
3780 ArrayList<ActivityRecord> thumbnails = null;
Dianne Hackborn80a4af22012-08-27 19:18:31 -07003781 ArrayList<UserStartedState> startingUsers = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003782 int NS = 0;
3783 int NF = 0;
3784 int NT = 0;
3785 IApplicationThread sendThumbnail = null;
3786 boolean booting = false;
3787 boolean enableScreen = false;
Dianne Hackborn42e620c2012-06-24 13:20:51 -07003788 boolean activityRemoved = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003789
3790 synchronized (mService) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08003791 ActivityRecord r = ActivityRecord.forToken(token);
3792 if (r != null) {
3793 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07003794 r.finishLaunchTickingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003795 }
3796
3797 // Get the activity record.
Craig Mautner05d6272ba2013-02-11 09:39:27 -08003798 int index = mHistory.indexOf(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003799 if (index >= 0) {
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003800 res = r;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003801
3802 if (fromTimeout) {
3803 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
3804 }
3805
3806 // This is a hack to semi-deal with a race condition
3807 // in the client where it can be constructed with a
3808 // newer configuration from when we asked it to launch.
3809 // We'll update with whatever configuration it now says
3810 // it used to launch.
3811 if (config != null) {
3812 r.configuration = config;
3813 }
3814
3815 // No longer need to keep the device awake.
3816 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
3817 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
3818 mLaunchingActivity.release();
3819 }
3820
3821 // We are now idle. If someone is waiting for a thumbnail from
3822 // us, we can now deliver.
3823 r.idle = true;
3824 mService.scheduleAppGcsLocked();
3825 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
3826 sendThumbnail = r.app.thread;
3827 r.thumbnailNeeded = false;
3828 }
3829
3830 // If this activity is fullscreen, set up to hide those under it.
3831
3832 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
3833 ensureActivitiesVisibleLocked(null, 0);
3834
3835 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
3836 if (mMainStack) {
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07003837 if (!mService.mBooted) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003838 mService.mBooted = true;
3839 enableScreen = true;
3840 }
3841 }
3842
3843 } else if (fromTimeout) {
3844 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
3845 }
3846
3847 // Atomically retrieve all of the other things to do.
3848 stops = processStoppingActivitiesLocked(true);
3849 NS = stops != null ? stops.size() : 0;
3850 if ((NF=mFinishingActivities.size()) > 0) {
3851 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
3852 mFinishingActivities.clear();
3853 }
Craig Mautnercae015f2013-02-08 14:31:27 -08003854 if ((NT=mCancelledThumbnails.size()) > 0) {
3855 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
3856 mCancelledThumbnails.clear();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003857 }
3858
3859 if (mMainStack) {
3860 booting = mService.mBooting;
3861 mService.mBooting = false;
3862 }
Dianne Hackborn80a4af22012-08-27 19:18:31 -07003863 if (mStartingUsers.size() > 0) {
3864 startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
3865 mStartingUsers.clear();
3866 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003867 }
3868
3869 int i;
3870
3871 // Send thumbnail if requested.
3872 if (sendThumbnail != null) {
3873 try {
3874 sendThumbnail.requestThumbnail(token);
3875 } catch (Exception e) {
3876 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
3877 mService.sendPendingThumbnail(null, token, null, null, true);
3878 }
3879 }
3880
3881 // Stop any activities that are scheduled to do so but have been
3882 // waiting for the next one to start.
3883 for (i=0; i<NS; i++) {
Craig Mautner05d6272ba2013-02-11 09:39:27 -08003884 ActivityRecord r = stops.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003885 synchronized (mService) {
3886 if (r.finishing) {
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07003887 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003888 } else {
3889 stopActivityLocked(r);
3890 }
3891 }
3892 }
3893
3894 // Finish any activities that are scheduled to do so but have been
3895 // waiting for the next one to start.
3896 for (i=0; i<NF; i++) {
Craig Mautner05d6272ba2013-02-11 09:39:27 -08003897 ActivityRecord r = finishes.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003898 synchronized (mService) {
Dianne Hackborn42e620c2012-06-24 13:20:51 -07003899 activityRemoved = destroyActivityLocked(r, true, false, "finish-idle");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003900 }
3901 }
3902
3903 // Report back to any thumbnail receivers.
3904 for (i=0; i<NT; i++) {
Craig Mautner05d6272ba2013-02-11 09:39:27 -08003905 ActivityRecord r = thumbnails.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003906 mService.sendPendingThumbnail(r, null, null, null, true);
3907 }
3908
3909 if (booting) {
3910 mService.finishBooting();
Dianne Hackborn80a4af22012-08-27 19:18:31 -07003911 } else if (startingUsers != null) {
3912 for (i=0; i<startingUsers.size(); i++) {
3913 mService.finishUserSwitch(startingUsers.get(i));
3914 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003915 }
3916
3917 mService.trimApplications();
3918 //dump();
3919 //mWindowManager.dump();
3920
3921 if (enableScreen) {
3922 mService.enableScreenAfterBoot();
3923 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003924
Dianne Hackborn42e620c2012-06-24 13:20:51 -07003925 if (activityRemoved) {
3926 resumeTopActivityLocked(null);
3927 }
3928
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003929 return res;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003930 }
3931
3932 /**
3933 * @return Returns true if the activity is being finished, false if for
3934 * some reason it is being left as-is.
3935 */
3936 final boolean requestFinishActivityLocked(IBinder token, int resultCode,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07003937 Intent resultData, String reason, boolean oomAdj) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003938 int index = indexOfTokenLocked(token);
Christopher Tated3f175c2012-06-14 14:16:54 -07003939 if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07003940 TAG, "Finishing activity @" + index + ": token=" + token
Christopher Tated3f175c2012-06-14 14:16:54 -07003941 + ", result=" + resultCode + ", data=" + resultData
3942 + ", reason=" + reason);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003943 if (index < 0) {
3944 return false;
3945 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003946 ActivityRecord r = mHistory.get(index);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003947
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07003948 finishActivityLocked(r, index, resultCode, resultData, reason, oomAdj);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003949 return true;
3950 }
3951
Dianne Hackbornecc5a9c2012-04-26 18:56:09 -07003952 final void finishSubActivityLocked(IBinder token, String resultWho, int requestCode) {
3953 ActivityRecord self = isInStackLocked(token);
3954 if (self == null) {
3955 return;
3956 }
3957
3958 int i;
3959 for (i=mHistory.size()-1; i>=0; i--) {
Craig Mautner05d6272ba2013-02-11 09:39:27 -08003960 ActivityRecord r = mHistory.get(i);
Dianne Hackbornecc5a9c2012-04-26 18:56:09 -07003961 if (r.resultTo == self && r.requestCode == requestCode) {
3962 if ((r.resultWho == null && resultWho == null) ||
3963 (r.resultWho != null && r.resultWho.equals(resultWho))) {
3964 finishActivityLocked(r, i,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07003965 Activity.RESULT_CANCELED, null, "request-sub", false);
Dianne Hackbornecc5a9c2012-04-26 18:56:09 -07003966 }
3967 }
3968 }
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07003969 mService.updateOomAdjLocked();
Dianne Hackbornecc5a9c2012-04-26 18:56:09 -07003970 }
3971
Craig Mautner05d6272ba2013-02-11 09:39:27 -08003972 final void finishTopRunningActivityLocked(ProcessRecord app) {
3973 ActivityRecord r = topRunningActivityLocked(null);
3974 if (r != null && r.app == app) {
3975 // If the top running activity is from this crashing
3976 // process, then terminate it to avoid getting in a loop.
3977 Slog.w(TAG, " Force finishing activity "
3978 + r.intent.getComponent().flattenToShortString());
3979 int index = mHistory.indexOf(r);
3980 r.stack.finishActivityLocked(r, index,
3981 Activity.RESULT_CANCELED, null, "crashed", false);
3982 // Also terminate any activities below it that aren't yet
3983 // stopped, to avoid a situation where one will get
3984 // re-start our crashing activity once it gets resumed again.
3985 index--;
3986 if (index >= 0) {
3987 r = mHistory.get(index);
3988 if (r.state == ActivityState.RESUMED
3989 || r.state == ActivityState.PAUSING
3990 || r.state == ActivityState.PAUSED) {
3991 if (!r.isHomeActivity || mService.mHomeProcess != r.app) {
3992 Slog.w(TAG, " Force finishing activity "
3993 + r.intent.getComponent().flattenToShortString());
3994 r.stack.finishActivityLocked(r, index,
3995 Activity.RESULT_CANCELED, null, "crashed", false);
3996 }
3997 }
3998 }
3999 }
4000 }
4001
Dianne Hackbornecc5a9c2012-04-26 18:56:09 -07004002 final boolean finishActivityAffinityLocked(IBinder token) {
4003 int index = indexOfTokenLocked(token);
4004 if (DEBUG_RESULTS) Slog.v(
4005 TAG, "Finishing activity affinity @" + index + ": token=" + token);
4006 if (index < 0) {
4007 return false;
4008 }
4009 ActivityRecord r = mHistory.get(index);
4010
Amith Yamasanibfc1be12012-05-15 11:12:17 -07004011 while (index >= 0) {
Dianne Hackbornecc5a9c2012-04-26 18:56:09 -07004012 ActivityRecord cur = mHistory.get(index);
4013 if (cur.task != r.task) {
4014 break;
4015 }
4016 if (cur.taskAffinity == null && r.taskAffinity != null) {
4017 break;
4018 }
4019 if (cur.taskAffinity != null && !cur.taskAffinity.equals(r.taskAffinity)) {
4020 break;
4021 }
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07004022 finishActivityLocked(cur, index, Activity.RESULT_CANCELED, null,
4023 "request-affinity", true);
Dianne Hackbornecc5a9c2012-04-26 18:56:09 -07004024 index--;
4025 }
4026 return true;
4027 }
4028
Dianne Hackborn5c607432012-02-28 14:44:19 -08004029 final void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
4030 // send the result
4031 ActivityRecord resultTo = r.resultTo;
4032 if (resultTo != null) {
4033 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
4034 + " who=" + r.resultWho + " req=" + r.requestCode
4035 + " res=" + resultCode + " data=" + resultData);
4036 if (r.info.applicationInfo.uid > 0) {
4037 mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4038 resultTo.packageName, resultData,
4039 resultTo.getUriPermissionsLocked());
4040 }
4041 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4042 resultData);
4043 r.resultTo = null;
4044 }
4045 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
4046
4047 // Make sure this HistoryRecord is not holding on to other resources,
4048 // because clients have remote IPC references to this object so we
4049 // can't assume that will go away and want to avoid circular IPC refs.
4050 r.results = null;
4051 r.pendingResults = null;
4052 r.newIntents = null;
4053 r.icicle = null;
4054 }
4055
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004056 /**
4057 * @return Returns true if this activity has been removed from the history
4058 * list, or false if it is still in the list and will be removed later.
4059 */
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004060 final boolean finishActivityLocked(ActivityRecord r,
4061 int resultCode, Intent resultData, String reason, boolean oomAdj) {
4062 int index = mHistory.indexOf(r);
4063 if (index >= 0) {
4064 return finishActivityLocked(r, index, resultCode, resultData, reason, false, oomAdj);
4065 }
4066 return false;
4067 }
4068
4069 /**
4070 * @return Returns true if this activity has been removed from the history
4071 * list, or false if it is still in the list and will be removed later.
4072 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004073 final boolean finishActivityLocked(ActivityRecord r, int index,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07004074 int resultCode, Intent resultData, String reason, boolean oomAdj) {
4075 return finishActivityLocked(r, index, resultCode, resultData, reason, false, oomAdj);
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07004076 }
4077
4078 /**
4079 * @return Returns true if this activity has been removed from the history
4080 * list, or false if it is still in the list and will be removed later.
4081 */
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07004082 final boolean finishActivityLocked(ActivityRecord r, int index, int resultCode,
4083 Intent resultData, String reason, boolean immediate, boolean oomAdj) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004084 if (r.finishing) {
4085 Slog.w(TAG, "Duplicate finish request for " + r);
4086 return false;
4087 }
4088
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08004089 r.makeFinishing();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004090 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
Dianne Hackbornb12e1352012-09-26 11:39:20 -07004091 r.userId, System.identityHashCode(r),
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004092 r.task.taskId, r.shortComponentName, reason);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004093 if (index < (mHistory.size()-1)) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004094 ActivityRecord next = mHistory.get(index+1);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004095 if (next.task == r.task) {
4096 if (r.frontOfTask) {
4097 // The next activity is now the front of the task.
4098 next.frontOfTask = true;
4099 }
4100 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
4101 // If the caller asked that this activity (and all above it)
4102 // be cleared when the task is reset, don't lose that information,
4103 // but propagate it up to the next activity.
4104 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
4105 }
4106 }
4107 }
4108
4109 r.pauseKeyDispatchingLocked();
4110 if (mMainStack) {
4111 if (mService.mFocusedActivity == r) {
4112 mService.setFocusedActivityLocked(topRunningActivityLocked(null));
4113 }
4114 }
4115
Dianne Hackborn5c607432012-02-28 14:44:19 -08004116 finishActivityResultsLocked(r, resultCode, resultData);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004117
4118 if (mService.mPendingThumbnails.size() > 0) {
4119 // There are clients waiting to receive thumbnails so, in case
4120 // this is an activity that someone is waiting for, add it
4121 // to the pending list so we can correctly update the clients.
Craig Mautnercae015f2013-02-08 14:31:27 -08004122 mCancelledThumbnails.add(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004123 }
4124
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07004125 if (immediate) {
4126 return finishCurrentActivityLocked(r, index,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07004127 FINISH_IMMEDIATELY, oomAdj) == null;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07004128 } else if (mResumedActivity == r) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004129 boolean endTask = index <= 0
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004130 || (mHistory.get(index-1)).task != r.task;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004131 if (DEBUG_TRANSITION) Slog.v(TAG,
4132 "Prepare close transition: finishing " + r);
4133 mService.mWindowManager.prepareAppTransition(endTask
Craig Mautner4b71aa12012-12-27 17:20:01 -08004134 ? AppTransition.TRANSIT_TASK_CLOSE
4135 : AppTransition.TRANSIT_ACTIVITY_CLOSE, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004136
4137 // Tell window manager to prepare for this one to be removed.
Dianne Hackbornbe707852011-11-11 14:32:10 -08004138 mService.mWindowManager.setAppVisibility(r.appToken, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004139
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08004140 if (mPausingActivity == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004141 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4142 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
4143 startPausingLocked(false, false);
4144 }
4145
4146 } else if (r.state != ActivityState.PAUSING) {
4147 // If the activity is PAUSING, we will complete the finish once
4148 // it is done pausing; else we can just directly finish it here.
4149 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
4150 return finishCurrentActivityLocked(r, index,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07004151 FINISH_AFTER_PAUSE, oomAdj) == null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004152 } else {
4153 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
4154 }
4155
4156 return false;
4157 }
4158
4159 private static final int FINISH_IMMEDIATELY = 0;
4160 private static final int FINISH_AFTER_PAUSE = 1;
4161 private static final int FINISH_AFTER_VISIBLE = 2;
4162
4163 private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07004164 int mode, boolean oomAdj) {
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004165 final int index = mHistory.indexOf(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004166 if (index < 0) {
4167 return null;
4168 }
4169
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07004170 return finishCurrentActivityLocked(r, index, mode, oomAdj);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004171 }
4172
4173 private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07004174 int index, int mode, boolean oomAdj) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004175 // First things first: if this activity is currently visible,
4176 // and the resumed activity is not yet visible, then hold off on
4177 // finishing until the resumed one becomes visible.
4178 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4179 if (!mStoppingActivities.contains(r)) {
4180 mStoppingActivities.add(r);
4181 if (mStoppingActivities.size() > 3) {
4182 // If we already have a few activities waiting to stop,
4183 // then give up on things going idle and start clearing
4184 // them out.
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07004185 scheduleIdleLocked();
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08004186 } else {
4187 checkReadyForSleepLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004188 }
4189 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004190 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
4191 + " (finish requested)");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004192 r.state = ActivityState.STOPPING;
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07004193 if (oomAdj) {
4194 mService.updateOomAdjLocked();
4195 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004196 return r;
4197 }
4198
4199 // make sure the record is cleaned out of other places.
4200 mStoppingActivities.remove(r);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08004201 mGoingToSleepActivities.remove(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004202 mWaitingVisibleActivities.remove(r);
4203 if (mResumedActivity == r) {
4204 mResumedActivity = null;
4205 }
4206 final ActivityState prevState = r.state;
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004207 if (DEBUG_STATES) Slog.v(TAG, "Moving to FINISHING: " + r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004208 r.state = ActivityState.FINISHING;
4209
4210 if (mode == FINISH_IMMEDIATELY
4211 || prevState == ActivityState.STOPPED
4212 || prevState == ActivityState.INITIALIZING) {
4213 // If this activity is already stopped, we can just finish
4214 // it right now.
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07004215 boolean activityRemoved = destroyActivityLocked(r, true,
4216 oomAdj, "finish-imm");
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004217 if (activityRemoved) {
4218 resumeTopActivityLocked(null);
4219 }
4220 return activityRemoved ? null : r;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004221 }
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004222
4223 // Need to go through the full pause cycle to get this
4224 // activity into the stopped state and then finish it.
4225 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
4226 mFinishingActivities.add(r);
4227 resumeTopActivityLocked(null);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004228 return r;
4229 }
4230
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004231 final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode,
4232 Intent resultData) {
4233 final int start = mHistory.indexOf(srec);
4234 if (start < 0) {
4235 // Current activity is not in history stack; do nothing.
4236 return false;
4237 }
4238 int finishTo = start - 1;
4239 ActivityRecord parent = null;
4240 boolean foundParentInTask = false;
4241 ComponentName dest = destIntent.getComponent();
4242 if (dest != null) {
4243 TaskRecord tr = srec.task;
4244 for (int i = start - 1; i >= 0; i--) {
4245 ActivityRecord r = mHistory.get(i);
4246 if (tr != r.task) {
4247 // Couldn't find parent in the same task; stop at the one above this.
4248 // (Root of current task; in-app "home" behavior)
4249 // Always at least finish the current activity.
4250 finishTo = Math.min(start - 1, i + 1);
4251 parent = mHistory.get(finishTo);
4252 break;
4253 } else if (r.info.packageName.equals(dest.getPackageName()) &&
4254 r.info.name.equals(dest.getClassName())) {
4255 finishTo = i;
4256 parent = r;
4257 foundParentInTask = true;
4258 break;
4259 }
4260 }
4261 }
4262
4263 IActivityController controller = mService.mController;
4264 if (controller != null) {
4265 ActivityRecord next = topRunningActivityLocked(srec.appToken, 0);
4266 if (next != null) {
4267 // ask watcher if this is allowed
4268 boolean resumeOK = true;
4269 try {
4270 resumeOK = controller.activityResuming(next.packageName);
4271 } catch (RemoteException e) {
4272 mService.mController = null;
4273 }
4274
4275 if (!resumeOK) {
4276 return false;
4277 }
4278 }
4279 }
4280 final long origId = Binder.clearCallingIdentity();
4281 for (int i = start; i > finishTo; i--) {
4282 ActivityRecord r = mHistory.get(i);
4283 requestFinishActivityLocked(r.appToken, resultCode, resultData,
4284 "navigate-up", true);
4285 // Only return the supplied result for the first activity finished
4286 resultCode = Activity.RESULT_CANCELED;
4287 resultData = null;
4288 }
4289
4290 if (parent != null && foundParentInTask) {
4291 final int parentLaunchMode = parent.info.launchMode;
4292 final int destIntentFlags = destIntent.getFlags();
4293 if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE ||
4294 parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
4295 parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
4296 (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
4297 parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent);
4298 } else {
4299 try {
4300 ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
4301 destIntent.getComponent(), 0, srec.userId);
4302 int res = startActivityLocked(srec.app.thread, destIntent,
4303 null, aInfo, parent.appToken, null,
4304 0, -1, parent.launchedFromUid, parent.launchedFromPackage,
4305 0, null, true, null);
4306 foundParentInTask = res == ActivityManager.START_SUCCESS;
4307 } catch (RemoteException e) {
4308 foundParentInTask = false;
4309 }
4310 requestFinishActivityLocked(parent.appToken, resultCode,
4311 resultData, "navigate-up", true);
4312 }
4313 }
4314 Binder.restoreCallingIdentity(origId);
4315 return foundParentInTask;
4316 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004317 /**
4318 * Perform the common clean-up of an activity record. This is called both
4319 * as part of destroyActivityLocked() (when destroying the client-side
4320 * representation) and cleaning things up as a result of its hosting
4321 * processing going away, in which case there is no remaining client-side
4322 * state to destroy so only the cleanup here is needed.
4323 */
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004324 final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices,
4325 boolean setState) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004326 if (mResumedActivity == r) {
4327 mResumedActivity = null;
4328 }
4329 if (mService.mFocusedActivity == r) {
4330 mService.mFocusedActivity = null;
4331 }
4332
4333 r.configDestroy = false;
4334 r.frozenBeforeDestroy = false;
4335
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004336 if (setState) {
4337 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (cleaning up)");
4338 r.state = ActivityState.DESTROYED;
Dianne Hackborn07981492013-01-28 11:36:23 -08004339 if (DEBUG_APP) Slog.v(TAG, "Clearing app during cleanUp for activity " + r);
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004340 r.app = null;
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004341 }
4342
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004343 // Make sure this record is no longer in the pending finishes list.
4344 // This could happen, for example, if we are trimming activities
4345 // down to the max limit while they are still waiting to finish.
4346 mFinishingActivities.remove(r);
4347 mWaitingVisibleActivities.remove(r);
4348
4349 // Remove any pending results.
4350 if (r.finishing && r.pendingResults != null) {
4351 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4352 PendingIntentRecord rec = apr.get();
4353 if (rec != null) {
4354 mService.cancelIntentSenderLocked(rec, false);
4355 }
4356 }
4357 r.pendingResults = null;
4358 }
4359
4360 if (cleanServices) {
4361 cleanUpActivityServicesLocked(r);
4362 }
4363
4364 if (mService.mPendingThumbnails.size() > 0) {
4365 // There are clients waiting to receive thumbnails so, in case
4366 // this is an activity that someone is waiting for, add it
4367 // to the pending list so we can correctly update the clients.
Craig Mautnercae015f2013-02-08 14:31:27 -08004368 mCancelledThumbnails.add(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004369 }
4370
4371 // Get rid of any pending idle timeouts.
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004372 removeTimeoutsForActivityLocked(r);
4373 }
4374
4375 private void removeTimeoutsForActivityLocked(ActivityRecord r) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004376 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
Dianne Hackborn162bc0e2012-04-09 14:06:16 -07004377 mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004378 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004379 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07004380 r.finishLaunchTickingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004381 }
4382
Dianne Hackborn5c607432012-02-28 14:44:19 -08004383 final void removeActivityFromHistoryLocked(ActivityRecord r) {
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004384 finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
4385 r.makeFinishing();
4386 if (DEBUG_ADD_REMOVE) {
4387 RuntimeException here = new RuntimeException("here");
4388 here.fillInStackTrace();
4389 Slog.i(TAG, "Removing activity " + r + " from stack");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004390 }
Craig Mautner11bf9a52013-02-19 14:08:51 -08004391 final TaskRecord task = r.task;
4392 if (task != null) {
4393 task.removeActivity(r);
Craig Mautner5d9c7be2013-02-15 14:02:56 -08004394 }
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004395 mHistory.remove(r);
4396 r.takeFromHistory();
4397 removeTimeoutsForActivityLocked(r);
4398 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
4399 + " (removed from history)");
4400 r.state = ActivityState.DESTROYED;
Dianne Hackborn07981492013-01-28 11:36:23 -08004401 if (DEBUG_APP) Slog.v(TAG, "Clearing app during remove for activity " + r);
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004402 r.app = null;
4403 mService.mWindowManager.removeAppToken(r.appToken);
4404 if (VALIDATE_TOKENS) {
4405 validateAppTokensLocked();
4406 }
4407 cleanUpActivityServicesLocked(r);
4408 r.removeUriPermissionsLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004409 }
4410
4411 /**
4412 * Perform clean-up of service connections in an activity record.
4413 */
4414 final void cleanUpActivityServicesLocked(ActivityRecord r) {
4415 // Throw away any services that have been bound by this activity.
4416 if (r.connections != null) {
4417 Iterator<ConnectionRecord> it = r.connections.iterator();
4418 while (it.hasNext()) {
4419 ConnectionRecord c = it.next();
Dianne Hackborn599db5c2012-08-03 19:28:48 -07004420 mService.mServices.removeConnectionLocked(c, null, r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004421 }
4422 r.connections = null;
4423 }
4424 }
Dianne Hackborn755c8bf2012-05-07 15:06:09 -07004425
4426 final void scheduleDestroyActivities(ProcessRecord owner, boolean oomAdj, String reason) {
4427 Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG);
4428 msg.obj = new ScheduleDestroyArgs(owner, oomAdj, reason);
4429 mHandler.sendMessage(msg);
4430 }
4431
Dianne Hackborn28695e02011-11-02 21:59:51 -07004432 final void destroyActivitiesLocked(ProcessRecord owner, boolean oomAdj, String reason) {
Dianne Hackborn755c8bf2012-05-07 15:06:09 -07004433 boolean lastIsOpaque = false;
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004434 boolean activityRemoved = false;
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004435 for (int i=mHistory.size()-1; i>=0; i--) {
4436 ActivityRecord r = mHistory.get(i);
Dianne Hackborn755c8bf2012-05-07 15:06:09 -07004437 if (r.finishing) {
4438 continue;
4439 }
4440 if (r.fullscreen) {
4441 lastIsOpaque = true;
4442 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004443 if (owner != null && r.app != owner) {
4444 continue;
4445 }
Dianne Hackborn755c8bf2012-05-07 15:06:09 -07004446 if (!lastIsOpaque) {
4447 continue;
4448 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004449 // We can destroy this one if we have its icicle saved and
4450 // it is not in the process of pausing/stopping/finishing.
Dianne Hackborn755c8bf2012-05-07 15:06:09 -07004451 if (r.app != null && r != mResumedActivity && r != mPausingActivity
4452 && r.haveState && !r.visible && r.stopped
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004453 && r.state != ActivityState.DESTROYING
4454 && r.state != ActivityState.DESTROYED) {
Dianne Hackborn755c8bf2012-05-07 15:06:09 -07004455 if (DEBUG_SWITCH) Slog.v(TAG, "Destroying " + r + " in state " + r.state
4456 + " resumed=" + mResumedActivity
4457 + " pausing=" + mPausingActivity);
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004458 if (destroyActivityLocked(r, true, oomAdj, reason)) {
4459 activityRemoved = true;
4460 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004461 }
4462 }
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004463 if (activityRemoved) {
4464 resumeTopActivityLocked(null);
4465 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004466 }
4467
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004468 /**
4469 * Destroy the current CLIENT SIDE instance of an activity. This may be
4470 * called both when actually finishing an activity, or when performing
4471 * a configuration switch where we destroy the current client-side object
4472 * but then create a new client-side object for this same HistoryRecord.
4473 */
4474 final boolean destroyActivityLocked(ActivityRecord r,
Dianne Hackborn28695e02011-11-02 21:59:51 -07004475 boolean removeFromApp, boolean oomAdj, String reason) {
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004476 if (DEBUG_SWITCH || DEBUG_CLEANUP) Slog.v(
Dianne Hackborn755c8bf2012-05-07 15:06:09 -07004477 TAG, "Removing activity from " + reason + ": token=" + r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004478 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
4479 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
Dianne Hackbornb12e1352012-09-26 11:39:20 -07004480 r.userId, System.identityHashCode(r),
Dianne Hackborn28695e02011-11-02 21:59:51 -07004481 r.task.taskId, r.shortComponentName, reason);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004482
4483 boolean removedFromHistory = false;
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004484
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004485 cleanUpActivityLocked(r, false, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004486
4487 final boolean hadApp = r.app != null;
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004488
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004489 if (hadApp) {
4490 if (removeFromApp) {
4491 int idx = r.app.activities.indexOf(r);
4492 if (idx >= 0) {
4493 r.app.activities.remove(idx);
4494 }
4495 if (mService.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
4496 mService.mHeavyWeightProcess = null;
4497 mService.mHandler.sendEmptyMessage(
4498 ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG);
4499 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004500 if (r.app.activities.size() == 0) {
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07004501 // No longer have activities, so update oom adj.
4502 mService.updateOomAdjLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004503 }
4504 }
4505
4506 boolean skipDestroy = false;
4507
4508 try {
4509 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
Dianne Hackbornbe707852011-11-11 14:32:10 -08004510 r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004511 r.configChangeFlags);
4512 } catch (Exception e) {
4513 // We can just ignore exceptions here... if the process
4514 // has crashed, our death notification will clean things
4515 // up.
4516 //Slog.w(TAG, "Exception thrown during finish", e);
4517 if (r.finishing) {
4518 removeActivityFromHistoryLocked(r);
4519 removedFromHistory = true;
4520 skipDestroy = true;
4521 }
4522 }
4523
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004524 r.nowVisible = false;
4525
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004526 // If the activity is finishing, we need to wait on removing it
4527 // from the list to give it a chance to do its cleanup. During
4528 // that time it may make calls back with its token so we need to
4529 // be able to find it on the list and so we don't want to remove
4530 // it from the list yet. Otherwise, we can just immediately put
4531 // it in the destroyed state since we are not removing it from the
4532 // list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004533 if (r.finishing && !skipDestroy) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004534 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYING: " + r
4535 + " (destroy requested)");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004536 r.state = ActivityState.DESTROYING;
4537 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4538 msg.obj = r;
4539 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4540 } else {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004541 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
4542 + " (destroy skipped)");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004543 r.state = ActivityState.DESTROYED;
Dianne Hackborn07981492013-01-28 11:36:23 -08004544 if (DEBUG_APP) Slog.v(TAG, "Clearing app during destroy for activity " + r);
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004545 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004546 }
4547 } else {
4548 // remove this record from the history.
4549 if (r.finishing) {
4550 removeActivityFromHistoryLocked(r);
4551 removedFromHistory = true;
4552 } else {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004553 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
4554 + " (no app)");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004555 r.state = ActivityState.DESTROYED;
Dianne Hackborn07981492013-01-28 11:36:23 -08004556 if (DEBUG_APP) Slog.v(TAG, "Clearing app during destroy for activity " + r);
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004557 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004558 }
4559 }
4560
4561 r.configChangeFlags = 0;
4562
4563 if (!mLRUActivities.remove(r) && hadApp) {
4564 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
4565 }
4566
4567 return removedFromHistory;
4568 }
4569
4570 final void activityDestroyed(IBinder token) {
4571 synchronized (mService) {
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004572 final long origId = Binder.clearCallingIdentity();
4573 try {
4574 ActivityRecord r = ActivityRecord.forToken(token);
4575 if (r != null) {
4576 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004577 }
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004578
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004579 int index = mHistory.indexOf(r);
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004580 if (index >= 0) {
4581 if (r.state == ActivityState.DESTROYING) {
Dianne Hackborn45a25bc2012-06-28 13:49:17 -07004582 cleanUpActivityLocked(r, true, false);
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004583 removeActivityFromHistoryLocked(r);
4584 }
4585 }
4586 resumeTopActivityLocked(null);
4587 } finally {
4588 Binder.restoreCallingIdentity(origId);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004589 }
4590 }
4591 }
4592
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004593 private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list,
4594 ProcessRecord app, String listName) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004595 int i = list.size();
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004596 if (DEBUG_CLEANUP) Slog.v(
4597 TAG, "Removing app " + app + " from list " + listName
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004598 + " with " + i + " entries");
4599 while (i > 0) {
4600 i--;
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004601 ActivityRecord r = list.get(i);
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004602 if (DEBUG_CLEANUP) Slog.v(TAG, "Record #" + i + " " + r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004603 if (r.app == app) {
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004604 if (DEBUG_CLEANUP) Slog.v(TAG, "---> REMOVING this entry!");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004605 list.remove(i);
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004606 removeTimeoutsForActivityLocked(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004607 }
4608 }
4609 }
4610
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004611 boolean removeHistoryRecordsForAppLocked(ProcessRecord app) {
4612 removeHistoryRecordsForAppLocked(mLRUActivities, app, "mLRUActivities");
4613 removeHistoryRecordsForAppLocked(mStoppingActivities, app, "mStoppingActivities");
4614 removeHistoryRecordsForAppLocked(mGoingToSleepActivities, app, "mGoingToSleepActivities");
4615 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app,
4616 "mWaitingVisibleActivities");
4617 removeHistoryRecordsForAppLocked(mFinishingActivities, app, "mFinishingActivities");
4618
4619 boolean hasVisibleActivities = false;
4620
4621 // Clean out the history list.
4622 int i = mHistory.size();
4623 if (DEBUG_CLEANUP) Slog.v(
4624 TAG, "Removing app " + app + " from history with " + i + " entries");
4625 while (i > 0) {
4626 i--;
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004627 ActivityRecord r = mHistory.get(i);
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004628 if (DEBUG_CLEANUP) Slog.v(
4629 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4630 if (r.app == app) {
Dianne Hackborn07981492013-01-28 11:36:23 -08004631 boolean remove;
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004632 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Dianne Hackborn07981492013-01-28 11:36:23 -08004633 // Don't currently have state for the activity, or
4634 // it is finishing -- always remove it.
4635 remove = true;
4636 } else if (r.launchCount > 2 &&
4637 r.lastLaunchTime > (SystemClock.uptimeMillis()-60000)) {
4638 // We have launched this activity too many times since it was
4639 // able to run, so give up and remove it.
4640 remove = true;
4641 } else {
4642 // The process may be gone, but the activity lives on!
4643 remove = false;
4644 }
4645 if (remove) {
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004646 if (ActivityStack.DEBUG_ADD_REMOVE || DEBUG_CLEANUP) {
4647 RuntimeException here = new RuntimeException("here");
4648 here.fillInStackTrace();
4649 Slog.i(TAG, "Removing activity " + r + " from stack at " + i
4650 + ": haveState=" + r.haveState
4651 + " stateNotNeeded=" + r.stateNotNeeded
4652 + " finishing=" + r.finishing
4653 + " state=" + r.state, here);
4654 }
4655 if (!r.finishing) {
4656 Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
4657 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
4658 r.userId, System.identityHashCode(r),
4659 r.task.taskId, r.shortComponentName,
4660 "proc died without state saved");
4661 }
4662 removeActivityFromHistoryLocked(r);
4663
4664 } else {
4665 // We have the current state for this activity, so
4666 // it can be restarted later when needed.
4667 if (localLOGV) Slog.v(
4668 TAG, "Keeping entry, setting app to null");
4669 if (r.visible) {
4670 hasVisibleActivities = true;
4671 }
Dianne Hackborn07981492013-01-28 11:36:23 -08004672 if (DEBUG_APP) Slog.v(TAG, "Clearing app during removeHistory for activity "
4673 + r);
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004674 r.app = null;
4675 r.nowVisible = false;
4676 if (!r.haveState) {
4677 if (ActivityStack.DEBUG_SAVED_STATE) Slog.i(TAG,
4678 "App died, clearing saved state of " + r);
4679 r.icicle = null;
4680 }
4681 }
4682
4683 r.stack.cleanUpActivityLocked(r, true, true);
4684 }
4685 }
4686
4687 return hasVisibleActivities;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004688 }
4689
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004690 /**
4691 * Move the current home activity's task (if one exists) to the front
4692 * of the stack.
4693 */
4694 final void moveHomeToFrontLocked() {
Craig Mautner11bf9a52013-02-19 14:08:51 -08004695 newMoveHomeToFrontLocked();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004696 TaskRecord homeTask = null;
4697 for (int i=mHistory.size()-1; i>=0; i--) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004698 ActivityRecord hr = mHistory.get(i);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004699 if (hr.isHomeActivity) {
4700 homeTask = hr.task;
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08004701 break;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004702 }
4703 }
4704 if (homeTask != null) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08004705// moveTaskToFrontLocked(homeTask, null, null);
4706 }
4707 }
4708
4709 final void newMoveHomeToFrontLocked() {
4710 TaskRecord homeTask = null;
4711 for (int taskNdx = mTaskHistory.size() - 1; homeTask == null && taskNdx >= 0; --taskNdx) {
4712 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
4713 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
4714 final ActivityRecord r = activities.get(activityNdx);
4715 if (r.isHomeActivity) {
4716 homeTask = r.task;
4717 break;
4718 }
4719 }
4720 }
4721 if (homeTask != null) {
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07004722 moveTaskToFrontLocked(homeTask, null, null);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004723 }
4724 }
4725
Dianne Hackborn7f58b952012-04-18 12:59:29 -07004726 final void updateTransitLocked(int transit, Bundle options) {
4727 if (options != null) {
4728 ActivityRecord r = topRunningActivityLocked(null);
4729 if (r != null && r.state != ActivityState.RESUMED) {
4730 r.updateOptionsLocked(options);
4731 } else {
4732 ActivityOptions.abort(options);
4733 }
4734 }
4735 mService.mWindowManager.prepareAppTransition(transit, false);
4736 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004737
Craig Mautnercae015f2013-02-08 14:31:27 -08004738 final boolean findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
4739 for (int i = mHistory.size() - 1; i >= 0; i--) {
4740 ActivityRecord hr = mHistory.get(i);
4741 if (hr.task.taskId == taskId) {
4742 if ((flags & ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
4743 mUserLeaving = true;
4744 }
4745 if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
4746 // Caller wants the home activity moved with it. To accomplish this,
4747 // we'll just move the home task to the top first.
4748 moveHomeToFrontLocked();
4749 }
4750 moveTaskToFrontLocked(hr.task, null, options);
4751 return true;
4752 }
4753 }
4754 return false;
4755 }
4756
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07004757 final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004758
4759 final int task = tr.taskId;
4760 int top = mHistory.size()-1;
4761
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004762 if (top < 0 || (mHistory.get(top)).task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004763 // nothing to do!
4764 return;
4765 }
4766
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004767
4768 // Shift all activities with this task up to the top
4769 // of the stack, keeping them in the same internal order.
Craig Mautner11bf9a52013-02-19 14:08:51 -08004770 int pos = top;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004771 while (pos >= 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004772 ActivityRecord r = mHistory.get(pos);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004773 if (localLOGV) Slog.v(
4774 TAG, "At " + pos + " ckp " + r.task + ": " + r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004775 if (r.task.taskId == task) {
4776 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07004777 if (DEBUG_ADD_REMOVE) {
4778 RuntimeException here = new RuntimeException("here");
4779 here.fillInStackTrace();
4780 Slog.i(TAG, "Removing and adding activity " + r + " to stack at " + top, here);
4781 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004782 mHistory.remove(pos);
4783 mHistory.add(top, r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004784 top--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004785 }
4786 pos--;
4787 }
Craig Mautner11bf9a52013-02-19 14:08:51 -08004788 //
4789 // Start new code here! Delete everything above.
4790 //
4791 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004792
Craig Mautner11bf9a52013-02-19 14:08:51 -08004793 final int numTasks = mTaskHistory.size();
4794 final int index = mTaskHistory.indexOf(tr);
4795 if (numTasks == 0 || index < 0 || index == numTasks - 1) {
4796 // nothing to do!
4797 if (reason != null &&
4798 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
4799 ActivityOptions.abort(options);
4800 } else {
4801 updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
4802 }
4803 return;
4804 }
4805
4806 // Shift all activities with this task up to the top
4807 // of the stack, keeping them in the same internal order.
4808 mTaskHistory.remove(tr);
4809 mTaskHistory.add(tr);
4810
4811 if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare to front transition: task=" + tr);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004812 if (reason != null &&
4813 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08004814 mService.mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004815 ActivityRecord r = topRunningActivityLocked(null);
4816 if (r != null) {
4817 mNoAnimActivities.add(r);
4818 }
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07004819 ActivityOptions.abort(options);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004820 } else {
Craig Mautner4b71aa12012-12-27 17:20:01 -08004821 updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004822 }
Craig Mautner30e2d722013-02-12 11:30:16 -08004823
Craig Mautner30e2d722013-02-12 11:30:16 -08004824 mService.mWindowManager.moveTaskToTop(task);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004825
4826 finishTaskMoveLocked(task);
Dianne Hackbornb12e1352012-09-26 11:39:20 -07004827 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, task);
Craig Mautner11bf9a52013-02-19 14:08:51 -08004828
4829 if (VALIDATE_TOKENS) {
4830 validateAppTokensLocked();
4831 }
4832 if (VALIDATE_TASK_REPLACE) {
4833 verifyActivityRecords(true);
4834 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004835 }
4836
4837 private final void finishTaskMoveLocked(int task) {
4838 resumeTopActivityLocked(null);
4839 }
4840
4841 /**
4842 * Worker method for rearranging history stack. Implements the function of moving all
4843 * activities for a specific task (gathering them if disjoint) into a single group at the
4844 * bottom of the stack.
4845 *
4846 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
4847 * to premeptively cancel the move.
4848 *
4849 * @param task The taskId to collect and move to the bottom.
4850 * @return Returns true if the move completed, false if not.
4851 */
4852 final boolean moveTaskToBackLocked(int task, ActivityRecord reason) {
4853 Slog.i(TAG, "moveTaskToBack: " + task);
Craig Mautnerb44de0d2013-02-21 20:00:58 -08004854
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004855 // If we have a watcher, preflight the move before committing to it. First check
4856 // for *other* available tasks, but if none are available, then try again allowing the
4857 // current task to be selected.
4858 if (mMainStack && mService.mController != null) {
4859 ActivityRecord next = topRunningActivityLocked(null, task);
4860 if (next == null) {
4861 next = topRunningActivityLocked(null, 0);
4862 }
4863 if (next != null) {
4864 // ask watcher if this is allowed
4865 boolean moveOK = true;
4866 try {
4867 moveOK = mService.mController.activityResuming(next.packageName);
4868 } catch (RemoteException e) {
4869 mService.mController = null;
4870 }
4871 if (!moveOK) {
4872 return false;
4873 }
4874 }
4875 }
4876
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004877 if (DEBUG_TRANSITION) Slog.v(TAG,
4878 "Prepare to back transition: task=" + task);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004879
Craig Mautner11bf9a52013-02-19 14:08:51 -08004880 final TaskRecord tr = mTaskIdToTaskRecord.get(task);
4881 mTaskHistory.remove(tr);
4882 mTaskHistory.add(0, tr);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004883
Craig Mautnerb44de0d2013-02-21 20:00:58 -08004884 // BEGIN REGION TO REMOVE.
4885 final int N = mHistory.size();
4886 int bottom = 0;
4887 int pos = 0;
4888
4889 // Shift all activities with this task down to the bottom
4890 // of the stack, keeping them in the same internal order.
4891 while (pos < N) {
4892 ActivityRecord r = mHistory.get(pos);
4893 if (localLOGV) Slog.v(
4894 TAG, "At " + pos + " ckp " + r.task + ": " + r);
4895 if (r.task.taskId == task) {
4896 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
4897 if (DEBUG_ADD_REMOVE) {
4898 RuntimeException here = new RuntimeException("here");
4899 here.fillInStackTrace();
4900 Slog.i(TAG, "Removing and adding activity " + r + " to stack at "
4901 + bottom, here);
4902 }
4903 mHistory.remove(pos);
4904 mHistory.add(bottom, r);
4905 bottom++;
4906 }
4907 pos++;
4908 }
4909 if (VALIDATE_TASK_REPLACE) {
4910 verifyActivityRecords(true);
4911 }
4912 // END REGION TO REMOVE
4913
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004914 if (reason != null &&
4915 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08004916 mService.mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004917 ActivityRecord r = topRunningActivityLocked(null);
4918 if (r != null) {
4919 mNoAnimActivities.add(r);
4920 }
4921 } else {
Dianne Hackborn7da6ac32010-12-09 19:22:04 -08004922 mService.mWindowManager.prepareAppTransition(
Craig Mautner4b71aa12012-12-27 17:20:01 -08004923 AppTransition.TRANSIT_TASK_TO_BACK, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004924 }
Craig Mautner30e2d722013-02-12 11:30:16 -08004925 mService.mWindowManager.moveTaskToBottom(task);
Craig Mautnerb44de0d2013-02-21 20:00:58 -08004926
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004927 if (VALIDATE_TOKENS) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08004928 validateAppTokensLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004929 }
4930
4931 finishTaskMoveLocked(task);
4932 return true;
4933 }
Dianne Hackborn15491c62012-09-19 10:59:14 -07004934
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004935 public ActivityManager.TaskThumbnails getTaskThumbnailsLocked(TaskRecord tr) {
4936 TaskAccessInfo info = getTaskAccessInfoLocked(tr.taskId, true);
4937 ActivityRecord resumed = mResumedActivity;
4938 if (resumed != null && resumed.thumbHolder == tr) {
4939 info.mainThumbnail = resumed.stack.screenshotActivities(resumed);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004940 }
Dianne Hackborn6a864952012-09-21 18:46:11 -07004941 if (info.mainThumbnail == null) {
4942 info.mainThumbnail = tr.lastThumbnail;
4943 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004944 return info;
4945 }
4946
Dianne Hackborn15491c62012-09-19 10:59:14 -07004947 public Bitmap getTaskTopThumbnailLocked(TaskRecord tr) {
4948 ActivityRecord resumed = mResumedActivity;
4949 if (resumed != null && resumed.task == tr) {
4950 // This task is the current resumed task, we just need to take
4951 // a screenshot of it and return that.
4952 return resumed.stack.screenshotActivities(resumed);
4953 }
4954 // Return the information about the task, to figure out the top
4955 // thumbnail to return.
4956 TaskAccessInfo info = getTaskAccessInfoLocked(tr.taskId, true);
4957 if (info.numSubThumbbails <= 0) {
Dianne Hackborn6a864952012-09-21 18:46:11 -07004958 return info.mainThumbnail != null ? info.mainThumbnail : tr.lastThumbnail;
Dianne Hackborn15491c62012-09-19 10:59:14 -07004959 }
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004960 return info.subtasks.get(info.numSubThumbbails-1).holder.lastThumbnail;
Dianne Hackborn15491c62012-09-19 10:59:14 -07004961 }
4962
Dianne Hackborn9da2d402012-03-15 13:43:08 -07004963 public ActivityRecord removeTaskActivitiesLocked(int taskId, int subTaskIndex,
4964 boolean taskRequired) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004965 TaskAccessInfo info = getTaskAccessInfoLocked(taskId, false);
4966 if (info.root == null) {
Dianne Hackborn9da2d402012-03-15 13:43:08 -07004967 if (taskRequired) {
4968 Slog.w(TAG, "removeTaskLocked: unknown taskId " + taskId);
4969 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004970 return null;
4971 }
4972
4973 if (subTaskIndex < 0) {
4974 // Just remove the entire task.
4975 performClearTaskAtIndexLocked(taskId, info.rootIndex);
4976 return info.root;
4977 }
4978
4979 if (subTaskIndex >= info.subtasks.size()) {
Dianne Hackborn9da2d402012-03-15 13:43:08 -07004980 if (taskRequired) {
4981 Slog.w(TAG, "removeTaskLocked: unknown subTaskIndex " + subTaskIndex);
4982 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004983 return null;
4984 }
4985
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004986 // Remove all of this task's activities starting at the sub task.
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004987 TaskAccessInfo.SubTask subtask = info.subtasks.get(subTaskIndex);
4988 performClearTaskAtIndexLocked(taskId, subtask.index);
4989 return subtask.activity;
4990 }
4991
4992 public TaskAccessInfo getTaskAccessInfoLocked(int taskId, boolean inclThumbs) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004993 final TaskAccessInfo thumbs = new TaskAccessInfo();
4994 // How many different sub-thumbnails?
4995 final int NA = mHistory.size();
4996 int j = 0;
4997 ThumbnailHolder holder = null;
4998 while (j < NA) {
4999 ActivityRecord ar = mHistory.get(j);
5000 if (!ar.finishing && ar.task.taskId == taskId) {
Dianne Hackborn8da429e2012-09-23 12:52:19 -07005001 thumbs.root = ar;
5002 thumbs.rootIndex = j;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005003 holder = ar.thumbHolder;
Dianne Hackborn15491c62012-09-19 10:59:14 -07005004 if (holder != null) {
5005 thumbs.mainThumbnail = holder.lastThumbnail;
5006 }
5007 j++;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005008 break;
5009 }
5010 j++;
5011 }
5012
5013 if (j >= NA) {
5014 return thumbs;
5015 }
5016
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005017 ArrayList<TaskAccessInfo.SubTask> subtasks = new ArrayList<TaskAccessInfo.SubTask>();
5018 thumbs.subtasks = subtasks;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005019 while (j < NA) {
5020 ActivityRecord ar = mHistory.get(j);
5021 j++;
5022 if (ar.finishing) {
5023 continue;
5024 }
5025 if (ar.task.taskId != taskId) {
5026 break;
5027 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005028 if (ar.thumbHolder != holder && holder != null) {
5029 thumbs.numSubThumbbails++;
5030 holder = ar.thumbHolder;
5031 TaskAccessInfo.SubTask sub = new TaskAccessInfo.SubTask();
Dianne Hackborn15491c62012-09-19 10:59:14 -07005032 sub.holder = holder;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005033 sub.activity = ar;
5034 sub.index = j-1;
5035 subtasks.add(sub);
5036 }
5037 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005038 if (thumbs.numSubThumbbails > 0) {
5039 thumbs.retriever = new IThumbnailRetriever.Stub() {
Craig Mautner05d6272ba2013-02-11 09:39:27 -08005040 @Override
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005041 public Bitmap getThumbnail(int index) {
5042 if (index < 0 || index >= thumbs.subtasks.size()) {
5043 return null;
5044 }
Dianne Hackborn15491c62012-09-19 10:59:14 -07005045 TaskAccessInfo.SubTask sub = thumbs.subtasks.get(index);
5046 ActivityRecord resumed = mResumedActivity;
5047 if (resumed != null && resumed.thumbHolder == sub.holder) {
5048 return resumed.stack.screenshotActivities(resumed);
5049 }
5050 return sub.holder.lastThumbnail;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005051 }
5052 };
5053 }
5054 return thumbs;
5055 }
5056
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005057 private final void logStartActivity(int tag, ActivityRecord r,
5058 TaskRecord task) {
5059 EventLog.writeEvent(tag,
Dianne Hackbornb12e1352012-09-26 11:39:20 -07005060 r.userId, System.identityHashCode(r), task.taskId,
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005061 r.shortComponentName, r.intent.getAction(),
5062 r.intent.getType(), r.intent.getDataString(),
5063 r.intent.getFlags());
5064 }
5065
5066 /**
5067 * Make sure the given activity matches the current configuration. Returns
5068 * false if the activity had to be destroyed. Returns true if the
5069 * configuration is the same, or the activity will remain running as-is
5070 * for whatever reason. Ensures the HistoryRecord is updated with the
5071 * correct configuration and all other bookkeeping is handled.
5072 */
5073 final boolean ensureActivityConfigurationLocked(ActivityRecord r,
5074 int globalChanges) {
5075 if (mConfigWillChange) {
5076 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
5077 "Skipping config check (will change): " + r);
5078 return true;
5079 }
5080
5081 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
5082 "Ensuring correct configuration: " + r);
5083
5084 // Short circuit: if the two configurations are the exact same
5085 // object (the common case), then there is nothing to do.
5086 Configuration newConfig = mService.mConfiguration;
Dianne Hackborne2515ee2011-04-27 18:52:56 -04005087 if (r.configuration == newConfig && !r.forceNewConfig) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005088 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
5089 "Configuration unchanged in " + r);
5090 return true;
5091 }
5092
5093 // We don't worry about activities that are finishing.
5094 if (r.finishing) {
5095 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
5096 "Configuration doesn't matter in finishing " + r);
5097 r.stopFreezingScreenLocked(false);
5098 return true;
5099 }
5100
5101 // Okay we now are going to make this activity have the new config.
5102 // But then we need to figure out how it needs to deal with that.
5103 Configuration oldConfig = r.configuration;
5104 r.configuration = newConfig;
Dianne Hackborn58f42a52011-10-10 13:46:34 -07005105
5106 // Determine what has changed. May be nothing, if this is a config
5107 // that has come back from the app after going idle. In that case
5108 // we just want to leave the official config object now in the
5109 // activity and do nothing else.
5110 final int changes = oldConfig.diff(newConfig);
5111 if (changes == 0 && !r.forceNewConfig) {
5112 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
5113 "Configuration no differences in " + r);
5114 return true;
5115 }
5116
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005117 // If the activity isn't currently running, just leave the new
5118 // configuration and it will pick that up next time it starts.
5119 if (r.app == null || r.app.thread == null) {
5120 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
5121 "Configuration doesn't matter not running " + r);
5122 r.stopFreezingScreenLocked(false);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04005123 r.forceNewConfig = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005124 return true;
5125 }
5126
Dianne Hackborn58f42a52011-10-10 13:46:34 -07005127 // Figure out how to handle the changes between the configurations.
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -07005128 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
5129 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
5130 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborne6676352011-06-01 16:51:20 -07005131 + Integer.toHexString(r.info.getRealConfigChanged())
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -07005132 + ", newConfig=" + newConfig);
5133 }
Dianne Hackborne6676352011-06-01 16:51:20 -07005134 if ((changes&(~r.info.getRealConfigChanged())) != 0 || r.forceNewConfig) {
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -07005135 // Aha, the activity isn't handling the change, so DIE DIE DIE.
5136 r.configChangeFlags |= changes;
5137 r.startFreezingScreenLocked(r.app, globalChanges);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04005138 r.forceNewConfig = false;
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -07005139 if (r.app == null || r.app.thread == null) {
5140 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackbornb61a0262012-05-14 17:19:18 -07005141 "Config is destroying non-running " + r);
Dianne Hackborn28695e02011-11-02 21:59:51 -07005142 destroyActivityLocked(r, true, false, "config");
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -07005143 } else if (r.state == ActivityState.PAUSING) {
5144 // A little annoying: we are waiting for this activity to
5145 // finish pausing. Let's not do anything now, but just
5146 // flag that it needs to be restarted when done pausing.
5147 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackbornb61a0262012-05-14 17:19:18 -07005148 "Config is skipping already pausing " + r);
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -07005149 r.configDestroy = true;
5150 return true;
5151 } else if (r.state == ActivityState.RESUMED) {
5152 // Try to optimize this case: the configuration is changing
5153 // and we need to restart the top, resumed activity.
5154 // Instead of doing the normal handshaking, just say
5155 // "restart!".
5156 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackbornb61a0262012-05-14 17:19:18 -07005157 "Config is relaunching resumed " + r);
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -07005158 relaunchActivityLocked(r, r.configChangeFlags, true);
5159 r.configChangeFlags = 0;
5160 } else {
5161 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackbornb61a0262012-05-14 17:19:18 -07005162 "Config is relaunching non-resumed " + r);
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -07005163 relaunchActivityLocked(r, r.configChangeFlags, false);
5164 r.configChangeFlags = 0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005165 }
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -07005166
5167 // All done... tell the caller we weren't able to keep this
5168 // activity around.
5169 return false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005170 }
5171
5172 // Default case: the activity can handle this new configuration, so
5173 // hand it over. Note that we don't need to give it the new
5174 // configuration, since we always send configuration changes to all
5175 // process when they happen so it can just use whatever configuration
5176 // it last got.
5177 if (r.app != null && r.app.thread != null) {
5178 try {
5179 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
Dianne Hackbornbe707852011-11-11 14:32:10 -08005180 r.app.thread.scheduleActivityConfigurationChanged(r.appToken);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005181 } catch (RemoteException e) {
5182 // If process died, whatever.
5183 }
5184 }
5185 r.stopFreezingScreenLocked(false);
5186
5187 return true;
5188 }
5189
5190 private final boolean relaunchActivityLocked(ActivityRecord r,
5191 int changes, boolean andResume) {
5192 List<ResultInfo> results = null;
5193 List<Intent> newIntents = null;
5194 if (andResume) {
5195 results = r.results;
5196 newIntents = r.newIntents;
5197 }
5198 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
5199 + " with results=" + results + " newIntents=" + newIntents
5200 + " andResume=" + andResume);
5201 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
Dianne Hackbornb12e1352012-09-26 11:39:20 -07005202 : EventLogTags.AM_RELAUNCH_ACTIVITY, r.userId, System.identityHashCode(r),
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005203 r.task.taskId, r.shortComponentName);
5204
5205 r.startFreezingScreenLocked(r.app, 0);
5206
5207 try {
Dianne Hackbornb61a0262012-05-14 17:19:18 -07005208 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
5209 (andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ")
5210 + r);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04005211 r.forceNewConfig = false;
Dianne Hackbornbe707852011-11-11 14:32:10 -08005212 r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents,
Dianne Hackborn813075a62011-11-14 17:45:19 -08005213 changes, !andResume, new Configuration(mService.mConfiguration));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005214 // Note: don't need to call pauseIfSleepingLocked() here, because
5215 // the caller will only pass in 'andResume' if this activity is
5216 // currently resumed, which implies we aren't sleeping.
5217 } catch (RemoteException e) {
Dianne Hackbornb61a0262012-05-14 17:19:18 -07005218 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG, "Relaunch failed", e);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005219 }
5220
5221 if (andResume) {
5222 r.results = null;
5223 r.newIntents = null;
5224 if (mMainStack) {
5225 mService.reportResumedActivityLocked(r);
5226 }
Dianne Hackbornb61a0262012-05-14 17:19:18 -07005227 r.state = ActivityState.RESUMED;
5228 } else {
5229 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5230 r.state = ActivityState.PAUSED;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005231 }
5232
5233 return true;
5234 }
Dianne Hackborn90c52de2011-09-23 12:57:44 -07005235
5236 public void dismissKeyguardOnNextActivityLocked() {
5237 mDismissKeyguardOnNextActivity = true;
5238 }
Craig Mautnercae015f2013-02-08 14:31:27 -08005239
5240 boolean willActivityBeVisibleLocked(IBinder token) {
5241 int i;
5242 for (i = mHistory.size() - 1; i >= 0; i--) {
5243 ActivityRecord r = mHistory.get(i);
5244 if (r.appToken == token) {
5245 return true;
5246 }
5247 if (r.fullscreen && !r.finishing) {
5248 return false;
5249 }
5250 }
5251 return true;
5252 }
5253
5254 void closeSystemDialogsLocked() {
5255 for (int i = mHistory.size() - 1; i >= 0; i--) {
5256 ActivityRecord r = mHistory.get(i);
5257 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5258 r.stack.finishActivityLocked(r, i,
5259 Activity.RESULT_CANCELED, null, "close-sys", true);
5260 }
5261 }
5262 }
5263
5264 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
5265 boolean didSomething = false;
5266 TaskRecord lastTask = null;
5267 final int N = mHistory.size();
5268 for (int i = 0; i < N; i++) {
5269 ActivityRecord r = mHistory.get(i);
5270 final boolean samePackage = r.packageName.equals(name)
5271 || (name == null && r.userId == userId);
5272 if ((userId == UserHandle.USER_ALL || r.userId == userId)
5273 && (samePackage || r.task == lastTask)
5274 && (r.app == null || evenPersistent || !r.app.persistent)) {
5275 if (!doit) {
5276 if (r.finishing) {
5277 // If this activity is just finishing, then it is not
5278 // interesting as far as something to stop.
5279 continue;
5280 }
5281 return true;
5282 }
5283 didSomething = true;
5284 Slog.i(TAG, " Force finishing activity " + r);
5285 if (samePackage) {
5286 if (r.app != null) {
5287 r.app.removed = true;
5288 }
5289 r.app = null;
5290 }
5291 lastTask = r.task;
5292 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
5293 null, "force-stop", true)) {
5294 i--;
5295 }
5296 }
5297 }
5298 return didSomething;
5299 }
5300
5301 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
5302 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
5303 ActivityRecord topRecord = null;
5304 int pos = mHistory.size() - 1;
5305 ActivityRecord next = pos >= 0 ? mHistory.get(pos) : null;
5306 ActivityRecord top = null;
5307 TaskRecord curTask = null;
5308 int numActivities = 0;
5309 int numRunning = 0;
5310 while (pos >= 0 && maxNum > 0) {
5311 final ActivityRecord r = next;
5312 pos--;
5313 next = pos >= 0 ? mHistory.get(pos) : null;
5314
5315 // Initialize state for next task if needed.
5316 if (top == null || (top.state == ActivityState.INITIALIZING && top.task == r.task)) {
5317 top = r;
5318 curTask = r.task;
5319 numActivities = numRunning = 0;
5320 }
5321
5322 // Add 'r' into the current task.
5323 numActivities++;
5324 if (r.app != null && r.app.thread != null) {
5325 numRunning++;
5326 }
5327
5328 if (localLOGV) Slog.v(
5329 TAG, r.intent.getComponent().flattenToShortString()
5330 + ": task=" + r.task);
5331
5332 // If the next one is a different task, generate a new
5333 // TaskInfo entry for what we have.
5334 if (next == null || next.task != curTask) {
5335 RunningTaskInfo ci = new RunningTaskInfo();
5336 ci.id = curTask.taskId;
5337 ci.baseActivity = r.intent.getComponent();
5338 ci.topActivity = top.intent.getComponent();
5339 if (top.thumbHolder != null) {
5340 ci.description = top.thumbHolder.lastDescription;
5341 }
5342 ci.numActivities = numActivities;
5343 ci.numRunning = numRunning;
5344 //System.out.println(
5345 // "#" + maxNum + ": " + " descr=" + ci.description);
5346 if (receiver != null) {
5347 if (localLOGV) Slog.v(
5348 TAG, "State=" + top.state + "Idle=" + top.idle
5349 + " app=" + top.app
5350 + " thr=" + (top.app != null ? top.app.thread : null));
5351 if (top.state == ActivityState.RESUMED || top.state == ActivityState.PAUSING) {
5352 if (top.idle && top.app != null && top.app.thread != null) {
5353 topRecord = top;
5354 } else {
5355 top.thumbnailNeeded = true;
5356 }
5357 }
5358 pending.pendingRecords.add(top);
5359 }
5360 list.add(ci);
5361 maxNum--;
5362 top = null;
5363 }
5364 }
5365 return topRecord;
5366 }
5367
5368 public void unhandledBackLocked() {
5369 int top = mHistory.size() - 1;
5370 if (DEBUG_SWITCH) Slog.d(
5371 TAG, "Performing unhandledBack(): top activity at " + top);
5372 if (top > 0) {
5373 finishActivityLocked(mHistory.get(top),
5374 top, Activity.RESULT_CANCELED, null, "unhandled-back", true);
5375 }
5376 }
5377
5378 void handleAppCrashLocked(ProcessRecord app) {
5379 for (int i = mHistory.size() - 1; i >= 0; i--) {
5380 ActivityRecord r = mHistory.get(i);
5381 if (r.app == app) {
5382 Slog.w(TAG, " Force finishing activity "
5383 + r.intent.getComponent().flattenToShortString());
5384 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
5385 null, "crashed", false);
5386 }
5387 }
5388 }
5389
5390 void dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
5391 boolean dumpClient, String dumpPackage) {
5392 ActivityManagerService.dumpHistoryList(fd, pw, mHistory, " ", "Hist", true, !dumpAll,
5393 dumpClient, dumpPackage);
5394 }
5395
5396 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
5397 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
5398
5399 if ("all".equals(name)) {
5400 for (ActivityRecord r1 : mHistory) {
5401 activities.add(r1);
5402 }
5403 } else if ("top".equals(name)) {
5404 final int N = mHistory.size();
5405 if (N > 0) {
5406 activities.add(mHistory.get(N-1));
5407 }
5408 } else {
5409 ItemMatcher matcher = new ItemMatcher();
5410 matcher.build(name);
5411
5412 for (ActivityRecord r1 : mHistory) {
5413 if (matcher.match(r1, r1.intent.getComponent())) {
5414 activities.add(r1);
5415 }
5416 }
5417 }
5418
5419 return activities;
5420 }
5421
5422 ActivityRecord restartPackage(String packageName) {
5423 ActivityRecord starting = topRunningActivityLocked(null);
5424
5425 // All activities that came from the package must be
5426 // restarted as if there was a config change.
5427 for (int i = mHistory.size() - 1; i >= 0; i--) {
5428 ActivityRecord a = mHistory.get(i);
5429 if (a.info.packageName.equals(packageName)) {
5430 a.forceNewConfig = true;
5431 if (starting != null && a == starting && a.visible) {
5432 a.startFreezingScreenLocked(starting.app, ActivityInfo.CONFIG_SCREEN_LAYOUT);
5433 }
5434 }
5435 }
5436
5437 return starting;
5438 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08005439
Craig Mautner11bf9a52013-02-19 14:08:51 -08005440 void rebuildTaskHistory() {
5441 mTaskHistory.clear();
5442 final int numActivities = mHistory.size();
5443 TaskRecord task = null;
5444 for (int i = 0; i < numActivities; ++i) {
5445 final ActivityRecord r = mHistory.get(i);
5446 if (r.task != task) {
5447 task = r.task;
5448 task.mActivities.clear();
5449 mTaskHistory.add(task);
5450 }
5451 task.mActivities.add(r);
5452 }
5453 }
5454
5455 boolean verifyActivityRecords(boolean rebuild) {
5456 final int numHistory = mHistory.size();
5457 int historyNdx = 0;
5458
5459 final int numTasks = mTaskHistory.size();
5460 int taskNdx;
5461 for (taskNdx = historyNdx = 0; taskNdx < numTasks; ++taskNdx) {
5462 final TaskRecord task = mTaskHistory.get(taskNdx);
5463 final ArrayList<ActivityRecord> activities = task.mActivities;
5464 final int numActivities = activities.size();
5465 int activityNdx;
5466 for (activityNdx = 0;
5467 activityNdx < numActivities && historyNdx < numHistory;
5468 ++activityNdx, ++historyNdx) {
5469 ActivityRecord r1 = mHistory.get(historyNdx);
5470 ActivityRecord r2 = activities.get(activityNdx);
5471 if (r1 != r2) {
5472 break;
5473 }
5474 }
5475 if (activityNdx != numActivities) {
5476 // either a mismatch or mHistory ran out before mTaskHistory.
Craig Mautner5d9c7be2013-02-15 14:02:56 -08005477 break;
5478 }
5479 }
Craig Mautner11bf9a52013-02-19 14:08:51 -08005480 if (taskNdx != numTasks || historyNdx != numHistory) {
5481 logHistories("verifyActivityRecords", rebuild);
5482 return true;
Craig Mautner5d9c7be2013-02-15 14:02:56 -08005483 }
Craig Mautner11bf9a52013-02-19 14:08:51 -08005484 return false;
5485 }
5486
5487 private void logHistories(String caller, boolean rebuild) {
5488 Slog.w(TAG, "Mismatch! " + caller + " mHistory=" + mHistory);
5489 ArrayList<ArrayList<ActivityRecord>> nestedRecords =
5490 new ArrayList<ArrayList<ActivityRecord>>();
5491 for (TaskRecord task : mTaskHistory) {
5492 nestedRecords.add(task.mActivities);
5493 }
5494 Slog.w(TAG, "Mismatch! " + caller + " mTaskHistory" + nestedRecords);
5495 Slog.w(TAG, "Mismatch! " + caller + " lastHistoryModifier=" + mLastHistoryModifier
5496 + " Caller=" + Debug.getCallers(4));
5497 if (rebuild) {
5498 rebuildTaskHistory();
Craig Mautner5d9c7be2013-02-15 14:02:56 -08005499 }
5500 }
5501
5502 private TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
5503 boolean toTop) {
5504 TaskRecord oldTask = mTaskIdToTaskRecord.get(taskId);
5505 if (oldTask != null) {
5506 Slog.w(TAG, "createTaskRecord: Reusing taskId=" + taskId + " without removing");
5507 mTaskHistory.remove(oldTask);
5508 }
5509 TaskRecord task = new TaskRecord(taskId, info, intent);
5510 mTaskIdToTaskRecord.put(taskId, task);
5511 if (toTop) {
5512 mTaskHistory.add(task);
5513 } else {
5514 mTaskHistory.add(0, task);
5515 }
5516 return task;
5517 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005518}