blob: 88572b977db0d1d5ff63c6d881967b865d8b0638 [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 Mautnerd44711d2013-02-23 11:24:36 -08001060 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1061 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
1062 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1063 activities.get(activityNdx).setSleeping(false);
1064 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001065 }
1066 mGoingToSleepActivities.clear();
1067 }
1068
1069 void activitySleptLocked(ActivityRecord r) {
1070 mGoingToSleepActivities.remove(r);
1071 checkReadyForSleepLocked();
1072 }
1073
1074 void checkReadyForSleepLocked() {
1075 if (!mService.isSleeping()) {
1076 // Do not care.
1077 return;
1078 }
1079
1080 if (!mSleepTimeout) {
1081 if (mResumedActivity != null) {
1082 // Still have something resumed; can't sleep until it is paused.
1083 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause " + mResumedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001084 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
1085 startPausingLocked(false, true);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001086 return;
1087 }
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001088 if (mPausingActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001089 // Still waiting for something to pause; can't sleep yet.
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001090 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still waiting to pause " + mPausingActivity);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001091 return;
1092 }
1093
1094 if (mStoppingActivities.size() > 0) {
1095 // Still need to tell some activities to stop; can't sleep yet.
1096 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
1097 + mStoppingActivities.size() + " activities");
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07001098 scheduleIdleLocked();
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001099 return;
1100 }
1101
1102 ensureActivitiesVisibleLocked(null, 0);
1103
1104 // Make sure any stopped but visible activities are now sleeping.
1105 // This ensures that the activity's onStop() is called.
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001106 if (VALIDATE_TASK_REPLACE) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08001107 verifyActivityRecords(true);
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001108 }
Craig Mautnerd44711d2013-02-23 11:24:36 -08001109 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1110 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
1111 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1112 final ActivityRecord r = activities.get(activityNdx);
1113 if (r.state == ActivityState.STOPPING || r.state == ActivityState.STOPPED) {
1114 r.setSleeping(true);
1115 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001116 }
1117 }
1118
1119 if (mGoingToSleepActivities.size() > 0) {
1120 // Still need to tell some activities to sleep; can't sleep yet.
1121 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
1122 + mGoingToSleepActivities.size() + " activities");
1123 return;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001124 }
1125 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001126
1127 mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
1128
1129 if (mGoingToSleep.isHeld()) {
1130 mGoingToSleep.release();
1131 }
1132 if (mService.mShuttingDown) {
1133 mService.notifyAll();
1134 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001135 }
Craig Mautner59c00972012-07-30 12:10:24 -07001136
Dianne Hackbornd2835932010-12-13 16:28:46 -08001137 public final Bitmap screenshotActivities(ActivityRecord who) {
Dianne Hackbornff801ec2011-01-22 18:05:38 -08001138 if (who.noDisplay) {
1139 return null;
1140 }
1141
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08001142 Resources res = mService.mContext.getResources();
1143 int w = mThumbnailWidth;
1144 int h = mThumbnailHeight;
1145 if (w < 0) {
1146 mThumbnailWidth = w =
1147 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
1148 mThumbnailHeight = h =
1149 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
1150 }
1151
1152 if (w > 0) {
Craig Mautnerb12428a2012-12-20 16:07:06 -08001153 if (who != mLastScreenshotActivity || mLastScreenshotBitmap == null
1154 || mLastScreenshotBitmap.getWidth() != w
1155 || mLastScreenshotBitmap.getHeight() != h) {
1156 mLastScreenshotActivity = who;
1157 mLastScreenshotBitmap = mService.mWindowManager.screenshotApplications(
1158 who.appToken, Display.DEFAULT_DISPLAY, w, h);
1159 }
1160 if (mLastScreenshotBitmap != null) {
1161 return mLastScreenshotBitmap.copy(Config.ARGB_8888, true);
1162 }
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08001163 }
1164 return null;
1165 }
1166
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001167 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001168 if (mPausingActivity != null) {
1169 RuntimeException e = new RuntimeException();
1170 Slog.e(TAG, "Trying to pause when pause is already pending for "
1171 + mPausingActivity, e);
1172 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001173 ActivityRecord prev = mResumedActivity;
1174 if (prev == null) {
1175 RuntimeException e = new RuntimeException();
1176 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
1177 resumeTopActivityLocked(null);
1178 return;
1179 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07001180 if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev);
1181 else if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001182 mResumedActivity = null;
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001183 mPausingActivity = prev;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001184 mLastPausedActivity = prev;
1185 prev.state = ActivityState.PAUSING;
1186 prev.task.touchActiveTime();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07001187 prev.updateThumbnail(screenshotActivities(prev), null);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001188
1189 mService.updateCpuStats();
1190
1191 if (prev.app != null && prev.app.thread != null) {
1192 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
1193 try {
1194 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
Dianne Hackbornb12e1352012-09-26 11:39:20 -07001195 prev.userId, System.identityHashCode(prev),
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001196 prev.shortComponentName);
Dianne Hackbornbe707852011-11-11 14:32:10 -08001197 prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
1198 userLeaving, prev.configChangeFlags);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001199 if (mMainStack) {
1200 mService.updateUsageStats(prev, false);
1201 }
1202 } catch (Exception e) {
1203 // Ignore exception, if process died other code will cleanup.
1204 Slog.w(TAG, "Exception thrown during pause", e);
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001205 mPausingActivity = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001206 mLastPausedActivity = null;
1207 }
1208 } else {
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001209 mPausingActivity = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001210 mLastPausedActivity = null;
1211 }
1212
1213 // If we are not going to sleep, we want to ensure the device is
1214 // awake until the next activity is started.
1215 if (!mService.mSleeping && !mService.mShuttingDown) {
1216 mLaunchingActivity.acquire();
1217 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
1218 // To be safe, don't allow the wake lock to be held for too long.
1219 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1220 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
1221 }
1222 }
1223
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001224
1225 if (mPausingActivity != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001226 // Have the window manager pause its key dispatching until the new
1227 // activity has started. If we're pausing the activity just because
1228 // the screen is being turned off and the UI is sleeping, don't interrupt
1229 // key dispatch; the same activity will pick it up again on wakeup.
1230 if (!uiSleeping) {
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001231 prev.pauseKeyDispatchingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001232 } else {
1233 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
1234 }
1235
1236 // Schedule a pause timeout in case the app doesn't respond.
1237 // We don't give it much time because this directly impacts the
1238 // responsiveness seen by the user.
1239 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
1240 msg.obj = prev;
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07001241 prev.pauseTime = SystemClock.uptimeMillis();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001242 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
1243 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
1244 } else {
1245 // This activity failed to schedule the
1246 // pause, so just treat it as being paused now.
1247 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001248 resumeTopActivityLocked(null);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001249 }
1250 }
Dianne Hackbornad9b32112012-09-17 15:35:01 -07001251
1252 final void activityResumed(IBinder token) {
Dianne Hackbornad9b32112012-09-17 15:35:01 -07001253 synchronized (mService) {
Craig Mautnerd44711d2013-02-23 11:24:36 -08001254 final ActivityRecord r = isInStackLocked(token);
1255 if (r != null) {
Dianne Hackbornad9b32112012-09-17 15:35:01 -07001256 if (DEBUG_SAVED_STATE) Slog.i(TAG, "Resumed activity; dropping state of: " + r);
1257 r.icicle = null;
1258 r.haveState = false;
1259 }
1260 }
1261 }
1262
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08001263 final void activityPaused(IBinder token, boolean timeout) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001264 if (DEBUG_PAUSE) Slog.v(
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08001265 TAG, "Activity paused: token=" + token + ", timeout=" + timeout);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001266
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001267 synchronized (mService) {
Craig Mautnerd44711d2013-02-23 11:24:36 -08001268 final ActivityRecord r = isInStackLocked(token);
1269 if (r != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001270 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001271 if (mPausingActivity == r) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07001272 if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r
1273 + (timeout ? " (due to timeout)" : " (pause complete)"));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001274 r.state = ActivityState.PAUSED;
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001275 completePauseLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001276 } else {
1277 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
Dianne Hackbornb12e1352012-09-26 11:39:20 -07001278 r.userId, System.identityHashCode(r), r.shortComponentName,
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001279 mPausingActivity != null
1280 ? mPausingActivity.shortComponentName : "(none)");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001281 }
1282 }
1283 }
1284 }
1285
Dianne Hackbornce86ba82011-07-13 19:33:41 -07001286 final void activityStoppedLocked(ActivityRecord r, Bundle icicle, Bitmap thumbnail,
1287 CharSequence description) {
Dianne Hackbornb61a0262012-05-14 17:19:18 -07001288 if (r.state != ActivityState.STOPPING) {
1289 Slog.i(TAG, "Activity reported stop, but no longer stopping: " + r);
1290 mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
1291 return;
1292 }
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07001293 if (DEBUG_SAVED_STATE) Slog.i(TAG, "Saving icicle of " + r + ": " + icicle);
Dianne Hackborn162bc0e2012-04-09 14:06:16 -07001294 if (icicle != null) {
1295 // If icicle is null, this is happening due to a timeout, so we
1296 // haven't really saved the state.
1297 r.icicle = icicle;
1298 r.haveState = true;
Dianne Hackborn07981492013-01-28 11:36:23 -08001299 r.launchCount = 0;
Dianne Hackborn162bc0e2012-04-09 14:06:16 -07001300 r.updateThumbnail(thumbnail, description);
1301 }
1302 if (!r.stopped) {
1303 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r + " (stop complete)");
1304 mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
1305 r.stopped = true;
1306 r.state = ActivityState.STOPPED;
Dianne Hackborn6e3d6da2012-06-15 12:05:27 -07001307 if (r.finishing) {
1308 r.clearOptionsLocked();
1309 } else {
Dianne Hackborn162bc0e2012-04-09 14:06:16 -07001310 if (r.configDestroy) {
1311 destroyActivityLocked(r, true, false, "stop-config");
1312 resumeTopActivityLocked(null);
1313 } else {
1314 // Now that this process has stopped, we may want to consider
1315 // it to be the previous app to try to keep around in case
1316 // the user wants to return to it.
1317 ProcessRecord fgApp = null;
1318 if (mResumedActivity != null) {
1319 fgApp = mResumedActivity.app;
1320 } else if (mPausingActivity != null) {
1321 fgApp = mPausingActivity.app;
1322 }
1323 if (r.app != null && fgApp != null && r.app != fgApp
1324 && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
1325 && r.app != mService.mHomeProcess) {
1326 mService.mPreviousProcess = r.app;
1327 mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
1328 }
Dianne Hackborn50685602011-12-01 12:23:37 -08001329 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07001330 }
1331 }
1332 }
1333
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001334 private final void completePauseLocked() {
1335 ActivityRecord prev = mPausingActivity;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001336 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
1337
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001338 if (prev != null) {
1339 if (prev.finishing) {
1340 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07001341 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false);
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001342 } else if (prev.app != null) {
1343 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
1344 if (prev.waitingVisible) {
1345 prev.waitingVisible = false;
1346 mWaitingVisibleActivities.remove(prev);
1347 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
1348 TAG, "Complete pause, no longer waiting: " + prev);
Dianne Hackborncbb722e2012-02-07 18:33:49 -08001349 }
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001350 if (prev.configDestroy) {
1351 // The previous is being paused because the configuration
1352 // is changing, which means it is actually stopping...
1353 // To juggle the fact that we are also starting a new
1354 // instance right now, we need to first completely stop
1355 // the current instance before starting the new one.
1356 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
1357 destroyActivityLocked(prev, true, false, "pause-config");
1358 } else {
1359 mStoppingActivities.add(prev);
1360 if (mStoppingActivities.size() > 3) {
1361 // If we already have a few activities waiting to stop,
1362 // then give up on things going idle and start clearing
1363 // them out.
1364 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
1365 scheduleIdleLocked();
1366 } else {
1367 checkReadyForSleepLocked();
1368 }
1369 }
1370 } else {
1371 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
1372 prev = null;
Dianne Hackborncbb722e2012-02-07 18:33:49 -08001373 }
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001374 mPausingActivity = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001375 }
Dianne Hackborncbb722e2012-02-07 18:33:49 -08001376
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001377 if (!mService.isSleeping()) {
1378 resumeTopActivityLocked(prev);
1379 } else {
Dianne Hackborncbb722e2012-02-07 18:33:49 -08001380 checkReadyForSleepLocked();
Dianne Hackborncc5a0552012-10-01 16:32:39 -07001381 ActivityRecord top = topRunningActivityLocked(null);
1382 if (top == null || (prev != null && top != prev)) {
1383 // If there are no more activities available to run,
1384 // do resume anyway to start something. Also if the top
1385 // activity on the stack is not the just paused activity,
1386 // we need to go ahead and resume it to ensure we complete
1387 // an in-flight app switch.
Dianne Hackborn42e620c2012-06-24 13:20:51 -07001388 resumeTopActivityLocked(null);
1389 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001390 }
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001391
1392 if (prev != null) {
1393 prev.resumeKeyDispatchingLocked();
1394 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001395
1396 if (prev.app != null && prev.cpuTimeAtResume > 0
1397 && mService.mBatteryStatsService.isOnBattery()) {
1398 long diff = 0;
1399 synchronized (mService.mProcessStatsThread) {
1400 diff = mService.mProcessStats.getCpuTimeForPid(prev.app.pid)
1401 - prev.cpuTimeAtResume;
1402 }
1403 if (diff > 0) {
1404 BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics();
1405 synchronized (bsi) {
1406 BatteryStatsImpl.Uid.Proc ps =
1407 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
1408 prev.info.packageName);
1409 if (ps != null) {
1410 ps.addForegroundTimeLocked(diff);
1411 }
1412 }
1413 }
1414 }
1415 prev.cpuTimeAtResume = 0; // reset it
1416 }
1417
1418 /**
1419 * Once we know that we have asked an application to put an activity in
1420 * the resumed state (either by launching it or explicitly telling it),
1421 * this function updates the rest of our state to match that fact.
1422 */
1423 private final void completeResumeLocked(ActivityRecord next) {
1424 next.idle = false;
1425 next.results = null;
1426 next.newIntents = null;
1427
1428 // schedule an idle timeout in case the app doesn't do it for us.
1429 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1430 msg.obj = next;
1431 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
1432
1433 if (false) {
1434 // The activity was never told to pause, so just keep
1435 // things going as-is. To maintain our own state,
1436 // we need to emulate it coming back and saying it is
1437 // idle.
1438 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
1439 msg.obj = next;
1440 mHandler.sendMessage(msg);
1441 }
1442
1443 if (mMainStack) {
1444 mService.reportResumedActivityLocked(next);
1445 }
Dianne Hackborn15491c62012-09-19 10:59:14 -07001446
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001447 if (mMainStack) {
1448 mService.setFocusedActivityLocked(next);
1449 }
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001450 next.resumeKeyDispatchingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001451 ensureActivitiesVisibleLocked(null, 0);
1452 mService.mWindowManager.executeAppTransition();
1453 mNoAnimActivities.clear();
1454
1455 // Mark the point when the activity is resuming
1456 // TODO: To be more accurate, the mark should be before the onCreate,
1457 // not after the onResume. But for subsequent starts, onResume is fine.
1458 if (next.app != null) {
1459 synchronized (mService.mProcessStatsThread) {
1460 next.cpuTimeAtResume = mService.mProcessStats.getCpuTimeForPid(next.app.pid);
1461 }
1462 } else {
1463 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
1464 }
1465 }
1466
1467 /**
1468 * Make sure that all activities that need to be visible (that is, they
1469 * currently can be seen by the user) actually are.
1470 */
1471 final void ensureActivitiesVisibleLocked(ActivityRecord top,
1472 ActivityRecord starting, String onlyThisProcess, int configChanges) {
1473 if (DEBUG_VISBILITY) Slog.v(
1474 TAG, "ensureActivitiesVisible behind " + top
1475 + " configChanges=0x" + Integer.toHexString(configChanges));
1476
1477 // If the top activity is not fullscreen, then we need to
1478 // make sure any activities under it are now visible.
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001479 if (VALIDATE_TASK_REPLACE) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08001480 verifyActivityRecords(true);
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001481 }
Craig Mautnerd44711d2013-02-23 11:24:36 -08001482 boolean aboveTop = true;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001483 boolean behindFullscreen = false;
Craig Mautnerd44711d2013-02-23 11:24:36 -08001484 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1485 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
1486 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1487 final ActivityRecord r = activities.get(activityNdx);
1488 if (r.finishing) {
1489 continue;
1490 }
1491 if (aboveTop && r != top) {
1492 continue;
1493 }
1494 aboveTop = false;
1495 if (!behindFullscreen) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001496 if (DEBUG_VISBILITY) Slog.v(
Craig Mautnerd44711d2013-02-23 11:24:36 -08001497 TAG, "Make visible? " + r + " finishing=" + r.finishing
1498 + " state=" + r.state);
1499
1500 final boolean doThisProcess = onlyThisProcess == null
1501 || onlyThisProcess.equals(r.processName);
1502
1503 // First: if this is not the current activity being started, make
1504 // sure it matches the current configuration.
1505 if (r != starting && doThisProcess) {
1506 ensureActivityConfigurationLocked(r, 0);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001507 }
Craig Mautnerd44711d2013-02-23 11:24:36 -08001508
1509 if (r.app == null || r.app.thread == null) {
1510 if (onlyThisProcess == null
1511 || onlyThisProcess.equals(r.processName)) {
1512 // This activity needs to be visible, but isn't even
1513 // running... get it started, but don't resume it
1514 // at this point.
1515 if (DEBUG_VISBILITY) Slog.v(
1516 TAG, "Start and freeze screen for " + r);
1517 if (r != starting) {
1518 r.startFreezingScreenLocked(r.app, configChanges);
1519 }
1520 if (!r.visible) {
1521 if (DEBUG_VISBILITY) Slog.v(
1522 TAG, "Starting and making visible: " + r);
1523 mService.mWindowManager.setAppVisibility(r.appToken, true);
1524 }
1525 if (r != starting) {
1526 startSpecificActivityLocked(r, false, false);
1527 }
1528 }
1529
1530 } else if (r.visible) {
1531 // If this activity is already visible, then there is nothing
1532 // else to do here.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001533 if (DEBUG_VISBILITY) Slog.v(
Craig Mautnerd44711d2013-02-23 11:24:36 -08001534 TAG, "Skipping: already visible at " + r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001535 r.stopFreezingScreenLocked(false);
Craig Mautnerd44711d2013-02-23 11:24:36 -08001536
1537 } else if (onlyThisProcess == null) {
1538 // This activity is not currently visible, but is running.
1539 // Tell it to become visible.
1540 r.visible = true;
1541 if (r.state != ActivityState.RESUMED && r != starting) {
1542 // If this activity is paused, tell it
1543 // to now show its window.
1544 if (DEBUG_VISBILITY) Slog.v(
1545 TAG, "Making visible and scheduling visibility: " + r);
1546 try {
1547 mService.mWindowManager.setAppVisibility(r.appToken, true);
1548 r.sleeping = false;
1549 r.app.pendingUiClean = true;
1550 r.app.thread.scheduleWindowVisibility(r.appToken, true);
1551 r.stopFreezingScreenLocked(false);
1552 } catch (Exception e) {
1553 // Just skip on any failure; we'll make it
1554 // visible when it next restarts.
1555 Slog.w(TAG, "Exception thrown making visibile: "
1556 + r.intent.getComponent(), e);
1557 }
1558 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001559 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001560
Craig Mautnerd44711d2013-02-23 11:24:36 -08001561 // Aggregate current change flags.
1562 configChanges |= r.configChangeFlags;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001563
Craig Mautnerd44711d2013-02-23 11:24:36 -08001564 if (r.fullscreen) {
1565 // At this point, nothing else needs to be shown
1566 if (DEBUG_VISBILITY) Slog.v(
1567 TAG, "Stopping: fullscreen at " + r);
1568 behindFullscreen = true;
1569 }
1570 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001571 if (r.visible) {
1572 if (DEBUG_VISBILITY) Slog.v(
1573 TAG, "Making invisible: " + r);
1574 r.visible = false;
1575 try {
Dianne Hackbornbe707852011-11-11 14:32:10 -08001576 mService.mWindowManager.setAppVisibility(r.appToken, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001577 if ((r.state == ActivityState.STOPPING
1578 || r.state == ActivityState.STOPPED)
1579 && r.app != null && r.app.thread != null) {
1580 if (DEBUG_VISBILITY) Slog.v(
1581 TAG, "Scheduling invisibility: " + r);
Dianne Hackbornbe707852011-11-11 14:32:10 -08001582 r.app.thread.scheduleWindowVisibility(r.appToken, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001583 }
1584 } catch (Exception e) {
1585 // Just skip on any failure; we'll make it
1586 // visible when it next restarts.
1587 Slog.w(TAG, "Exception thrown making hidden: "
1588 + r.intent.getComponent(), e);
1589 }
1590 } else {
1591 if (DEBUG_VISBILITY) Slog.v(
1592 TAG, "Already invisible: " + r);
1593 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001594 }
1595 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001596 }
1597 }
1598
1599 /**
1600 * Version of ensureActivitiesVisible that can easily be called anywhere.
1601 */
1602 final void ensureActivitiesVisibleLocked(ActivityRecord starting,
1603 int configChanges) {
1604 ActivityRecord r = topRunningActivityLocked(null);
1605 if (r != null) {
1606 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
1607 }
1608 }
1609
1610 /**
1611 * Ensure that the top activity in the stack is resumed.
1612 *
1613 * @param prev The previously resumed activity, for when in the process
1614 * of pausing; can be null to call from elsewhere.
1615 *
1616 * @return Returns true if something is being resumed, or false if
1617 * nothing happened.
1618 */
1619 final boolean resumeTopActivityLocked(ActivityRecord prev) {
Dianne Hackborn84375872012-06-01 19:03:50 -07001620 return resumeTopActivityLocked(prev, null);
1621 }
1622
1623 final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001624 // Find the first activity that is not finishing.
1625 ActivityRecord next = topRunningActivityLocked(null);
1626
1627 // Remember how we'll process this pause/resume situation, and ensure
1628 // that the state is reset however we wind up proceeding.
1629 final boolean userLeaving = mUserLeaving;
1630 mUserLeaving = false;
1631
1632 if (next == null) {
1633 // There are no more activities! Let's just start up the
1634 // Launcher...
1635 if (mMainStack) {
Dianne Hackborn84375872012-06-01 19:03:50 -07001636 ActivityOptions.abort(options);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001637 return mService.startHomeActivityLocked(mCurrentUser);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001638 }
1639 }
1640
1641 next.delayedResume = false;
1642
1643 // If the top activity is the resumed one, nothing to do.
1644 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
1645 // Make sure we have executed any pending transitions, since there
1646 // should be nothing left to do at this point.
1647 mService.mWindowManager.executeAppTransition();
1648 mNoAnimActivities.clear();
Dianne Hackborn84375872012-06-01 19:03:50 -07001649 ActivityOptions.abort(options);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001650 return false;
1651 }
1652
1653 // If we are sleeping, and there is no resumed activity, and the top
1654 // activity is paused, well that is the state we want.
1655 if ((mService.mSleeping || mService.mShuttingDown)
p13451dbad2872012-04-18 11:39:23 +09001656 && mLastPausedActivity == next
1657 && (next.state == ActivityState.PAUSED
1658 || next.state == ActivityState.STOPPED
1659 || next.state == ActivityState.STOPPING)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001660 // Make sure we have executed any pending transitions, since there
1661 // should be nothing left to do at this point.
1662 mService.mWindowManager.executeAppTransition();
1663 mNoAnimActivities.clear();
Dianne Hackborn84375872012-06-01 19:03:50 -07001664 ActivityOptions.abort(options);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001665 return false;
1666 }
Dianne Hackborn80a4af22012-08-27 19:18:31 -07001667
1668 // Make sure that the user who owns this activity is started. If not,
1669 // we will just leave it as is because someone should be bringing
1670 // another user's activities to the top of the stack.
1671 if (mService.mStartedUsers.get(next.userId) == null) {
1672 Slog.w(TAG, "Skipping resume of top activity " + next
1673 + ": user " + next.userId + " is stopped");
1674 return false;
1675 }
1676
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001677 // The activity may be waiting for stop, but that is no longer
1678 // appropriate for it.
1679 mStoppingActivities.remove(next);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001680 mGoingToSleepActivities.remove(next);
1681 next.sleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001682 mWaitingVisibleActivities.remove(next);
1683
Dianne Hackborn84375872012-06-01 19:03:50 -07001684 next.updateOptionsLocked(options);
1685
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001686 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
1687
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001688 // If we are currently pausing an activity, then don't do anything
1689 // until that is done.
1690 if (mPausingActivity != null) {
Dianne Hackborncc5a0552012-10-01 16:32:39 -07001691 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG,
1692 "Skip resume: pausing=" + mPausingActivity);
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08001693 return false;
1694 }
1695
Dianne Hackborn0dad3642010-09-09 21:25:35 -07001696 // Okay we are now going to start a switch, to 'next'. We may first
1697 // have to pause the current activity, but this is an important point
1698 // where we have decided to go to 'next' so keep track of that.
Dianne Hackborn034093a42010-09-20 22:24:38 -07001699 // XXX "App Redirected" dialog is getting too many false positives
1700 // at this point, so turn off for now.
1701 if (false) {
1702 if (mLastStartedActivity != null && !mLastStartedActivity.finishing) {
1703 long now = SystemClock.uptimeMillis();
1704 final boolean inTime = mLastStartedActivity.startTime != 0
1705 && (mLastStartedActivity.startTime + START_WARN_TIME) >= now;
1706 final int lastUid = mLastStartedActivity.info.applicationInfo.uid;
1707 final int nextUid = next.info.applicationInfo.uid;
1708 if (inTime && lastUid != nextUid
1709 && lastUid != next.launchedFromUid
1710 && mService.checkPermission(
1711 android.Manifest.permission.STOP_APP_SWITCHES,
1712 -1, next.launchedFromUid)
1713 != PackageManager.PERMISSION_GRANTED) {
1714 mService.showLaunchWarningLocked(mLastStartedActivity, next);
1715 } else {
1716 next.startTime = now;
1717 mLastStartedActivity = next;
1718 }
Dianne Hackborn0dad3642010-09-09 21:25:35 -07001719 } else {
Dianne Hackborn034093a42010-09-20 22:24:38 -07001720 next.startTime = SystemClock.uptimeMillis();
Dianne Hackborn0dad3642010-09-09 21:25:35 -07001721 mLastStartedActivity = next;
1722 }
Dianne Hackborn0dad3642010-09-09 21:25:35 -07001723 }
1724
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001725 // We need to start pausing the current activity so the top one
1726 // can be resumed...
1727 if (mResumedActivity != null) {
1728 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
Dianne Hackbornad9b32112012-09-17 15:35:01 -07001729 // At this point we want to put the upcoming activity's process
1730 // at the top of the LRU list, since we know we will be needing it
1731 // very soon and it would be a waste to let it get killed if it
1732 // happens to be sitting towards the end.
1733 if (next.app != null && next.app.thread != null) {
1734 // No reason to do full oom adj update here; we'll let that
1735 // happen whenever it needs to later.
Dianne Hackbornb12e1352012-09-26 11:39:20 -07001736 mService.updateLruProcessLocked(next.app, false);
Dianne Hackbornad9b32112012-09-17 15:35:01 -07001737 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001738 startPausingLocked(userLeaving, false);
1739 return true;
1740 }
1741
Christopher Tated3f175c2012-06-14 14:16:54 -07001742 // If the most recent activity was noHistory but was only stopped rather
1743 // than stopped+finished because the device went to sleep, we need to make
1744 // sure to finish it as we're making a new activity topmost.
1745 final ActivityRecord last = mLastPausedActivity;
1746 if (mService.mSleeping && last != null && !last.finishing) {
1747 if ((last.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
1748 || (last.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
1749 if (DEBUG_STATES) {
1750 Slog.d(TAG, "no-history finish of " + last + " on new resume");
1751 }
1752 requestFinishActivityLocked(last.appToken, Activity.RESULT_CANCELED, null,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07001753 "no-history", false);
Christopher Tated3f175c2012-06-14 14:16:54 -07001754 }
1755 }
1756
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001757 if (prev != null && prev != next) {
1758 if (!prev.waitingVisible && next != null && !next.nowVisible) {
1759 prev.waitingVisible = true;
1760 mWaitingVisibleActivities.add(prev);
1761 if (DEBUG_SWITCH) Slog.v(
1762 TAG, "Resuming top, waiting visible to hide: " + prev);
1763 } else {
1764 // The next activity is already visible, so hide the previous
1765 // activity's windows right now so we can show the new one ASAP.
1766 // We only do this if the previous is finishing, which should mean
1767 // it is on top of the one being resumed so hiding it quickly
1768 // is good. Otherwise, we want to do the normal route of allowing
1769 // the resumed activity to be shown so we can decide if the
1770 // previous should actually be hidden depending on whether the
1771 // new one is found to be full-screen or not.
1772 if (prev.finishing) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08001773 mService.mWindowManager.setAppVisibility(prev.appToken, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001774 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
1775 + prev + ", waitingVisible="
1776 + (prev != null ? prev.waitingVisible : null)
1777 + ", nowVisible=" + next.nowVisible);
1778 } else {
1779 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
1780 + prev + ", waitingVisible="
1781 + (prev != null ? prev.waitingVisible : null)
1782 + ", nowVisible=" + next.nowVisible);
1783 }
1784 }
1785 }
1786
Dianne Hackborne7f97212011-02-24 14:40:20 -08001787 // Launching this app's activity, make sure the app is no longer
1788 // considered stopped.
1789 try {
1790 AppGlobals.getPackageManager().setPackageStoppedState(
Amith Yamasani483f3b02012-03-13 16:08:00 -07001791 next.packageName, false, next.userId); /* TODO: Verify if correct userid */
Dianne Hackborne7f97212011-02-24 14:40:20 -08001792 } catch (RemoteException e1) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08001793 } catch (IllegalArgumentException e) {
1794 Slog.w(TAG, "Failed trying to unstop package "
1795 + next.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08001796 }
1797
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001798 // We are starting up the next activity, so tell the window manager
1799 // that the previous one will be hidden soon. This way it can know
1800 // to ignore it when computing the desired screen orientation.
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07001801 boolean noAnim = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001802 if (prev != null) {
1803 if (prev.finishing) {
1804 if (DEBUG_TRANSITION) Slog.v(TAG,
1805 "Prepare close transition: prev=" + prev);
1806 if (mNoAnimActivities.contains(prev)) {
Dianne Hackborn7da6ac32010-12-09 19:22:04 -08001807 mService.mWindowManager.prepareAppTransition(
Craig Mautner4b71aa12012-12-27 17:20:01 -08001808 AppTransition.TRANSIT_NONE, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001809 } else {
1810 mService.mWindowManager.prepareAppTransition(prev.task == next.task
Craig Mautner4b71aa12012-12-27 17:20:01 -08001811 ? AppTransition.TRANSIT_ACTIVITY_CLOSE
1812 : AppTransition.TRANSIT_TASK_CLOSE, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001813 }
Dianne Hackbornbe707852011-11-11 14:32:10 -08001814 mService.mWindowManager.setAppWillBeHidden(prev.appToken);
1815 mService.mWindowManager.setAppVisibility(prev.appToken, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001816 } else {
1817 if (DEBUG_TRANSITION) Slog.v(TAG,
1818 "Prepare open transition: prev=" + prev);
1819 if (mNoAnimActivities.contains(next)) {
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07001820 noAnim = true;
Dianne Hackborn7da6ac32010-12-09 19:22:04 -08001821 mService.mWindowManager.prepareAppTransition(
Craig Mautner4b71aa12012-12-27 17:20:01 -08001822 AppTransition.TRANSIT_NONE, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001823 } else {
1824 mService.mWindowManager.prepareAppTransition(prev.task == next.task
Craig Mautner4b71aa12012-12-27 17:20:01 -08001825 ? AppTransition.TRANSIT_ACTIVITY_OPEN
1826 : AppTransition.TRANSIT_TASK_OPEN, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001827 }
1828 }
1829 if (false) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08001830 mService.mWindowManager.setAppWillBeHidden(prev.appToken);
1831 mService.mWindowManager.setAppVisibility(prev.appToken, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001832 }
1833 } else if (mHistory.size() > 1) {
1834 if (DEBUG_TRANSITION) Slog.v(TAG,
1835 "Prepare open transition: no previous");
1836 if (mNoAnimActivities.contains(next)) {
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07001837 noAnim = true;
Dianne Hackborn7da6ac32010-12-09 19:22:04 -08001838 mService.mWindowManager.prepareAppTransition(
Craig Mautner4b71aa12012-12-27 17:20:01 -08001839 AppTransition.TRANSIT_NONE, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001840 } else {
Dianne Hackborn7da6ac32010-12-09 19:22:04 -08001841 mService.mWindowManager.prepareAppTransition(
Craig Mautner4b71aa12012-12-27 17:20:01 -08001842 AppTransition.TRANSIT_ACTIVITY_OPEN, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001843 }
1844 }
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07001845 if (!noAnim) {
1846 next.applyOptionsLocked();
1847 } else {
1848 next.clearOptionsLocked();
1849 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001850
1851 if (next.app != null && next.app.thread != null) {
1852 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
1853
1854 // This activity is now becoming visible.
Dianne Hackbornbe707852011-11-11 14:32:10 -08001855 mService.mWindowManager.setAppVisibility(next.appToken, true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001856
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07001857 // schedule launch ticks to collect information about slow apps.
1858 next.startLaunchTickingLocked();
1859
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001860 ActivityRecord lastResumedActivity = mResumedActivity;
1861 ActivityState lastState = next.state;
1862
1863 mService.updateCpuStats();
1864
Dianne Hackbornce86ba82011-07-13 19:33:41 -07001865 if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + next + " (in existing)");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001866 next.state = ActivityState.RESUMED;
1867 mResumedActivity = next;
1868 next.task.touchActiveTime();
Dianne Hackborn88819b22010-12-21 18:18:02 -08001869 if (mMainStack) {
1870 mService.addRecentTaskLocked(next.task);
1871 }
Dianne Hackbornb12e1352012-09-26 11:39:20 -07001872 mService.updateLruProcessLocked(next.app, true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001873 updateLRUListLocked(next);
1874
1875 // Have the window manager re-evaluate the orientation of
1876 // the screen based on the new activity order.
1877 boolean updated = false;
1878 if (mMainStack) {
1879 synchronized (mService) {
1880 Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
1881 mService.mConfiguration,
Dianne Hackbornbe707852011-11-11 14:32:10 -08001882 next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001883 if (config != null) {
1884 next.frozenBeforeDestroy = true;
1885 }
Dianne Hackborn813075a62011-11-14 17:45:19 -08001886 updated = mService.updateConfigurationLocked(config, next, false, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001887 }
1888 }
1889 if (!updated) {
1890 // The configuration update wasn't able to keep the existing
1891 // instance of the activity, and instead started a new one.
1892 // We should be all done, but let's just make sure our activity
1893 // is still at the top and schedule another run if something
1894 // weird happened.
1895 ActivityRecord nextNext = topRunningActivityLocked(null);
1896 if (DEBUG_SWITCH) Slog.i(TAG,
1897 "Activity config changed during resume: " + next
1898 + ", new next: " + nextNext);
1899 if (nextNext != next) {
1900 // Do over!
1901 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
1902 }
1903 if (mMainStack) {
1904 mService.setFocusedActivityLocked(next);
1905 }
1906 ensureActivitiesVisibleLocked(null, 0);
1907 mService.mWindowManager.executeAppTransition();
1908 mNoAnimActivities.clear();
1909 return true;
1910 }
1911
1912 try {
1913 // Deliver all pending results.
Craig Mautner05d6272ba2013-02-11 09:39:27 -08001914 ArrayList<ResultInfo> a = next.results;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001915 if (a != null) {
1916 final int N = a.size();
1917 if (!next.finishing && N > 0) {
1918 if (DEBUG_RESULTS) Slog.v(
1919 TAG, "Delivering results to " + next
1920 + ": " + a);
Dianne Hackbornbe707852011-11-11 14:32:10 -08001921 next.app.thread.scheduleSendResult(next.appToken, a);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001922 }
1923 }
1924
1925 if (next.newIntents != null) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08001926 next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001927 }
1928
1929 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
Dianne Hackbornb12e1352012-09-26 11:39:20 -07001930 next.userId, System.identityHashCode(next),
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001931 next.task.taskId, next.shortComponentName);
1932
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001933 next.sleeping = false;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001934 showAskCompatModeDialogLocked(next);
Dianne Hackborn905577f2011-09-07 18:31:28 -07001935 next.app.pendingUiClean = true;
Dianne Hackbornbe707852011-11-11 14:32:10 -08001936 next.app.thread.scheduleResumeActivity(next.appToken,
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001937 mService.isNextTransitionForward());
1938
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08001939 checkReadyForSleepLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001940
1941 } catch (Exception e) {
1942 // Whoops, need to restart this activity!
Dianne Hackbornce86ba82011-07-13 19:33:41 -07001943 if (DEBUG_STATES) Slog.v(TAG, "Resume failed; resetting state to "
1944 + lastState + ": " + next);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001945 next.state = lastState;
1946 mResumedActivity = lastResumedActivity;
1947 Slog.i(TAG, "Restarting because process died: " + next);
1948 if (!next.hasBeenLaunched) {
1949 next.hasBeenLaunched = true;
1950 } else {
1951 if (SHOW_APP_STARTING_PREVIEW && mMainStack) {
1952 mService.mWindowManager.setAppStartingWindow(
Dianne Hackbornbe707852011-11-11 14:32:10 -08001953 next.appToken, next.packageName, next.theme,
Dianne Hackborn2f0b1752011-05-31 17:59:49 -07001954 mService.compatibilityInfoForPackageLocked(
1955 next.info.applicationInfo),
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001956 next.nonLocalizedLabel,
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001957 next.labelRes, next.icon, next.windowFlags,
1958 null, true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001959 }
1960 }
1961 startSpecificActivityLocked(next, true, false);
1962 return true;
1963 }
1964
1965 // From this point on, if something goes wrong there is no way
1966 // to recover the activity.
1967 try {
1968 next.visible = true;
1969 completeResumeLocked(next);
1970 } catch (Exception e) {
1971 // If any exception gets thrown, toss away this
1972 // activity and try the next one.
1973 Slog.w(TAG, "Exception thrown during resume of " + next, e);
Dianne Hackbornbe707852011-11-11 14:32:10 -08001974 requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07001975 "resume-exception", true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001976 return true;
1977 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001978 next.stopped = false;
1979
1980 } else {
1981 // Whoops, need to restart this activity!
1982 if (!next.hasBeenLaunched) {
1983 next.hasBeenLaunched = true;
1984 } else {
1985 if (SHOW_APP_STARTING_PREVIEW) {
1986 mService.mWindowManager.setAppStartingWindow(
Dianne Hackbornbe707852011-11-11 14:32:10 -08001987 next.appToken, next.packageName, next.theme,
Dianne Hackborn2f0b1752011-05-31 17:59:49 -07001988 mService.compatibilityInfoForPackageLocked(
1989 next.info.applicationInfo),
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001990 next.nonLocalizedLabel,
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001991 next.labelRes, next.icon, next.windowFlags,
1992 null, true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001993 }
1994 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
1995 }
1996 startSpecificActivityLocked(next, true, true);
1997 }
1998
1999 return true;
2000 }
2001
Craig Mautner11bf9a52013-02-19 14:08:51 -08002002 /** Temporary until startActivityLocked is rewritten for tasks. */
2003 private int convertAddPos(int addPos) {
Craig Mautnerd44711d2013-02-23 11:24:36 -08002004 final ActivityRecord r = mHistory.get(addPos);
2005 return r.task.mActivities.indexOf(r);
Craig Mautner11bf9a52013-02-19 14:08:51 -08002006 }
2007
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002008 private final void startActivityLocked(ActivityRecord r, boolean newTask,
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07002009 boolean doResume, boolean keepCurTransition, Bundle options) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08002010 mLastHistoryModifier = "startActivityLocked";
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002011 final int NH = mHistory.size();
2012
2013 int addPos = -1;
2014
2015 if (!newTask) {
2016 // If starting in an existing task, find where that is...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002017 boolean startIt = true;
2018 for (int i = NH-1; i >= 0; i--) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002019 ActivityRecord p = mHistory.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002020 if (p.finishing) {
2021 continue;
2022 }
2023 if (p.task == r.task) {
2024 // Here it is! Now, if this is not yet visible to the
2025 // user, then just add it without starting; it will
2026 // get started when the user navigates back to it.
2027 addPos = i+1;
2028 if (!startIt) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07002029 if (DEBUG_ADD_REMOVE) {
2030 RuntimeException here = new RuntimeException("here");
2031 here.fillInStackTrace();
2032 Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos,
2033 here);
2034 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002035 r.task.addActivityToTop(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002036 mHistory.add(addPos, r);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002037 r.putInHistory();
Craig Mautner11bf9a52013-02-19 14:08:51 -08002038 mService.mWindowManager.addAppToken(convertAddPos(addPos), r.appToken,
2039 r.task.taskId, r.info.screenOrientation, r.fullscreen,
Craig Mautner5962b122012-10-05 14:45:52 -07002040 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002041 if (VALIDATE_TOKENS) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08002042 validateAppTokensLocked();
Craig Mautner11bf9a52013-02-19 14:08:51 -08002043 verifyActivityRecords(true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002044 }
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07002045 ActivityOptions.abort(options);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002046 return;
2047 }
2048 break;
2049 }
2050 if (p.fullscreen) {
2051 startIt = false;
2052 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002053 }
2054 }
2055
2056 // Place a new activity at top of stack, so it is next to interact
2057 // with the user.
2058 if (addPos < 0) {
Dianne Hackborn0dad3642010-09-09 21:25:35 -07002059 addPos = NH;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002060 }
2061
2062 // If we are not placing the new activity frontmost, we do not want
2063 // to deliver the onUserLeaving callback to the actual frontmost
2064 // activity
2065 if (addPos < NH) {
2066 mUserLeaving = false;
2067 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
2068 }
2069
2070 // Slot the activity into the history stack and proceed
Craig Mautner56f52db2013-02-25 10:03:01 -08002071 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos,
2072 new RuntimeException("here").fillInStackTrace());
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002073 r.task.addActivityToTop(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002074 mHistory.add(addPos, r);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002075 r.putInHistory();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002076 r.frontOfTask = newTask;
Craig Mautner11bf9a52013-02-19 14:08:51 -08002077 if (VALIDATE_TASK_REPLACE) {
2078 if (verifyActivityRecords(false)) {
2079 Slog.w(TAG, "startActivityLocked: addPos=" + addPos);
2080 }
2081 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002082 if (NH > 0) {
2083 // We want to show the starting preview window if we are
2084 // switching to a new task, or the next activity's process is
2085 // not currently running.
2086 boolean showStartingIcon = newTask;
2087 ProcessRecord proc = r.app;
2088 if (proc == null) {
2089 proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2090 }
2091 if (proc == null || proc.thread == null) {
2092 showStartingIcon = true;
2093 }
2094 if (DEBUG_TRANSITION) Slog.v(TAG,
2095 "Prepare open transition: starting " + r);
2096 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
Dianne Hackborn7da6ac32010-12-09 19:22:04 -08002097 mService.mWindowManager.prepareAppTransition(
Craig Mautner4b71aa12012-12-27 17:20:01 -08002098 AppTransition.TRANSIT_NONE, keepCurTransition);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002099 mNoAnimActivities.add(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002100 } else {
2101 mService.mWindowManager.prepareAppTransition(newTask
Craig Mautner4b71aa12012-12-27 17:20:01 -08002102 ? AppTransition.TRANSIT_TASK_OPEN
2103 : AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002104 mNoAnimActivities.remove(r);
2105 }
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07002106 r.updateOptionsLocked(options);
Craig Mautner11bf9a52013-02-19 14:08:51 -08002107 mService.mWindowManager.addAppToken(convertAddPos(addPos),
2108 r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen,
Craig Mautner5962b122012-10-05 14:45:52 -07002109 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002110 boolean doShow = true;
2111 if (newTask) {
2112 // Even though this activity is starting fresh, we still need
2113 // to reset it to make sure we apply affinities to move any
2114 // existing activities from other tasks in to it.
2115 // If the caller has requested that the target task be
2116 // reset, then do so.
2117 if ((r.intent.getFlags()
2118 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2119 resetTaskIfNeededLocked(r, r);
2120 doShow = topRunningNonDelayedActivityLocked(null) == r;
2121 }
2122 }
2123 if (SHOW_APP_STARTING_PREVIEW && doShow) {
2124 // Figure out if we are transitioning from another activity that is
2125 // "has the same starting icon" as the next one. This allows the
2126 // window manager to keep the previous window it had previously
2127 // created, if it still had one.
2128 ActivityRecord prev = mResumedActivity;
2129 if (prev != null) {
2130 // We don't want to reuse the previous starting preview if:
2131 // (1) The current activity is in a different task.
2132 if (prev.task != r.task) prev = null;
2133 // (2) The current activity is already displayed.
2134 else if (prev.nowVisible) prev = null;
2135 }
2136 mService.mWindowManager.setAppStartingWindow(
Dianne Hackbornbe707852011-11-11 14:32:10 -08002137 r.appToken, r.packageName, r.theme,
Dianne Hackborn2f0b1752011-05-31 17:59:49 -07002138 mService.compatibilityInfoForPackageLocked(
2139 r.info.applicationInfo), r.nonLocalizedLabel,
Dianne Hackbornbe707852011-11-11 14:32:10 -08002140 r.labelRes, r.icon, r.windowFlags,
2141 prev != null ? prev.appToken : null, showStartingIcon);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002142 }
2143 } else {
2144 // If this is the first activity, don't do any fancy animations,
2145 // because there is nothing for it to animate on top of.
Craig Mautner11bf9a52013-02-19 14:08:51 -08002146 mService.mWindowManager.addAppToken(convertAddPos(addPos), r.appToken, r.task.taskId,
Craig Mautner5962b122012-10-05 14:45:52 -07002147 r.info.screenOrientation, r.fullscreen,
2148 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07002149 ActivityOptions.abort(options);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002150 }
2151 if (VALIDATE_TOKENS) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08002152 validateAppTokensLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002153 }
2154
2155 if (doResume) {
2156 resumeTopActivityLocked(null);
2157 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002158 if (VALIDATE_TASK_REPLACE) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08002159 if (verifyActivityRecords(true)) {
2160 Slog.w(TAG, "startActivityLocked: addPos=" + addPos);
2161 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002162 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002163 }
2164
Dianne Hackbornbe707852011-11-11 14:32:10 -08002165 final void validateAppTokensLocked() {
2166 mValidateAppTokens.clear();
2167 mValidateAppTokens.ensureCapacity(mHistory.size());
Craig Mautnerb1fd65c02013-02-05 13:34:57 -08002168 int taskId = Integer.MIN_VALUE;
2169 TaskGroup task = null;
Dianne Hackbornbe707852011-11-11 14:32:10 -08002170 for (int i=0; i<mHistory.size(); i++) {
Craig Mautnerb1fd65c02013-02-05 13:34:57 -08002171 final ActivityRecord r = mHistory.get(i);
2172 if (taskId != r.task.taskId) {
2173 taskId = r.task.taskId;
2174 task = new TaskGroup();
2175 task.taskId = taskId;
2176 mValidateAppTokens.add(task);
2177 }
2178 task.tokens.add(r.appToken);
Dianne Hackbornbe707852011-11-11 14:32:10 -08002179 }
2180 mService.mWindowManager.validateAppTokens(mValidateAppTokens);
2181 }
2182
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002183 /**
2184 * Perform a reset of the given task, if needed as part of launching it.
2185 * Returns the new HistoryRecord at the top of the task.
2186 */
Craig Mautnere3a74d52013-02-22 14:14:58 -08002187/* private final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002188 ActivityRecord newActivity) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08002189 mLastHistoryModifier = "resetTaskIfNeededLocked";
2190
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002191 boolean forceReset = (newActivity.info.flags
2192 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002193 if (ACTIVITY_INACTIVE_RESET_TIME > 0
2194 && taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002195 if ((newActivity.info.flags
2196 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
2197 forceReset = true;
2198 }
2199 }
2200
2201 final TaskRecord task = taskTop.task;
2202
2203 // We are going to move through the history list so that we can look
2204 // at each activity 'target' with 'below' either the interesting
2205 // activity immediately below it in the stack or null.
2206 ActivityRecord target = null;
2207 int targetI = 0;
2208 int taskTopI = -1;
2209 int replyChainEnd = -1;
2210 int lastReparentPos = -1;
Dianne Hackborn9622ca42012-10-23 18:56:33 -07002211 ActivityOptions topOptions = null;
2212 boolean canMoveOptions = true;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002213 for (int i=mHistory.size()-1; i>=-1; i--) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002214 ActivityRecord below = i >= 0 ? mHistory.get(i) : null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002215
2216 if (below != null && below.finishing) {
2217 continue;
2218 }
Amith Yamasani04e0d262012-02-14 11:50:53 -08002219 // Don't check any lower in the stack if we're crossing a user boundary.
2220 if (below != null && below.userId != taskTop.userId) {
2221 break;
2222 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002223 if (target == null) {
2224 target = below;
2225 targetI = i;
2226 // If we were in the middle of a reply chain before this
2227 // task, it doesn't appear like the root of the chain wants
2228 // anything interesting, so drop it.
2229 replyChainEnd = -1;
2230 continue;
2231 }
2232
2233 final int flags = target.info.flags;
2234
2235 final boolean finishOnTaskLaunch =
2236 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
2237 final boolean allowTaskReparenting =
2238 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
2239
2240 if (target.task == task) {
2241 // We are inside of the task being reset... we'll either
2242 // finish this activity, push it out for another task,
2243 // or leave it as-is. We only do this
2244 // for activities that are not the root of the task (since
2245 // if we finish the root, we may no longer have the task!).
2246 if (taskTopI < 0) {
2247 taskTopI = targetI;
2248 }
2249 if (below != null && below.task == task) {
2250 final boolean clearWhenTaskReset =
2251 (target.intent.getFlags()
2252 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
2253 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
2254 // If this activity is sending a reply to a previous
2255 // activity, we can't do anything with it now until
2256 // we reach the start of the reply chain.
2257 // XXX note that we are assuming the result is always
2258 // to the previous activity, which is almost always
2259 // the case but we really shouldn't count on.
2260 if (replyChainEnd < 0) {
2261 replyChainEnd = targetI;
2262 }
2263 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
2264 && target.taskAffinity != null
2265 && !target.taskAffinity.equals(task.affinity)) {
2266 // If this activity has an affinity for another
2267 // task, then we need to move it out of here. We will
2268 // move it as far out of the way as possible, to the
2269 // bottom of the activity stack. This also keeps it
2270 // correctly ordered with any activities we previously
2271 // moved.
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002272 ActivityRecord p = mHistory.get(0);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002273 if (target.taskAffinity != null
2274 && target.taskAffinity.equals(p.task.affinity)) {
2275 // If the activity currently at the bottom has the
2276 // same task affinity as the one we are moving,
2277 // then merge it into the same task.
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002278 target.setTask(p.task, p.thumbHolder, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002279 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
2280 + " out to bottom task " + p.task);
2281 } else {
2282 mService.mCurTask++;
2283 if (mService.mCurTask <= 0) {
2284 mService.mCurTask = 1;
2285 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002286 target.setTask(createTaskRecord(mService.mCurTask, target.info, null,
2287 false), null, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002288 target.task.affinityIntent = target.intent;
2289 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
2290 + " out to new task " + target.task);
2291 }
Craig Mautner926f3832013-02-13 11:56:07 -08002292 mService.mWindowManager.setAppGroupId(target.appToken, target.task.taskId);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002293 if (replyChainEnd < 0) {
2294 replyChainEnd = targetI;
2295 }
2296 int dstPos = 0;
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002297 ThumbnailHolder curThumbHolder = target.thumbHolder;
Dianne Hackborn9622ca42012-10-23 18:56:33 -07002298 boolean gotOptions = !canMoveOptions;
Craig Mautner30e2d722013-02-12 11:30:16 -08002299 final int taskId = target.task.taskId;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002300 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002301 p = mHistory.get(srcPos);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002302 if (p.finishing) {
2303 continue;
2304 }
2305 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
2306 + " out to target's task " + target.task);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002307 p.setTask(target.task, curThumbHolder, false);
2308 curThumbHolder = p.thumbHolder;
Dianne Hackborn9622ca42012-10-23 18:56:33 -07002309 canMoveOptions = false;
2310 if (!gotOptions && topOptions == null) {
2311 topOptions = p.takeOptionsLocked();
2312 if (topOptions != null) {
2313 gotOptions = true;
2314 }
2315 }
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07002316 if (DEBUG_ADD_REMOVE) {
2317 RuntimeException here = new RuntimeException("here");
2318 here.fillInStackTrace();
2319 Slog.i(TAG, "Removing and adding activity " + p + " to stack at "
2320 + dstPos, here);
2321 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002322 mHistory.remove(srcPos);
2323 mHistory.add(dstPos, p);
Craig Mautner30e2d722013-02-12 11:30:16 -08002324 mService.mWindowManager.setAppGroupId(p.appToken, taskId);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002325 dstPos++;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002326 i++;
2327 }
Craig Mautner11bf9a52013-02-19 14:08:51 -08002328 rebuildTaskHistory();
Craig Mautner30e2d722013-02-12 11:30:16 -08002329 mService.mWindowManager.moveTaskToBottom(taskId);
2330 if (VALIDATE_TOKENS) {
2331 validateAppTokensLocked();
2332 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002333 if (taskTop == p) {
2334 taskTop = below;
2335 }
2336 if (taskTopI == replyChainEnd) {
2337 taskTopI = -1;
2338 }
2339 replyChainEnd = -1;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002340 } else if (forceReset || finishOnTaskLaunch
2341 || clearWhenTaskReset) {
2342 // If the activity should just be removed -- either
2343 // because it asks for it, or the task should be
2344 // cleared -- then finish it and anything that is
2345 // part of its reply chain.
2346 if (clearWhenTaskReset) {
2347 // In this case, we want to finish this activity
2348 // and everything above it, so be sneaky and pretend
2349 // like these are all in the reply chain.
2350 replyChainEnd = targetI+1;
2351 while (replyChainEnd < mHistory.size() &&
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002352 (mHistory.get(replyChainEnd)).task == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002353 replyChainEnd++;
2354 }
2355 replyChainEnd--;
2356 } else if (replyChainEnd < 0) {
2357 replyChainEnd = targetI;
2358 }
2359 ActivityRecord p = null;
Dianne Hackborn9622ca42012-10-23 18:56:33 -07002360 boolean gotOptions = !canMoveOptions;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002361 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002362 p = mHistory.get(srcPos);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002363 if (p.finishing) {
2364 continue;
2365 }
Dianne Hackborn9622ca42012-10-23 18:56:33 -07002366 canMoveOptions = false;
2367 if (!gotOptions && topOptions == null) {
2368 topOptions = p.takeOptionsLocked();
2369 if (topOptions != null) {
2370 gotOptions = true;
2371 }
2372 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002373 if (finishActivityLocked(p, srcPos,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07002374 Activity.RESULT_CANCELED, null, "reset", false)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002375 replyChainEnd--;
2376 srcPos--;
2377 }
2378 }
2379 if (taskTop == p) {
2380 taskTop = below;
2381 }
2382 if (taskTopI == replyChainEnd) {
2383 taskTopI = -1;
2384 }
2385 replyChainEnd = -1;
2386 } else {
2387 // If we were in the middle of a chain, well the
2388 // activity that started it all doesn't want anything
2389 // special, so leave it all as-is.
2390 replyChainEnd = -1;
2391 }
2392 } else {
2393 // Reached the bottom of the task -- any reply chain
2394 // should be left as-is.
2395 replyChainEnd = -1;
2396 }
Dianne Hackbornae0a0a82011-12-07 14:03:01 -08002397
2398 } else if (target.resultTo != null && (below == null
2399 || below.task == target.task)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002400 // If this activity is sending a reply to a previous
2401 // activity, we can't do anything with it now until
2402 // we reach the start of the reply chain.
2403 // XXX note that we are assuming the result is always
2404 // to the previous activity, which is almost always
2405 // the case but we really shouldn't count on.
2406 if (replyChainEnd < 0) {
2407 replyChainEnd = targetI;
2408 }
2409
2410 } else if (taskTopI >= 0 && allowTaskReparenting
2411 && task.affinity != null
2412 && task.affinity.equals(target.taskAffinity)) {
2413 // We are inside of another task... if this activity has
2414 // an affinity for our task, then either remove it if we are
2415 // clearing or move it over to our task. Note that
2416 // we currently punt on the case where we are resetting a
2417 // task that is not at the top but who has activities above
2418 // with an affinity to it... this is really not a normal
2419 // case, and we will need to later pull that task to the front
2420 // and usually at that point we will do the reset and pick
2421 // up those remaining activities. (This only happens if
2422 // someone starts an activity in a new task from an activity
2423 // in a task that is not currently on top.)
2424 if (forceReset || finishOnTaskLaunch) {
2425 if (replyChainEnd < 0) {
2426 replyChainEnd = targetI;
2427 }
2428 ActivityRecord p = null;
Dianne Hackbornae0a0a82011-12-07 14:03:01 -08002429 if (DEBUG_TASKS) Slog.v(TAG, "Finishing task at index "
2430 + targetI + " to " + replyChainEnd);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002431 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002432 p = mHistory.get(srcPos);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002433 if (p.finishing) {
2434 continue;
2435 }
2436 if (finishActivityLocked(p, srcPos,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07002437 Activity.RESULT_CANCELED, null, "reset", false)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002438 taskTopI--;
2439 lastReparentPos--;
2440 replyChainEnd--;
2441 srcPos--;
2442 }
2443 }
2444 replyChainEnd = -1;
2445 } else {
2446 if (replyChainEnd < 0) {
2447 replyChainEnd = targetI;
2448 }
Craig Mautner30e2d722013-02-12 11:30:16 -08002449 final int taskId = task.taskId;
Dianne Hackbornae0a0a82011-12-07 14:03:01 -08002450 if (DEBUG_TASKS) Slog.v(TAG, "Reparenting task at index "
2451 + targetI + " to " + replyChainEnd);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002452 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002453 ActivityRecord p = mHistory.get(srcPos);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002454 if (p.finishing) {
2455 continue;
2456 }
2457 if (lastReparentPos < 0) {
2458 lastReparentPos = taskTopI;
2459 taskTop = p;
2460 } else {
2461 lastReparentPos--;
2462 }
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07002463 if (DEBUG_ADD_REMOVE) {
2464 RuntimeException here = new RuntimeException("here");
2465 here.fillInStackTrace();
2466 Slog.i(TAG, "Removing and adding activity " + p + " to stack at "
2467 + lastReparentPos, here);
2468 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002469 mHistory.remove(srcPos);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002470 p.setTask(task, null, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002471 mHistory.add(lastReparentPos, p);
2472 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
Dianne Hackbornae0a0a82011-12-07 14:03:01 -08002473 + " from " + srcPos + " to " + lastReparentPos
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002474 + " in to resetting task " + task);
Craig Mautner30e2d722013-02-12 11:30:16 -08002475 mService.mWindowManager.setAppGroupId(p.appToken, taskId);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002476 }
Craig Mautner11bf9a52013-02-19 14:08:51 -08002477 rebuildTaskHistory();
Craig Mautner05d6272ba2013-02-11 09:39:27 -08002478 // TODO: This is wrong because it doesn't take lastReparentPos into account.
Craig Mautner30e2d722013-02-12 11:30:16 -08002479 mService.mWindowManager.moveTaskToTop(taskId);
2480 if (VALIDATE_TOKENS) {
2481 validateAppTokensLocked();
2482 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002483 replyChainEnd = -1;
2484
2485 // Now we've moved it in to place... but what if this is
2486 // a singleTop activity and we have put it on top of another
2487 // instance of the same activity? Then we drop the instance
2488 // below so it remains singleTop.
2489 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
2490 for (int j=lastReparentPos-1; j>=0; j--) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002491 ActivityRecord p = mHistory.get(j);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002492 if (p.finishing) {
2493 continue;
2494 }
2495 if (p.intent.getComponent().equals(target.intent.getComponent())) {
2496 if (finishActivityLocked(p, j,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07002497 Activity.RESULT_CANCELED, null, "replace", false)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002498 taskTopI--;
2499 lastReparentPos--;
2500 }
2501 }
2502 }
2503 }
2504 }
Dianne Hackbornae0a0a82011-12-07 14:03:01 -08002505
2506 } else if (below != null && below.task != target.task) {
2507 // We hit the botton of a task; the reply chain can't
2508 // pass through it.
2509 replyChainEnd = -1;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002510 }
2511
2512 target = below;
2513 targetI = i;
2514 }
Dianne Hackborn9622ca42012-10-23 18:56:33 -07002515
2516 if (topOptions != null) {
2517 // If we got some ActivityOptions from an activity on top that
2518 // was removed from the task, propagate them to the new real top.
2519 if (taskTop != null) {
2520 taskTop.updateOptionsLocked(topOptions);
2521 } else {
2522 topOptions.abort();
2523 }
2524 }
2525
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002526 if (VALIDATE_TASK_REPLACE) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08002527 verifyActivityRecords(true);
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002528 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002529 return taskTop;
2530 }
Craig Mautnere3a74d52013-02-22 14:14:58 -08002531*/
2532 /**
2533 * Helper method for #resetTaskIfNeededLocked.
2534 * We are inside of the task being reset... we'll either finish this activity, push it out
2535 * for another task, or leave it as-is.
2536 * @param task The task containing the Activity (taskTop) that might be reset.
2537 * @param forceReset
2538 * @return An ActivityOptions that needs to be processed.
2539 */
2540 private final ActivityOptions resetTargetTaskIfNeededLocked(TaskRecord task,
2541 boolean forceReset) {
2542 ActivityOptions topOptions = null;
2543
2544 int replyChainEnd = -1;
2545 boolean canMoveOptions = true;
2546
2547 // We only do this for activities that are not the root of the task (since if we finish
2548 // the root, we may no longer have the task!).
2549 final ArrayList<ActivityRecord> activities = task.mActivities;
2550 final int numActivities = activities.size();
2551 for (int i = numActivities - 1; i > 0; --i ) {
2552 ActivityRecord target = activities.get(i);
2553
2554 final int flags = target.info.flags;
2555 final boolean finishOnTaskLaunch =
2556 (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
2557 final boolean allowTaskReparenting =
2558 (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
2559 final boolean clearWhenTaskReset =
2560 (target.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
2561
2562 if (!finishOnTaskLaunch
2563 && !clearWhenTaskReset
2564 && target.resultTo != null) {
2565 // If this activity is sending a reply to a previous
2566 // activity, we can't do anything with it now until
2567 // we reach the start of the reply chain.
2568 // XXX note that we are assuming the result is always
2569 // to the previous activity, which is almost always
2570 // the case but we really shouldn't count on.
2571 if (replyChainEnd < 0) {
2572 replyChainEnd = i;
2573 }
2574 } else if (!finishOnTaskLaunch
2575 && !clearWhenTaskReset
2576 && allowTaskReparenting
2577 && target.taskAffinity != null
2578 && !target.taskAffinity.equals(task.affinity)) {
2579 // If this activity has an affinity for another
2580 // task, then we need to move it out of here. We will
2581 // move it as far out of the way as possible, to the
2582 // bottom of the activity stack. This also keeps it
2583 // correctly ordered with any activities we previously
2584 // moved.
2585 TaskRecord bottomTask = mTaskHistory.get(0);
2586 ActivityRecord p = bottomTask.mActivities.get(0);
2587 if (target.taskAffinity != null
2588 && target.taskAffinity.equals(p.task.affinity)) {
2589 // If the activity currently at the bottom has the
2590 // same task affinity as the one we are moving,
2591 // then merge it into the same task.
2592 if (VALIDATE_TASK_REPLACE) Slog.w(TAG,
2593 "resetTaskFoundIntended: would reparenting " + target + " to bottom " + p.task);
2594 target.setTask(p.task, p.thumbHolder, false);
2595 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
2596 + " out to bottom task " + p.task);
2597 } else {
2598 do {
2599 mService.mCurTask++;
2600 if (mService.mCurTask <= 0) {
2601 mService.mCurTask = 1;
2602 }
2603 } while (mTaskIdToTaskRecord.get(mService.mCurTask) != null);
2604 target.setTask(createTaskRecord(mService.mCurTask, target.info, null, false),
2605 null, false);
2606 target.task.affinityIntent = target.intent;
2607 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
2608 + " out to new task " + target.task);
2609 }
2610
2611 final TaskRecord targetTask = target.task;
2612 final int targetTaskId = targetTask.taskId;
2613 mService.mWindowManager.setAppGroupId(target.appToken, targetTaskId);
2614
2615 ThumbnailHolder curThumbHolder = target.thumbHolder;
2616 boolean gotOptions = !canMoveOptions;
2617
2618 final int start = replyChainEnd < 0 ? i : replyChainEnd;
2619 for (int srcPos = start; srcPos >= i; --srcPos) {
2620 p = activities.get(srcPos);
2621 if (p.finishing) {
2622 continue;
2623 }
2624
2625 curThumbHolder = p.thumbHolder;
2626 canMoveOptions = false;
2627 if (!gotOptions && topOptions == null) {
2628 topOptions = p.takeOptionsLocked();
2629 if (topOptions != null) {
2630 gotOptions = true;
2631 }
2632 }
2633 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing activity " + p + " from task="
2634 + task + " adding to task=" + targetTask,
2635 new RuntimeException("here").fillInStackTrace());
2636 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
2637 + " out to target's task " + target.task);
2638 p.setTask(targetTask, curThumbHolder, false);
2639 targetTask.addActivityAtBottom(p);
2640 mHistory.remove(p);
2641 mHistory.add(0, p);
2642 mService.mWindowManager.setAppGroupId(p.appToken, targetTaskId);
2643 }
2644
2645 mService.mWindowManager.moveTaskToBottom(targetTaskId);
2646 if (VALIDATE_TOKENS) {
2647 validateAppTokensLocked();
2648 }
2649
2650 replyChainEnd = -1;
2651 } else if (forceReset || finishOnTaskLaunch || clearWhenTaskReset) {
2652 // If the activity should just be removed -- either
2653 // because it asks for it, or the task should be
2654 // cleared -- then finish it and anything that is
2655 // part of its reply chain.
2656 int end;
2657 if (clearWhenTaskReset) {
2658 // In this case, we want to finish this activity
2659 // and everything above it, so be sneaky and pretend
2660 // like these are all in the reply chain.
2661 end = numActivities - 1;
2662 } else if (replyChainEnd < 0) {
2663 end = i;
2664 } else {
2665 end = replyChainEnd;
2666 }
2667 ActivityRecord p = null;
2668 boolean gotOptions = !canMoveOptions;
2669 for (int srcPos = i; srcPos <= end; srcPos++) {
2670 p = activities.get(srcPos);
2671 if (p.finishing) {
2672 continue;
2673 }
2674 canMoveOptions = false;
2675 if (!gotOptions && topOptions == null) {
2676 topOptions = p.takeOptionsLocked();
2677 if (topOptions != null) {
2678 gotOptions = true;
2679 }
2680 }
2681 if (DEBUG_TASKS || VALIDATE_TASK_REPLACE) Slog.w(TAG,
2682 "resetTaskIntendedTask: would call finishActivity on " + p);
Craig Mautnerd44711d2013-02-23 11:24:36 -08002683 if (finishActivityLocked(p, Activity.RESULT_CANCELED, null, "reset", false)) {
Craig Mautnere3a74d52013-02-22 14:14:58 -08002684 end--;
2685 srcPos--;
2686 }
2687 }
2688 replyChainEnd = -1;
2689 } else {
2690 // If we were in the middle of a chain, well the
2691 // activity that started it all doesn't want anything
2692 // special, so leave it all as-is.
2693 replyChainEnd = -1;
2694 }
2695 }
2696
2697 return topOptions;
2698 }
2699
2700 /**
2701 * Helper method for #resetTaskIfNeededLocked. Processes all of the activities in a given
2702 * TaskRecord looking for an affinity with the task of resetTaskIfNeededLocked.taskTop.
2703 * @param affinityTask The task we are looking for an affinity to.
2704 * @param task Task that resetTaskIfNeededLocked.taskTop belongs to.
2705 * @param topTaskIsHigher True if #task has already been processed by resetTaskIfNeededLocked.
2706 * @param forceReset Flag passed in to resetTaskIfNeededLocked.
2707 */
2708 private final void resetAffinityTaskIfNeededLocked(TaskRecord affinityTask, TaskRecord task,
2709 boolean topTaskIsHigher, boolean forceReset
2710 , ActivityRecord taskTop
2711 ) {
2712 int replyChainEnd = -1;
2713 final int taskId = task.taskId;
2714 final String taskAffinity = task.affinity;
2715
2716 final ArrayList<ActivityRecord> activities = affinityTask.mActivities;
2717 final int numActivities = activities.size();
2718 // Do not operate on the root Activity.
2719 for (int i = numActivities - 1; i > 0; --i) {
2720 ActivityRecord target = activities.get(i);
2721
2722 final int flags = target.info.flags;
2723 boolean finishOnTaskLaunch = (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
2724 boolean allowTaskReparenting = (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
2725
2726 if (target.resultTo != null) {
2727 // If this activity is sending a reply to a previous
2728 // activity, we can't do anything with it now until
2729 // we reach the start of the reply chain.
2730 // XXX note that we are assuming the result is always
2731 // to the previous activity, which is almost always
2732 // the case but we really shouldn't count on.
2733 if (replyChainEnd < 0) {
2734 replyChainEnd = i;
2735 }
2736 } else if (topTaskIsHigher
2737 && allowTaskReparenting
2738 && taskAffinity != null
2739 && taskAffinity.equals(target.taskAffinity)) {
2740 // This activity has an affinity for our task. Either remove it if we are
2741 // clearing or move it over to our task. Note that
2742 // we currently punt on the case where we are resetting a
2743 // task that is not at the top but who has activities above
2744 // with an affinity to it... this is really not a normal
2745 // case, and we will need to later pull that task to the front
2746 // and usually at that point we will do the reset and pick
2747 // up those remaining activities. (This only happens if
2748 // someone starts an activity in a new task from an activity
2749 // in a task that is not currently on top.)
2750 if (forceReset || finishOnTaskLaunch) {
2751 final int start = replyChainEnd >= 0 ? replyChainEnd : i;
2752 if (DEBUG_TASKS) Slog.v(TAG, "Finishing task at index " + start + " to " + i);
2753 for (int srcPos = start; srcPos >= i; --srcPos) {
2754 final ActivityRecord p = activities.get(srcPos);
2755 if (p.finishing) {
2756 continue;
2757 }
2758 if (VALIDATE_TASK_REPLACE) Slog.w(TAG,
2759 "resetAffinityTaskIfNeededLocked: calling finishActivity on " + p);
Craig Mautnerd44711d2013-02-23 11:24:36 -08002760 finishActivityLocked(p, Activity.RESULT_CANCELED, null, "reset", false);
Craig Mautnere3a74d52013-02-22 14:14:58 -08002761 }
2762 } else {
2763 int taskTopI = mHistory.indexOf(taskTop);
2764 final int end = replyChainEnd >= 0 ? replyChainEnd : i;
2765 if (DEBUG_TASKS) Slog.v(TAG, "Reparenting task at index " + i + " to " + end);
2766 for (int srcPos = i; srcPos <= end; ++srcPos) {
2767 final ActivityRecord p = activities.get(srcPos);
2768 if (p.finishing) {
2769 continue;
2770 }
2771 p.setTask(task, null, false);
2772 task.addActivityToTop(p);
2773
2774 mHistory.remove(p);
2775 mHistory.add(taskTopI--, p);
2776
2777 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing and adding activity " + p
2778 + " to stack at " + task,
2779 new RuntimeException("here").fillInStackTrace());
2780 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p + " from " + srcPos
2781 + " in to resetting task " + task);
2782 mService.mWindowManager.setAppGroupId(p.appToken, taskId);
2783 }
2784 mService.mWindowManager.moveTaskToTop(taskId);
2785 if (VALIDATE_TOKENS) {
2786 validateAppTokensLocked();
2787 }
2788 if (VALIDATE_TASK_REPLACE) {
2789 verifyActivityRecords(false);
2790 }
2791
2792 // Now we've moved it in to place... but what if this is
2793 // a singleTop activity and we have put it on top of another
2794 // instance of the same activity? Then we drop the instance
2795 // below so it remains singleTop.
2796 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
2797 ArrayList<ActivityRecord> taskActivities = task.mActivities;
2798 boolean found = false;
2799 int targetNdx = taskActivities.indexOf(target);
2800 if (targetNdx > 0) {
2801 ActivityRecord p = taskActivities.get(targetNdx - 1);
2802 if (p.intent.getComponent().equals(target.intent.getComponent())) {
Craig Mautnerd44711d2013-02-23 11:24:36 -08002803 if (finishActivityLocked(p, Activity.RESULT_CANCELED, null, "replace",
2804 false)) {
Craig Mautnere3a74d52013-02-22 14:14:58 -08002805 taskTopI--;
2806 }
2807 }
2808 }
2809 }
2810 }
2811
2812 replyChainEnd = -1;
2813 }
2814 }
2815 }
2816
2817 private final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
2818 ActivityRecord newActivity) {
2819 boolean forceReset =
2820 (newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
2821 if (ACTIVITY_INACTIVE_RESET_TIME > 0
2822 && taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
2823 if ((newActivity.info.flags & ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
2824 forceReset = true;
2825 }
2826 }
2827
2828 final TaskRecord task = taskTop.task;
2829
2830 /** False until we evaluate the TaskRecord associated with taskTop. Switches to true
2831 * for remaining tasks. Used for later tasks to reparent to task. */
2832 boolean taskFound = false;
2833
2834 /** If ActivityOptions are moved out and need to be aborted or moved to taskTop. */
2835 ActivityOptions topOptions = null;
2836
2837 for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
2838 final TaskRecord targetTask = mTaskHistory.get(i);
2839
2840 if (targetTask == task) {
2841 topOptions = resetTargetTaskIfNeededLocked(task, forceReset);
2842 taskFound = true;
2843 } else {
2844 resetAffinityTaskIfNeededLocked(targetTask, task, taskFound, forceReset, taskTop);
2845 }
2846 }
2847
2848 taskTop = task.getTopActivity();
2849 if (topOptions != null) {
2850 // If we got some ActivityOptions from an activity on top that
2851 // was removed from the task, propagate them to the new real top.
2852 if (taskTop != null) {
2853 if (VALIDATE_TASK_REPLACE) Slog.w(TAG,
2854 "newResetTaskIfNeededLocked: would call updateOptionsLocked " + topOptions);
2855 taskTop.updateOptionsLocked(topOptions);
2856 } else {
2857 if (VALIDATE_TASK_REPLACE) Slog.w(TAG,
2858 "newResetTaskIfNeededLocked: would call " + topOptions + " abort");
2859 topOptions.abort();
2860 }
2861 }
2862
2863 return taskTop;
2864 }
2865
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002866 /**
2867 * Perform clear operation as requested by
2868 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2869 * stack to the given task, then look for
2870 * an instance of that activity in the stack and, if found, finish all
2871 * activities on top of it and return the instance.
2872 *
2873 * @param newR Description of the new activity being started.
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002874 * @return Returns the old activity that should be continued to be used,
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002875 * or null if none was found.
2876 */
2877 private final ActivityRecord performClearTaskLocked(int taskId,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002878 ActivityRecord newR, int launchFlags) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002879 int i = mHistory.size();
2880
2881 // First find the requested task.
2882 while (i > 0) {
2883 i--;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002884 ActivityRecord r = mHistory.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002885 if (r.task.taskId == taskId) {
2886 i++;
2887 break;
2888 }
2889 }
2890
2891 // Now clear it.
2892 while (i > 0) {
2893 i--;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002894 ActivityRecord r = mHistory.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002895 if (r.finishing) {
2896 continue;
2897 }
2898 if (r.task.taskId != taskId) {
2899 return null;
2900 }
2901 if (r.realActivity.equals(newR.realActivity)) {
2902 // Here it is! Now finish everything in front...
2903 ActivityRecord ret = r;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002904 while (i < (mHistory.size()-1)) {
2905 i++;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002906 r = mHistory.get(i);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002907 if (r.task.taskId != taskId) {
2908 break;
2909 }
2910 if (r.finishing) {
2911 continue;
2912 }
Dianne Hackborn9622ca42012-10-23 18:56:33 -07002913 ActivityOptions opts = r.takeOptionsLocked();
2914 if (opts != null) {
2915 ret.updateOptionsLocked(opts);
2916 }
Craig Mautnerd44711d2013-02-23 11:24:36 -08002917 if (finishActivityLocked(r, Activity.RESULT_CANCELED, null,
2918 "clear", false)) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002919 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002920 }
2921 }
2922
2923 // Finally, if this is a normal launch mode (that is, not
2924 // expecting onNewIntent()), then we will finish the current
2925 // instance of the activity so a new fresh one can be started.
2926 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
2927 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
2928 if (!ret.finishing) {
Craig Mautner05d6272ba2013-02-11 09:39:27 -08002929 int index = mHistory.indexOf(ret);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002930 if (index >= 0) {
Craig Mautnerd44711d2013-02-23 11:24:36 -08002931 finishActivityLocked(ret, Activity.RESULT_CANCELED, null,
2932 "clear", false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002933 }
2934 return null;
2935 }
2936 }
2937
2938 return ret;
2939 }
2940 }
2941
2942 return null;
2943 }
2944
2945 /**
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002946 * Completely remove all activities associated with an existing
2947 * task starting at a specified index.
2948 */
2949 private final void performClearTaskAtIndexLocked(int taskId, int i) {
Dianne Hackborneabd3282011-10-13 16:26:49 -07002950 while (i < mHistory.size()) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002951 ActivityRecord r = mHistory.get(i);
2952 if (r.task.taskId != taskId) {
2953 // Whoops hit the end.
2954 return;
2955 }
2956 if (r.finishing) {
2957 i++;
2958 continue;
2959 }
Craig Mautnerd44711d2013-02-23 11:24:36 -08002960 if (!finishActivityLocked(r, Activity.RESULT_CANCELED, null,
2961 "clear", false)) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002962 i++;
2963 }
2964 }
2965 }
2966
2967 /**
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002968 * Completely remove all activities associated with an existing task.
2969 */
2970 private final void performClearTaskLocked(int taskId) {
2971 int i = mHistory.size();
2972
2973 // First find the requested task.
2974 while (i > 0) {
2975 i--;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002976 ActivityRecord r = mHistory.get(i);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002977 if (r.task.taskId == taskId) {
2978 i++;
2979 break;
2980 }
2981 }
2982
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002983 // Now find the start and clear it.
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002984 while (i > 0) {
2985 i--;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002986 ActivityRecord r = mHistory.get(i);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002987 if (r.finishing) {
2988 continue;
2989 }
2990 if (r.task.taskId != taskId) {
2991 // We hit the bottom. Now finish it all...
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07002992 performClearTaskAtIndexLocked(taskId, i+1);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002993 return;
2994 }
2995 }
2996 }
2997
2998 /**
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002999 * Find the activity in the history stack within the given task. Returns
3000 * the index within the history at which it's found, or < 0 if not found.
3001 */
Craig Mautner56f52db2013-02-25 10:03:01 -08003002 private final ActivityRecord findActivityInHistoryLocked(ActivityRecord r, TaskRecord task) {
3003 final ComponentName realActivity = r.realActivity;
3004 ArrayList<ActivityRecord> activities = task.mActivities;
3005 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3006 ActivityRecord candidate = activities.get(activityNdx);
Dianne Hackborn45a25bc2012-06-28 13:49:17 -07003007 if (candidate.finishing) {
3008 continue;
3009 }
Craig Mautner56f52db2013-02-25 10:03:01 -08003010 if (candidate.realActivity.equals(realActivity)) {
3011 return candidate;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003012 }
3013 }
Craig Mautner56f52db2013-02-25 10:03:01 -08003014 return null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003015 }
3016
3017 /**
3018 * Reorder the history stack so that the activity at the given index is
3019 * brought to the front.
3020 */
Craig Mautner56f52db2013-02-25 10:03:01 -08003021 private final void moveActivityToFrontLocked(ActivityRecord newTop) {
3022 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing and adding activity " + newTop
3023 + " to stack at top", new RuntimeException("here").fillInStackTrace());
3024
3025 final TaskRecord task = newTop.task;
3026 task.getTopActivity().frontOfTask = false;
3027 task.mActivities.remove(newTop);
3028 task.mActivities.add(newTop);
3029 newTop.frontOfTask = true;
3030
3031 mHistory.remove(newTop);
3032 mHistory.add(newTop);
Craig Mautner11bf9a52013-02-19 14:08:51 -08003033 if (VALIDATE_TASK_REPLACE) {
3034 verifyActivityRecords(true);
3035 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003036 }
3037
3038 final int startActivityLocked(IApplicationThread caller,
Dianne Hackborna4972e92012-03-14 10:38:05 -07003039 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003040 String resultWho, int requestCode,
Dianne Hackbornf265ea92013-01-31 15:00:51 -08003041 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003042 boolean componentSpecified, ActivityRecord[] outActivity) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08003043 mLastHistoryModifier = "startActivityLocked(IApplicationThread)";
Dianne Hackbornefb58102010-10-14 16:47:34 -07003044
Dianne Hackborna4972e92012-03-14 10:38:05 -07003045 int err = ActivityManager.START_SUCCESS;
Dianne Hackbornefb58102010-10-14 16:47:34 -07003046
3047 ProcessRecord callerApp = null;
3048 if (caller != null) {
3049 callerApp = mService.getRecordForAppLocked(caller);
3050 if (callerApp != null) {
3051 callingPid = callerApp.pid;
3052 callingUid = callerApp.info.uid;
3053 } else {
3054 Slog.w(TAG, "Unable to find app for caller " + caller
3055 + " (pid=" + callingPid + ") when starting: "
3056 + intent.toString());
Dianne Hackborna4972e92012-03-14 10:38:05 -07003057 err = ActivityManager.START_PERMISSION_DENIED;
Dianne Hackbornefb58102010-10-14 16:47:34 -07003058 }
3059 }
3060
Dianne Hackborna4972e92012-03-14 10:38:05 -07003061 if (err == ActivityManager.START_SUCCESS) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07003062 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
Dianne Hackborn5fe7e2a2012-10-04 11:58:16 -07003063 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
3064 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
Dianne Hackbornefb58102010-10-14 16:47:34 -07003065 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003066
3067 ActivityRecord sourceRecord = null;
3068 ActivityRecord resultRecord = null;
3069 if (resultTo != null) {
Craig Mautner56f52db2013-02-25 10:03:01 -08003070 sourceRecord = isInStackLocked(resultTo);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003071 if (DEBUG_RESULTS) Slog.v(
Craig Mautner56f52db2013-02-25 10:03:01 -08003072 TAG, "Will send result to " + resultTo + " " + sourceRecord);
3073 if (sourceRecord != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003074 if (requestCode >= 0 && !sourceRecord.finishing) {
3075 resultRecord = sourceRecord;
3076 }
3077 }
3078 }
3079
3080 int launchFlags = intent.getFlags();
3081
3082 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3083 && sourceRecord != null) {
3084 // Transfer the result target from the source activity to the new
3085 // one being started, including any failures.
3086 if (requestCode >= 0) {
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003087 ActivityOptions.abort(options);
Dianne Hackborna4972e92012-03-14 10:38:05 -07003088 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003089 }
3090 resultRecord = sourceRecord.resultTo;
3091 resultWho = sourceRecord.resultWho;
3092 requestCode = sourceRecord.requestCode;
3093 sourceRecord.resultTo = null;
3094 if (resultRecord != null) {
3095 resultRecord.removeResultsLocked(
3096 sourceRecord, resultWho, requestCode);
3097 }
3098 }
3099
Dianne Hackborna4972e92012-03-14 10:38:05 -07003100 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003101 // We couldn't find a class that can handle the given Intent.
3102 // That's the end of that!
Dianne Hackborna4972e92012-03-14 10:38:05 -07003103 err = ActivityManager.START_INTENT_NOT_RESOLVED;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003104 }
3105
Dianne Hackborna4972e92012-03-14 10:38:05 -07003106 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003107 // We couldn't find the specific class specified in the Intent.
3108 // Also the end of the line.
Dianne Hackborna4972e92012-03-14 10:38:05 -07003109 err = ActivityManager.START_CLASS_NOT_FOUND;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003110 }
3111
Dianne Hackborna4972e92012-03-14 10:38:05 -07003112 if (err != ActivityManager.START_SUCCESS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003113 if (resultRecord != null) {
3114 sendActivityResultLocked(-1,
3115 resultRecord, resultWho, requestCode,
3116 Activity.RESULT_CANCELED, null);
3117 }
Dianne Hackborn90c52de2011-09-23 12:57:44 -07003118 mDismissKeyguardOnNextActivity = false;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003119 ActivityOptions.abort(options);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003120 return err;
3121 }
3122
Jeff Sharkey35be7562012-04-18 19:16:15 -07003123 final int startAnyPerm = mService.checkPermission(
3124 START_ANY_ACTIVITY, callingPid, callingUid);
3125 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08003126 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
Jeff Sharkey35be7562012-04-18 19:16:15 -07003127 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003128 if (resultRecord != null) {
3129 sendActivityResultLocked(-1,
3130 resultRecord, resultWho, requestCode,
3131 Activity.RESULT_CANCELED, null);
3132 }
Dianne Hackborn90c52de2011-09-23 12:57:44 -07003133 mDismissKeyguardOnNextActivity = false;
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08003134 String msg;
3135 if (!aInfo.exported) {
3136 msg = "Permission Denial: starting " + intent.toString()
3137 + " from " + callerApp + " (pid=" + callingPid
3138 + ", uid=" + callingUid + ")"
3139 + " not exported from uid " + aInfo.applicationInfo.uid;
3140 } else {
3141 msg = "Permission Denial: starting " + intent.toString()
3142 + " from " + callerApp + " (pid=" + callingPid
3143 + ", uid=" + callingUid + ")"
3144 + " requires " + aInfo.permission;
3145 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003146 Slog.w(TAG, msg);
3147 throw new SecurityException(msg);
3148 }
3149
3150 if (mMainStack) {
3151 if (mService.mController != null) {
3152 boolean abort = false;
3153 try {
3154 // The Intent we give to the watcher has the extra data
3155 // stripped off, since it can contain private information.
3156 Intent watchIntent = intent.cloneFilter();
3157 abort = !mService.mController.activityStarting(watchIntent,
3158 aInfo.applicationInfo.packageName);
3159 } catch (RemoteException e) {
3160 mService.mController = null;
3161 }
3162
3163 if (abort) {
3164 if (resultRecord != null) {
3165 sendActivityResultLocked(-1,
3166 resultRecord, resultWho, requestCode,
3167 Activity.RESULT_CANCELED, null);
3168 }
3169 // We pretend to the caller that it was really started, but
3170 // they will just get a cancel result.
Dianne Hackborn90c52de2011-09-23 12:57:44 -07003171 mDismissKeyguardOnNextActivity = false;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003172 ActivityOptions.abort(options);
Dianne Hackborna4972e92012-03-14 10:38:05 -07003173 return ActivityManager.START_SUCCESS;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003174 }
3175 }
3176 }
Amith Yamasani742a6712011-05-04 14:49:28 -07003177
Dianne Hackbornf265ea92013-01-31 15:00:51 -08003178 ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid, callingPackage,
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003179 intent, resolvedType, aInfo, mService.mConfiguration,
3180 resultRecord, resultWho, requestCode, componentSpecified);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003181 if (outActivity != null) {
3182 outActivity[0] = r;
3183 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003184
3185 if (mMainStack) {
3186 if (mResumedActivity == null
3187 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3188 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3189 PendingActivityLaunch pal = new PendingActivityLaunch();
3190 pal.r = r;
3191 pal.sourceRecord = sourceRecord;
Dianne Hackborna4972e92012-03-14 10:38:05 -07003192 pal.startFlags = startFlags;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003193 mService.mPendingActivityLaunches.add(pal);
Dianne Hackborn90c52de2011-09-23 12:57:44 -07003194 mDismissKeyguardOnNextActivity = false;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003195 ActivityOptions.abort(options);
Dianne Hackborna4972e92012-03-14 10:38:05 -07003196 return ActivityManager.START_SWITCHES_CANCELED;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003197 }
3198 }
3199
3200 if (mService.mDidAppSwitch) {
3201 // This is the second allowed switch since we stopped switches,
3202 // so now just generally allow switches. Use case: user presses
3203 // home (switches disabled, switch to home, mDidAppSwitch now true);
3204 // user taps a home icon (coming from home so allowed, we hit here
3205 // and now allow anyone to switch again).
3206 mService.mAppSwitchesAllowedTime = 0;
3207 } else {
3208 mService.mDidAppSwitch = true;
3209 }
3210
3211 mService.doPendingActivityLaunchesLocked(false);
3212 }
3213
Dianne Hackborn90c52de2011-09-23 12:57:44 -07003214 err = startActivityUncheckedLocked(r, sourceRecord,
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003215 startFlags, true, options);
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08003216 if (mDismissKeyguardOnNextActivity && mPausingActivity == null) {
Dianne Hackborn90c52de2011-09-23 12:57:44 -07003217 // Someone asked to have the keyguard dismissed on the next
3218 // activity start, but we are not actually doing an activity
3219 // switch... just dismiss the keyguard now, because we
3220 // probably want to see whatever is behind it.
3221 mDismissKeyguardOnNextActivity = false;
3222 mService.mWindowManager.dismissKeyguard();
3223 }
3224 return err;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003225 }
3226
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003227 final void moveHomeToFrontFromLaunchLocked(int launchFlags) {
3228 if ((launchFlags &
3229 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
3230 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
3231 // Caller wants to appear on home activity, so before starting
3232 // their own activity we will bring home to the front.
3233 moveHomeToFrontLocked();
3234 }
3235 }
3236
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003237 final int startActivityUncheckedLocked(ActivityRecord r,
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003238 ActivityRecord sourceRecord, int startFlags, boolean doResume,
3239 Bundle options) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003240 final Intent intent = r.intent;
3241 final int callingUid = r.launchedFromUid;
Amith Yamasani742a6712011-05-04 14:49:28 -07003242
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003243 int launchFlags = intent.getFlags();
3244
3245 // We'll invoke onUserLeaving before onPause only if the launching
3246 // activity did not explicitly state that this is an automated launch.
3247 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
3248 if (DEBUG_USER_LEAVING) Slog.v(TAG,
3249 "startActivity() => mUserLeaving=" + mUserLeaving);
3250
3251 // If the caller has asked not to resume at this point, we make note
3252 // of this in the record so that we can skip it when trying to find
3253 // the top running activity.
3254 if (!doResume) {
3255 r.delayedResume = true;
3256 }
3257
3258 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3259 != 0 ? r : null;
3260
3261 // If the onlyIfNeeded flag is set, then we can do this if the activity
3262 // being launched is the same as the one making the call... or, as
3263 // a special case, if we do not know the caller then we count the
3264 // current top activity as the caller.
Dianne Hackborna4972e92012-03-14 10:38:05 -07003265 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003266 ActivityRecord checkedCaller = sourceRecord;
3267 if (checkedCaller == null) {
3268 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
3269 }
3270 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3271 // Caller is not the same as launcher, so always needed.
Dianne Hackborna4972e92012-03-14 10:38:05 -07003272 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003273 }
3274 }
3275
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003276 if (sourceRecord == null) {
3277 // This activity is not being started from another... in this
3278 // case we -always- start a new task.
3279 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
3280 Slog.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
3281 + intent);
3282 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3283 }
3284 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3285 // The original activity who is starting us is running as a single
3286 // instance... this new activity it is starting must go on its
3287 // own task.
3288 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3289 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3290 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3291 // The activity being started is a single instance... it always
3292 // gets launched into its own task.
3293 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3294 }
3295
3296 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3297 // For whatever reason this activity is being launched into a new
3298 // task... yet the caller has requested a result back. Well, that
3299 // is pretty messed up, so instead immediately send back a cancel
3300 // and let the new task continue launched as normal without a
3301 // dependency on its originator.
3302 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
3303 sendActivityResultLocked(-1,
3304 r.resultTo, r.resultWho, r.requestCode,
3305 Activity.RESULT_CANCELED, null);
3306 r.resultTo = null;
3307 }
3308
3309 boolean addingToTask = false;
Dianne Hackborn03fcc332012-05-15 12:49:40 -07003310 boolean movedHome = false;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003311 TaskRecord reuseTask = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003312 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3313 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3314 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3315 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3316 // If bring to front is requested, and no result is requested, and
3317 // we can find a task that was started with this same
3318 // component, then instead of launching bring that one to the front.
3319 if (r.resultTo == null) {
3320 // See if there is a task to bring to the front. If this is
3321 // a SINGLE_INSTANCE activity, there can be one and only one
3322 // instance of it in the history, and it is always in its own
3323 // unique task, so we do a special search.
3324 ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3325 ? findTaskLocked(intent, r.info)
3326 : findActivityLocked(intent, r.info);
3327 if (taskTop != null) {
3328 if (taskTop.task.intent == null) {
3329 // This task was started because of movement of
3330 // the activity based on affinity... now that we
3331 // are actually launching it, we can assign the
3332 // base intent.
3333 taskTop.task.setIntent(intent, r.info);
3334 }
3335 // If the target task is not in the front, then we need
3336 // to bring it to the front... except... well, with
3337 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3338 // to have the same behavior as if a new instance was
3339 // being started, which means not bringing it to the front
3340 // if the caller is not itself in the front.
3341 ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop);
Jean-Baptiste Queru66a5d692010-10-25 17:27:16 -07003342 if (curTop != null && curTop.task != taskTop.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003343 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3344 boolean callerAtFront = sourceRecord == null
3345 || curTop.task == sourceRecord.task;
3346 if (callerAtFront) {
3347 // We really do want to push this one into the
3348 // user's face, right now.
Dianne Hackborn03fcc332012-05-15 12:49:40 -07003349 movedHome = true;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003350 moveHomeToFrontFromLaunchLocked(launchFlags);
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003351 moveTaskToFrontLocked(taskTop.task, r, options);
Dianne Hackborn84375872012-06-01 19:03:50 -07003352 options = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003353 }
3354 }
3355 // If the caller has requested that the target task be
3356 // reset, then do so.
3357 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3358 taskTop = resetTaskIfNeededLocked(taskTop, r);
3359 }
Dianne Hackborna4972e92012-03-14 10:38:05 -07003360 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003361 // We don't need to start a new activity, and
3362 // the client said not to do anything if that
3363 // is the case, so this is it! And for paranoia, make
3364 // sure we have correctly resumed the top activity.
3365 if (doResume) {
Dianne Hackborn84375872012-06-01 19:03:50 -07003366 resumeTopActivityLocked(null, options);
3367 } else {
3368 ActivityOptions.abort(options);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003369 }
Dianne Hackborna4972e92012-03-14 10:38:05 -07003370 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003371 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003372 if ((launchFlags &
3373 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
3374 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
3375 // The caller has requested to completely replace any
Dianne Hackborn7da6ac32010-12-09 19:22:04 -08003376 // existing task with its new activity. Well that should
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003377 // not be too hard...
3378 reuseTask = taskTop.task;
3379 performClearTaskLocked(taskTop.task.taskId);
3380 reuseTask.setIntent(r.intent, r.info);
3381 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003382 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3383 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3384 // In this situation we want to remove all activities
3385 // from the task up to the one being started. In most
3386 // cases this means we are resetting the task to its
3387 // initial state.
3388 ActivityRecord top = performClearTaskLocked(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003389 taskTop.task.taskId, r, launchFlags);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003390 if (top != null) {
3391 if (top.frontOfTask) {
3392 // Activity aliases may mean we use different
3393 // intents for the top activity, so make sure
3394 // the task now has the identity of the new
3395 // intent.
3396 top.task.setIntent(r.intent, r.info);
3397 }
3398 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
Dianne Hackborn39792d22010-08-19 18:01:52 -07003399 top.deliverNewIntentLocked(callingUid, r.intent);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003400 } else {
3401 // A special case: we need to
3402 // start the activity because it is not currently
3403 // running, and the caller has asked to clear the
3404 // current task to have this activity at the top.
3405 addingToTask = true;
3406 // Now pretend like this activity is being started
3407 // by the top of its task, so it is put in the
3408 // right place.
3409 sourceRecord = taskTop;
3410 }
3411 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3412 // In this case the top activity on the task is the
3413 // same as the one being launched, so we take that
3414 // as a request to bring the task to the foreground.
3415 // If the top activity in the task is the root
3416 // activity, deliver this new intent to it if it
3417 // desires.
Johan Viktorssonf363dfd2012-02-16 17:05:16 +01003418 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3419 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003420 && taskTop.realActivity.equals(r.realActivity)) {
3421 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
3422 if (taskTop.frontOfTask) {
3423 taskTop.task.setIntent(r.intent, r.info);
3424 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07003425 taskTop.deliverNewIntentLocked(callingUid, r.intent);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003426 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3427 // In this case we are launching the root activity
3428 // of the task, but with a different intent. We
3429 // should start a new instance on top.
3430 addingToTask = true;
3431 sourceRecord = taskTop;
3432 }
3433 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3434 // In this case an activity is being launched in to an
3435 // existing task, without resetting that task. This
3436 // is typically the situation of launching an activity
3437 // from a notification or shortcut. We want to place
3438 // the new activity on top of the current task.
3439 addingToTask = true;
3440 sourceRecord = taskTop;
3441 } else if (!taskTop.task.rootWasReset) {
3442 // In this case we are launching in to an existing task
3443 // that has not yet been started from its front door.
3444 // The current task has been brought to the front.
3445 // Ideally, we'd probably like to place this new task
3446 // at the bottom of its stack, but that's a little hard
3447 // to do with the current organization of the code so
3448 // for now we'll just drop it.
3449 taskTop.task.setIntent(r.intent, r.info);
3450 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003451 if (!addingToTask && reuseTask == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003452 // We didn't do anything... but it was needed (a.k.a., client
3453 // don't use that intent!) And for paranoia, make
3454 // sure we have correctly resumed the top activity.
3455 if (doResume) {
Dianne Hackborn84375872012-06-01 19:03:50 -07003456 resumeTopActivityLocked(null, options);
3457 } else {
3458 ActivityOptions.abort(options);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003459 }
Dianne Hackborna4972e92012-03-14 10:38:05 -07003460 return ActivityManager.START_TASK_TO_FRONT;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003461 }
3462 }
3463 }
3464 }
3465
3466 //String uri = r.intent.toURI();
3467 //Intent intent2 = new Intent(uri);
3468 //Slog.i(TAG, "Given intent: " + r.intent);
3469 //Slog.i(TAG, "URI is: " + uri);
3470 //Slog.i(TAG, "To intent: " + intent2);
3471
3472 if (r.packageName != null) {
3473 // If the activity being launched is the same as the one currently
3474 // at the top, then we need to check if it should only be launched
3475 // once.
3476 ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);
3477 if (top != null && r.resultTo == null) {
Amith Yamasani742a6712011-05-04 14:49:28 -07003478 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003479 if (top.app != null && top.app.thread != null) {
3480 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3481 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3482 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3483 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
3484 // For paranoia, make sure we have correctly
3485 // resumed the top activity.
3486 if (doResume) {
3487 resumeTopActivityLocked(null);
3488 }
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003489 ActivityOptions.abort(options);
Dianne Hackborna4972e92012-03-14 10:38:05 -07003490 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003491 // We don't need to start a new activity, and
3492 // the client said not to do anything if that
3493 // is the case, so this is it!
Dianne Hackborna4972e92012-03-14 10:38:05 -07003494 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003495 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07003496 top.deliverNewIntentLocked(callingUid, r.intent);
Dianne Hackborna4972e92012-03-14 10:38:05 -07003497 return ActivityManager.START_DELIVERED_TO_TOP;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003498 }
3499 }
3500 }
3501 }
3502
3503 } else {
3504 if (r.resultTo != null) {
3505 sendActivityResultLocked(-1,
3506 r.resultTo, r.resultWho, r.requestCode,
3507 Activity.RESULT_CANCELED, null);
3508 }
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003509 ActivityOptions.abort(options);
Dianne Hackborna4972e92012-03-14 10:38:05 -07003510 return ActivityManager.START_CLASS_NOT_FOUND;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003511 }
3512
3513 boolean newTask = false;
Dianne Hackborn7da6ac32010-12-09 19:22:04 -08003514 boolean keepCurTransition = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003515
3516 // Should this be considered a new task?
3517 if (r.resultTo == null && !addingToTask
3518 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003519 if (reuseTask == null) {
3520 // todo: should do better management of integers.
3521 mService.mCurTask++;
3522 if (mService.mCurTask <= 0) {
3523 mService.mCurTask = 1;
3524 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08003525 r.setTask(createTaskRecord(mService.mCurTask, r.info, intent, true), null, true);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003526 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
3527 + " in new task " + r.task);
3528 } else {
Dianne Hackbornf26fd992011-04-08 18:14:09 -07003529 r.setTask(reuseTask, reuseTask, true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003530 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003531 newTask = true;
Dianne Hackborn03fcc332012-05-15 12:49:40 -07003532 if (!movedHome) {
3533 moveHomeToFrontFromLaunchLocked(launchFlags);
3534 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003535
3536 } else if (sourceRecord != null) {
3537 if (!addingToTask &&
3538 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3539 // In this case, we are adding the activity to an existing
3540 // task, but the caller has asked to clear that task if the
3541 // activity is already running.
3542 ActivityRecord top = performClearTaskLocked(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003543 sourceRecord.task.taskId, r, launchFlags);
Dianne Hackborn7da6ac32010-12-09 19:22:04 -08003544 keepCurTransition = true;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003545 if (top != null) {
3546 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
Dianne Hackborn39792d22010-08-19 18:01:52 -07003547 top.deliverNewIntentLocked(callingUid, r.intent);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003548 // For paranoia, make sure we have correctly
3549 // resumed the top activity.
3550 if (doResume) {
3551 resumeTopActivityLocked(null);
3552 }
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003553 ActivityOptions.abort(options);
Dianne Hackborna4972e92012-03-14 10:38:05 -07003554 return ActivityManager.START_DELIVERED_TO_TOP;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003555 }
3556 } else if (!addingToTask &&
3557 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3558 // In this case, we are launching an activity in our own task
3559 // that may already be running somewhere in the history, and
3560 // we want to shuffle it to the front of the stack if so.
Craig Mautner56f52db2013-02-25 10:03:01 -08003561 final ActivityRecord top = findActivityInHistoryLocked(r, sourceRecord.task);
3562 if (top != null) {
3563 moveActivityToFrontLocked(top);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003564 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003565 top.updateOptionsLocked(options);
Dianne Hackborn39792d22010-08-19 18:01:52 -07003566 top.deliverNewIntentLocked(callingUid, r.intent);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003567 if (doResume) {
3568 resumeTopActivityLocked(null);
3569 }
Dianne Hackborna4972e92012-03-14 10:38:05 -07003570 return ActivityManager.START_DELIVERED_TO_TOP;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003571 }
3572 }
3573 // An existing activity is starting this new activity, so we want
3574 // to keep the new one in the same task as the one that is starting
3575 // it.
Dianne Hackbornf26fd992011-04-08 18:14:09 -07003576 r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003577 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
3578 + " in existing task " + r.task);
3579
3580 } else {
3581 // This not being started from an existing activity, and not part
3582 // of a new task... just put it in the top task, though these days
3583 // this case should never happen.
3584 final int N = mHistory.size();
3585 ActivityRecord prev =
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003586 N > 0 ? mHistory.get(N-1) : null;
Dianne Hackbornf26fd992011-04-08 18:14:09 -07003587 r.setTask(prev != null
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003588 ? prev.task
Craig Mautner5d9c7be2013-02-15 14:02:56 -08003589 : createTaskRecord(mService.mCurTask, r.info, intent, true), null, true);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003590 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
3591 + " in new guessed " + r.task);
3592 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07003593
Dianne Hackborn39792d22010-08-19 18:01:52 -07003594 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
Dianne Hackborn7e269642010-08-25 19:50:20 -07003595 intent, r.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07003596
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003597 if (newTask) {
Dianne Hackbornb12e1352012-09-26 11:39:20 -07003598 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003599 }
3600 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003601 startActivityLocked(r, newTask, doResume, keepCurTransition, options);
Dianne Hackborna4972e92012-03-14 10:38:05 -07003602 return ActivityManager.START_SUCCESS;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003603 }
3604
Dianne Hackborna4972e92012-03-14 10:38:05 -07003605 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
Amith Yamasani483f3b02012-03-13 16:08:00 -07003606 String profileFile, ParcelFileDescriptor profileFd, int userId) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003607 // Collect information about the target of the Intent.
3608 ActivityInfo aInfo;
3609 try {
3610 ResolveInfo rInfo =
3611 AppGlobals.getPackageManager().resolveIntent(
3612 intent, resolvedType,
3613 PackageManager.MATCH_DEFAULT_ONLY
Amith Yamasani483f3b02012-03-13 16:08:00 -07003614 | ActivityManagerService.STOCK_PM_FLAGS, userId);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003615 aInfo = rInfo != null ? rInfo.activityInfo : null;
3616 } catch (RemoteException e) {
3617 aInfo = null;
3618 }
3619
3620 if (aInfo != null) {
3621 // Store the found target back into the intent, because now that
3622 // we have it we never want to do this again. For example, if the
3623 // user navigates back to this point in the history, we should
3624 // always restart the exact same activity.
3625 intent.setComponent(new ComponentName(
3626 aInfo.applicationInfo.packageName, aInfo.name));
3627
3628 // Don't debug things in the system process
Dianne Hackborna4972e92012-03-14 10:38:05 -07003629 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003630 if (!aInfo.processName.equals("system")) {
3631 mService.setDebugApp(aInfo.processName, true, false);
3632 }
3633 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003634
Dianne Hackborna4972e92012-03-14 10:38:05 -07003635 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
Siva Velusamy92a8b222012-03-09 16:24:04 -08003636 if (!aInfo.processName.equals("system")) {
3637 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
3638 }
3639 }
3640
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003641 if (profileFile != null) {
3642 if (!aInfo.processName.equals("system")) {
3643 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
Dianne Hackborna4972e92012-03-14 10:38:05 -07003644 profileFile, profileFd,
3645 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003646 }
3647 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003648 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003649 return aInfo;
3650 }
3651
3652 final int startActivityMayWait(IApplicationThread caller, int callingUid,
Dianne Hackbornf265ea92013-01-31 15:00:51 -08003653 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
Dianne Hackborna4972e92012-03-14 10:38:05 -07003654 String resultWho, int requestCode, int startFlags, String profileFile,
3655 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
3656 Bundle options, int userId) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003657 // Refuse possible leaked file descriptors
3658 if (intent != null && intent.hasFileDescriptors()) {
3659 throw new IllegalArgumentException("File descriptors passed in Intent");
3660 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003661 boolean componentSpecified = intent.getComponent() != null;
3662
3663 // Don't modify the client's object!
3664 intent = new Intent(intent);
3665
3666 // Collect information about the target of the Intent.
Dianne Hackborna4972e92012-03-14 10:38:05 -07003667 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
Amith Yamasani483f3b02012-03-13 16:08:00 -07003668 profileFile, profileFd, userId);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003669
3670 synchronized (mService) {
3671 int callingPid;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003672 if (callingUid >= 0) {
3673 callingPid = -1;
3674 } else if (caller == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003675 callingPid = Binder.getCallingPid();
3676 callingUid = Binder.getCallingUid();
3677 } else {
3678 callingPid = callingUid = -1;
3679 }
3680
3681 mConfigWillChange = config != null
3682 && mService.mConfiguration.diff(config) != 0;
3683 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3684 "Starting activity when config will change = " + mConfigWillChange);
3685
3686 final long origId = Binder.clearCallingIdentity();
3687
3688 if (mMainStack && aInfo != null &&
Dianne Hackborn54e570f2010-10-04 18:32:32 -07003689 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003690 // This may be a heavy-weight process! Check to see if we already
3691 // have another, different heavy-weight process running.
3692 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
3693 if (mService.mHeavyWeightProcess != null &&
3694 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
3695 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
3696 int realCallingPid = callingPid;
3697 int realCallingUid = callingUid;
3698 if (caller != null) {
3699 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
3700 if (callerApp != null) {
3701 realCallingPid = callerApp.pid;
3702 realCallingUid = callerApp.info.uid;
3703 } else {
3704 Slog.w(TAG, "Unable to find app for caller " + caller
3705 + " (pid=" + realCallingPid + ") when starting: "
3706 + intent.toString());
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07003707 ActivityOptions.abort(options);
Dianne Hackborna4972e92012-03-14 10:38:05 -07003708 return ActivityManager.START_PERMISSION_DENIED;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003709 }
3710 }
3711
3712 IIntentSender target = mService.getIntentSenderLocked(
Dianne Hackborna4972e92012-03-14 10:38:05 -07003713 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
Dianne Hackborn41203752012-08-31 14:05:51 -07003714 realCallingUid, userId, null, null, 0, new Intent[] { intent },
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003715 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003716 | PendingIntent.FLAG_ONE_SHOT, null);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003717
3718 Intent newIntent = new Intent();
3719 if (requestCode >= 0) {
3720 // Caller is requesting a result.
3721 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
3722 }
3723 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
3724 new IntentSender(target));
3725 if (mService.mHeavyWeightProcess.activities.size() > 0) {
3726 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
3727 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
3728 hist.packageName);
3729 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
3730 hist.task.taskId);
3731 }
3732 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
3733 aInfo.packageName);
3734 newIntent.setFlags(intent.getFlags());
3735 newIntent.setClassName("android",
3736 HeavyWeightSwitcherActivity.class.getName());
3737 intent = newIntent;
3738 resolvedType = null;
3739 caller = null;
3740 callingUid = Binder.getCallingUid();
3741 callingPid = Binder.getCallingPid();
3742 componentSpecified = true;
3743 try {
3744 ResolveInfo rInfo =
3745 AppGlobals.getPackageManager().resolveIntent(
3746 intent, null,
3747 PackageManager.MATCH_DEFAULT_ONLY
Amith Yamasani483f3b02012-03-13 16:08:00 -07003748 | ActivityManagerService.STOCK_PM_FLAGS, userId);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003749 aInfo = rInfo != null ? rInfo.activityInfo : null;
Amith Yamasani742a6712011-05-04 14:49:28 -07003750 aInfo = mService.getActivityInfoForUser(aInfo, userId);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003751 } catch (RemoteException e) {
3752 aInfo = null;
3753 }
3754 }
3755 }
3756 }
3757
3758 int res = startActivityLocked(caller, intent, resolvedType,
Dianne Hackborna4972e92012-03-14 10:38:05 -07003759 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
Dianne Hackbornf265ea92013-01-31 15:00:51 -08003760 callingPackage, startFlags, options, componentSpecified, null);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003761
3762 if (mConfigWillChange && mMainStack) {
3763 // If the caller also wants to switch to a new configuration,
3764 // do so now. This allows a clean switch, as we are waiting
3765 // for the current activity to pause (so we will not destroy
3766 // it), and have not yet started the next activity.
3767 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3768 "updateConfiguration()");
3769 mConfigWillChange = false;
3770 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3771 "Updating to new configuration after starting activity.");
Dianne Hackborn813075a62011-11-14 17:45:19 -08003772 mService.updateConfigurationLocked(config, null, false, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003773 }
3774
3775 Binder.restoreCallingIdentity(origId);
3776
3777 if (outResult != null) {
3778 outResult.result = res;
Dianne Hackborna4972e92012-03-14 10:38:05 -07003779 if (res == ActivityManager.START_SUCCESS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003780 mWaitingActivityLaunched.add(outResult);
3781 do {
3782 try {
Dianne Hackbornba0492d2010-10-12 19:01:46 -07003783 mService.wait();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003784 } catch (InterruptedException e) {
3785 }
3786 } while (!outResult.timeout && outResult.who == null);
Dianne Hackborna4972e92012-03-14 10:38:05 -07003787 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003788 ActivityRecord r = this.topRunningActivityLocked(null);
3789 if (r.nowVisible) {
3790 outResult.timeout = false;
3791 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3792 outResult.totalTime = 0;
3793 outResult.thisTime = 0;
3794 } else {
3795 outResult.thisTime = SystemClock.uptimeMillis();
3796 mWaitingActivityVisible.add(outResult);
3797 do {
3798 try {
Dianne Hackbornba0492d2010-10-12 19:01:46 -07003799 mService.wait();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003800 } catch (InterruptedException e) {
3801 }
3802 } while (!outResult.timeout && outResult.who == null);
3803 }
3804 }
3805 }
3806
3807 return res;
3808 }
3809 }
3810
Dianne Hackbornf265ea92013-01-31 15:00:51 -08003811 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
Dianne Hackborna4972e92012-03-14 10:38:05 -07003812 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
3813 Bundle options, int userId) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003814 if (intents == null) {
3815 throw new NullPointerException("intents is null");
3816 }
3817 if (resolvedTypes == null) {
3818 throw new NullPointerException("resolvedTypes is null");
3819 }
3820 if (intents.length != resolvedTypes.length) {
3821 throw new IllegalArgumentException("intents are length different than resolvedTypes");
3822 }
3823
3824 ActivityRecord[] outActivity = new ActivityRecord[1];
3825
3826 int callingPid;
3827 if (callingUid >= 0) {
3828 callingPid = -1;
3829 } else if (caller == null) {
3830 callingPid = Binder.getCallingPid();
3831 callingUid = Binder.getCallingUid();
3832 } else {
3833 callingPid = callingUid = -1;
3834 }
3835 final long origId = Binder.clearCallingIdentity();
3836 try {
3837 synchronized (mService) {
3838
3839 for (int i=0; i<intents.length; i++) {
3840 Intent intent = intents[i];
3841 if (intent == null) {
3842 continue;
3843 }
3844
3845 // Refuse possible leaked file descriptors
3846 if (intent != null && intent.hasFileDescriptors()) {
3847 throw new IllegalArgumentException("File descriptors passed in Intent");
3848 }
3849
3850 boolean componentSpecified = intent.getComponent() != null;
3851
3852 // Don't modify the client's object!
3853 intent = new Intent(intent);
3854
3855 // Collect information about the target of the Intent.
Dianne Hackborna4972e92012-03-14 10:38:05 -07003856 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
Amith Yamasani483f3b02012-03-13 16:08:00 -07003857 0, null, null, userId);
Amith Yamasani742a6712011-05-04 14:49:28 -07003858 // TODO: New, check if this is correct
3859 aInfo = mService.getActivityInfoForUser(aInfo, userId);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003860
3861 if (mMainStack && aInfo != null && (aInfo.applicationInfo.flags
3862 & ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
3863 throw new IllegalArgumentException(
3864 "FLAG_CANT_SAVE_STATE not supported here");
3865 }
3866
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003867 Bundle theseOptions;
3868 if (options != null && i == intents.length-1) {
3869 theseOptions = options;
3870 } else {
3871 theseOptions = null;
3872 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003873 int res = startActivityLocked(caller, intent, resolvedTypes[i],
Dianne Hackbornf265ea92013-01-31 15:00:51 -08003874 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
Dianne Hackborn7a2195c2012-03-19 17:38:00 -07003875 0, theseOptions, componentSpecified, outActivity);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003876 if (res < 0) {
3877 return res;
3878 }
3879
Dianne Hackbornbe707852011-11-11 14:32:10 -08003880 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003881 }
3882 }
3883 } finally {
3884 Binder.restoreCallingIdentity(origId);
3885 }
3886
Dianne Hackborna4972e92012-03-14 10:38:05 -07003887 return ActivityManager.START_SUCCESS;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003888 }
3889
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003890 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
3891 long thisTime, long totalTime) {
3892 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3893 WaitResult w = mWaitingActivityLaunched.get(i);
3894 w.timeout = timeout;
3895 if (r != null) {
3896 w.who = new ComponentName(r.info.packageName, r.info.name);
3897 }
3898 w.thisTime = thisTime;
3899 w.totalTime = totalTime;
3900 }
3901 mService.notifyAll();
3902 }
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08003903
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003904 void reportActivityVisibleLocked(ActivityRecord r) {
3905 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3906 WaitResult w = mWaitingActivityVisible.get(i);
3907 w.timeout = false;
3908 if (r != null) {
3909 w.who = new ComponentName(r.info.packageName, r.info.name);
3910 }
3911 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3912 w.thisTime = w.totalTime;
3913 }
3914 mService.notifyAll();
Dianne Hackborn90c52de2011-09-23 12:57:44 -07003915
3916 if (mDismissKeyguardOnNextActivity) {
3917 mDismissKeyguardOnNextActivity = false;
3918 mService.mWindowManager.dismissKeyguard();
3919 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003920 }
3921
3922 void sendActivityResultLocked(int callingUid, ActivityRecord r,
3923 String resultWho, int requestCode, int resultCode, Intent data) {
3924
3925 if (callingUid > 0) {
3926 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
Dianne Hackborn7e269642010-08-25 19:50:20 -07003927 data, r.getUriPermissionsLocked());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003928 }
3929
3930 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
3931 + " : who=" + resultWho + " req=" + requestCode
3932 + " res=" + resultCode + " data=" + data);
3933 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
3934 try {
3935 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
3936 list.add(new ResultInfo(resultWho, requestCode,
3937 resultCode, data));
Dianne Hackbornbe707852011-11-11 14:32:10 -08003938 r.app.thread.scheduleSendResult(r.appToken, list);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003939 return;
3940 } catch (Exception e) {
3941 Slog.w(TAG, "Exception thrown sending result to " + r, e);
3942 }
3943 }
3944
3945 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
3946 }
3947
3948 private final void stopActivityLocked(ActivityRecord r) {
3949 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
3950 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3951 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3952 if (!r.finishing) {
Christopher Tated3f175c2012-06-14 14:16:54 -07003953 if (!mService.mSleeping) {
3954 if (DEBUG_STATES) {
3955 Slog.d(TAG, "no-history finish of " + r);
3956 }
3957 requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07003958 "no-history", false);
Christopher Tated3f175c2012-06-14 14:16:54 -07003959 } else {
3960 if (DEBUG_STATES) Slog.d(TAG, "Not finishing noHistory " + r
3961 + " on stop because we're just sleeping");
3962 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003963 }
Christopher Tate5007ddd2012-06-12 13:08:18 -07003964 }
3965
3966 if (r.app != null && r.app.thread != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003967 if (mMainStack) {
3968 if (mService.mFocusedActivity == r) {
3969 mService.setFocusedActivityLocked(topRunningActivityLocked(null));
3970 }
3971 }
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08003972 r.resumeKeyDispatchingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003973 try {
3974 r.stopped = false;
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003975 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
3976 + " (stop requested)");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003977 r.state = ActivityState.STOPPING;
3978 if (DEBUG_VISBILITY) Slog.v(
3979 TAG, "Stopping visible=" + r.visible + " for " + r);
3980 if (!r.visible) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08003981 mService.mWindowManager.setAppVisibility(r.appToken, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003982 }
Dianne Hackbornbe707852011-11-11 14:32:10 -08003983 r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08003984 if (mService.isSleeping()) {
3985 r.setSleeping(true);
3986 }
Dianne Hackborn162bc0e2012-04-09 14:06:16 -07003987 Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG);
3988 msg.obj = r;
3989 mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003990 } catch (Exception e) {
3991 // Maybe just ignore exceptions here... if the process
3992 // has crashed, our death notification will clean things
3993 // up.
3994 Slog.w(TAG, "Exception thrown during pause", e);
3995 // Just in case, assume it to be stopped.
3996 r.stopped = true;
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003997 if (DEBUG_STATES) Slog.v(TAG, "Stop failed; moving to STOPPED: " + r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003998 r.state = ActivityState.STOPPED;
3999 if (r.configDestroy) {
Dianne Hackborn28695e02011-11-02 21:59:51 -07004000 destroyActivityLocked(r, true, false, "stop-except");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004001 }
4002 }
4003 }
4004 }
4005
4006 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(
4007 boolean remove) {
4008 int N = mStoppingActivities.size();
4009 if (N <= 0) return null;
4010
4011 ArrayList<ActivityRecord> stops = null;
4012
4013 final boolean nowVisible = mResumedActivity != null
4014 && mResumedActivity.nowVisible
4015 && !mResumedActivity.waitingVisible;
4016 for (int i=0; i<N; i++) {
4017 ActivityRecord s = mStoppingActivities.get(i);
4018 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
4019 + nowVisible + " waitingVisible=" + s.waitingVisible
4020 + " finishing=" + s.finishing);
4021 if (s.waitingVisible && nowVisible) {
4022 mWaitingVisibleActivities.remove(s);
4023 s.waitingVisible = false;
4024 if (s.finishing) {
4025 // If this activity is finishing, it is sitting on top of
4026 // everyone else but we now know it is no longer needed...
4027 // so get rid of it. Otherwise, we need to go through the
4028 // normal flow and hide it once we determine that it is
4029 // hidden by the activities in front of it.
4030 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
Dianne Hackbornbe707852011-11-11 14:32:10 -08004031 mService.mWindowManager.setAppVisibility(s.appToken, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004032 }
4033 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08004034 if ((!s.waitingVisible || mService.isSleeping()) && remove) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004035 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
4036 if (stops == null) {
4037 stops = new ArrayList<ActivityRecord>();
4038 }
4039 stops.add(s);
4040 mStoppingActivities.remove(i);
4041 N--;
4042 i--;
4043 }
4044 }
4045
4046 return stops;
4047 }
4048
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07004049 final void scheduleIdleLocked() {
4050 Message msg = Message.obtain();
4051 msg.what = IDLE_NOW_MSG;
4052 mHandler.sendMessage(msg);
4053 }
4054
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07004055 final ActivityRecord activityIdleInternal(IBinder token, boolean fromTimeout,
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004056 Configuration config) {
4057 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
4058
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07004059 ActivityRecord res = null;
4060
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004061 ArrayList<ActivityRecord> stops = null;
4062 ArrayList<ActivityRecord> finishes = null;
4063 ArrayList<ActivityRecord> thumbnails = null;
Dianne Hackborn80a4af22012-08-27 19:18:31 -07004064 ArrayList<UserStartedState> startingUsers = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004065 int NS = 0;
4066 int NF = 0;
4067 int NT = 0;
4068 IApplicationThread sendThumbnail = null;
4069 boolean booting = false;
4070 boolean enableScreen = false;
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004071 boolean activityRemoved = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004072
4073 synchronized (mService) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08004074 ActivityRecord r = ActivityRecord.forToken(token);
4075 if (r != null) {
4076 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07004077 r.finishLaunchTickingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004078 }
4079
4080 // Get the activity record.
Craig Mautnerd44711d2013-02-23 11:24:36 -08004081 if (isInStackLocked(token) != null) {
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07004082 res = r;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004083
4084 if (fromTimeout) {
4085 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
4086 }
4087
4088 // This is a hack to semi-deal with a race condition
4089 // in the client where it can be constructed with a
4090 // newer configuration from when we asked it to launch.
4091 // We'll update with whatever configuration it now says
4092 // it used to launch.
4093 if (config != null) {
4094 r.configuration = config;
4095 }
4096
4097 // No longer need to keep the device awake.
4098 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
4099 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
4100 mLaunchingActivity.release();
4101 }
4102
4103 // We are now idle. If someone is waiting for a thumbnail from
4104 // us, we can now deliver.
4105 r.idle = true;
4106 mService.scheduleAppGcsLocked();
4107 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
4108 sendThumbnail = r.app.thread;
4109 r.thumbnailNeeded = false;
4110 }
4111
4112 // If this activity is fullscreen, set up to hide those under it.
4113
4114 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
4115 ensureActivitiesVisibleLocked(null, 0);
4116
4117 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
4118 if (mMainStack) {
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07004119 if (!mService.mBooted) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004120 mService.mBooted = true;
4121 enableScreen = true;
4122 }
4123 }
4124
4125 } else if (fromTimeout) {
4126 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
4127 }
4128
4129 // Atomically retrieve all of the other things to do.
4130 stops = processStoppingActivitiesLocked(true);
4131 NS = stops != null ? stops.size() : 0;
4132 if ((NF=mFinishingActivities.size()) > 0) {
4133 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
4134 mFinishingActivities.clear();
4135 }
Craig Mautnercae015f2013-02-08 14:31:27 -08004136 if ((NT=mCancelledThumbnails.size()) > 0) {
4137 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
4138 mCancelledThumbnails.clear();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004139 }
4140
4141 if (mMainStack) {
4142 booting = mService.mBooting;
4143 mService.mBooting = false;
4144 }
Dianne Hackborn80a4af22012-08-27 19:18:31 -07004145 if (mStartingUsers.size() > 0) {
4146 startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
4147 mStartingUsers.clear();
4148 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004149 }
4150
4151 int i;
4152
4153 // Send thumbnail if requested.
4154 if (sendThumbnail != null) {
4155 try {
4156 sendThumbnail.requestThumbnail(token);
4157 } catch (Exception e) {
4158 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
4159 mService.sendPendingThumbnail(null, token, null, null, true);
4160 }
4161 }
4162
4163 // Stop any activities that are scheduled to do so but have been
4164 // waiting for the next one to start.
4165 for (i=0; i<NS; i++) {
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004166 ActivityRecord r = stops.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004167 synchronized (mService) {
4168 if (r.finishing) {
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07004169 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004170 } else {
4171 stopActivityLocked(r);
4172 }
4173 }
4174 }
4175
4176 // Finish any activities that are scheduled to do so but have been
4177 // waiting for the next one to start.
4178 for (i=0; i<NF; i++) {
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004179 ActivityRecord r = finishes.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004180 synchronized (mService) {
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004181 activityRemoved = destroyActivityLocked(r, true, false, "finish-idle");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004182 }
4183 }
4184
4185 // Report back to any thumbnail receivers.
4186 for (i=0; i<NT; i++) {
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004187 ActivityRecord r = thumbnails.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004188 mService.sendPendingThumbnail(r, null, null, null, true);
4189 }
4190
4191 if (booting) {
4192 mService.finishBooting();
Dianne Hackborn80a4af22012-08-27 19:18:31 -07004193 } else if (startingUsers != null) {
4194 for (i=0; i<startingUsers.size(); i++) {
4195 mService.finishUserSwitch(startingUsers.get(i));
4196 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004197 }
4198
4199 mService.trimApplications();
4200 //dump();
4201 //mWindowManager.dump();
4202
4203 if (enableScreen) {
4204 mService.enableScreenAfterBoot();
4205 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07004206
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004207 if (activityRemoved) {
4208 resumeTopActivityLocked(null);
4209 }
4210
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07004211 return res;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004212 }
4213
4214 /**
4215 * @return Returns true if the activity is being finished, false if for
4216 * some reason it is being left as-is.
4217 */
4218 final boolean requestFinishActivityLocked(IBinder token, int resultCode,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07004219 Intent resultData, String reason, boolean oomAdj) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004220 int index = indexOfTokenLocked(token);
Christopher Tated3f175c2012-06-14 14:16:54 -07004221 if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07004222 TAG, "Finishing activity @" + index + ": token=" + token
Christopher Tated3f175c2012-06-14 14:16:54 -07004223 + ", result=" + resultCode + ", data=" + resultData
4224 + ", reason=" + reason);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004225 if (index < 0) {
4226 return false;
4227 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004228 ActivityRecord r = mHistory.get(index);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004229
Craig Mautnerd44711d2013-02-23 11:24:36 -08004230 finishActivityLocked(r, resultCode, resultData, reason, oomAdj);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004231 return true;
4232 }
4233
Dianne Hackbornecc5a9c2012-04-26 18:56:09 -07004234 final void finishSubActivityLocked(IBinder token, String resultWho, int requestCode) {
4235 ActivityRecord self = isInStackLocked(token);
4236 if (self == null) {
4237 return;
4238 }
4239
4240 int i;
4241 for (i=mHistory.size()-1; i>=0; i--) {
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004242 ActivityRecord r = mHistory.get(i);
Dianne Hackbornecc5a9c2012-04-26 18:56:09 -07004243 if (r.resultTo == self && r.requestCode == requestCode) {
4244 if ((r.resultWho == null && resultWho == null) ||
4245 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Craig Mautnerd44711d2013-02-23 11:24:36 -08004246 finishActivityLocked(r, Activity.RESULT_CANCELED,
4247 null, "request-sub", false);
Dianne Hackbornecc5a9c2012-04-26 18:56:09 -07004248 }
4249 }
4250 }
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07004251 mService.updateOomAdjLocked();
Dianne Hackbornecc5a9c2012-04-26 18:56:09 -07004252 }
4253
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004254 final void finishTopRunningActivityLocked(ProcessRecord app) {
4255 ActivityRecord r = topRunningActivityLocked(null);
4256 if (r != null && r.app == app) {
4257 // If the top running activity is from this crashing
4258 // process, then terminate it to avoid getting in a loop.
4259 Slog.w(TAG, " Force finishing activity "
4260 + r.intent.getComponent().flattenToShortString());
4261 int index = mHistory.indexOf(r);
Craig Mautnerd44711d2013-02-23 11:24:36 -08004262 r.stack.finishActivityLocked(r, Activity.RESULT_CANCELED,
4263 null, "crashed", false);
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004264 // Also terminate any activities below it that aren't yet
4265 // stopped, to avoid a situation where one will get
4266 // re-start our crashing activity once it gets resumed again.
4267 index--;
4268 if (index >= 0) {
4269 r = mHistory.get(index);
4270 if (r.state == ActivityState.RESUMED
4271 || r.state == ActivityState.PAUSING
4272 || r.state == ActivityState.PAUSED) {
4273 if (!r.isHomeActivity || mService.mHomeProcess != r.app) {
4274 Slog.w(TAG, " Force finishing activity "
4275 + r.intent.getComponent().flattenToShortString());
Craig Mautnerd44711d2013-02-23 11:24:36 -08004276 r.stack.finishActivityLocked(r, Activity.RESULT_CANCELED,
4277 null, "crashed", false);
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004278 }
4279 }
4280 }
4281 }
4282 }
4283
Dianne Hackbornecc5a9c2012-04-26 18:56:09 -07004284 final boolean finishActivityAffinityLocked(IBinder token) {
4285 int index = indexOfTokenLocked(token);
4286 if (DEBUG_RESULTS) Slog.v(
4287 TAG, "Finishing activity affinity @" + index + ": token=" + token);
4288 if (index < 0) {
4289 return false;
4290 }
4291 ActivityRecord r = mHistory.get(index);
4292
Amith Yamasanibfc1be12012-05-15 11:12:17 -07004293 while (index >= 0) {
Dianne Hackbornecc5a9c2012-04-26 18:56:09 -07004294 ActivityRecord cur = mHistory.get(index);
4295 if (cur.task != r.task) {
4296 break;
4297 }
4298 if (cur.taskAffinity == null && r.taskAffinity != null) {
4299 break;
4300 }
4301 if (cur.taskAffinity != null && !cur.taskAffinity.equals(r.taskAffinity)) {
4302 break;
4303 }
Craig Mautnerd44711d2013-02-23 11:24:36 -08004304 finishActivityLocked(cur, Activity.RESULT_CANCELED, null, "request-affinity",
4305 true);
Dianne Hackbornecc5a9c2012-04-26 18:56:09 -07004306 index--;
4307 }
4308 return true;
4309 }
4310
Dianne Hackborn5c607432012-02-28 14:44:19 -08004311 final void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
4312 // send the result
4313 ActivityRecord resultTo = r.resultTo;
4314 if (resultTo != null) {
4315 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
4316 + " who=" + r.resultWho + " req=" + r.requestCode
4317 + " res=" + resultCode + " data=" + resultData);
4318 if (r.info.applicationInfo.uid > 0) {
4319 mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4320 resultTo.packageName, resultData,
4321 resultTo.getUriPermissionsLocked());
4322 }
4323 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4324 resultData);
4325 r.resultTo = null;
4326 }
4327 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
4328
4329 // Make sure this HistoryRecord is not holding on to other resources,
4330 // because clients have remote IPC references to this object so we
4331 // can't assume that will go away and want to avoid circular IPC refs.
4332 r.results = null;
4333 r.pendingResults = null;
4334 r.newIntents = null;
4335 r.icicle = null;
4336 }
4337
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004338 /**
4339 * @return Returns true if this activity has been removed from the history
4340 * list, or false if it is still in the list and will be removed later.
4341 */
Craig Mautnerd44711d2013-02-23 11:24:36 -08004342 final boolean finishActivityLocked(ActivityRecord r, int resultCode,
4343 Intent resultData, String reason, boolean oomAdj) {
4344 return finishActivityLocked(r, resultCode, resultData, reason, false, oomAdj);
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004345 }
4346
4347 /**
4348 * @return Returns true if this activity has been removed from the history
4349 * list, or false if it is still in the list and will be removed later.
4350 */
Craig Mautnerd44711d2013-02-23 11:24:36 -08004351 final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
4352 String reason, boolean immediate, boolean oomAdj) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004353 if (r.finishing) {
4354 Slog.w(TAG, "Duplicate finish request for " + r);
4355 return false;
4356 }
4357
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08004358 r.makeFinishing();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004359 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
Dianne Hackbornb12e1352012-09-26 11:39:20 -07004360 r.userId, System.identityHashCode(r),
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004361 r.task.taskId, r.shortComponentName, reason);
Craig Mautnerd44711d2013-02-23 11:24:36 -08004362 final ArrayList<ActivityRecord> activities = r.task.mActivities;
4363 final int index = activities.indexOf(r);
4364 if (index < (activities.size() - 1)) {
4365 ActivityRecord next = activities.get(index+1);
4366 if (r.frontOfTask) {
4367 // The next activity is now the front of the task.
4368 next.frontOfTask = true;
4369 }
4370 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
4371 // If the caller asked that this activity (and all above it)
4372 // be cleared when the task is reset, don't lose that information,
4373 // but propagate it up to the next activity.
4374 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004375 }
4376 }
4377
4378 r.pauseKeyDispatchingLocked();
4379 if (mMainStack) {
4380 if (mService.mFocusedActivity == r) {
4381 mService.setFocusedActivityLocked(topRunningActivityLocked(null));
4382 }
4383 }
4384
Dianne Hackborn5c607432012-02-28 14:44:19 -08004385 finishActivityResultsLocked(r, resultCode, resultData);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004386
4387 if (mService.mPendingThumbnails.size() > 0) {
4388 // There are clients waiting to receive thumbnails so, in case
4389 // this is an activity that someone is waiting for, add it
4390 // to the pending list so we can correctly update the clients.
Craig Mautnercae015f2013-02-08 14:31:27 -08004391 mCancelledThumbnails.add(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004392 }
4393
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07004394 if (immediate) {
Craig Mautnerd44711d2013-02-23 11:24:36 -08004395 return finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, oomAdj) == null;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07004396 } else if (mResumedActivity == r) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004397 boolean endTask = index <= 0
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004398 || (mHistory.get(index-1)).task != r.task;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004399 if (DEBUG_TRANSITION) Slog.v(TAG,
4400 "Prepare close transition: finishing " + r);
4401 mService.mWindowManager.prepareAppTransition(endTask
Craig Mautner4b71aa12012-12-27 17:20:01 -08004402 ? AppTransition.TRANSIT_TASK_CLOSE
4403 : AppTransition.TRANSIT_ACTIVITY_CLOSE, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004404
4405 // Tell window manager to prepare for this one to be removed.
Dianne Hackbornbe707852011-11-11 14:32:10 -08004406 mService.mWindowManager.setAppVisibility(r.appToken, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004407
Dianne Hackborn621e2fe2012-02-16 17:07:33 -08004408 if (mPausingActivity == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004409 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4410 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
4411 startPausingLocked(false, false);
4412 }
4413
4414 } else if (r.state != ActivityState.PAUSING) {
4415 // If the activity is PAUSING, we will complete the finish once
4416 // it is done pausing; else we can just directly finish it here.
4417 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
Craig Mautnerd44711d2013-02-23 11:24:36 -08004418 return finishCurrentActivityLocked(r, FINISH_AFTER_PAUSE, oomAdj) == null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004419 } else {
4420 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
4421 }
4422
4423 return false;
4424 }
4425
4426 private static final int FINISH_IMMEDIATELY = 0;
4427 private static final int FINISH_AFTER_PAUSE = 1;
4428 private static final int FINISH_AFTER_VISIBLE = 2;
4429
Craig Mautnerd44711d2013-02-23 11:24:36 -08004430
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004431 private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07004432 int mode, boolean oomAdj) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004433 // First things first: if this activity is currently visible,
4434 // and the resumed activity is not yet visible, then hold off on
4435 // finishing until the resumed one becomes visible.
4436 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4437 if (!mStoppingActivities.contains(r)) {
4438 mStoppingActivities.add(r);
4439 if (mStoppingActivities.size() > 3) {
4440 // If we already have a few activities waiting to stop,
4441 // then give up on things going idle and start clearing
4442 // them out.
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07004443 scheduleIdleLocked();
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08004444 } else {
4445 checkReadyForSleepLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004446 }
4447 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004448 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
4449 + " (finish requested)");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004450 r.state = ActivityState.STOPPING;
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07004451 if (oomAdj) {
4452 mService.updateOomAdjLocked();
4453 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004454 return r;
4455 }
4456
4457 // make sure the record is cleaned out of other places.
4458 mStoppingActivities.remove(r);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08004459 mGoingToSleepActivities.remove(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004460 mWaitingVisibleActivities.remove(r);
4461 if (mResumedActivity == r) {
4462 mResumedActivity = null;
4463 }
4464 final ActivityState prevState = r.state;
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004465 if (DEBUG_STATES) Slog.v(TAG, "Moving to FINISHING: " + r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004466 r.state = ActivityState.FINISHING;
4467
4468 if (mode == FINISH_IMMEDIATELY
4469 || prevState == ActivityState.STOPPED
4470 || prevState == ActivityState.INITIALIZING) {
4471 // If this activity is already stopped, we can just finish
4472 // it right now.
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07004473 boolean activityRemoved = destroyActivityLocked(r, true,
4474 oomAdj, "finish-imm");
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004475 if (activityRemoved) {
4476 resumeTopActivityLocked(null);
4477 }
4478 return activityRemoved ? null : r;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004479 }
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004480
4481 // Need to go through the full pause cycle to get this
4482 // activity into the stopped state and then finish it.
4483 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
4484 mFinishingActivities.add(r);
4485 resumeTopActivityLocked(null);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004486 return r;
4487 }
4488
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004489 final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode,
4490 Intent resultData) {
4491 final int start = mHistory.indexOf(srec);
4492 if (start < 0) {
4493 // Current activity is not in history stack; do nothing.
4494 return false;
4495 }
4496 int finishTo = start - 1;
4497 ActivityRecord parent = null;
4498 boolean foundParentInTask = false;
4499 ComponentName dest = destIntent.getComponent();
4500 if (dest != null) {
4501 TaskRecord tr = srec.task;
4502 for (int i = start - 1; i >= 0; i--) {
4503 ActivityRecord r = mHistory.get(i);
4504 if (tr != r.task) {
4505 // Couldn't find parent in the same task; stop at the one above this.
4506 // (Root of current task; in-app "home" behavior)
4507 // Always at least finish the current activity.
4508 finishTo = Math.min(start - 1, i + 1);
4509 parent = mHistory.get(finishTo);
4510 break;
4511 } else if (r.info.packageName.equals(dest.getPackageName()) &&
4512 r.info.name.equals(dest.getClassName())) {
4513 finishTo = i;
4514 parent = r;
4515 foundParentInTask = true;
4516 break;
4517 }
4518 }
4519 }
4520
4521 IActivityController controller = mService.mController;
4522 if (controller != null) {
4523 ActivityRecord next = topRunningActivityLocked(srec.appToken, 0);
4524 if (next != null) {
4525 // ask watcher if this is allowed
4526 boolean resumeOK = true;
4527 try {
4528 resumeOK = controller.activityResuming(next.packageName);
4529 } catch (RemoteException e) {
4530 mService.mController = null;
4531 }
4532
4533 if (!resumeOK) {
4534 return false;
4535 }
4536 }
4537 }
4538 final long origId = Binder.clearCallingIdentity();
4539 for (int i = start; i > finishTo; i--) {
4540 ActivityRecord r = mHistory.get(i);
4541 requestFinishActivityLocked(r.appToken, resultCode, resultData,
4542 "navigate-up", true);
4543 // Only return the supplied result for the first activity finished
4544 resultCode = Activity.RESULT_CANCELED;
4545 resultData = null;
4546 }
4547
4548 if (parent != null && foundParentInTask) {
4549 final int parentLaunchMode = parent.info.launchMode;
4550 final int destIntentFlags = destIntent.getFlags();
4551 if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE ||
4552 parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
4553 parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
4554 (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
4555 parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent);
4556 } else {
4557 try {
4558 ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
4559 destIntent.getComponent(), 0, srec.userId);
4560 int res = startActivityLocked(srec.app.thread, destIntent,
4561 null, aInfo, parent.appToken, null,
4562 0, -1, parent.launchedFromUid, parent.launchedFromPackage,
4563 0, null, true, null);
4564 foundParentInTask = res == ActivityManager.START_SUCCESS;
4565 } catch (RemoteException e) {
4566 foundParentInTask = false;
4567 }
4568 requestFinishActivityLocked(parent.appToken, resultCode,
4569 resultData, "navigate-up", true);
4570 }
4571 }
4572 Binder.restoreCallingIdentity(origId);
4573 return foundParentInTask;
4574 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004575 /**
4576 * Perform the common clean-up of an activity record. This is called both
4577 * as part of destroyActivityLocked() (when destroying the client-side
4578 * representation) and cleaning things up as a result of its hosting
4579 * processing going away, in which case there is no remaining client-side
4580 * state to destroy so only the cleanup here is needed.
4581 */
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004582 final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices,
4583 boolean setState) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004584 if (mResumedActivity == r) {
4585 mResumedActivity = null;
4586 }
4587 if (mService.mFocusedActivity == r) {
4588 mService.mFocusedActivity = null;
4589 }
4590
4591 r.configDestroy = false;
4592 r.frozenBeforeDestroy = false;
4593
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004594 if (setState) {
4595 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (cleaning up)");
4596 r.state = ActivityState.DESTROYED;
Dianne Hackborn07981492013-01-28 11:36:23 -08004597 if (DEBUG_APP) Slog.v(TAG, "Clearing app during cleanUp for activity " + r);
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004598 r.app = null;
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004599 }
4600
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004601 // Make sure this record is no longer in the pending finishes list.
4602 // This could happen, for example, if we are trimming activities
4603 // down to the max limit while they are still waiting to finish.
4604 mFinishingActivities.remove(r);
4605 mWaitingVisibleActivities.remove(r);
4606
4607 // Remove any pending results.
4608 if (r.finishing && r.pendingResults != null) {
4609 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4610 PendingIntentRecord rec = apr.get();
4611 if (rec != null) {
4612 mService.cancelIntentSenderLocked(rec, false);
4613 }
4614 }
4615 r.pendingResults = null;
4616 }
4617
4618 if (cleanServices) {
4619 cleanUpActivityServicesLocked(r);
4620 }
4621
4622 if (mService.mPendingThumbnails.size() > 0) {
4623 // There are clients waiting to receive thumbnails so, in case
4624 // this is an activity that someone is waiting for, add it
4625 // to the pending list so we can correctly update the clients.
Craig Mautnercae015f2013-02-08 14:31:27 -08004626 mCancelledThumbnails.add(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004627 }
4628
4629 // Get rid of any pending idle timeouts.
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004630 removeTimeoutsForActivityLocked(r);
4631 }
4632
4633 private void removeTimeoutsForActivityLocked(ActivityRecord r) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004634 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
Dianne Hackborn162bc0e2012-04-09 14:06:16 -07004635 mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004636 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004637 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07004638 r.finishLaunchTickingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004639 }
4640
Dianne Hackborn5c607432012-02-28 14:44:19 -08004641 final void removeActivityFromHistoryLocked(ActivityRecord r) {
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004642 finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
4643 r.makeFinishing();
4644 if (DEBUG_ADD_REMOVE) {
4645 RuntimeException here = new RuntimeException("here");
4646 here.fillInStackTrace();
4647 Slog.i(TAG, "Removing activity " + r + " from stack");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004648 }
Craig Mautner11bf9a52013-02-19 14:08:51 -08004649 final TaskRecord task = r.task;
4650 if (task != null) {
4651 task.removeActivity(r);
Craig Mautner5d9c7be2013-02-15 14:02:56 -08004652 }
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004653 mHistory.remove(r);
4654 r.takeFromHistory();
4655 removeTimeoutsForActivityLocked(r);
4656 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
4657 + " (removed from history)");
4658 r.state = ActivityState.DESTROYED;
Dianne Hackborn07981492013-01-28 11:36:23 -08004659 if (DEBUG_APP) Slog.v(TAG, "Clearing app during remove for activity " + r);
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004660 r.app = null;
4661 mService.mWindowManager.removeAppToken(r.appToken);
4662 if (VALIDATE_TOKENS) {
4663 validateAppTokensLocked();
4664 }
4665 cleanUpActivityServicesLocked(r);
4666 r.removeUriPermissionsLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004667 }
4668
4669 /**
4670 * Perform clean-up of service connections in an activity record.
4671 */
4672 final void cleanUpActivityServicesLocked(ActivityRecord r) {
4673 // Throw away any services that have been bound by this activity.
4674 if (r.connections != null) {
4675 Iterator<ConnectionRecord> it = r.connections.iterator();
4676 while (it.hasNext()) {
4677 ConnectionRecord c = it.next();
Dianne Hackborn599db5c2012-08-03 19:28:48 -07004678 mService.mServices.removeConnectionLocked(c, null, r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004679 }
4680 r.connections = null;
4681 }
4682 }
Dianne Hackborn755c8bf2012-05-07 15:06:09 -07004683
4684 final void scheduleDestroyActivities(ProcessRecord owner, boolean oomAdj, String reason) {
4685 Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG);
4686 msg.obj = new ScheduleDestroyArgs(owner, oomAdj, reason);
4687 mHandler.sendMessage(msg);
4688 }
4689
Dianne Hackborn28695e02011-11-02 21:59:51 -07004690 final void destroyActivitiesLocked(ProcessRecord owner, boolean oomAdj, String reason) {
Dianne Hackborn755c8bf2012-05-07 15:06:09 -07004691 boolean lastIsOpaque = false;
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004692 boolean activityRemoved = false;
Craig Mautnerd44711d2013-02-23 11:24:36 -08004693 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4694 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
4695 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
4696 final ActivityRecord r = activities.get(activityNdx);
4697 if (r.finishing) {
4698 continue;
4699 }
4700 if (r.fullscreen) {
4701 lastIsOpaque = true;
4702 }
4703 if (owner != null && r.app != owner) {
4704 continue;
4705 }
4706 if (!lastIsOpaque) {
4707 continue;
4708 }
4709 // We can destroy this one if we have its icicle saved and
4710 // it is not in the process of pausing/stopping/finishing.
4711 if (r.app != null && r != mResumedActivity && r != mPausingActivity
4712 && r.haveState && !r.visible && r.stopped
4713 && r.state != ActivityState.DESTROYING
4714 && r.state != ActivityState.DESTROYED) {
4715 if (DEBUG_SWITCH) Slog.v(TAG, "Destroying " + r + " in state " + r.state
4716 + " resumed=" + mResumedActivity
4717 + " pausing=" + mPausingActivity);
4718 if (destroyActivityLocked(r, true, oomAdj, reason)) {
4719 activityRemoved = true;
4720 }
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004721 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004722 }
4723 }
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004724 if (activityRemoved) {
4725 resumeTopActivityLocked(null);
4726 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004727 }
4728
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004729 /**
4730 * Destroy the current CLIENT SIDE instance of an activity. This may be
4731 * called both when actually finishing an activity, or when performing
4732 * a configuration switch where we destroy the current client-side object
4733 * but then create a new client-side object for this same HistoryRecord.
4734 */
4735 final boolean destroyActivityLocked(ActivityRecord r,
Dianne Hackborn28695e02011-11-02 21:59:51 -07004736 boolean removeFromApp, boolean oomAdj, String reason) {
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004737 if (DEBUG_SWITCH || DEBUG_CLEANUP) Slog.v(
Dianne Hackborn755c8bf2012-05-07 15:06:09 -07004738 TAG, "Removing activity from " + reason + ": token=" + r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004739 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
4740 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
Dianne Hackbornb12e1352012-09-26 11:39:20 -07004741 r.userId, System.identityHashCode(r),
Dianne Hackborn28695e02011-11-02 21:59:51 -07004742 r.task.taskId, r.shortComponentName, reason);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004743
4744 boolean removedFromHistory = false;
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004745
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004746 cleanUpActivityLocked(r, false, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004747
4748 final boolean hadApp = r.app != null;
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004749
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004750 if (hadApp) {
4751 if (removeFromApp) {
4752 int idx = r.app.activities.indexOf(r);
4753 if (idx >= 0) {
4754 r.app.activities.remove(idx);
4755 }
4756 if (mService.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
4757 mService.mHeavyWeightProcess = null;
4758 mService.mHandler.sendEmptyMessage(
4759 ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG);
4760 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004761 if (r.app.activities.size() == 0) {
Dianne Hackborn2d1b3782012-09-09 17:49:39 -07004762 // No longer have activities, so update oom adj.
4763 mService.updateOomAdjLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004764 }
4765 }
4766
4767 boolean skipDestroy = false;
4768
4769 try {
4770 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
Dianne Hackbornbe707852011-11-11 14:32:10 -08004771 r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004772 r.configChangeFlags);
4773 } catch (Exception e) {
4774 // We can just ignore exceptions here... if the process
4775 // has crashed, our death notification will clean things
4776 // up.
4777 //Slog.w(TAG, "Exception thrown during finish", e);
4778 if (r.finishing) {
4779 removeActivityFromHistoryLocked(r);
4780 removedFromHistory = true;
4781 skipDestroy = true;
4782 }
4783 }
4784
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004785 r.nowVisible = false;
4786
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004787 // If the activity is finishing, we need to wait on removing it
4788 // from the list to give it a chance to do its cleanup. During
4789 // that time it may make calls back with its token so we need to
4790 // be able to find it on the list and so we don't want to remove
4791 // it from the list yet. Otherwise, we can just immediately put
4792 // it in the destroyed state since we are not removing it from the
4793 // list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004794 if (r.finishing && !skipDestroy) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004795 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYING: " + r
4796 + " (destroy requested)");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004797 r.state = ActivityState.DESTROYING;
4798 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4799 msg.obj = r;
4800 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4801 } else {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004802 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
4803 + " (destroy skipped)");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004804 r.state = ActivityState.DESTROYED;
Dianne Hackborn07981492013-01-28 11:36:23 -08004805 if (DEBUG_APP) Slog.v(TAG, "Clearing app during destroy for activity " + r);
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004806 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004807 }
4808 } else {
4809 // remove this record from the history.
4810 if (r.finishing) {
4811 removeActivityFromHistoryLocked(r);
4812 removedFromHistory = true;
4813 } else {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004814 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
4815 + " (no app)");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004816 r.state = ActivityState.DESTROYED;
Dianne Hackborn07981492013-01-28 11:36:23 -08004817 if (DEBUG_APP) Slog.v(TAG, "Clearing app during destroy for activity " + r);
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004818 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004819 }
4820 }
4821
4822 r.configChangeFlags = 0;
4823
4824 if (!mLRUActivities.remove(r) && hadApp) {
4825 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
4826 }
4827
4828 return removedFromHistory;
4829 }
4830
4831 final void activityDestroyed(IBinder token) {
4832 synchronized (mService) {
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004833 final long origId = Binder.clearCallingIdentity();
4834 try {
4835 ActivityRecord r = ActivityRecord.forToken(token);
4836 if (r != null) {
4837 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004838 }
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004839
Craig Mautnerd44711d2013-02-23 11:24:36 -08004840 if (isInStackLocked(token) != null) {
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004841 if (r.state == ActivityState.DESTROYING) {
Dianne Hackborn45a25bc2012-06-28 13:49:17 -07004842 cleanUpActivityLocked(r, true, false);
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004843 removeActivityFromHistoryLocked(r);
4844 }
4845 }
4846 resumeTopActivityLocked(null);
4847 } finally {
4848 Binder.restoreCallingIdentity(origId);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004849 }
4850 }
4851 }
4852
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004853 private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list,
4854 ProcessRecord app, String listName) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004855 int i = list.size();
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004856 if (DEBUG_CLEANUP) Slog.v(
4857 TAG, "Removing app " + app + " from list " + listName
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004858 + " with " + i + " entries");
4859 while (i > 0) {
4860 i--;
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004861 ActivityRecord r = list.get(i);
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004862 if (DEBUG_CLEANUP) Slog.v(TAG, "Record #" + i + " " + r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004863 if (r.app == app) {
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004864 if (DEBUG_CLEANUP) Slog.v(TAG, "---> REMOVING this entry!");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004865 list.remove(i);
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004866 removeTimeoutsForActivityLocked(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004867 }
4868 }
4869 }
4870
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004871 boolean removeHistoryRecordsForAppLocked(ProcessRecord app) {
4872 removeHistoryRecordsForAppLocked(mLRUActivities, app, "mLRUActivities");
4873 removeHistoryRecordsForAppLocked(mStoppingActivities, app, "mStoppingActivities");
4874 removeHistoryRecordsForAppLocked(mGoingToSleepActivities, app, "mGoingToSleepActivities");
4875 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app,
4876 "mWaitingVisibleActivities");
4877 removeHistoryRecordsForAppLocked(mFinishingActivities, app, "mFinishingActivities");
4878
4879 boolean hasVisibleActivities = false;
4880
4881 // Clean out the history list.
4882 int i = mHistory.size();
4883 if (DEBUG_CLEANUP) Slog.v(
4884 TAG, "Removing app " + app + " from history with " + i + " entries");
4885 while (i > 0) {
4886 i--;
Craig Mautner05d6272ba2013-02-11 09:39:27 -08004887 ActivityRecord r = mHistory.get(i);
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004888 if (DEBUG_CLEANUP) Slog.v(
4889 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4890 if (r.app == app) {
Dianne Hackborn07981492013-01-28 11:36:23 -08004891 boolean remove;
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004892 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Dianne Hackborn07981492013-01-28 11:36:23 -08004893 // Don't currently have state for the activity, or
4894 // it is finishing -- always remove it.
4895 remove = true;
4896 } else if (r.launchCount > 2 &&
4897 r.lastLaunchTime > (SystemClock.uptimeMillis()-60000)) {
4898 // We have launched this activity too many times since it was
4899 // able to run, so give up and remove it.
4900 remove = true;
4901 } else {
4902 // The process may be gone, but the activity lives on!
4903 remove = false;
4904 }
4905 if (remove) {
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004906 if (ActivityStack.DEBUG_ADD_REMOVE || DEBUG_CLEANUP) {
4907 RuntimeException here = new RuntimeException("here");
4908 here.fillInStackTrace();
4909 Slog.i(TAG, "Removing activity " + r + " from stack at " + i
4910 + ": haveState=" + r.haveState
4911 + " stateNotNeeded=" + r.stateNotNeeded
4912 + " finishing=" + r.finishing
4913 + " state=" + r.state, here);
4914 }
4915 if (!r.finishing) {
4916 Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
4917 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
4918 r.userId, System.identityHashCode(r),
4919 r.task.taskId, r.shortComponentName,
4920 "proc died without state saved");
4921 }
4922 removeActivityFromHistoryLocked(r);
4923
4924 } else {
4925 // We have the current state for this activity, so
4926 // it can be restarted later when needed.
4927 if (localLOGV) Slog.v(
4928 TAG, "Keeping entry, setting app to null");
4929 if (r.visible) {
4930 hasVisibleActivities = true;
4931 }
Dianne Hackborn07981492013-01-28 11:36:23 -08004932 if (DEBUG_APP) Slog.v(TAG, "Clearing app during removeHistory for activity "
4933 + r);
Dianne Hackborncc5a0552012-10-01 16:32:39 -07004934 r.app = null;
4935 r.nowVisible = false;
4936 if (!r.haveState) {
4937 if (ActivityStack.DEBUG_SAVED_STATE) Slog.i(TAG,
4938 "App died, clearing saved state of " + r);
4939 r.icicle = null;
4940 }
4941 }
4942
4943 r.stack.cleanUpActivityLocked(r, true, true);
4944 }
4945 }
4946
4947 return hasVisibleActivities;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004948 }
4949
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004950 /**
4951 * Move the current home activity's task (if one exists) to the front
4952 * of the stack.
4953 */
4954 final void moveHomeToFrontLocked() {
Craig Mautner11bf9a52013-02-19 14:08:51 -08004955 newMoveHomeToFrontLocked();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004956 TaskRecord homeTask = null;
4957 for (int i=mHistory.size()-1; i>=0; i--) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004958 ActivityRecord hr = mHistory.get(i);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004959 if (hr.isHomeActivity) {
4960 homeTask = hr.task;
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08004961 break;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004962 }
4963 }
4964 if (homeTask != null) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08004965// moveTaskToFrontLocked(homeTask, null, null);
4966 }
4967 }
4968
4969 final void newMoveHomeToFrontLocked() {
4970 TaskRecord homeTask = null;
4971 for (int taskNdx = mTaskHistory.size() - 1; homeTask == null && taskNdx >= 0; --taskNdx) {
4972 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
4973 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
4974 final ActivityRecord r = activities.get(activityNdx);
4975 if (r.isHomeActivity) {
4976 homeTask = r.task;
4977 break;
4978 }
4979 }
4980 }
4981 if (homeTask != null) {
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07004982 moveTaskToFrontLocked(homeTask, null, null);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004983 }
4984 }
4985
Dianne Hackborn7f58b952012-04-18 12:59:29 -07004986 final void updateTransitLocked(int transit, Bundle options) {
4987 if (options != null) {
4988 ActivityRecord r = topRunningActivityLocked(null);
4989 if (r != null && r.state != ActivityState.RESUMED) {
4990 r.updateOptionsLocked(options);
4991 } else {
4992 ActivityOptions.abort(options);
4993 }
4994 }
4995 mService.mWindowManager.prepareAppTransition(transit, false);
4996 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004997
Craig Mautnercae015f2013-02-08 14:31:27 -08004998 final boolean findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
4999 for (int i = mHistory.size() - 1; i >= 0; i--) {
5000 ActivityRecord hr = mHistory.get(i);
5001 if (hr.task.taskId == taskId) {
5002 if ((flags & ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5003 mUserLeaving = true;
5004 }
5005 if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5006 // Caller wants the home activity moved with it. To accomplish this,
5007 // we'll just move the home task to the top first.
5008 moveHomeToFrontLocked();
5009 }
5010 moveTaskToFrontLocked(hr.task, null, options);
5011 return true;
5012 }
5013 }
5014 return false;
5015 }
5016
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07005017 final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005018
5019 final int task = tr.taskId;
5020 int top = mHistory.size()-1;
5021
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005022 if (top < 0 || (mHistory.get(top)).task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005023 // nothing to do!
5024 return;
5025 }
5026
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005027
5028 // Shift all activities with this task up to the top
5029 // of the stack, keeping them in the same internal order.
Craig Mautner11bf9a52013-02-19 14:08:51 -08005030 int pos = top;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005031 while (pos >= 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005032 ActivityRecord r = mHistory.get(pos);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005033 if (localLOGV) Slog.v(
5034 TAG, "At " + pos + " ckp " + r.task + ": " + r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005035 if (r.task.taskId == task) {
5036 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07005037 if (DEBUG_ADD_REMOVE) {
5038 RuntimeException here = new RuntimeException("here");
5039 here.fillInStackTrace();
5040 Slog.i(TAG, "Removing and adding activity " + r + " to stack at " + top, here);
5041 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005042 mHistory.remove(pos);
5043 mHistory.add(top, r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005044 top--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005045 }
5046 pos--;
5047 }
Craig Mautner11bf9a52013-02-19 14:08:51 -08005048 //
5049 // Start new code here! Delete everything above.
5050 //
5051 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005052
Craig Mautner11bf9a52013-02-19 14:08:51 -08005053 final int numTasks = mTaskHistory.size();
5054 final int index = mTaskHistory.indexOf(tr);
5055 if (numTasks == 0 || index < 0 || index == numTasks - 1) {
5056 // nothing to do!
5057 if (reason != null &&
5058 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
5059 ActivityOptions.abort(options);
5060 } else {
5061 updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
5062 }
5063 return;
5064 }
5065
5066 // Shift all activities with this task up to the top
5067 // of the stack, keeping them in the same internal order.
5068 mTaskHistory.remove(tr);
5069 mTaskHistory.add(tr);
5070
5071 if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare to front transition: task=" + tr);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005072 if (reason != null &&
5073 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08005074 mService.mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005075 ActivityRecord r = topRunningActivityLocked(null);
5076 if (r != null) {
5077 mNoAnimActivities.add(r);
5078 }
Dianne Hackborn8078d8c2012-03-20 11:11:26 -07005079 ActivityOptions.abort(options);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005080 } else {
Craig Mautner4b71aa12012-12-27 17:20:01 -08005081 updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005082 }
Craig Mautner30e2d722013-02-12 11:30:16 -08005083
Craig Mautner30e2d722013-02-12 11:30:16 -08005084 mService.mWindowManager.moveTaskToTop(task);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005085
5086 finishTaskMoveLocked(task);
Dianne Hackbornb12e1352012-09-26 11:39:20 -07005087 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, task);
Craig Mautner11bf9a52013-02-19 14:08:51 -08005088
5089 if (VALIDATE_TOKENS) {
5090 validateAppTokensLocked();
5091 }
5092 if (VALIDATE_TASK_REPLACE) {
5093 verifyActivityRecords(true);
5094 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005095 }
5096
5097 private final void finishTaskMoveLocked(int task) {
5098 resumeTopActivityLocked(null);
5099 }
5100
5101 /**
5102 * Worker method for rearranging history stack. Implements the function of moving all
5103 * activities for a specific task (gathering them if disjoint) into a single group at the
5104 * bottom of the stack.
5105 *
5106 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
5107 * to premeptively cancel the move.
5108 *
5109 * @param task The taskId to collect and move to the bottom.
5110 * @return Returns true if the move completed, false if not.
5111 */
5112 final boolean moveTaskToBackLocked(int task, ActivityRecord reason) {
5113 Slog.i(TAG, "moveTaskToBack: " + task);
Craig Mautnerb44de0d2013-02-21 20:00:58 -08005114
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005115 // If we have a watcher, preflight the move before committing to it. First check
5116 // for *other* available tasks, but if none are available, then try again allowing the
5117 // current task to be selected.
5118 if (mMainStack && mService.mController != null) {
5119 ActivityRecord next = topRunningActivityLocked(null, task);
5120 if (next == null) {
5121 next = topRunningActivityLocked(null, 0);
5122 }
5123 if (next != null) {
5124 // ask watcher if this is allowed
5125 boolean moveOK = true;
5126 try {
5127 moveOK = mService.mController.activityResuming(next.packageName);
5128 } catch (RemoteException e) {
5129 mService.mController = null;
5130 }
5131 if (!moveOK) {
5132 return false;
5133 }
5134 }
5135 }
5136
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005137 if (DEBUG_TRANSITION) Slog.v(TAG,
5138 "Prepare to back transition: task=" + task);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005139
Craig Mautner11bf9a52013-02-19 14:08:51 -08005140 final TaskRecord tr = mTaskIdToTaskRecord.get(task);
5141 mTaskHistory.remove(tr);
5142 mTaskHistory.add(0, tr);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005143
Craig Mautnerb44de0d2013-02-21 20:00:58 -08005144 // BEGIN REGION TO REMOVE.
5145 final int N = mHistory.size();
5146 int bottom = 0;
5147 int pos = 0;
5148
5149 // Shift all activities with this task down to the bottom
5150 // of the stack, keeping them in the same internal order.
5151 while (pos < N) {
5152 ActivityRecord r = mHistory.get(pos);
5153 if (localLOGV) Slog.v(
5154 TAG, "At " + pos + " ckp " + r.task + ": " + r);
5155 if (r.task.taskId == task) {
5156 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
5157 if (DEBUG_ADD_REMOVE) {
5158 RuntimeException here = new RuntimeException("here");
5159 here.fillInStackTrace();
5160 Slog.i(TAG, "Removing and adding activity " + r + " to stack at "
5161 + bottom, here);
5162 }
5163 mHistory.remove(pos);
5164 mHistory.add(bottom, r);
5165 bottom++;
5166 }
5167 pos++;
5168 }
5169 if (VALIDATE_TASK_REPLACE) {
5170 verifyActivityRecords(true);
5171 }
5172 // END REGION TO REMOVE
5173
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005174 if (reason != null &&
5175 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
Craig Mautner11bf9a52013-02-19 14:08:51 -08005176 mService.mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005177 ActivityRecord r = topRunningActivityLocked(null);
5178 if (r != null) {
5179 mNoAnimActivities.add(r);
5180 }
5181 } else {
Dianne Hackborn7da6ac32010-12-09 19:22:04 -08005182 mService.mWindowManager.prepareAppTransition(
Craig Mautner4b71aa12012-12-27 17:20:01 -08005183 AppTransition.TRANSIT_TASK_TO_BACK, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005184 }
Craig Mautner30e2d722013-02-12 11:30:16 -08005185 mService.mWindowManager.moveTaskToBottom(task);
Craig Mautnerb44de0d2013-02-21 20:00:58 -08005186
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005187 if (VALIDATE_TOKENS) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08005188 validateAppTokensLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005189 }
5190
5191 finishTaskMoveLocked(task);
5192 return true;
5193 }
Dianne Hackborn15491c62012-09-19 10:59:14 -07005194
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005195 public ActivityManager.TaskThumbnails getTaskThumbnailsLocked(TaskRecord tr) {
5196 TaskAccessInfo info = getTaskAccessInfoLocked(tr.taskId, true);
5197 ActivityRecord resumed = mResumedActivity;
5198 if (resumed != null && resumed.thumbHolder == tr) {
5199 info.mainThumbnail = resumed.stack.screenshotActivities(resumed);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005200 }
Dianne Hackborn6a864952012-09-21 18:46:11 -07005201 if (info.mainThumbnail == null) {
5202 info.mainThumbnail = tr.lastThumbnail;
5203 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005204 return info;
5205 }
5206
Dianne Hackborn15491c62012-09-19 10:59:14 -07005207 public Bitmap getTaskTopThumbnailLocked(TaskRecord tr) {
5208 ActivityRecord resumed = mResumedActivity;
5209 if (resumed != null && resumed.task == tr) {
5210 // This task is the current resumed task, we just need to take
5211 // a screenshot of it and return that.
5212 return resumed.stack.screenshotActivities(resumed);
5213 }
5214 // Return the information about the task, to figure out the top
5215 // thumbnail to return.
5216 TaskAccessInfo info = getTaskAccessInfoLocked(tr.taskId, true);
5217 if (info.numSubThumbbails <= 0) {
Dianne Hackborn6a864952012-09-21 18:46:11 -07005218 return info.mainThumbnail != null ? info.mainThumbnail : tr.lastThumbnail;
Dianne Hackborn15491c62012-09-19 10:59:14 -07005219 }
Craig Mautner05d6272ba2013-02-11 09:39:27 -08005220 return info.subtasks.get(info.numSubThumbbails-1).holder.lastThumbnail;
Dianne Hackborn15491c62012-09-19 10:59:14 -07005221 }
5222
Dianne Hackborn9da2d402012-03-15 13:43:08 -07005223 public ActivityRecord removeTaskActivitiesLocked(int taskId, int subTaskIndex,
5224 boolean taskRequired) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005225 TaskAccessInfo info = getTaskAccessInfoLocked(taskId, false);
5226 if (info.root == null) {
Dianne Hackborn9da2d402012-03-15 13:43:08 -07005227 if (taskRequired) {
5228 Slog.w(TAG, "removeTaskLocked: unknown taskId " + taskId);
5229 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005230 return null;
5231 }
5232
5233 if (subTaskIndex < 0) {
5234 // Just remove the entire task.
5235 performClearTaskAtIndexLocked(taskId, info.rootIndex);
5236 return info.root;
5237 }
5238
5239 if (subTaskIndex >= info.subtasks.size()) {
Dianne Hackborn9da2d402012-03-15 13:43:08 -07005240 if (taskRequired) {
5241 Slog.w(TAG, "removeTaskLocked: unknown subTaskIndex " + subTaskIndex);
5242 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005243 return null;
5244 }
5245
Dianne Hackborncc5a0552012-10-01 16:32:39 -07005246 // Remove all of this task's activities starting at the sub task.
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005247 TaskAccessInfo.SubTask subtask = info.subtasks.get(subTaskIndex);
5248 performClearTaskAtIndexLocked(taskId, subtask.index);
5249 return subtask.activity;
5250 }
5251
5252 public TaskAccessInfo getTaskAccessInfoLocked(int taskId, boolean inclThumbs) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005253 final TaskAccessInfo thumbs = new TaskAccessInfo();
5254 // How many different sub-thumbnails?
5255 final int NA = mHistory.size();
5256 int j = 0;
5257 ThumbnailHolder holder = null;
5258 while (j < NA) {
5259 ActivityRecord ar = mHistory.get(j);
5260 if (!ar.finishing && ar.task.taskId == taskId) {
Dianne Hackborn8da429e2012-09-23 12:52:19 -07005261 thumbs.root = ar;
5262 thumbs.rootIndex = j;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005263 holder = ar.thumbHolder;
Dianne Hackborn15491c62012-09-19 10:59:14 -07005264 if (holder != null) {
5265 thumbs.mainThumbnail = holder.lastThumbnail;
5266 }
5267 j++;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005268 break;
5269 }
5270 j++;
5271 }
5272
5273 if (j >= NA) {
5274 return thumbs;
5275 }
5276
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005277 ArrayList<TaskAccessInfo.SubTask> subtasks = new ArrayList<TaskAccessInfo.SubTask>();
5278 thumbs.subtasks = subtasks;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005279 while (j < NA) {
5280 ActivityRecord ar = mHistory.get(j);
5281 j++;
5282 if (ar.finishing) {
5283 continue;
5284 }
5285 if (ar.task.taskId != taskId) {
5286 break;
5287 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005288 if (ar.thumbHolder != holder && holder != null) {
5289 thumbs.numSubThumbbails++;
5290 holder = ar.thumbHolder;
5291 TaskAccessInfo.SubTask sub = new TaskAccessInfo.SubTask();
Dianne Hackborn15491c62012-09-19 10:59:14 -07005292 sub.holder = holder;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005293 sub.activity = ar;
5294 sub.index = j-1;
5295 subtasks.add(sub);
5296 }
5297 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005298 if (thumbs.numSubThumbbails > 0) {
5299 thumbs.retriever = new IThumbnailRetriever.Stub() {
Craig Mautner05d6272ba2013-02-11 09:39:27 -08005300 @Override
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005301 public Bitmap getThumbnail(int index) {
5302 if (index < 0 || index >= thumbs.subtasks.size()) {
5303 return null;
5304 }
Dianne Hackborn15491c62012-09-19 10:59:14 -07005305 TaskAccessInfo.SubTask sub = thumbs.subtasks.get(index);
5306 ActivityRecord resumed = mResumedActivity;
5307 if (resumed != null && resumed.thumbHolder == sub.holder) {
5308 return resumed.stack.screenshotActivities(resumed);
5309 }
5310 return sub.holder.lastThumbnail;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005311 }
5312 };
5313 }
5314 return thumbs;
5315 }
5316
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005317 private final void logStartActivity(int tag, ActivityRecord r,
5318 TaskRecord task) {
5319 EventLog.writeEvent(tag,
Dianne Hackbornb12e1352012-09-26 11:39:20 -07005320 r.userId, System.identityHashCode(r), task.taskId,
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005321 r.shortComponentName, r.intent.getAction(),
5322 r.intent.getType(), r.intent.getDataString(),
5323 r.intent.getFlags());
5324 }
5325
5326 /**
5327 * Make sure the given activity matches the current configuration. Returns
5328 * false if the activity had to be destroyed. Returns true if the
5329 * configuration is the same, or the activity will remain running as-is
5330 * for whatever reason. Ensures the HistoryRecord is updated with the
5331 * correct configuration and all other bookkeeping is handled.
5332 */
5333 final boolean ensureActivityConfigurationLocked(ActivityRecord r,
5334 int globalChanges) {
5335 if (mConfigWillChange) {
5336 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
5337 "Skipping config check (will change): " + r);
5338 return true;
5339 }
5340
5341 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
5342 "Ensuring correct configuration: " + r);
5343
5344 // Short circuit: if the two configurations are the exact same
5345 // object (the common case), then there is nothing to do.
5346 Configuration newConfig = mService.mConfiguration;
Dianne Hackborne2515ee2011-04-27 18:52:56 -04005347 if (r.configuration == newConfig && !r.forceNewConfig) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005348 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
5349 "Configuration unchanged in " + r);
5350 return true;
5351 }
5352
5353 // We don't worry about activities that are finishing.
5354 if (r.finishing) {
5355 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
5356 "Configuration doesn't matter in finishing " + r);
5357 r.stopFreezingScreenLocked(false);
5358 return true;
5359 }
5360
5361 // Okay we now are going to make this activity have the new config.
5362 // But then we need to figure out how it needs to deal with that.
5363 Configuration oldConfig = r.configuration;
5364 r.configuration = newConfig;
Dianne Hackborn58f42a52011-10-10 13:46:34 -07005365
5366 // Determine what has changed. May be nothing, if this is a config
5367 // that has come back from the app after going idle. In that case
5368 // we just want to leave the official config object now in the
5369 // activity and do nothing else.
5370 final int changes = oldConfig.diff(newConfig);
5371 if (changes == 0 && !r.forceNewConfig) {
5372 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
5373 "Configuration no differences in " + r);
5374 return true;
5375 }
5376
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005377 // If the activity isn't currently running, just leave the new
5378 // configuration and it will pick that up next time it starts.
5379 if (r.app == null || r.app.thread == null) {
5380 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
5381 "Configuration doesn't matter not running " + r);
5382 r.stopFreezingScreenLocked(false);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04005383 r.forceNewConfig = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005384 return true;
5385 }
5386
Dianne Hackborn58f42a52011-10-10 13:46:34 -07005387 // Figure out how to handle the changes between the configurations.
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -07005388 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
5389 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
5390 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborne6676352011-06-01 16:51:20 -07005391 + Integer.toHexString(r.info.getRealConfigChanged())
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -07005392 + ", newConfig=" + newConfig);
5393 }
Dianne Hackborne6676352011-06-01 16:51:20 -07005394 if ((changes&(~r.info.getRealConfigChanged())) != 0 || r.forceNewConfig) {
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -07005395 // Aha, the activity isn't handling the change, so DIE DIE DIE.
5396 r.configChangeFlags |= changes;
5397 r.startFreezingScreenLocked(r.app, globalChanges);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04005398 r.forceNewConfig = false;
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -07005399 if (r.app == null || r.app.thread == null) {
5400 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackbornb61a0262012-05-14 17:19:18 -07005401 "Config is destroying non-running " + r);
Dianne Hackborn28695e02011-11-02 21:59:51 -07005402 destroyActivityLocked(r, true, false, "config");
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -07005403 } else if (r.state == ActivityState.PAUSING) {
5404 // A little annoying: we are waiting for this activity to
5405 // finish pausing. Let's not do anything now, but just
5406 // flag that it needs to be restarted when done pausing.
5407 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackbornb61a0262012-05-14 17:19:18 -07005408 "Config is skipping already pausing " + r);
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -07005409 r.configDestroy = true;
5410 return true;
5411 } else if (r.state == ActivityState.RESUMED) {
5412 // Try to optimize this case: the configuration is changing
5413 // and we need to restart the top, resumed activity.
5414 // Instead of doing the normal handshaking, just say
5415 // "restart!".
5416 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackbornb61a0262012-05-14 17:19:18 -07005417 "Config is relaunching resumed " + r);
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -07005418 relaunchActivityLocked(r, r.configChangeFlags, true);
5419 r.configChangeFlags = 0;
5420 } else {
5421 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackbornb61a0262012-05-14 17:19:18 -07005422 "Config is relaunching non-resumed " + r);
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -07005423 relaunchActivityLocked(r, r.configChangeFlags, false);
5424 r.configChangeFlags = 0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005425 }
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -07005426
5427 // All done... tell the caller we weren't able to keep this
5428 // activity around.
5429 return false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005430 }
5431
5432 // Default case: the activity can handle this new configuration, so
5433 // hand it over. Note that we don't need to give it the new
5434 // configuration, since we always send configuration changes to all
5435 // process when they happen so it can just use whatever configuration
5436 // it last got.
5437 if (r.app != null && r.app.thread != null) {
5438 try {
5439 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
Dianne Hackbornbe707852011-11-11 14:32:10 -08005440 r.app.thread.scheduleActivityConfigurationChanged(r.appToken);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005441 } catch (RemoteException e) {
5442 // If process died, whatever.
5443 }
5444 }
5445 r.stopFreezingScreenLocked(false);
5446
5447 return true;
5448 }
5449
5450 private final boolean relaunchActivityLocked(ActivityRecord r,
5451 int changes, boolean andResume) {
5452 List<ResultInfo> results = null;
5453 List<Intent> newIntents = null;
5454 if (andResume) {
5455 results = r.results;
5456 newIntents = r.newIntents;
5457 }
5458 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
5459 + " with results=" + results + " newIntents=" + newIntents
5460 + " andResume=" + andResume);
5461 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
Dianne Hackbornb12e1352012-09-26 11:39:20 -07005462 : EventLogTags.AM_RELAUNCH_ACTIVITY, r.userId, System.identityHashCode(r),
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005463 r.task.taskId, r.shortComponentName);
5464
5465 r.startFreezingScreenLocked(r.app, 0);
5466
5467 try {
Dianne Hackbornb61a0262012-05-14 17:19:18 -07005468 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
5469 (andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ")
5470 + r);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04005471 r.forceNewConfig = false;
Dianne Hackbornbe707852011-11-11 14:32:10 -08005472 r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents,
Dianne Hackborn813075a62011-11-14 17:45:19 -08005473 changes, !andResume, new Configuration(mService.mConfiguration));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005474 // Note: don't need to call pauseIfSleepingLocked() here, because
5475 // the caller will only pass in 'andResume' if this activity is
5476 // currently resumed, which implies we aren't sleeping.
5477 } catch (RemoteException e) {
Dianne Hackbornb61a0262012-05-14 17:19:18 -07005478 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG, "Relaunch failed", e);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005479 }
5480
5481 if (andResume) {
5482 r.results = null;
5483 r.newIntents = null;
5484 if (mMainStack) {
5485 mService.reportResumedActivityLocked(r);
5486 }
Dianne Hackbornb61a0262012-05-14 17:19:18 -07005487 r.state = ActivityState.RESUMED;
5488 } else {
5489 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5490 r.state = ActivityState.PAUSED;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005491 }
5492
5493 return true;
5494 }
Dianne Hackborn90c52de2011-09-23 12:57:44 -07005495
5496 public void dismissKeyguardOnNextActivityLocked() {
5497 mDismissKeyguardOnNextActivity = true;
5498 }
Craig Mautnercae015f2013-02-08 14:31:27 -08005499
5500 boolean willActivityBeVisibleLocked(IBinder token) {
Craig Mautnerd44711d2013-02-23 11:24:36 -08005501 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
5502 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
5503 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
5504 final ActivityRecord r = activities.get(activityNdx);
5505 if (r.appToken == token) {
5506 return true;
5507 }
5508 if (r.fullscreen && !r.finishing) {
5509 return false;
5510 }
Craig Mautnercae015f2013-02-08 14:31:27 -08005511 }
5512 }
5513 return true;
5514 }
5515
5516 void closeSystemDialogsLocked() {
Craig Mautnerd44711d2013-02-23 11:24:36 -08005517 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
5518 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
5519 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
5520 final ActivityRecord r = activities.get(activityNdx);
5521 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5522 r.stack.finishActivityLocked(r, Activity.RESULT_CANCELED,
5523 null, "close-sys", true);
5524 }
Craig Mautnercae015f2013-02-08 14:31:27 -08005525 }
5526 }
5527 }
5528
5529 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
5530 boolean didSomething = false;
5531 TaskRecord lastTask = null;
Craig Mautner56f52db2013-02-25 10:03:01 -08005532 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
5533 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
5534 int numActivities = activities.size();
5535 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
5536 ActivityRecord r = activities.get(activityNdx);
5537 final boolean samePackage = r.packageName.equals(name)
5538 || (name == null && r.userId == userId);
5539 if ((userId == UserHandle.USER_ALL || r.userId == userId)
5540 && (samePackage || r.task == lastTask)
5541 && (r.app == null || evenPersistent || !r.app.persistent)) {
5542 if (!doit) {
5543 if (r.finishing) {
5544 // If this activity is just finishing, then it is not
5545 // interesting as far as something to stop.
5546 continue;
5547 }
5548 return true;
Craig Mautnercae015f2013-02-08 14:31:27 -08005549 }
Craig Mautner56f52db2013-02-25 10:03:01 -08005550 didSomething = true;
5551 Slog.i(TAG, " Force finishing activity " + r);
5552 if (samePackage) {
5553 if (r.app != null) {
5554 r.app.removed = true;
5555 }
5556 r.app = null;
Craig Mautnercae015f2013-02-08 14:31:27 -08005557 }
Craig Mautner56f52db2013-02-25 10:03:01 -08005558 lastTask = r.task;
5559 r.stack.finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop",
5560 true);
Craig Mautnercae015f2013-02-08 14:31:27 -08005561 }
5562 }
5563 }
5564 return didSomething;
5565 }
5566
5567 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
5568 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
5569 ActivityRecord topRecord = null;
5570 int pos = mHistory.size() - 1;
5571 ActivityRecord next = pos >= 0 ? mHistory.get(pos) : null;
5572 ActivityRecord top = null;
5573 TaskRecord curTask = null;
5574 int numActivities = 0;
5575 int numRunning = 0;
5576 while (pos >= 0 && maxNum > 0) {
5577 final ActivityRecord r = next;
5578 pos--;
5579 next = pos >= 0 ? mHistory.get(pos) : null;
5580
5581 // Initialize state for next task if needed.
5582 if (top == null || (top.state == ActivityState.INITIALIZING && top.task == r.task)) {
5583 top = r;
5584 curTask = r.task;
5585 numActivities = numRunning = 0;
5586 }
5587
5588 // Add 'r' into the current task.
5589 numActivities++;
5590 if (r.app != null && r.app.thread != null) {
5591 numRunning++;
5592 }
5593
5594 if (localLOGV) Slog.v(
5595 TAG, r.intent.getComponent().flattenToShortString()
5596 + ": task=" + r.task);
5597
5598 // If the next one is a different task, generate a new
5599 // TaskInfo entry for what we have.
5600 if (next == null || next.task != curTask) {
5601 RunningTaskInfo ci = new RunningTaskInfo();
5602 ci.id = curTask.taskId;
5603 ci.baseActivity = r.intent.getComponent();
5604 ci.topActivity = top.intent.getComponent();
5605 if (top.thumbHolder != null) {
5606 ci.description = top.thumbHolder.lastDescription;
5607 }
5608 ci.numActivities = numActivities;
5609 ci.numRunning = numRunning;
5610 //System.out.println(
5611 // "#" + maxNum + ": " + " descr=" + ci.description);
5612 if (receiver != null) {
5613 if (localLOGV) Slog.v(
5614 TAG, "State=" + top.state + "Idle=" + top.idle
5615 + " app=" + top.app
5616 + " thr=" + (top.app != null ? top.app.thread : null));
5617 if (top.state == ActivityState.RESUMED || top.state == ActivityState.PAUSING) {
5618 if (top.idle && top.app != null && top.app.thread != null) {
5619 topRecord = top;
5620 } else {
5621 top.thumbnailNeeded = true;
5622 }
5623 }
5624 pending.pendingRecords.add(top);
5625 }
5626 list.add(ci);
5627 maxNum--;
5628 top = null;
5629 }
5630 }
5631 return topRecord;
5632 }
5633
5634 public void unhandledBackLocked() {
5635 int top = mHistory.size() - 1;
5636 if (DEBUG_SWITCH) Slog.d(
5637 TAG, "Performing unhandledBack(): top activity at " + top);
5638 if (top > 0) {
5639 finishActivityLocked(mHistory.get(top),
Craig Mautnerd44711d2013-02-23 11:24:36 -08005640 Activity.RESULT_CANCELED, null, "unhandled-back", true);
Craig Mautnercae015f2013-02-08 14:31:27 -08005641 }
5642 }
5643
5644 void handleAppCrashLocked(ProcessRecord app) {
Craig Mautnerd44711d2013-02-23 11:24:36 -08005645 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
5646 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
5647 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
5648 final ActivityRecord r = activities.get(activityNdx);
5649 if (r.app == app) {
5650 Slog.w(TAG, " Force finishing activity "
5651 + r.intent.getComponent().flattenToShortString());
5652 r.stack.finishActivityLocked(r, Activity.RESULT_CANCELED, null, "crashed",
5653 false);
5654 }
Craig Mautnercae015f2013-02-08 14:31:27 -08005655 }
5656 }
5657 }
5658
5659 void dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
5660 boolean dumpClient, String dumpPackage) {
5661 ActivityManagerService.dumpHistoryList(fd, pw, mHistory, " ", "Hist", true, !dumpAll,
5662 dumpClient, dumpPackage);
5663 }
5664
5665 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
5666 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
5667
5668 if ("all".equals(name)) {
5669 for (ActivityRecord r1 : mHistory) {
5670 activities.add(r1);
5671 }
5672 } else if ("top".equals(name)) {
5673 final int N = mHistory.size();
5674 if (N > 0) {
5675 activities.add(mHistory.get(N-1));
5676 }
5677 } else {
5678 ItemMatcher matcher = new ItemMatcher();
5679 matcher.build(name);
5680
5681 for (ActivityRecord r1 : mHistory) {
5682 if (matcher.match(r1, r1.intent.getComponent())) {
5683 activities.add(r1);
5684 }
5685 }
5686 }
5687
5688 return activities;
5689 }
5690
5691 ActivityRecord restartPackage(String packageName) {
5692 ActivityRecord starting = topRunningActivityLocked(null);
5693
5694 // All activities that came from the package must be
5695 // restarted as if there was a config change.
5696 for (int i = mHistory.size() - 1; i >= 0; i--) {
5697 ActivityRecord a = mHistory.get(i);
5698 if (a.info.packageName.equals(packageName)) {
5699 a.forceNewConfig = true;
5700 if (starting != null && a == starting && a.visible) {
5701 a.startFreezingScreenLocked(starting.app, ActivityInfo.CONFIG_SCREEN_LAYOUT);
5702 }
5703 }
5704 }
5705
5706 return starting;
5707 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08005708
Craig Mautner11bf9a52013-02-19 14:08:51 -08005709 void rebuildTaskHistory() {
5710 mTaskHistory.clear();
5711 final int numActivities = mHistory.size();
5712 TaskRecord task = null;
5713 for (int i = 0; i < numActivities; ++i) {
5714 final ActivityRecord r = mHistory.get(i);
5715 if (r.task != task) {
5716 task = r.task;
5717 task.mActivities.clear();
5718 mTaskHistory.add(task);
5719 }
5720 task.mActivities.add(r);
5721 }
5722 }
5723
5724 boolean verifyActivityRecords(boolean rebuild) {
5725 final int numHistory = mHistory.size();
5726 int historyNdx = 0;
5727
5728 final int numTasks = mTaskHistory.size();
5729 int taskNdx;
5730 for (taskNdx = historyNdx = 0; taskNdx < numTasks; ++taskNdx) {
5731 final TaskRecord task = mTaskHistory.get(taskNdx);
5732 final ArrayList<ActivityRecord> activities = task.mActivities;
5733 final int numActivities = activities.size();
5734 int activityNdx;
5735 for (activityNdx = 0;
5736 activityNdx < numActivities && historyNdx < numHistory;
5737 ++activityNdx, ++historyNdx) {
5738 ActivityRecord r1 = mHistory.get(historyNdx);
5739 ActivityRecord r2 = activities.get(activityNdx);
5740 if (r1 != r2) {
5741 break;
5742 }
5743 }
5744 if (activityNdx != numActivities) {
5745 // either a mismatch or mHistory ran out before mTaskHistory.
Craig Mautner5d9c7be2013-02-15 14:02:56 -08005746 break;
5747 }
5748 }
Craig Mautner11bf9a52013-02-19 14:08:51 -08005749 if (taskNdx != numTasks || historyNdx != numHistory) {
5750 logHistories("verifyActivityRecords", rebuild);
5751 return true;
Craig Mautner5d9c7be2013-02-15 14:02:56 -08005752 }
Craig Mautner11bf9a52013-02-19 14:08:51 -08005753 return false;
5754 }
5755
5756 private void logHistories(String caller, boolean rebuild) {
5757 Slog.w(TAG, "Mismatch! " + caller + " mHistory=" + mHistory);
5758 ArrayList<ArrayList<ActivityRecord>> nestedRecords =
5759 new ArrayList<ArrayList<ActivityRecord>>();
5760 for (TaskRecord task : mTaskHistory) {
5761 nestedRecords.add(task.mActivities);
5762 }
5763 Slog.w(TAG, "Mismatch! " + caller + " mTaskHistory" + nestedRecords);
5764 Slog.w(TAG, "Mismatch! " + caller + " lastHistoryModifier=" + mLastHistoryModifier
5765 + " Caller=" + Debug.getCallers(4));
5766 if (rebuild) {
5767 rebuildTaskHistory();
Craig Mautner5d9c7be2013-02-15 14:02:56 -08005768 }
5769 }
5770
5771 private TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
5772 boolean toTop) {
5773 TaskRecord oldTask = mTaskIdToTaskRecord.get(taskId);
5774 if (oldTask != null) {
5775 Slog.w(TAG, "createTaskRecord: Reusing taskId=" + taskId + " without removing");
5776 mTaskHistory.remove(oldTask);
5777 }
5778 TaskRecord task = new TaskRecord(taskId, info, intent);
5779 mTaskIdToTaskRecord.put(taskId, task);
5780 if (toTop) {
5781 mTaskHistory.add(task);
5782 } else {
5783 mTaskHistory.add(0, task);
5784 }
5785 return task;
5786 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005787}