OSDN Git Service

Launch activity behind launching task.
[android-x86/frameworks-base.git] / services / core / java / com / android / server / am / ActivityStack.java
1 /*
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
17 package com.android.server.am;
18
19 import static com.android.server.am.ActivityManagerService.TAG;
20 import static com.android.server.am.ActivityManagerService.localLOGV;
21 import static com.android.server.am.ActivityManagerService.DEBUG_CLEANUP;
22 import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION;
23 import static com.android.server.am.ActivityManagerService.DEBUG_PAUSE;
24 import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
25 import static com.android.server.am.ActivityManagerService.DEBUG_STACK;
26 import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
27 import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
28 import static com.android.server.am.ActivityManagerService.DEBUG_TRANSITION;
29 import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
30 import static com.android.server.am.ActivityManagerService.DEBUG_VISBILITY;
31 import static com.android.server.am.ActivityManagerService.VALIDATE_TOKENS;
32
33 import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
34 import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
35
36 import static com.android.server.am.ActivityStackSupervisor.DEBUG_ADD_REMOVE;
37 import static com.android.server.am.ActivityStackSupervisor.DEBUG_APP;
38 import static com.android.server.am.ActivityStackSupervisor.DEBUG_CONTAINERS;
39 import static com.android.server.am.ActivityStackSupervisor.DEBUG_SAVED_STATE;
40 import static com.android.server.am.ActivityStackSupervisor.DEBUG_SCREENSHOTS;
41 import static com.android.server.am.ActivityStackSupervisor.DEBUG_STATES;
42 import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
43
44 import com.android.internal.app.IVoiceInteractor;
45 import com.android.internal.os.BatteryStatsImpl;
46 import com.android.server.Watchdog;
47 import com.android.server.am.ActivityManagerService.ItemMatcher;
48 import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
49 import com.android.server.am.ActivityStackSupervisor.ActivityDisplay;
50 import com.android.server.wm.AppTransition;
51 import com.android.server.wm.TaskGroup;
52 import com.android.server.wm.WindowManagerService;
53
54 import android.app.Activity;
55 import android.app.ActivityManager;
56 import android.app.ActivityOptions;
57 import android.app.AppGlobals;
58 import android.app.IActivityController;
59 import android.app.ResultInfo;
60 import android.app.ActivityManager.RunningTaskInfo;
61 import android.content.ComponentName;
62 import android.content.Intent;
63 import android.content.pm.ActivityInfo;
64 import android.content.pm.PackageManager;
65 import android.content.res.Configuration;
66 import android.content.res.Resources;
67 import android.graphics.Bitmap;
68 import android.net.Uri;
69 import android.os.Binder;
70 import android.os.Bundle;
71 import android.os.Debug;
72 import android.os.Handler;
73 import android.os.IBinder;
74 import android.os.Looper;
75 import android.os.Message;
76 import android.os.PersistableBundle;
77 import android.os.RemoteException;
78 import android.os.SystemClock;
79 import android.os.Trace;
80 import android.os.UserHandle;
81 import android.service.voice.IVoiceInteractionSession;
82 import android.util.EventLog;
83 import android.util.Slog;
84 import android.view.Display;
85
86 import java.io.FileDescriptor;
87 import java.io.PrintWriter;
88 import java.lang.ref.WeakReference;
89 import java.util.ArrayList;
90 import java.util.Iterator;
91 import java.util.List;
92 import java.util.Objects;
93
94 /**
95  * State and management of a single stack of activities.
96  */
97 final class ActivityStack {
98
99     // Ticks during which we check progress while waiting for an app to launch.
100     static final int LAUNCH_TICK = 500;
101
102     // How long we wait until giving up on the last activity to pause.  This
103     // is short because it directly impacts the responsiveness of starting the
104     // next activity.
105     static final int PAUSE_TIMEOUT = 500;
106
107     // How long we wait for the activity to tell us it has stopped before
108     // giving up.  This is a good amount of time because we really need this
109     // from the application in order to get its saved state.
110     static final int STOP_TIMEOUT = 10*1000;
111
112     // How long we wait until giving up on an activity telling us it has
113     // finished destroying itself.
114     static final int DESTROY_TIMEOUT = 10*1000;
115
116     // How long until we reset a task when the user returns to it.  Currently
117     // disabled.
118     static final long ACTIVITY_INACTIVE_RESET_TIME = 0;
119
120     // How long between activity launches that we consider safe to not warn
121     // the user about an unexpected activity being launched on top.
122     static final long START_WARN_TIME = 5*1000;
123
124     // Set to false to disable the preview that is shown while a new activity
125     // is being started.
126     static final boolean SHOW_APP_STARTING_PREVIEW = true;
127
128     // How long to wait for all background Activities to redraw following a call to
129     // convertToTranslucent().
130     static final long TRANSLUCENT_CONVERSION_TIMEOUT = 2000;
131
132     static final boolean SCREENSHOT_FORCE_565 = ActivityManager.isLowRamDeviceStatic();
133
134     enum ActivityState {
135         INITIALIZING,
136         RESUMED,
137         PAUSING,
138         PAUSED,
139         STOPPING,
140         STOPPED,
141         FINISHING,
142         DESTROYING,
143         DESTROYED
144     }
145
146     final ActivityManagerService mService;
147     final WindowManagerService mWindowManager;
148
149     /**
150      * The back history of all previous (and possibly still
151      * running) activities.  It contains #TaskRecord objects.
152      */
153     private ArrayList<TaskRecord> mTaskHistory = new ArrayList<TaskRecord>();
154
155     /**
156      * Used for validating app tokens with window manager.
157      */
158     final ArrayList<TaskGroup> mValidateAppTokens = new ArrayList<TaskGroup>();
159
160     /**
161      * List of running activities, sorted by recent usage.
162      * The first entry in the list is the least recently used.
163      * It contains HistoryRecord objects.
164      */
165     final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<ActivityRecord>();
166
167     /**
168      * Animations that for the current transition have requested not to
169      * be considered for the transition animation.
170      */
171     final ArrayList<ActivityRecord> mNoAnimActivities = new ArrayList<ActivityRecord>();
172
173     /**
174      * When we are in the process of pausing an activity, before starting the
175      * next one, this variable holds the activity that is currently being paused.
176      */
177     ActivityRecord mPausingActivity = null;
178
179     /**
180      * This is the last activity that we put into the paused state.  This is
181      * used to determine if we need to do an activity transition while sleeping,
182      * when we normally hold the top activity paused.
183      */
184     ActivityRecord mLastPausedActivity = null;
185
186     /**
187      * Activities that specify No History must be removed once the user navigates away from them.
188      * If the device goes to sleep with such an activity in the paused state then we save it here
189      * and finish it later if another activity replaces it on wakeup.
190      */
191     ActivityRecord mLastNoHistoryActivity = null;
192
193     /**
194      * Current activity that is resumed, or null if there is none.
195      */
196     ActivityRecord mResumedActivity = null;
197
198     /**
199      * This is the last activity that has been started.  It is only used to
200      * identify when multiple activities are started at once so that the user
201      * can be warned they may not be in the activity they think they are.
202      */
203     ActivityRecord mLastStartedActivity = null;
204
205     // The topmost Activity passed to convertToTranslucent(). When non-null it means we are
206     // waiting for all Activities in mUndrawnActivitiesBelowTopTranslucent to be removed as they
207     // are drawn. When the last member of mUndrawnActivitiesBelowTopTranslucent is removed the
208     // Activity in mTranslucentActivityWaiting is notified via
209     // Activity.onTranslucentConversionComplete(false). If a timeout occurs prior to the last
210     // background activity being drawn then the same call will be made with a true value.
211     ActivityRecord mTranslucentActivityWaiting = null;
212     private ArrayList<ActivityRecord> mUndrawnActivitiesBelowTopTranslucent =
213             new ArrayList<ActivityRecord>();
214     // Options passed from the caller of the convertToTranslucent to the activity that will
215     // appear below it.
216     ActivityOptions mReturningActivityOptions = null;
217
218     /**
219      * Set when we know we are going to be calling updateConfiguration()
220      * soon, so want to skip intermediate config checks.
221      */
222     boolean mConfigWillChange;
223
224     long mLaunchStartTime = 0;
225     long mFullyDrawnStartTime = 0;
226
227     /**
228      * Save the most recent screenshot for reuse. This keeps Recents from taking two identical
229      * screenshots, one for the Recents thumbnail and one for the pauseActivity thumbnail.
230      */
231     private ActivityRecord mLastScreenshotActivity = null;
232     private Bitmap mLastScreenshotBitmap = null;
233
234     int mThumbnailWidth = -1;
235     int mThumbnailHeight = -1;
236
237     int mCurrentUser;
238
239     final int mStackId;
240     final ActivityContainer mActivityContainer;
241     /** The other stacks, in order, on the attached display. Updated at attach/detach time. */
242     ArrayList<ActivityStack> mStacks;
243     /** The attached Display's unique identifier, or -1 if detached */
244     int mDisplayId;
245
246     /** Run all ActivityStacks through this */
247     final ActivityStackSupervisor mStackSupervisor;
248
249     static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
250     static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
251     static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
252     static final int STOP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 4;
253     static final int DESTROY_ACTIVITIES_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 5;
254     static final int TRANSLUCENT_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6;
255     static final int STOP_MEDIA_PLAYING_TIMEOUT_MSG =
256             ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 7;
257
258     static class ScheduleDestroyArgs {
259         final ProcessRecord mOwner;
260         final String mReason;
261         ScheduleDestroyArgs(ProcessRecord owner, String reason) {
262             mOwner = owner;
263             mReason = reason;
264         }
265     }
266
267     final Handler mHandler;
268
269     final class ActivityStackHandler extends Handler {
270         //public Handler() {
271         //    if (localLOGV) Slog.v(TAG, "Handler started!");
272         //}
273         ActivityStackHandler(Looper looper) {
274             super(looper);
275         }
276
277         @Override
278         public void handleMessage(Message msg) {
279             switch (msg.what) {
280                 case PAUSE_TIMEOUT_MSG: {
281                     ActivityRecord r = (ActivityRecord)msg.obj;
282                     // We don't at this point know if the activity is fullscreen,
283                     // so we need to be conservative and assume it isn't.
284                     Slog.w(TAG, "Activity pause timeout for " + r);
285                     synchronized (mService) {
286                         if (r.app != null) {
287                             mService.logAppTooSlow(r.app, r.pauseTime, "pausing " + r);
288                         }
289                         activityPausedLocked(r.appToken, true, r.persistentState);
290                     }
291                 } break;
292                 case LAUNCH_TICK_MSG: {
293                     ActivityRecord r = (ActivityRecord)msg.obj;
294                     synchronized (mService) {
295                         if (r.continueLaunchTickingLocked()) {
296                             mService.logAppTooSlow(r.app, r.launchTickTime, "launching " + r);
297                         }
298                     }
299                 } break;
300                 case DESTROY_TIMEOUT_MSG: {
301                     ActivityRecord r = (ActivityRecord)msg.obj;
302                     // We don't at this point know if the activity is fullscreen,
303                     // so we need to be conservative and assume it isn't.
304                     Slog.w(TAG, "Activity destroy timeout for " + r);
305                     synchronized (mService) {
306                         activityDestroyedLocked(r != null ? r.appToken : null);
307                     }
308                 } break;
309                 case STOP_TIMEOUT_MSG: {
310                     ActivityRecord r = (ActivityRecord)msg.obj;
311                     // We don't at this point know if the activity is fullscreen,
312                     // so we need to be conservative and assume it isn't.
313                     Slog.w(TAG, "Activity stop timeout for " + r);
314                     synchronized (mService) {
315                         if (r.isInHistory()) {
316                             activityStoppedLocked(r, null, null, null);
317                         }
318                     }
319                 } break;
320                 case DESTROY_ACTIVITIES_MSG: {
321                     ScheduleDestroyArgs args = (ScheduleDestroyArgs)msg.obj;
322                     synchronized (mService) {
323                         destroyActivitiesLocked(args.mOwner, args.mReason);
324                     }
325                 } break;
326                 case TRANSLUCENT_TIMEOUT_MSG: {
327                     synchronized (mService) {
328                         notifyActivityDrawnLocked(null);
329                     }
330                 } break;
331                 case STOP_MEDIA_PLAYING_TIMEOUT_MSG: {
332                     synchronized (mService) {
333                         final ActivityRecord r = getMediaPlayer();
334                         Slog.e(TAG, "Timeout waiting for stopMediaPlaying player=" + r);
335                         if (r != null) {
336                             mService.killAppAtUsersRequest(r.app, null);
337                         }
338                     }
339                 } break;
340             }
341         }
342     }
343
344     int numActivities() {
345         int count = 0;
346         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
347             count += mTaskHistory.get(taskNdx).mActivities.size();
348         }
349         return count;
350     }
351
352     ActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer) {
353         mActivityContainer = activityContainer;
354         mStackSupervisor = activityContainer.getOuter();
355         mService = mStackSupervisor.mService;
356         mHandler = new ActivityStackHandler(mService.mHandler.getLooper());
357         mWindowManager = mService.mWindowManager;
358         mStackId = activityContainer.mStackId;
359         mCurrentUser = mService.mCurrentUserId;
360         // Get the activity screenshot thumbnail dimensions
361         Resources res = mService.mContext.getResources();
362         mThumbnailWidth = res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
363         mThumbnailHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
364     }
365
366     /**
367      * Checks whether the userid is a profile of the current user.
368      */
369     private boolean isCurrentProfileLocked(int userId) {
370         if (userId == mCurrentUser) return true;
371         for (int i = 0; i < mService.mCurrentProfileIds.length; i++) {
372             if (mService.mCurrentProfileIds[i] == userId) return true;
373         }
374         return false;
375     }
376
377     boolean okToShowLocked(ActivityRecord r) {
378         return isCurrentProfileLocked(r.userId)
379                 || (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0;
380     }
381
382     final ActivityRecord topRunningActivityLocked(ActivityRecord notTop) {
383         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
384             ActivityRecord r = mTaskHistory.get(taskNdx).topRunningActivityLocked(notTop);
385             if (r != null) {
386                 return r;
387             }
388         }
389         return null;
390     }
391
392     final ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
393         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
394             final TaskRecord task = mTaskHistory.get(taskNdx);
395             final ArrayList<ActivityRecord> activities = task.mActivities;
396             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
397                 ActivityRecord r = activities.get(activityNdx);
398                 if (!r.finishing && !r.delayedResume && r != notTop && okToShowLocked(r)) {
399                     return r;
400                 }
401             }
402         }
403         return null;
404     }
405
406     /**
407      * This is a simplified version of topRunningActivityLocked that provides a number of
408      * optional skip-over modes.  It is intended for use with the ActivityController hook only.
409      *
410      * @param token If non-null, any history records matching this token will be skipped.
411      * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
412      *
413      * @return Returns the HistoryRecord of the next activity on the stack.
414      */
415     final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) {
416         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
417             TaskRecord task = mTaskHistory.get(taskNdx);
418             if (task.taskId == taskId) {
419                 continue;
420             }
421             ArrayList<ActivityRecord> activities = task.mActivities;
422             for (int i = activities.size() - 1; i >= 0; --i) {
423                 final ActivityRecord r = activities.get(i);
424                 // Note: the taskId check depends on real taskId fields being non-zero
425                 if (!r.finishing && (token != r.appToken) && okToShowLocked(r)) {
426                     return r;
427                 }
428             }
429         }
430         return null;
431     }
432
433     final ActivityRecord topActivity() {
434         // Iterate to find the first non-empty task stack. Note that this code can
435         // be simplified once we stop storing tasks with empty mActivities lists.
436         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
437             ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
438             final int topActivityNdx = activities.size() - 1;
439             if (topActivityNdx >= 0) {
440                 return activities.get(topActivityNdx);
441             }
442         }
443         return null;
444     }
445
446     final TaskRecord topTask() {
447         final int size = mTaskHistory.size();
448         if (size > 0) {
449             return mTaskHistory.get(size - 1);
450         }
451         return null;
452     }
453
454     TaskRecord taskForIdLocked(int id) {
455         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
456             final TaskRecord task = mTaskHistory.get(taskNdx);
457             if (task.taskId == id) {
458                 return task;
459             }
460         }
461         return null;
462     }
463
464     ActivityRecord isInStackLocked(IBinder token) {
465         final ActivityRecord r = ActivityRecord.forToken(token);
466         if (r != null) {
467             final TaskRecord task = r.task;
468             if (task.mActivities.contains(r) && mTaskHistory.contains(task)) {
469                 if (task.stack != this) Slog.w(TAG,
470                     "Illegal state! task does not point to stack it is in.");
471                 return r;
472             }
473         }
474         return null;
475     }
476
477     final boolean updateLRUListLocked(ActivityRecord r) {
478         final boolean hadit = mLRUActivities.remove(r);
479         mLRUActivities.add(r);
480         return hadit;
481     }
482
483     final boolean isHomeStack() {
484         return mStackId == HOME_STACK_ID;
485     }
486
487     final boolean isOnHomeDisplay() {
488         return isAttached() &&
489                 mActivityContainer.mActivityDisplay.mDisplayId == Display.DEFAULT_DISPLAY;
490     }
491
492     final void moveToFront() {
493         if (isAttached()) {
494             if (isOnHomeDisplay()) {
495                 mStackSupervisor.moveHomeStack(isHomeStack());
496             }
497             mStacks.remove(this);
498             mStacks.add(this);
499         }
500     }
501
502     final boolean isAttached() {
503         return mStacks != null;
504     }
505
506     /**
507      * Returns the top activity in any existing task matching the given
508      * Intent.  Returns null if no such task is found.
509      */
510     ActivityRecord findTaskLocked(ActivityRecord target) {
511         Intent intent = target.intent;
512         ActivityInfo info = target.info;
513         ComponentName cls = intent.getComponent();
514         if (info.targetActivity != null) {
515             cls = new ComponentName(info.packageName, info.targetActivity);
516         }
517         final int userId = UserHandle.getUserId(info.applicationInfo.uid);
518         boolean isDocument = intent != null & intent.isDocument();
519         // If documentData is non-null then it must match the existing task data.
520         Uri documentData = isDocument ? intent.getData() : null;
521
522         if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + target + " in " + this);
523         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
524             final TaskRecord task = mTaskHistory.get(taskNdx);
525             if (task.voiceSession != null) {
526                 // We never match voice sessions; those always run independently.
527                 if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": voice session");
528                 continue;
529             }
530             if (task.userId != userId) {
531                 // Looking for a different task.
532                 if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": different user");
533                 continue;
534             }
535             final ActivityRecord r = task.getTopActivity();
536             if (r == null || r.finishing || r.userId != userId ||
537                     r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
538                 if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": mismatch root " + r);
539                 continue;
540             }
541
542             final Intent taskIntent = task.intent;
543             final Intent affinityIntent = task.affinityIntent;
544             final boolean taskIsDocument;
545             final Uri taskDocumentData;
546             if (taskIntent != null && taskIntent.isDocument()) {
547                 taskIsDocument = true;
548                 taskDocumentData = taskIntent.getData();
549             } else if (affinityIntent != null && affinityIntent.isDocument()) {
550                 taskIsDocument = true;
551                 taskDocumentData = affinityIntent.getData();
552             } else {
553                 taskIsDocument = false;
554                 taskDocumentData = null;
555             }
556
557             if (DEBUG_TASKS) Slog.d(TAG, "Comparing existing cls="
558                     + taskIntent.getComponent().flattenToShortString()
559                     + "/aff=" + r.task.affinity + " to new cls="
560                     + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
561             if (!isDocument && !taskIsDocument && task.affinity != null) {
562                 if (task.affinity.equals(target.taskAffinity)) {
563                     if (DEBUG_TASKS) Slog.d(TAG, "Found matching affinity!");
564                     return r;
565                 }
566             } else if (taskIntent != null && taskIntent.getComponent() != null &&
567                     taskIntent.getComponent().compareTo(cls) == 0 &&
568                     Objects.equals(documentData, taskDocumentData)) {
569                 if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
570                 //dump();
571                 if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
572                         + r.intent);
573                 return r;
574             } else if (affinityIntent != null && affinityIntent.getComponent() != null &&
575                     affinityIntent.getComponent().compareTo(cls) == 0 &&
576                     Objects.equals(documentData, taskDocumentData)) {
577                 if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
578                 //dump();
579                 if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
580                         + r.intent);
581                 return r;
582             } else if (DEBUG_TASKS) {
583                 Slog.d(TAG, "Not a match: " + task);
584             }
585         }
586
587         return null;
588     }
589
590     /**
591      * Returns the first activity (starting from the top of the stack) that
592      * is the same as the given activity.  Returns null if no such activity
593      * is found.
594      */
595     ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
596         ComponentName cls = intent.getComponent();
597         if (info.targetActivity != null) {
598             cls = new ComponentName(info.packageName, info.targetActivity);
599         }
600         final int userId = UserHandle.getUserId(info.applicationInfo.uid);
601
602         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
603             TaskRecord task = mTaskHistory.get(taskNdx);
604             if (!isCurrentProfileLocked(task.userId)) {
605                 return null;
606             }
607             final ArrayList<ActivityRecord> activities = task.mActivities;
608             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
609                 ActivityRecord r = activities.get(activityNdx);
610                 if (!r.finishing && r.intent.getComponent().equals(cls) && r.userId == userId) {
611                     //Slog.i(TAG, "Found matching class!");
612                     //dump();
613                     //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
614                     return r;
615                 }
616             }
617         }
618
619         return null;
620     }
621
622     /*
623      * Move the activities around in the stack to bring a user to the foreground.
624      */
625     final void switchUserLocked(int userId) {
626         if (mCurrentUser == userId) {
627             return;
628         }
629         mCurrentUser = userId;
630
631         // Move userId's tasks to the top.
632         int index = mTaskHistory.size();
633         for (int i = 0; i < index; ) {
634             TaskRecord task = mTaskHistory.get(i);
635             if (isCurrentProfileLocked(task.userId)) {
636                 if (DEBUG_TASKS) Slog.d(TAG, "switchUserLocked: stack=" + getStackId() +
637                         " moving " + task + " to top");
638                 mTaskHistory.remove(i);
639                 mTaskHistory.add(task);
640                 --index;
641                 // Use same value for i.
642             } else {
643                 ++i;
644             }
645         }
646         if (VALIDATE_TOKENS) {
647             validateAppTokensLocked();
648         }
649     }
650
651     void minimalResumeActivityLocked(ActivityRecord r) {
652         r.state = ActivityState.RESUMED;
653         if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + r
654                 + " (starting new instance)");
655         r.stopped = false;
656         mResumedActivity = r;
657         r.task.touchActiveTime();
658         mService.addRecentTaskLocked(r.task);
659         completeResumeLocked(r);
660         mStackSupervisor.checkReadyForSleepLocked();
661         setLaunchTime(r);
662         if (DEBUG_SAVED_STATE) Slog.i(TAG, "Launch completed; removing icicle of " + r.icicle);
663     }
664
665     private void startLaunchTraces() {
666         if (mFullyDrawnStartTime != 0)  {
667             Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
668         }
669         Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching", 0);
670         Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
671     }
672
673     private void stopFullyDrawnTraceIfNeeded() {
674         if (mFullyDrawnStartTime != 0 && mLaunchStartTime == 0) {
675             Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
676             mFullyDrawnStartTime = 0;
677         }
678     }
679
680     void setLaunchTime(ActivityRecord r) {
681         if (r.displayStartTime == 0) {
682             r.fullyDrawnStartTime = r.displayStartTime = SystemClock.uptimeMillis();
683             if (mLaunchStartTime == 0) {
684                 startLaunchTraces();
685                 mLaunchStartTime = mFullyDrawnStartTime = r.displayStartTime;
686             }
687         } else if (mLaunchStartTime == 0) {
688             startLaunchTraces();
689             mLaunchStartTime = mFullyDrawnStartTime = SystemClock.uptimeMillis();
690         }
691     }
692
693     void clearLaunchTime(ActivityRecord r) {
694         // Make sure that there is no activity waiting for this to launch.
695         if (mStackSupervisor.mWaitingActivityLaunched.isEmpty()) {
696             r.displayStartTime = r.fullyDrawnStartTime = 0;
697         } else {
698             mStackSupervisor.removeTimeoutsForActivityLocked(r);
699             mStackSupervisor.scheduleIdleTimeoutLocked(r);
700         }
701     }
702
703     void awakeFromSleepingLocked() {
704         // Ensure activities are no longer sleeping.
705         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
706             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
707             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
708                 activities.get(activityNdx).setSleeping(false);
709             }
710         }
711     }
712
713     /**
714      * @return true if something must be done before going to sleep.
715      */
716     boolean checkReadyForSleepLocked() {
717         if (mResumedActivity != null) {
718             // Still have something resumed; can't sleep until it is paused.
719             if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause " + mResumedActivity);
720             if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
721             startPausingLocked(false, true);
722             return true;
723         }
724         if (mPausingActivity != null) {
725             // Still waiting for something to pause; can't sleep yet.
726             if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still waiting to pause " + mPausingActivity);
727             return true;
728         }
729
730         return false;
731     }
732
733     void goToSleep() {
734         ensureActivitiesVisibleLocked(null, 0);
735
736         // Make sure any stopped but visible activities are now sleeping.
737         // This ensures that the activity's onStop() is called.
738         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
739             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
740             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
741                 final ActivityRecord r = activities.get(activityNdx);
742                 if (r.state == ActivityState.STOPPING || r.state == ActivityState.STOPPED) {
743                     r.setSleeping(true);
744                 }
745             }
746         }
747     }
748
749     /**
750      * This resets the saved state from the last screenshot, forcing a new screenshot to be taken
751      * again when requested.
752      */
753     private void invalidateLastScreenshot() {
754         mLastScreenshotActivity = null;
755         if (mLastScreenshotBitmap != null) {
756             mLastScreenshotBitmap.recycle();
757         }
758         mLastScreenshotBitmap = null;
759     }
760
761     public final Bitmap screenshotActivities(ActivityRecord who) {
762         if (DEBUG_SCREENSHOTS) Slog.d(TAG, "screenshotActivities: " + who);
763         if (who.noDisplay) {
764             if (DEBUG_SCREENSHOTS) Slog.d(TAG, "\tNo display");
765             return null;
766         }
767
768         if (isHomeStack()) {
769             // This is an optimization -- since we never show Home or Recents within Recents itself,
770             // we can just go ahead and skip taking the screenshot if this is the home stack.  In
771             // the case where the most recent task is not the task that was supplied, then the stack
772             // has changed, so invalidate the last screenshot().
773             invalidateLastScreenshot();
774             if (DEBUG_SCREENSHOTS) Slog.d(TAG, "\tIs Home stack? " + isHomeStack());
775             return null;
776         }
777
778         int w = mThumbnailWidth;
779         int h = mThumbnailHeight;
780         if (w > 0) {
781             if (who != mLastScreenshotActivity || mLastScreenshotBitmap == null
782                     || mLastScreenshotActivity.state == ActivityState.RESUMED
783                     || mLastScreenshotBitmap.getWidth() != w
784                     || mLastScreenshotBitmap.getHeight() != h) {
785                 if (DEBUG_SCREENSHOTS) Slog.d(TAG, "\tUpdating screenshot");
786                 mLastScreenshotActivity = who;
787                 mLastScreenshotBitmap = mWindowManager.screenshotApplications(
788                         who.appToken, Display.DEFAULT_DISPLAY, w, h, SCREENSHOT_FORCE_565);
789             }
790             if (mLastScreenshotBitmap != null) {
791                 if (DEBUG_SCREENSHOTS) Slog.d(TAG, "\tReusing last screenshot");
792                 return mLastScreenshotBitmap.copy(mLastScreenshotBitmap.getConfig(), true);
793             }
794         }
795         Slog.e(TAG, "Invalid thumbnail dimensions: " + w + "x" + h);
796         return null;
797     }
798
799     final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
800         if (mPausingActivity != null) {
801             Slog.e(TAG, "Trying to pause when pause is already pending for "
802                   + mPausingActivity, new RuntimeException("here").fillInStackTrace());
803         }
804         ActivityRecord prev = mResumedActivity;
805         if (prev == null) {
806             Slog.e(TAG, "Trying to pause when nothing is resumed",
807                     new RuntimeException("here").fillInStackTrace());
808             mStackSupervisor.resumeTopActivitiesLocked();
809             return;
810         }
811
812         if (mActivityContainer.mParentActivity == null) {
813             // Top level stack, not a child. Look for child stacks.
814             mStackSupervisor.pauseChildStacks(prev, userLeaving, uiSleeping);
815         }
816
817         if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev);
818         else if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
819         mResumedActivity = null;
820         mPausingActivity = prev;
821         mLastPausedActivity = prev;
822         mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
823                 || (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
824         prev.state = ActivityState.PAUSING;
825         prev.task.touchActiveTime();
826         clearLaunchTime(prev);
827         final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
828         if (mService.mHasRecents && (next == null || next.noDisplay || next.task != prev.task)) {
829             prev.updateThumbnail(screenshotActivities(prev), null);
830         }
831         stopFullyDrawnTraceIfNeeded();
832
833         mService.updateCpuStats();
834
835         if (prev.app != null && prev.app.thread != null) {
836             if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
837             try {
838                 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
839                         prev.userId, System.identityHashCode(prev),
840                         prev.shortComponentName);
841                 mService.updateUsageStats(prev, false);
842                 prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
843                         userLeaving, prev.configChangeFlags);
844             } catch (Exception e) {
845                 // Ignore exception, if process died other code will cleanup.
846                 Slog.w(TAG, "Exception thrown during pause", e);
847                 mPausingActivity = null;
848                 mLastPausedActivity = null;
849                 mLastNoHistoryActivity = null;
850             }
851         } else {
852             mPausingActivity = null;
853             mLastPausedActivity = null;
854             mLastNoHistoryActivity = null;
855         }
856
857         // If we are not going to sleep, we want to ensure the device is
858         // awake until the next activity is started.
859         if (!mService.isSleepingOrShuttingDown()) {
860             mStackSupervisor.acquireLaunchWakelock();
861         }
862
863         if (mPausingActivity != null) {
864             // Have the window manager pause its key dispatching until the new
865             // activity has started.  If we're pausing the activity just because
866             // the screen is being turned off and the UI is sleeping, don't interrupt
867             // key dispatch; the same activity will pick it up again on wakeup.
868             if (!uiSleeping) {
869                 prev.pauseKeyDispatchingLocked();
870             } else {
871                 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
872             }
873
874             // Schedule a pause timeout in case the app doesn't respond.
875             // We don't give it much time because this directly impacts the
876             // responsiveness seen by the user.
877             Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
878             msg.obj = prev;
879             prev.pauseTime = SystemClock.uptimeMillis();
880             mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
881             if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
882         } else {
883             // This activity failed to schedule the
884             // pause, so just treat it as being paused now.
885             if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
886             mStackSupervisor.getFocusedStack().resumeTopActivityLocked(null);
887         }
888     }
889
890     final void activityPausedLocked(IBinder token, boolean timeout,
891             PersistableBundle persistentState) {
892         if (DEBUG_PAUSE) Slog.v(
893             TAG, "Activity paused: token=" + token + ", timeout=" + timeout);
894
895         final ActivityRecord r = isInStackLocked(token);
896         if (r != null) {
897             mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
898             if (persistentState != null) {
899                 r.persistentState = persistentState;
900                 mService.notifyTaskPersisterLocked(r.task, false);
901             }
902             if (mPausingActivity == r) {
903                 if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r
904                         + (timeout ? " (due to timeout)" : " (pause complete)"));
905                 r.state = ActivityState.PAUSED;
906                 completePauseLocked();
907             } else {
908                 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
909                         r.userId, System.identityHashCode(r), r.shortComponentName,
910                         mPausingActivity != null
911                             ? mPausingActivity.shortComponentName : "(none)");
912             }
913         }
914     }
915
916     final void activityStoppedLocked(ActivityRecord r, Bundle icicle,
917             PersistableBundle persistentState, CharSequence description) {
918         if (r.state != ActivityState.STOPPING) {
919             Slog.i(TAG, "Activity reported stop, but no longer stopping: " + r);
920             mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
921             return;
922         }
923         if (persistentState != null) {
924             r.persistentState = persistentState;
925             mService.notifyTaskPersisterLocked(r.task, false);
926         }
927         if (DEBUG_SAVED_STATE) Slog.i(TAG, "Saving icicle of " + r + ": " + icicle);
928         if (icicle != null) {
929             // If icicle is null, this is happening due to a timeout, so we
930             // haven't really saved the state.
931             r.icicle = icicle;
932             r.haveState = true;
933             r.launchCount = 0;
934             r.updateThumbnail(null, description);
935         }
936         if (!r.stopped) {
937             if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r + " (stop complete)");
938             mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
939             r.stopped = true;
940             r.state = ActivityState.STOPPED;
941             if (mActivityContainer.mActivityDisplay.mMediaPlayingActivity == r) {
942                 mStackSupervisor.setMediaPlayingLocked(r, false);
943             }
944             if (r.finishing) {
945                 r.clearOptionsLocked();
946             } else {
947                 if (r.configDestroy) {
948                     destroyActivityLocked(r, true, "stop-config");
949                     mStackSupervisor.resumeTopActivitiesLocked();
950                 } else {
951                     mStackSupervisor.updatePreviousProcessLocked(r);
952                 }
953             }
954         }
955     }
956
957     private void completePauseLocked() {
958         ActivityRecord prev = mPausingActivity;
959         if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
960
961         if (prev != null) {
962             if (prev.finishing) {
963                 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
964                 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false);
965             } else if (prev.app != null) {
966                 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
967                 if (prev.waitingVisible) {
968                     prev.waitingVisible = false;
969                     mStackSupervisor.mWaitingVisibleActivities.remove(prev);
970                     if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
971                             TAG, "Complete pause, no longer waiting: " + prev);
972                 }
973                 if (prev.configDestroy) {
974                     // The previous is being paused because the configuration
975                     // is changing, which means it is actually stopping...
976                     // To juggle the fact that we are also starting a new
977                     // instance right now, we need to first completely stop
978                     // the current instance before starting the new one.
979                     if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
980                     destroyActivityLocked(prev, true, "pause-config");
981                 } else if (!isMediaPlaying()) {
982                     // If we were playing then resumeTopActivities will release resources before
983                     // stopping.
984                     mStackSupervisor.mStoppingActivities.add(prev);
985                     if (mStackSupervisor.mStoppingActivities.size() > 3 ||
986                             prev.frontOfTask && mTaskHistory.size() <= 1) {
987                         // If we already have a few activities waiting to stop,
988                         // then give up on things going idle and start clearing
989                         // them out. Or if r is the last of activity of the last task the stack
990                         // will be empty and must be cleared immediately.
991                         if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
992                         mStackSupervisor.scheduleIdleLocked();
993                     } else {
994                         mStackSupervisor.checkReadyForSleepLocked();
995                     }
996                 }
997             } else {
998                 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
999                 prev = null;
1000             }
1001             mPausingActivity = null;
1002         }
1003
1004         final ActivityStack topStack = mStackSupervisor.getFocusedStack();
1005         if (!mService.isSleepingOrShuttingDown()) {
1006             mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);
1007         } else {
1008             mStackSupervisor.checkReadyForSleepLocked();
1009             ActivityRecord top = topStack.topRunningActivityLocked(null);
1010             if (top == null || (prev != null && top != prev)) {
1011                 // If there are no more activities available to run,
1012                 // do resume anyway to start something.  Also if the top
1013                 // activity on the stack is not the just paused activity,
1014                 // we need to go ahead and resume it to ensure we complete
1015                 // an in-flight app switch.
1016                 mStackSupervisor.resumeTopActivitiesLocked(topStack, null, null);
1017             }
1018         }
1019
1020         if (prev != null) {
1021             prev.resumeKeyDispatchingLocked();
1022
1023             if (prev.app != null && prev.cpuTimeAtResume > 0
1024                     && mService.mBatteryStatsService.isOnBattery()) {
1025                 long diff;
1026                 synchronized (mService.mProcessCpuThread) {
1027                     diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid)
1028                             - prev.cpuTimeAtResume;
1029                 }
1030                 if (diff > 0) {
1031                     BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics();
1032                     synchronized (bsi) {
1033                         BatteryStatsImpl.Uid.Proc ps =
1034                                 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
1035                                         prev.info.packageName);
1036                         if (ps != null) {
1037                             ps.addForegroundTimeLocked(diff);
1038                         }
1039                     }
1040                 }
1041             }
1042             prev.cpuTimeAtResume = 0; // reset it
1043         }
1044     }
1045
1046     /**
1047      * Once we know that we have asked an application to put an activity in
1048      * the resumed state (either by launching it or explicitly telling it),
1049      * this function updates the rest of our state to match that fact.
1050      */
1051     private void completeResumeLocked(ActivityRecord next) {
1052         next.idle = false;
1053         next.results = null;
1054         next.newIntents = null;
1055         if (next.nowVisible) {
1056             // We won't get a call to reportActivityVisibleLocked() so dismiss lockscreen now.
1057             mStackSupervisor.dismissKeyguard();
1058         }
1059
1060         // schedule an idle timeout in case the app doesn't do it for us.
1061         mStackSupervisor.scheduleIdleTimeoutLocked(next);
1062
1063         mStackSupervisor.reportResumedActivityLocked(next);
1064
1065         next.resumeKeyDispatchingLocked();
1066         mNoAnimActivities.clear();
1067
1068         // Mark the point when the activity is resuming
1069         // TODO: To be more accurate, the mark should be before the onCreate,
1070         //       not after the onResume. But for subsequent starts, onResume is fine.
1071         if (next.app != null) {
1072             synchronized (mService.mProcessCpuThread) {
1073                 next.cpuTimeAtResume = mService.mProcessCpuTracker.getCpuTimeForPid(next.app.pid);
1074             }
1075         } else {
1076             next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
1077         }
1078
1079         // If we are resuming the activity that we had last screenshotted, then we know it will be
1080         // updated, so invalidate the last screenshot to ensure we take a fresh one when requested
1081         if (next == mLastScreenshotActivity) {
1082             invalidateLastScreenshot();
1083         }
1084         mReturningActivityOptions = null;
1085     }
1086
1087     private void setVisibile(ActivityRecord r, boolean visible) {
1088         r.visible = visible;
1089         mWindowManager.setAppVisibility(r.appToken, visible);
1090         final ArrayList<ActivityContainer> containers = r.mChildContainers;
1091         for (int containerNdx = containers.size() - 1; containerNdx >= 0; --containerNdx) {
1092             ActivityContainer container = containers.get(containerNdx);
1093             container.setVisible(visible);
1094         }
1095     }
1096
1097     // Checks if any of the stacks above this one has a fullscreen activity behind it.
1098     // If so, this stack is hidden, otherwise it is visible.
1099     private boolean isStackVisible() {
1100         if (!isAttached()) {
1101             return false;
1102         }
1103
1104         if (mStackSupervisor.isFrontStack(this)) {
1105             return true;
1106         }
1107
1108         /**
1109          * Start at the task above this one and go up, looking for a visible
1110          * fullscreen activity, or a translucent activity that requested the
1111          * wallpaper to be shown behind it.
1112          */
1113         for (int i = mStacks.indexOf(this) + 1; i < mStacks.size(); i++) {
1114             final ArrayList<TaskRecord> tasks = mStacks.get(i).getAllTasks();
1115             for (int taskNdx = 0; taskNdx < tasks.size(); taskNdx++) {
1116                 final TaskRecord task = tasks.get(taskNdx);
1117                 final ArrayList<ActivityRecord> activities = task.mActivities;
1118                 for (int activityNdx = 0; activityNdx < activities.size(); activityNdx++) {
1119                     final ActivityRecord r = activities.get(activityNdx);
1120
1121                     // Conditions for an activity to obscure the stack we're
1122                     // examining:
1123                     // 1. Not Finishing AND Visible AND:
1124                     // 2. Either:
1125                     // - Full Screen Activity OR
1126                     // - On top of Home and our stack is NOT home
1127                     if (!r.finishing && r.visible && (r.fullscreen ||
1128                             (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()))) {
1129                         return false;
1130                     }
1131                 }
1132             }
1133         }
1134
1135         return true;
1136     }
1137
1138     /**
1139      * Make sure that all activities that need to be visible (that is, they
1140      * currently can be seen by the user) actually are.
1141      */
1142     final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
1143         ActivityRecord top = topRunningActivityLocked(null);
1144         if (top == null) {
1145             return;
1146         }
1147         if (DEBUG_VISBILITY) Slog.v(
1148                 TAG, "ensureActivitiesVisible behind " + top
1149                 + " configChanges=0x" + Integer.toHexString(configChanges));
1150
1151         if (mTranslucentActivityWaiting != top) {
1152             mUndrawnActivitiesBelowTopTranslucent.clear();
1153             if (mTranslucentActivityWaiting != null) {
1154                 // Call the callback with a timeout indication.
1155                 notifyActivityDrawnLocked(null);
1156                 mTranslucentActivityWaiting = null;
1157             }
1158             mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG);
1159         }
1160
1161         // If the top activity is not fullscreen, then we need to
1162         // make sure any activities under it are now visible.
1163         boolean aboveTop = true;
1164         boolean behindFullscreen = !isStackVisible();
1165
1166         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1167             final TaskRecord task = mTaskHistory.get(taskNdx);
1168             final ArrayList<ActivityRecord> activities = task.mActivities;
1169             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1170                 final ActivityRecord r = activities.get(activityNdx);
1171                 if (r.finishing) {
1172                     continue;
1173                 }
1174                 if (aboveTop && r != top) {
1175                     continue;
1176                 }
1177                 aboveTop = false;
1178                 // mLaunchingBehind: Activities launching behind are at the back of the task stack
1179                 // but must be drawn initially for the animation as though they were visible.
1180                 if (!behindFullscreen || r.mLaunchTaskBehind) {
1181                     if (DEBUG_VISBILITY) Slog.v(
1182                             TAG, "Make visible? " + r + " finishing=" + r.finishing
1183                             + " state=" + r.state);
1184
1185                     // First: if this is not the current activity being started, make
1186                     // sure it matches the current configuration.
1187                     if (r != starting) {
1188                         ensureActivityConfigurationLocked(r, 0);
1189                     }
1190
1191                     if (r.app == null || r.app.thread == null) {
1192                         // This activity needs to be visible, but isn't even
1193                         // running...  get it started, but don't resume it
1194                         // at this point.
1195                         if (DEBUG_VISBILITY) Slog.v(TAG, "Start and freeze screen for " + r);
1196                         if (r != starting) {
1197                             r.startFreezingScreenLocked(r.app, configChanges);
1198                         }
1199                         if (!r.visible || r.mLaunchTaskBehind) {
1200                             if (DEBUG_VISBILITY) Slog.v(
1201                                     TAG, "Starting and making visible: " + r);
1202                             setVisibile(r, true);
1203                         }
1204                         if (r != starting) {
1205                             mStackSupervisor.startSpecificActivityLocked(r, false, false);
1206                         }
1207
1208                     } else if (r.visible) {
1209                         // If this activity is already visible, then there is nothing
1210                         // else to do here.
1211                         if (DEBUG_VISBILITY) Slog.v(TAG, "Skipping: already visible at " + r);
1212                         r.stopFreezingScreenLocked(false);
1213                         try {
1214                             if (mReturningActivityOptions != null && r == top && activityNdx > 0) {
1215                                 ActivityRecord under = activities.get(activityNdx - 1);
1216                                 under.app.thread.scheduleOnNewActivityOptions(under.appToken,
1217                                         mReturningActivityOptions);
1218                             }
1219                         } catch(RemoteException e) {
1220                         }
1221                     } else {
1222                         // This activity is not currently visible, but is running.
1223                         // Tell it to become visible.
1224                         r.visible = true;
1225                         if (r.state != ActivityState.RESUMED && r != starting) {
1226                             // If this activity is paused, tell it
1227                             // to now show its window.
1228                             if (DEBUG_VISBILITY) Slog.v(
1229                                     TAG, "Making visible and scheduling visibility: " + r);
1230                             try {
1231                                 if (mTranslucentActivityWaiting != null) {
1232                                     r.updateOptionsLocked(mReturningActivityOptions);
1233                                     mUndrawnActivitiesBelowTopTranslucent.add(r);
1234                                 }
1235                                 setVisibile(r, true);
1236                                 r.sleeping = false;
1237                                 r.app.pendingUiClean = true;
1238                                 r.app.thread.scheduleWindowVisibility(r.appToken, true);
1239                                 r.stopFreezingScreenLocked(false);
1240                             } catch (Exception e) {
1241                                 // Just skip on any failure; we'll make it
1242                                 // visible when it next restarts.
1243                                 Slog.w(TAG, "Exception thrown making visibile: "
1244                                         + r.intent.getComponent(), e);
1245                             }
1246                         }
1247                     }
1248
1249                     // Aggregate current change flags.
1250                     configChanges |= r.configChangeFlags;
1251
1252                     if (r.fullscreen) {
1253                         // At this point, nothing else needs to be shown
1254                         if (DEBUG_VISBILITY) Slog.v(TAG, "Fullscreen: at " + r);
1255                         behindFullscreen = true;
1256                     } else if (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()) {
1257                         if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r);
1258                         behindFullscreen = true;
1259                     }
1260                 } else {
1261                     if (DEBUG_VISBILITY) Slog.v(
1262                         TAG, "Make invisible? " + r + " finishing=" + r.finishing
1263                         + " state=" + r.state
1264                         + " behindFullscreen=" + behindFullscreen);
1265                     // Now for any activities that aren't visible to the user, make
1266                     // sure they no longer are keeping the screen frozen.
1267                     if (r.visible) {
1268                         if (DEBUG_VISBILITY) Slog.v(TAG, "Making invisible: " + r);
1269                         try {
1270                             setVisibile(r, false);
1271                             switch (r.state) {
1272                                 case STOPPING:
1273                                 case STOPPED:
1274                                     if (r.app != null && r.app.thread != null) {
1275                                         if (DEBUG_VISBILITY) Slog.v(
1276                                                 TAG, "Scheduling invisibility: " + r);
1277                                         r.app.thread.scheduleWindowVisibility(r.appToken, false);
1278                                     }
1279                                     break;
1280
1281                                 case INITIALIZING:
1282                                 case RESUMED:
1283                                 case PAUSING:
1284                                 case PAUSED:
1285                                     // This case created for transitioning activities from
1286                                     // translucent to opaque {@link Activity#convertToOpaque}.
1287                                     if (getMediaPlayer() == r) {
1288                                         releaseMediaResources();
1289                                     } else {
1290                                         if (!mStackSupervisor.mStoppingActivities.contains(r)) {
1291                                             mStackSupervisor.mStoppingActivities.add(r);
1292                                         }
1293                                         mStackSupervisor.scheduleIdleLocked();
1294                                     }
1295                                     break;
1296
1297                                 default:
1298                                     break;
1299                             }
1300                         } catch (Exception e) {
1301                             // Just skip on any failure; we'll make it
1302                             // visible when it next restarts.
1303                             Slog.w(TAG, "Exception thrown making hidden: "
1304                                     + r.intent.getComponent(), e);
1305                         }
1306                     } else {
1307                         if (DEBUG_VISBILITY) Slog.v(TAG, "Already invisible: " + r);
1308                     }
1309                 }
1310             }
1311         }
1312
1313         if (mTranslucentActivityWaiting != null &&
1314                 mUndrawnActivitiesBelowTopTranslucent.isEmpty()) {
1315             // Nothing is getting drawn or everything was already visible, don't wait for timeout.
1316             notifyActivityDrawnLocked(null);
1317         }
1318     }
1319
1320     void convertToTranslucent(ActivityRecord r, ActivityOptions options) {
1321         mTranslucentActivityWaiting = r;
1322         mUndrawnActivitiesBelowTopTranslucent.clear();
1323         mReturningActivityOptions = options;
1324         mHandler.sendEmptyMessageDelayed(TRANSLUCENT_TIMEOUT_MSG, TRANSLUCENT_CONVERSION_TIMEOUT);
1325     }
1326
1327     /**
1328      * Called as activities below the top translucent activity are redrawn. When the last one is
1329      * redrawn notify the top activity by calling
1330      * {@link Activity#onTranslucentConversionComplete}.
1331      *
1332      * @param r The most recent background activity to be drawn. Or, if r is null then a timeout
1333      * occurred and the activity will be notified immediately.
1334      */
1335     void notifyActivityDrawnLocked(ActivityRecord r) {
1336         mActivityContainer.setDrawn();
1337         if ((r == null)
1338                 || (mUndrawnActivitiesBelowTopTranslucent.remove(r) &&
1339                         mUndrawnActivitiesBelowTopTranslucent.isEmpty())) {
1340             // The last undrawn activity below the top has just been drawn. If there is an
1341             // opaque activity at the top, notify it that it can become translucent safely now.
1342             final ActivityRecord waitingActivity = mTranslucentActivityWaiting;
1343             mTranslucentActivityWaiting = null;
1344             mUndrawnActivitiesBelowTopTranslucent.clear();
1345             mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG);
1346
1347             if (waitingActivity != null) {
1348                 mWindowManager.setWindowOpaque(waitingActivity.appToken, false);
1349                 if (waitingActivity.app != null && waitingActivity.app.thread != null) {
1350                     try {
1351                         waitingActivity.app.thread.scheduleTranslucentConversionComplete(
1352                                 waitingActivity.appToken, r != null);
1353                     } catch (RemoteException e) {
1354                     }
1355                 }
1356             }
1357         }
1358     }
1359
1360     /** If any activities below the top running one are in the INITIALIZING state and they have a
1361      * starting window displayed then remove that starting window. It is possible that the activity
1362      * in this state will never resumed in which case that starting window will be orphaned. */
1363     void cancelInitializingActivities() {
1364         final ActivityRecord topActivity = topRunningActivityLocked(null);
1365         boolean aboveTop = true;
1366         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1367             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
1368             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1369                 final ActivityRecord r = activities.get(activityNdx);
1370                 if (aboveTop) {
1371                     if (r == topActivity) {
1372                         aboveTop = false;
1373                     }
1374                     continue;
1375                 }
1376
1377                 if (r.state == ActivityState.INITIALIZING && r.mStartingWindowShown) {
1378                     if (DEBUG_VISBILITY) Slog.w(TAG, "Found orphaned starting window " + r);
1379                     r.mStartingWindowShown = false;
1380                     mWindowManager.removeAppStartingWindow(r.appToken);
1381                 }
1382             }
1383         }
1384     }
1385
1386     /**
1387      * Ensure that the top activity in the stack is resumed.
1388      *
1389      * @param prev The previously resumed activity, for when in the process
1390      * of pausing; can be null to call from elsewhere.
1391      *
1392      * @return Returns true if something is being resumed, or false if
1393      * nothing happened.
1394      */
1395     final boolean resumeTopActivityLocked(ActivityRecord prev) {
1396         return resumeTopActivityLocked(prev, null);
1397     }
1398
1399     final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
1400         if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
1401
1402         ActivityRecord parent = mActivityContainer.mParentActivity;
1403         if ((parent != null && parent.state != ActivityState.RESUMED) ||
1404                 !mActivityContainer.isAttachedLocked()) {
1405             // Do not resume this stack if its parent is not resumed.
1406             // TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st.
1407             return false;
1408         }
1409
1410         cancelInitializingActivities();
1411
1412         // Find the first activity that is not finishing.
1413         ActivityRecord next = topRunningActivityLocked(null);
1414
1415         // Remember how we'll process this pause/resume situation, and ensure
1416         // that the state is reset however we wind up proceeding.
1417         final boolean userLeaving = mStackSupervisor.mUserLeaving;
1418         mStackSupervisor.mUserLeaving = false;
1419
1420         final TaskRecord prevTask = prev != null ? prev.task : null;
1421         if (next == null) {
1422             // There are no more activities!  Let's just start up the
1423             // Launcher...
1424             ActivityOptions.abort(options);
1425             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
1426             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1427             // Only resume home if on home display
1428             final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
1429                     HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
1430             return isOnHomeDisplay() &&
1431                     mStackSupervisor.resumeHomeStackTask(returnTaskType, prev);
1432         }
1433
1434         next.delayedResume = false;
1435
1436         // If the top activity is the resumed one, nothing to do.
1437         if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
1438                     mStackSupervisor.allResumedActivitiesComplete()) {
1439             // Make sure we have executed any pending transitions, since there
1440             // should be nothing left to do at this point.
1441             mWindowManager.executeAppTransition();
1442             mNoAnimActivities.clear();
1443             ActivityOptions.abort(options);
1444             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Top activity resumed " + next);
1445             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1446             return false;
1447         }
1448
1449         final TaskRecord nextTask = next.task;
1450         if (prevTask != null && prevTask.stack == this &&
1451                 prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
1452             if (DEBUG_STACK)  mStackSupervisor.validateTopActivitiesLocked();
1453             if (prevTask == nextTask) {
1454                 prevTask.setFrontOfTask();
1455             } else if (prevTask != topTask()) {
1456                 // This task is going away but it was supposed to return to the home stack.
1457                 // Now the task above it has to return to the home task instead.
1458                 final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
1459                 mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1460             } else {
1461                 if (DEBUG_STATES && isOnHomeDisplay()) Slog.d(TAG,
1462                         "resumeTopActivityLocked: Launching home next");
1463                 // Only resume home if on home display
1464                 final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
1465                         HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
1466                 return isOnHomeDisplay() &&
1467                         mStackSupervisor.resumeHomeStackTask(returnTaskType, prev);
1468             }
1469         }
1470
1471         // If we are sleeping, and there is no resumed activity, and the top
1472         // activity is paused, well that is the state we want.
1473         if (mService.isSleepingOrShuttingDown()
1474                 && mLastPausedActivity == next
1475                 && mStackSupervisor.allPausedActivitiesComplete()) {
1476             // Make sure we have executed any pending transitions, since there
1477             // should be nothing left to do at this point.
1478             mWindowManager.executeAppTransition();
1479             mNoAnimActivities.clear();
1480             ActivityOptions.abort(options);
1481             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Going to sleep and all paused");
1482             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1483             return false;
1484         }
1485
1486         // Make sure that the user who owns this activity is started.  If not,
1487         // we will just leave it as is because someone should be bringing
1488         // another user's activities to the top of the stack.
1489         if (mService.mStartedUsers.get(next.userId) == null) {
1490             Slog.w(TAG, "Skipping resume of top activity " + next
1491                     + ": user " + next.userId + " is stopped");
1492             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1493             return false;
1494         }
1495
1496         // The activity may be waiting for stop, but that is no longer
1497         // appropriate for it.
1498         mStackSupervisor.mStoppingActivities.remove(next);
1499         mStackSupervisor.mGoingToSleepActivities.remove(next);
1500         next.sleeping = false;
1501         mStackSupervisor.mWaitingVisibleActivities.remove(next);
1502
1503         if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
1504
1505         // If we are currently pausing an activity, then don't do anything
1506         // until that is done.
1507         if (!mStackSupervisor.allPausedActivitiesComplete()) {
1508             if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG,
1509                     "resumeTopActivityLocked: Skip resume: some activity pausing.");
1510             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1511             return false;
1512         }
1513
1514         // Okay we are now going to start a switch, to 'next'.  We may first
1515         // have to pause the current activity, but this is an important point
1516         // where we have decided to go to 'next' so keep track of that.
1517         // XXX "App Redirected" dialog is getting too many false positives
1518         // at this point, so turn off for now.
1519         if (false) {
1520             if (mLastStartedActivity != null && !mLastStartedActivity.finishing) {
1521                 long now = SystemClock.uptimeMillis();
1522                 final boolean inTime = mLastStartedActivity.startTime != 0
1523                         && (mLastStartedActivity.startTime + START_WARN_TIME) >= now;
1524                 final int lastUid = mLastStartedActivity.info.applicationInfo.uid;
1525                 final int nextUid = next.info.applicationInfo.uid;
1526                 if (inTime && lastUid != nextUid
1527                         && lastUid != next.launchedFromUid
1528                         && mService.checkPermission(
1529                                 android.Manifest.permission.STOP_APP_SWITCHES,
1530                                 -1, next.launchedFromUid)
1531                         != PackageManager.PERMISSION_GRANTED) {
1532                     mService.showLaunchWarningLocked(mLastStartedActivity, next);
1533                 } else {
1534                     next.startTime = now;
1535                     mLastStartedActivity = next;
1536                 }
1537             } else {
1538                 next.startTime = SystemClock.uptimeMillis();
1539                 mLastStartedActivity = next;
1540             }
1541         }
1542
1543         // We need to start pausing the current activity so the top one
1544         // can be resumed...
1545         boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving);
1546         if (mResumedActivity != null) {
1547             pausing = true;
1548             startPausingLocked(userLeaving, false);
1549             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);
1550         }
1551         if (pausing) {
1552             if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG,
1553                     "resumeTopActivityLocked: Skip resume: need to start pausing");
1554             // At this point we want to put the upcoming activity's process
1555             // at the top of the LRU list, since we know we will be needing it
1556             // very soon and it would be a waste to let it get killed if it
1557             // happens to be sitting towards the end.
1558             if (next.app != null && next.app.thread != null) {
1559                 mService.updateLruProcessLocked(next.app, true, null);
1560             }
1561             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1562             return true;
1563         }
1564
1565         // If the most recent activity was noHistory but was only stopped rather
1566         // than stopped+finished because the device went to sleep, we need to make
1567         // sure to finish it as we're making a new activity topmost.
1568         if (mService.isSleeping() && mLastNoHistoryActivity != null &&
1569                 !mLastNoHistoryActivity.finishing) {
1570             if (DEBUG_STATES) Slog.d(TAG, "no-history finish of " + mLastNoHistoryActivity +
1571                     " on new resume");
1572             requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
1573                     null, "no-history", false);
1574             mLastNoHistoryActivity = null;
1575         }
1576
1577         if (prev != null && prev != next) {
1578             if (!prev.waitingVisible && next != null && !next.nowVisible) {
1579                 prev.waitingVisible = true;
1580                 mStackSupervisor.mWaitingVisibleActivities.add(prev);
1581                 if (DEBUG_SWITCH) Slog.v(
1582                         TAG, "Resuming top, waiting visible to hide: " + prev);
1583             } else {
1584                 // The next activity is already visible, so hide the previous
1585                 // activity's windows right now so we can show the new one ASAP.
1586                 // We only do this if the previous is finishing, which should mean
1587                 // it is on top of the one being resumed so hiding it quickly
1588                 // is good.  Otherwise, we want to do the normal route of allowing
1589                 // the resumed activity to be shown so we can decide if the
1590                 // previous should actually be hidden depending on whether the
1591                 // new one is found to be full-screen or not.
1592                 if (prev.finishing) {
1593                     mWindowManager.setAppVisibility(prev.appToken, false);
1594                     if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
1595                             + prev + ", waitingVisible="
1596                             + (prev != null ? prev.waitingVisible : null)
1597                             + ", nowVisible=" + next.nowVisible);
1598                 } else {
1599                     if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
1600                         + prev + ", waitingVisible="
1601                         + (prev != null ? prev.waitingVisible : null)
1602                         + ", nowVisible=" + next.nowVisible);
1603                 }
1604             }
1605         }
1606
1607         // Launching this app's activity, make sure the app is no longer
1608         // considered stopped.
1609         try {
1610             AppGlobals.getPackageManager().setPackageStoppedState(
1611                     next.packageName, false, next.userId); /* TODO: Verify if correct userid */
1612         } catch (RemoteException e1) {
1613         } catch (IllegalArgumentException e) {
1614             Slog.w(TAG, "Failed trying to unstop package "
1615                     + next.packageName + ": " + e);
1616         }
1617
1618         // We are starting up the next activity, so tell the window manager
1619         // that the previous one will be hidden soon.  This way it can know
1620         // to ignore it when computing the desired screen orientation.
1621         boolean anim = true;
1622         if (prev != null) {
1623             if (prev.finishing) {
1624                 if (DEBUG_TRANSITION) Slog.v(TAG,
1625                         "Prepare close transition: prev=" + prev);
1626                 if (mNoAnimActivities.contains(prev)) {
1627                     anim = false;
1628                     mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
1629                 } else {
1630                     mWindowManager.prepareAppTransition(prev.task == next.task
1631                             ? AppTransition.TRANSIT_ACTIVITY_CLOSE
1632                             : AppTransition.TRANSIT_TASK_CLOSE, false);
1633                 }
1634                 mWindowManager.setAppWillBeHidden(prev.appToken);
1635                 mWindowManager.setAppVisibility(prev.appToken, false);
1636             } else {
1637                 if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: prev=" + prev);
1638                 if (mNoAnimActivities.contains(next)) {
1639                     anim = false;
1640                     mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
1641                 } else {
1642                     mWindowManager.prepareAppTransition(prev.task == next.task
1643                             ? AppTransition.TRANSIT_ACTIVITY_OPEN
1644                             : next.mLaunchTaskBehind
1645                                     ? AppTransition.TRANSIT_TASK_OPEN_BEHIND
1646                                     : AppTransition.TRANSIT_TASK_OPEN, false);
1647                 }
1648             }
1649             if (false) {
1650                 mWindowManager.setAppWillBeHidden(prev.appToken);
1651                 mWindowManager.setAppVisibility(prev.appToken, false);
1652             }
1653         } else {
1654             if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: no previous");
1655             if (mNoAnimActivities.contains(next)) {
1656                 anim = false;
1657                 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
1658             } else {
1659                 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_OPEN, false);
1660             }
1661         }
1662
1663         Bundle resumeAnimOptions = null;
1664         if (anim) {
1665             ActivityOptions opts = next.getOptionsForTargetActivityLocked();
1666             if (opts != null) {
1667                 resumeAnimOptions = opts.toBundle();
1668             }
1669             next.applyOptionsLocked();
1670         } else {
1671             next.clearOptionsLocked();
1672         }
1673
1674         ActivityStack lastStack = mStackSupervisor.getLastStack();
1675         if (next.app != null && next.app.thread != null) {
1676             if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
1677
1678             // This activity is now becoming visible.
1679             mWindowManager.setAppVisibility(next.appToken, true);
1680
1681             // schedule launch ticks to collect information about slow apps.
1682             next.startLaunchTickingLocked();
1683
1684             ActivityRecord lastResumedActivity =
1685                     lastStack == null ? null :lastStack.mResumedActivity;
1686             ActivityState lastState = next.state;
1687
1688             mService.updateCpuStats();
1689
1690             if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + next + " (in existing)");
1691             next.state = ActivityState.RESUMED;
1692             mResumedActivity = next;
1693             next.task.touchActiveTime();
1694             mService.addRecentTaskLocked(next.task);
1695             mService.updateLruProcessLocked(next.app, true, null);
1696             updateLRUListLocked(next);
1697             mService.updateOomAdjLocked();
1698
1699             // Have the window manager re-evaluate the orientation of
1700             // the screen based on the new activity order.
1701             boolean notUpdated = true;
1702             if (mStackSupervisor.isFrontStack(this)) {
1703                 Configuration config = mWindowManager.updateOrientationFromAppTokens(
1704                         mService.mConfiguration,
1705                         next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
1706                 if (config != null) {
1707                     next.frozenBeforeDestroy = true;
1708                 }
1709                 notUpdated = !mService.updateConfigurationLocked(config, next, false, false);
1710             }
1711
1712             if (notUpdated) {
1713                 // The configuration update wasn't able to keep the existing
1714                 // instance of the activity, and instead started a new one.
1715                 // We should be all done, but let's just make sure our activity
1716                 // is still at the top and schedule another run if something
1717                 // weird happened.
1718                 ActivityRecord nextNext = topRunningActivityLocked(null);
1719                 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
1720                         "Activity config changed during resume: " + next
1721                         + ", new next: " + nextNext);
1722                 if (nextNext != next) {
1723                     // Do over!
1724                     mStackSupervisor.scheduleResumeTopActivities();
1725                 }
1726                 if (mStackSupervisor.reportResumedActivityLocked(next)) {
1727                     mNoAnimActivities.clear();
1728                     if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1729                     return true;
1730                 }
1731                 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1732                 return false;
1733             }
1734
1735             try {
1736                 // Deliver all pending results.
1737                 ArrayList<ResultInfo> a = next.results;
1738                 if (a != null) {
1739                     final int N = a.size();
1740                     if (!next.finishing && N > 0) {
1741                         if (DEBUG_RESULTS) Slog.v(
1742                                 TAG, "Delivering results to " + next
1743                                 + ": " + a);
1744                         next.app.thread.scheduleSendResult(next.appToken, a);
1745                     }
1746                 }
1747
1748                 if (next.newIntents != null) {
1749                     next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
1750                 }
1751
1752                 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
1753                         next.userId, System.identityHashCode(next),
1754                         next.task.taskId, next.shortComponentName);
1755
1756                 next.sleeping = false;
1757                 mService.showAskCompatModeDialogLocked(next);
1758                 next.app.pendingUiClean = true;
1759                 next.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
1760                 next.clearOptionsLocked();
1761                 next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
1762                         mService.isNextTransitionForward(), resumeAnimOptions);
1763
1764                 mStackSupervisor.checkReadyForSleepLocked();
1765
1766                 if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Resumed " + next);
1767             } catch (Exception e) {
1768                 // Whoops, need to restart this activity!
1769                 if (DEBUG_STATES) Slog.v(TAG, "Resume failed; resetting state to "
1770                         + lastState + ": " + next);
1771                 next.state = lastState;
1772                 if (lastStack != null) {
1773                     lastStack.mResumedActivity = lastResumedActivity;
1774                 }
1775                 Slog.i(TAG, "Restarting because process died: " + next);
1776                 if (!next.hasBeenLaunched) {
1777                     next.hasBeenLaunched = true;
1778                 } else  if (SHOW_APP_STARTING_PREVIEW && lastStack != null &&
1779                         mStackSupervisor.isFrontStack(lastStack)) {
1780                     mWindowManager.setAppStartingWindow(
1781                             next.appToken, next.packageName, next.theme,
1782                             mService.compatibilityInfoForPackageLocked(next.info.applicationInfo),
1783                             next.nonLocalizedLabel, next.labelRes, next.icon, next.logo,
1784                             next.windowFlags, null, true);
1785                 }
1786                 mStackSupervisor.startSpecificActivityLocked(next, true, false);
1787                 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1788                 return true;
1789             }
1790
1791             // From this point on, if something goes wrong there is no way
1792             // to recover the activity.
1793             try {
1794                 next.visible = true;
1795                 completeResumeLocked(next);
1796             } catch (Exception e) {
1797                 // If any exception gets thrown, toss away this
1798                 // activity and try the next one.
1799                 Slog.w(TAG, "Exception thrown during resume of " + next, e);
1800                 requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
1801                         "resume-exception", true);
1802                 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1803                 return true;
1804             }
1805             next.stopped = false;
1806
1807         } else {
1808             // Whoops, need to restart this activity!
1809             if (!next.hasBeenLaunched) {
1810                 next.hasBeenLaunched = true;
1811             } else {
1812                 if (SHOW_APP_STARTING_PREVIEW) {
1813                     mWindowManager.setAppStartingWindow(
1814                             next.appToken, next.packageName, next.theme,
1815                             mService.compatibilityInfoForPackageLocked(
1816                                     next.info.applicationInfo),
1817                             next.nonLocalizedLabel,
1818                             next.labelRes, next.icon, next.logo, next.windowFlags,
1819                             null, true);
1820                 }
1821                 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
1822             }
1823             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Restarting " + next);
1824             mStackSupervisor.startSpecificActivityLocked(next, true, true);
1825         }
1826
1827         if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1828         return true;
1829     }
1830
1831     private void insertTaskAtTop(TaskRecord task) {
1832         // If this is being moved to the top by another activity or being launched from the home
1833         // activity, set mOnTopOfHome accordingly.
1834         if (isOnHomeDisplay()) {
1835             ActivityStack lastStack = mStackSupervisor.getLastStack();
1836             final boolean fromHome = lastStack.isHomeStack();
1837             if (!isHomeStack() && (fromHome || topTask() != task)) {
1838                 task.setTaskToReturnTo(fromHome
1839                         ? lastStack.topTask() == null
1840                                 ? HOME_ACTIVITY_TYPE
1841                                 : lastStack.topTask().taskType
1842                         : APPLICATION_ACTIVITY_TYPE);
1843             }
1844         } else {
1845             task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1846         }
1847
1848         mTaskHistory.remove(task);
1849         // Now put task at top.
1850         int taskNdx = mTaskHistory.size();
1851         if (!isCurrentProfileLocked(task.userId)) {
1852             // Put non-current user tasks below current user tasks.
1853             while (--taskNdx >= 0) {
1854                 if (!isCurrentProfileLocked(mTaskHistory.get(taskNdx).userId)) {
1855                     break;
1856                 }
1857             }
1858             ++taskNdx;
1859         }
1860         mTaskHistory.add(taskNdx, task);
1861         updateTaskMovement(task, true);
1862     }
1863
1864     final void startActivityLocked(ActivityRecord r, boolean newTask,
1865             boolean doResume, boolean keepCurTransition, Bundle options) {
1866         TaskRecord rTask = r.task;
1867         final int taskId = rTask.taskId;
1868         // mLaunchTaskBehind tasks get placed at the back of the task stack.
1869         if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
1870             // Last activity in task had been removed or ActivityManagerService is reusing task.
1871             // Insert or replace.
1872             // Might not even be in.
1873             insertTaskAtTop(rTask);
1874             mWindowManager.moveTaskToTop(taskId);
1875         }
1876         TaskRecord task = null;
1877         if (!newTask) {
1878             // If starting in an existing task, find where that is...
1879             boolean startIt = true;
1880             for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1881                 task = mTaskHistory.get(taskNdx);
1882                 if (task == r.task) {
1883                     // Here it is!  Now, if this is not yet visible to the
1884                     // user, then just add it without starting; it will
1885                     // get started when the user navigates back to it.
1886                     if (!startIt) {
1887                         if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
1888                                 + task, new RuntimeException("here").fillInStackTrace());
1889                         task.addActivityToTop(r);
1890                         r.putInHistory();
1891                         mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
1892                                 r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
1893                                 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
1894                                 r.userId, r.info.configChanges, task.voiceSession != null,
1895                                 r.mLaunchTaskBehind);
1896                         if (VALIDATE_TOKENS) {
1897                             validateAppTokensLocked();
1898                         }
1899                         ActivityOptions.abort(options);
1900                         return;
1901                     }
1902                     break;
1903                 } else if (task.numFullscreen > 0) {
1904                     startIt = false;
1905                 }
1906             }
1907         }
1908
1909         // Place a new activity at top of stack, so it is next to interact
1910         // with the user.
1911
1912         // If we are not placing the new activity frontmost, we do not want
1913         // to deliver the onUserLeaving callback to the actual frontmost
1914         // activity
1915         if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
1916             mStackSupervisor.mUserLeaving = false;
1917             if (DEBUG_USER_LEAVING) Slog.v(TAG,
1918                     "startActivity() behind front, mUserLeaving=false");
1919         }
1920
1921         task = r.task;
1922
1923         // Slot the activity into the history stack and proceed
1924         if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
1925                 new RuntimeException("here").fillInStackTrace());
1926         task.addActivityToTop(r);
1927         task.setFrontOfTask();
1928
1929         r.putInHistory();
1930         if (!isHomeStack() || numActivities() > 0) {
1931             // We want to show the starting preview window if we are
1932             // switching to a new task, or the next activity's process is
1933             // not currently running.
1934             boolean showStartingIcon = newTask;
1935             ProcessRecord proc = r.app;
1936             if (proc == null) {
1937                 proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
1938             }
1939             if (proc == null || proc.thread == null) {
1940                 showStartingIcon = true;
1941             }
1942             if (DEBUG_TRANSITION) Slog.v(TAG,
1943                     "Prepare open transition: starting " + r);
1944             if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
1945                 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, keepCurTransition);
1946                 mNoAnimActivities.add(r);
1947             } else {
1948                 mWindowManager.prepareAppTransition(newTask
1949                         ? r.mLaunchTaskBehind
1950                                 ? AppTransition.TRANSIT_TASK_OPEN_BEHIND
1951                                 : AppTransition.TRANSIT_TASK_OPEN
1952                         : AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
1953                 mNoAnimActivities.remove(r);
1954             }
1955             mWindowManager.addAppToken(task.mActivities.indexOf(r),
1956                     r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
1957                     (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId,
1958                     r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind);
1959             boolean doShow = true;
1960             if (newTask) {
1961                 // Even though this activity is starting fresh, we still need
1962                 // to reset it to make sure we apply affinities to move any
1963                 // existing activities from other tasks in to it.
1964                 // If the caller has requested that the target task be
1965                 // reset, then do so.
1966                 if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1967                     resetTaskIfNeededLocked(r, r);
1968                     doShow = topRunningNonDelayedActivityLocked(null) == r;
1969                 }
1970             } else if (options != null && new ActivityOptions(options).getAnimationType()
1971                     == ActivityOptions.ANIM_SCENE_TRANSITION) {
1972                 doShow = false;
1973             }
1974             if (r.mLaunchTaskBehind) {
1975                 // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
1976                 // tell WindowManager that r is visible even though it is at the back of the stack.
1977                 mWindowManager.setAppVisibility(r.appToken, true);
1978                 ensureActivitiesVisibleLocked(null, 0);
1979             } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
1980                 // Figure out if we are transitioning from another activity that is
1981                 // "has the same starting icon" as the next one.  This allows the
1982                 // window manager to keep the previous window it had previously
1983                 // created, if it still had one.
1984                 ActivityRecord prev = mResumedActivity;
1985                 if (prev != null) {
1986                     // We don't want to reuse the previous starting preview if:
1987                     // (1) The current activity is in a different task.
1988                     if (prev.task != r.task) {
1989                         prev = null;
1990                     }
1991                     // (2) The current activity is already displayed.
1992                     else if (prev.nowVisible) {
1993                         prev = null;
1994                     }
1995                 }
1996                 mWindowManager.setAppStartingWindow(
1997                         r.appToken, r.packageName, r.theme,
1998                         mService.compatibilityInfoForPackageLocked(
1999                                 r.info.applicationInfo), r.nonLocalizedLabel,
2000                         r.labelRes, r.icon, r.logo, r.windowFlags,
2001                         prev != null ? prev.appToken : null, showStartingIcon);
2002                 r.mStartingWindowShown = true;
2003             }
2004         } else {
2005             // If this is the first activity, don't do any fancy animations,
2006             // because there is nothing for it to animate on top of.
2007             mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
2008                     r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
2009                     (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId,
2010                     r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind);
2011             ActivityOptions.abort(options);
2012             options = null;
2013         }
2014         if (VALIDATE_TOKENS) {
2015             validateAppTokensLocked();
2016         }
2017
2018         if (doResume) {
2019             mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
2020         }
2021     }
2022
2023     final void validateAppTokensLocked() {
2024         mValidateAppTokens.clear();
2025         mValidateAppTokens.ensureCapacity(numActivities());
2026         final int numTasks = mTaskHistory.size();
2027         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
2028             TaskRecord task = mTaskHistory.get(taskNdx);
2029             final ArrayList<ActivityRecord> activities = task.mActivities;
2030             if (activities.isEmpty()) {
2031                 continue;
2032             }
2033             TaskGroup group = new TaskGroup();
2034             group.taskId = task.taskId;
2035             mValidateAppTokens.add(group);
2036             final int numActivities = activities.size();
2037             for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
2038                 final ActivityRecord r = activities.get(activityNdx);
2039                 group.tokens.add(r.appToken);
2040             }
2041         }
2042         mWindowManager.validateAppTokens(mStackId, mValidateAppTokens);
2043     }
2044
2045     /**
2046      * Perform a reset of the given task, if needed as part of launching it.
2047      * Returns the new HistoryRecord at the top of the task.
2048      */
2049     /**
2050      * Helper method for #resetTaskIfNeededLocked.
2051      * We are inside of the task being reset...  we'll either finish this activity, push it out
2052      * for another task, or leave it as-is.
2053      * @param task The task containing the Activity (taskTop) that might be reset.
2054      * @param forceReset
2055      * @return An ActivityOptions that needs to be processed.
2056      */
2057     final ActivityOptions resetTargetTaskIfNeededLocked(TaskRecord task, boolean forceReset) {
2058         ActivityOptions topOptions = null;
2059
2060         int replyChainEnd = -1;
2061         boolean canMoveOptions = true;
2062
2063         // We only do this for activities that are not the root of the task (since if we finish
2064         // the root, we may no longer have the task!).
2065         final ArrayList<ActivityRecord> activities = task.mActivities;
2066         final int numActivities = activities.size();
2067         final int rootActivityNdx = task.findEffectiveRootIndex();
2068         for (int i = numActivities - 1; i > rootActivityNdx; --i ) {
2069             ActivityRecord target = activities.get(i);
2070
2071             final int flags = target.info.flags;
2072             final boolean finishOnTaskLaunch =
2073                     (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
2074             final boolean allowTaskReparenting =
2075                     (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
2076             final boolean clearWhenTaskReset =
2077                     (target.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
2078
2079             if (!finishOnTaskLaunch
2080                     && !clearWhenTaskReset
2081                     && target.resultTo != null) {
2082                 // If this activity is sending a reply to a previous
2083                 // activity, we can't do anything with it now until
2084                 // we reach the start of the reply chain.
2085                 // XXX note that we are assuming the result is always
2086                 // to the previous activity, which is almost always
2087                 // the case but we really shouldn't count on.
2088                 if (replyChainEnd < 0) {
2089                     replyChainEnd = i;
2090                 }
2091             } else if (!finishOnTaskLaunch
2092                     && !clearWhenTaskReset
2093                     && allowTaskReparenting
2094                     && target.taskAffinity != null
2095                     && !target.taskAffinity.equals(task.affinity)) {
2096                 // If this activity has an affinity for another
2097                 // task, then we need to move it out of here.  We will
2098                 // move it as far out of the way as possible, to the
2099                 // bottom of the activity stack.  This also keeps it
2100                 // correctly ordered with any activities we previously
2101                 // moved.
2102                 final TaskRecord targetTask;
2103                 final ActivityRecord bottom =
2104                         !mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ?
2105                                 mTaskHistory.get(0).mActivities.get(0) : null;
2106                 if (bottom != null && target.taskAffinity != null
2107                         && target.taskAffinity.equals(bottom.task.affinity)) {
2108                     // If the activity currently at the bottom has the
2109                     // same task affinity as the one we are moving,
2110                     // then merge it into the same task.
2111                     targetTask = bottom.task;
2112                     if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
2113                             + " out to bottom task " + bottom.task);
2114                 } else {
2115                     targetTask = createTaskRecord(mStackSupervisor.getNextTaskId(), target.info,
2116                             null, null, null, false);
2117                     targetTask.affinityIntent = target.intent;
2118                     if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
2119                             + " out to new task " + target.task);
2120                 }
2121
2122                 final int targetTaskId = targetTask.taskId;
2123                 mWindowManager.setAppGroupId(target.appToken, targetTaskId);
2124
2125                 boolean noOptions = canMoveOptions;
2126                 final int start = replyChainEnd < 0 ? i : replyChainEnd;
2127                 for (int srcPos = start; srcPos >= i; --srcPos) {
2128                     final ActivityRecord p = activities.get(srcPos);
2129                     if (p.finishing) {
2130                         continue;
2131                     }
2132
2133                     canMoveOptions = false;
2134                     if (noOptions && topOptions == null) {
2135                         topOptions = p.takeOptionsLocked();
2136                         if (topOptions != null) {
2137                             noOptions = false;
2138                         }
2139                     }
2140                     if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing activity " + p + " from task="
2141                             + task + " adding to task=" + targetTask
2142                             + " Callers=" + Debug.getCallers(4));
2143                     if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
2144                             + " out to target's task " + target.task);
2145                     p.setTask(targetTask, null);
2146                     targetTask.addActivityAtBottom(p);
2147
2148                     mWindowManager.setAppGroupId(p.appToken, targetTaskId);
2149                 }
2150
2151                 mWindowManager.moveTaskToBottom(targetTaskId);
2152                 if (VALIDATE_TOKENS) {
2153                     validateAppTokensLocked();
2154                 }
2155
2156                 replyChainEnd = -1;
2157             } else if (forceReset || finishOnTaskLaunch || clearWhenTaskReset) {
2158                 // If the activity should just be removed -- either
2159                 // because it asks for it, or the task should be
2160                 // cleared -- then finish it and anything that is
2161                 // part of its reply chain.
2162                 int end;
2163                 if (clearWhenTaskReset) {
2164                     // In this case, we want to finish this activity
2165                     // and everything above it, so be sneaky and pretend
2166                     // like these are all in the reply chain.
2167                     end = numActivities - 1;
2168                 } else if (replyChainEnd < 0) {
2169                     end = i;
2170                 } else {
2171                     end = replyChainEnd;
2172                 }
2173                 boolean noOptions = canMoveOptions;
2174                 for (int srcPos = i; srcPos <= end; srcPos++) {
2175                     ActivityRecord p = activities.get(srcPos);
2176                     if (p.finishing) {
2177                         continue;
2178                     }
2179                     canMoveOptions = false;
2180                     if (noOptions && topOptions == null) {
2181                         topOptions = p.takeOptionsLocked();
2182                         if (topOptions != null) {
2183                             noOptions = false;
2184                         }
2185                     }
2186                     if (DEBUG_TASKS) Slog.w(TAG,
2187                             "resetTaskIntendedTask: calling finishActivity on " + p);
2188                     if (finishActivityLocked(p, Activity.RESULT_CANCELED, null, "reset", false)) {
2189                         end--;
2190                         srcPos--;
2191                     }
2192                 }
2193                 replyChainEnd = -1;
2194             } else {
2195                 // If we were in the middle of a chain, well the
2196                 // activity that started it all doesn't want anything
2197                 // special, so leave it all as-is.
2198                 replyChainEnd = -1;
2199             }
2200         }
2201
2202         return topOptions;
2203     }
2204
2205     /**
2206      * Helper method for #resetTaskIfNeededLocked. Processes all of the activities in a given
2207      * TaskRecord looking for an affinity with the task of resetTaskIfNeededLocked.taskTop.
2208      * @param affinityTask The task we are looking for an affinity to.
2209      * @param task Task that resetTaskIfNeededLocked.taskTop belongs to.
2210      * @param topTaskIsHigher True if #task has already been processed by resetTaskIfNeededLocked.
2211      * @param forceReset Flag passed in to resetTaskIfNeededLocked.
2212      */
2213     private int resetAffinityTaskIfNeededLocked(TaskRecord affinityTask, TaskRecord task,
2214             boolean topTaskIsHigher, boolean forceReset, int taskInsertionPoint) {
2215         int replyChainEnd = -1;
2216         final int taskId = task.taskId;
2217         final String taskAffinity = task.affinity;
2218
2219         final ArrayList<ActivityRecord> activities = affinityTask.mActivities;
2220         final int numActivities = activities.size();
2221         final int rootActivityNdx = affinityTask.findEffectiveRootIndex();
2222
2223         // Do not operate on or below the effective root Activity.
2224         for (int i = numActivities - 1; i > rootActivityNdx; --i) {
2225             ActivityRecord target = activities.get(i);
2226
2227             final int flags = target.info.flags;
2228             boolean finishOnTaskLaunch = (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
2229             boolean allowTaskReparenting = (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
2230
2231             if (target.resultTo != null) {
2232                 // If this activity is sending a reply to a previous
2233                 // activity, we can't do anything with it now until
2234                 // we reach the start of the reply chain.
2235                 // XXX note that we are assuming the result is always
2236                 // to the previous activity, which is almost always
2237                 // the case but we really shouldn't count on.
2238                 if (replyChainEnd < 0) {
2239                     replyChainEnd = i;
2240                 }
2241             } else if (topTaskIsHigher
2242                     && allowTaskReparenting
2243                     && taskAffinity != null
2244                     && taskAffinity.equals(target.taskAffinity)) {
2245                 // This activity has an affinity for our task. Either remove it if we are
2246                 // clearing or move it over to our task.  Note that
2247                 // we currently punt on the case where we are resetting a
2248                 // task that is not at the top but who has activities above
2249                 // with an affinity to it...  this is really not a normal
2250                 // case, and we will need to later pull that task to the front
2251                 // and usually at that point we will do the reset and pick
2252                 // up those remaining activities.  (This only happens if
2253                 // someone starts an activity in a new task from an activity
2254                 // in a task that is not currently on top.)
2255                 if (forceReset || finishOnTaskLaunch) {
2256                     final int start = replyChainEnd >= 0 ? replyChainEnd : i;
2257                     if (DEBUG_TASKS) Slog.v(TAG, "Finishing task at index " + start + " to " + i);
2258                     for (int srcPos = start; srcPos >= i; --srcPos) {
2259                         final ActivityRecord p = activities.get(srcPos);
2260                         if (p.finishing) {
2261                             continue;
2262                         }
2263                         finishActivityLocked(p, Activity.RESULT_CANCELED, null, "reset", false);
2264                     }
2265                 } else {
2266                     if (taskInsertionPoint < 0) {
2267                         taskInsertionPoint = task.mActivities.size();
2268
2269                     }
2270
2271                     final int start = replyChainEnd >= 0 ? replyChainEnd : i;
2272                     if (DEBUG_TASKS) Slog.v(TAG, "Reparenting from task=" + affinityTask + ":"
2273                             + start + "-" + i + " to task=" + task + ":" + taskInsertionPoint);
2274                     for (int srcPos = start; srcPos >= i; --srcPos) {
2275                         final ActivityRecord p = activities.get(srcPos);
2276                         p.setTask(task, null);
2277                         task.addActivityAtIndex(taskInsertionPoint, p);
2278
2279                         if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing and adding activity " + p
2280                                 + " to stack at " + task,
2281                                 new RuntimeException("here").fillInStackTrace());
2282                         if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p + " from " + srcPos
2283                                 + " in to resetting task " + task);
2284                         mWindowManager.setAppGroupId(p.appToken, taskId);
2285                     }
2286                     mWindowManager.moveTaskToTop(taskId);
2287                     if (VALIDATE_TOKENS) {
2288                         validateAppTokensLocked();
2289                     }
2290
2291                     // Now we've moved it in to place...  but what if this is
2292                     // a singleTop activity and we have put it on top of another
2293                     // instance of the same activity?  Then we drop the instance
2294                     // below so it remains singleTop.
2295                     if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
2296                         ArrayList<ActivityRecord> taskActivities = task.mActivities;
2297                         int targetNdx = taskActivities.indexOf(target);
2298                         if (targetNdx > 0) {
2299                             ActivityRecord p = taskActivities.get(targetNdx - 1);
2300                             if (p.intent.getComponent().equals(target.intent.getComponent())) {
2301                                 finishActivityLocked(p, Activity.RESULT_CANCELED, null, "replace",
2302                                         false);
2303                             }
2304                         }
2305                     }
2306                 }
2307
2308                 replyChainEnd = -1;
2309             }
2310         }
2311         return taskInsertionPoint;
2312     }
2313
2314     final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
2315             ActivityRecord newActivity) {
2316         boolean forceReset =
2317                 (newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
2318         if (ACTIVITY_INACTIVE_RESET_TIME > 0
2319                 && taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
2320             if ((newActivity.info.flags & ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
2321                 forceReset = true;
2322             }
2323         }
2324
2325         final TaskRecord task = taskTop.task;
2326
2327         /** False until we evaluate the TaskRecord associated with taskTop. Switches to true
2328          * for remaining tasks. Used for later tasks to reparent to task. */
2329         boolean taskFound = false;
2330
2331         /** If ActivityOptions are moved out and need to be aborted or moved to taskTop. */
2332         ActivityOptions topOptions = null;
2333
2334         // Preserve the location for reparenting in the new task.
2335         int reparentInsertionPoint = -1;
2336
2337         for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
2338             final TaskRecord targetTask = mTaskHistory.get(i);
2339
2340             if (targetTask == task) {
2341                 topOptions = resetTargetTaskIfNeededLocked(task, forceReset);
2342                 taskFound = true;
2343             } else {
2344                 reparentInsertionPoint = resetAffinityTaskIfNeededLocked(targetTask, task,
2345                         taskFound, forceReset, reparentInsertionPoint);
2346             }
2347         }
2348
2349         int taskNdx = mTaskHistory.indexOf(task);
2350         do {
2351             taskTop = mTaskHistory.get(taskNdx--).getTopActivity();
2352         } while (taskTop == null && taskNdx >= 0);
2353
2354         if (topOptions != null) {
2355             // If we got some ActivityOptions from an activity on top that
2356             // was removed from the task, propagate them to the new real top.
2357             if (taskTop != null) {
2358                 taskTop.updateOptionsLocked(topOptions);
2359             } else {
2360                 topOptions.abort();
2361             }
2362         }
2363
2364         return taskTop;
2365     }
2366
2367     void sendActivityResultLocked(int callingUid, ActivityRecord r,
2368             String resultWho, int requestCode, int resultCode, Intent data) {
2369
2370         if (callingUid > 0) {
2371             mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
2372                     data, r.getUriPermissionsLocked(), r.userId);
2373         }
2374
2375         if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
2376                 + " : who=" + resultWho + " req=" + requestCode
2377                 + " res=" + resultCode + " data=" + data);
2378         if (mResumedActivity == r && r.app != null && r.app.thread != null) {
2379             try {
2380                 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
2381                 list.add(new ResultInfo(resultWho, requestCode,
2382                         resultCode, data));
2383                 r.app.thread.scheduleSendResult(r.appToken, list);
2384                 return;
2385             } catch (Exception e) {
2386                 Slog.w(TAG, "Exception thrown sending result to " + r, e);
2387             }
2388         }
2389
2390         r.addResultLocked(null, resultWho, requestCode, resultCode, data);
2391     }
2392
2393     private void adjustFocusedActivityLocked(ActivityRecord r) {
2394         if (mStackSupervisor.isFrontStack(this) && mService.mFocusedActivity == r) {
2395             ActivityRecord next = topRunningActivityLocked(null);
2396             if (next != r) {
2397                 final TaskRecord task = r.task;
2398                 if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) {
2399                     mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo());
2400                 }
2401             }
2402             ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
2403             if (top != null) {
2404                 mService.setFocusedActivityLocked(top);
2405             }
2406         }
2407     }
2408
2409     final void stopActivityLocked(ActivityRecord r) {
2410         if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
2411         if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
2412                 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
2413             if (!r.finishing) {
2414                 if (!mService.isSleeping()) {
2415                     if (DEBUG_STATES) {
2416                         Slog.d(TAG, "no-history finish of " + r);
2417                     }
2418                     requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
2419                             "no-history", false);
2420                 } else {
2421                     if (DEBUG_STATES) Slog.d(TAG, "Not finishing noHistory " + r
2422                             + " on stop because we're just sleeping");
2423                 }
2424             }
2425         }
2426
2427         if (r.app != null && r.app.thread != null) {
2428             adjustFocusedActivityLocked(r);
2429             r.resumeKeyDispatchingLocked();
2430             try {
2431                 r.stopped = false;
2432                 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
2433                         + " (stop requested)");
2434                 r.state = ActivityState.STOPPING;
2435                 if (DEBUG_VISBILITY) Slog.v(
2436                         TAG, "Stopping visible=" + r.visible + " for " + r);
2437                 if (!r.visible) {
2438                     mWindowManager.setAppVisibility(r.appToken, false);
2439                 }
2440                 r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
2441                 if (mService.isSleepingOrShuttingDown()) {
2442                     r.setSleeping(true);
2443                 }
2444                 Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r);
2445                 mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
2446             } catch (Exception e) {
2447                 // Maybe just ignore exceptions here...  if the process
2448                 // has crashed, our death notification will clean things
2449                 // up.
2450                 Slog.w(TAG, "Exception thrown during pause", e);
2451                 // Just in case, assume it to be stopped.
2452                 r.stopped = true;
2453                 if (DEBUG_STATES) Slog.v(TAG, "Stop failed; moving to STOPPED: " + r);
2454                 r.state = ActivityState.STOPPED;
2455                 if (r.configDestroy) {
2456                     destroyActivityLocked(r, true, "stop-except");
2457                 }
2458             }
2459         }
2460     }
2461
2462     /**
2463      * @return Returns true if the activity is being finished, false if for
2464      * some reason it is being left as-is.
2465      */
2466     final boolean requestFinishActivityLocked(IBinder token, int resultCode,
2467             Intent resultData, String reason, boolean oomAdj) {
2468         ActivityRecord r = isInStackLocked(token);
2469         if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(
2470                 TAG, "Finishing activity token=" + token + " r="
2471                 + ", result=" + resultCode + ", data=" + resultData
2472                 + ", reason=" + reason);
2473         if (r == null) {
2474             return false;
2475         }
2476
2477         finishActivityLocked(r, resultCode, resultData, reason, oomAdj);
2478         return true;
2479     }
2480
2481     final void finishSubActivityLocked(ActivityRecord self, String resultWho, int requestCode) {
2482         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
2483             ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
2484             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
2485                 ActivityRecord r = activities.get(activityNdx);
2486                 if (r.resultTo == self && r.requestCode == requestCode) {
2487                     if ((r.resultWho == null && resultWho == null) ||
2488                         (r.resultWho != null && r.resultWho.equals(resultWho))) {
2489                         finishActivityLocked(r, Activity.RESULT_CANCELED, null, "request-sub",
2490                                 false);
2491                     }
2492                 }
2493             }
2494         }
2495         mService.updateOomAdjLocked();
2496     }
2497
2498     final void finishTopRunningActivityLocked(ProcessRecord app) {
2499         ActivityRecord r = topRunningActivityLocked(null);
2500         if (r != null && r.app == app) {
2501             // If the top running activity is from this crashing
2502             // process, then terminate it to avoid getting in a loop.
2503             Slog.w(TAG, "  Force finishing activity "
2504                     + r.intent.getComponent().flattenToShortString());
2505             int taskNdx = mTaskHistory.indexOf(r.task);
2506             int activityNdx = r.task.mActivities.indexOf(r);
2507             finishActivityLocked(r, Activity.RESULT_CANCELED, null, "crashed", false);
2508             // Also terminate any activities below it that aren't yet
2509             // stopped, to avoid a situation where one will get
2510             // re-start our crashing activity once it gets resumed again.
2511             --activityNdx;
2512             if (activityNdx < 0) {
2513                 do {
2514                     --taskNdx;
2515                     if (taskNdx < 0) {
2516                         break;
2517                     }
2518                     activityNdx = mTaskHistory.get(taskNdx).mActivities.size() - 1;
2519                 } while (activityNdx < 0);
2520             }
2521             if (activityNdx >= 0) {
2522                 r = mTaskHistory.get(taskNdx).mActivities.get(activityNdx);
2523                 if (r.state == ActivityState.RESUMED
2524                         || r.state == ActivityState.PAUSING
2525                         || r.state == ActivityState.PAUSED) {
2526                     if (!r.isHomeActivity() || mService.mHomeProcess != r.app) {
2527                         Slog.w(TAG, "  Force finishing activity "
2528                                 + r.intent.getComponent().flattenToShortString());
2529                         finishActivityLocked(r, Activity.RESULT_CANCELED, null, "crashed", false);
2530                     }
2531                 }
2532             }
2533         }
2534     }
2535
2536     final void finishVoiceTask(IVoiceInteractionSession session) {
2537         IBinder sessionBinder = session.asBinder();
2538         boolean didOne = false;
2539         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
2540             TaskRecord tr = mTaskHistory.get(taskNdx);
2541             if (tr.voiceSession != null && tr.voiceSession.asBinder() == sessionBinder) {
2542                 for (int activityNdx = tr.mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
2543                     ActivityRecord r = tr.mActivities.get(activityNdx);
2544                     if (!r.finishing) {
2545                         finishActivityLocked(r, Activity.RESULT_CANCELED, null, "finish-voice",
2546                                 false);
2547                         didOne = true;
2548                     }
2549                 }
2550             }
2551         }
2552         if (didOne) {
2553             mService.updateOomAdjLocked();
2554         }
2555     }
2556
2557     final boolean finishActivityAffinityLocked(ActivityRecord r) {
2558         ArrayList<ActivityRecord> activities = r.task.mActivities;
2559         for (int index = activities.indexOf(r); index >= 0; --index) {
2560             ActivityRecord cur = activities.get(index);
2561             if (!Objects.equals(cur.taskAffinity, r.taskAffinity)) {
2562                 break;
2563             }
2564             finishActivityLocked(cur, Activity.RESULT_CANCELED, null, "request-affinity", true);
2565         }
2566         return true;
2567     }
2568
2569     final void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
2570         // send the result
2571         ActivityRecord resultTo = r.resultTo;
2572         if (resultTo != null) {
2573             if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
2574                     + " who=" + r.resultWho + " req=" + r.requestCode
2575                     + " res=" + resultCode + " data=" + resultData);
2576             if (resultTo.userId != r.userId) {
2577                 if (resultData != null) {
2578                     resultData.prepareToLeaveUser(r.userId);
2579                 }
2580             }
2581             if (r.info.applicationInfo.uid > 0) {
2582                 mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
2583                         resultTo.packageName, resultData,
2584                         resultTo.getUriPermissionsLocked(), resultTo.userId);
2585             }
2586             resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
2587                                      resultData);
2588             r.resultTo = null;
2589         }
2590         else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
2591
2592         // Make sure this HistoryRecord is not holding on to other resources,
2593         // because clients have remote IPC references to this object so we
2594         // can't assume that will go away and want to avoid circular IPC refs.
2595         r.results = null;
2596         r.pendingResults = null;
2597         r.newIntents = null;
2598         r.icicle = null;
2599     }
2600
2601     /**
2602      * @return Returns true if this activity has been removed from the history
2603      * list, or false if it is still in the list and will be removed later.
2604      */
2605     final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
2606             String reason, boolean oomAdj) {
2607         if (r.finishing) {
2608             Slog.w(TAG, "Duplicate finish request for " + r);
2609             return false;
2610         }
2611
2612         r.makeFinishing();
2613         final TaskRecord task = r.task;
2614         EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
2615                 r.userId, System.identityHashCode(r),
2616                 task.taskId, r.shortComponentName, reason);
2617         final ArrayList<ActivityRecord> activities = task.mActivities;
2618         final int index = activities.indexOf(r);
2619         if (index < (activities.size() - 1)) {
2620             task.setFrontOfTask();
2621             if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2622                 // If the caller asked that this activity (and all above it)
2623                 // be cleared when the task is reset, don't lose that information,
2624                 // but propagate it up to the next activity.
2625                 ActivityRecord next = activities.get(index+1);
2626                 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
2627             }
2628         }
2629
2630         r.pauseKeyDispatchingLocked();
2631
2632         adjustFocusedActivityLocked(r);
2633
2634         finishActivityResultsLocked(r, resultCode, resultData);
2635
2636         if (mResumedActivity == r) {
2637             boolean endTask = index <= 0;
2638             if (DEBUG_VISBILITY || DEBUG_TRANSITION) Slog.v(TAG,
2639                     "Prepare close transition: finishing " + r);
2640             mWindowManager.prepareAppTransition(endTask
2641                     ? AppTransition.TRANSIT_TASK_CLOSE
2642                     : AppTransition.TRANSIT_ACTIVITY_CLOSE, false);
2643
2644             // Tell window manager to prepare for this one to be removed.
2645             mWindowManager.setAppVisibility(r.appToken, false);
2646
2647             if (mPausingActivity == null) {
2648                 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
2649                 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
2650                 startPausingLocked(false, false);
2651             }
2652
2653             if (endTask) {
2654                 mStackSupervisor.endLockTaskModeIfTaskEnding(task);
2655             }
2656         } else if (r.state != ActivityState.PAUSING) {
2657             // If the activity is PAUSING, we will complete the finish once
2658             // it is done pausing; else we can just directly finish it here.
2659             if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
2660             return finishCurrentActivityLocked(r, FINISH_AFTER_PAUSE, oomAdj) == null;
2661         } else {
2662             if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
2663         }
2664
2665         return false;
2666     }
2667
2668     static final int FINISH_IMMEDIATELY = 0;
2669     static final int FINISH_AFTER_PAUSE = 1;
2670     static final int FINISH_AFTER_VISIBLE = 2;
2671
2672     final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj) {
2673         // First things first: if this activity is currently visible,
2674         // and the resumed activity is not yet visible, then hold off on
2675         // finishing until the resumed one becomes visible.
2676         if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
2677             if (!mStackSupervisor.mStoppingActivities.contains(r)) {
2678                 mStackSupervisor.mStoppingActivities.add(r);
2679                 if (mStackSupervisor.mStoppingActivities.size() > 3
2680                         || r.frontOfTask && mTaskHistory.size() <= 1) {
2681                     // If we already have a few activities waiting to stop,
2682                     // then give up on things going idle and start clearing
2683                     // them out. Or if r is the last of activity of the last task the stack
2684                     // will be empty and must be cleared immediately.
2685                     mStackSupervisor.scheduleIdleLocked();
2686                 } else {
2687                     mStackSupervisor.checkReadyForSleepLocked();
2688                 }
2689             }
2690             if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
2691                     + " (finish requested)");
2692             r.state = ActivityState.STOPPING;
2693             if (oomAdj) {
2694                 mService.updateOomAdjLocked();
2695             }
2696             return r;
2697         }
2698
2699         // make sure the record is cleaned out of other places.
2700         mStackSupervisor.mStoppingActivities.remove(r);
2701         mStackSupervisor.mGoingToSleepActivities.remove(r);
2702         mStackSupervisor.mWaitingVisibleActivities.remove(r);
2703         if (mResumedActivity == r) {
2704             mResumedActivity = null;
2705         }
2706         final ActivityState prevState = r.state;
2707         if (DEBUG_STATES) Slog.v(TAG, "Moving to FINISHING: " + r);
2708         r.state = ActivityState.FINISHING;
2709
2710         if (mode == FINISH_IMMEDIATELY
2711                 || prevState == ActivityState.STOPPED
2712                 || prevState == ActivityState.INITIALIZING) {
2713             // If this activity is already stopped, we can just finish
2714             // it right now.
2715             r.makeFinishing();
2716             boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm");
2717             if (activityRemoved) {
2718                 mStackSupervisor.resumeTopActivitiesLocked();
2719             }
2720             if (DEBUG_CONTAINERS) Slog.d(TAG, 
2721                     "destroyActivityLocked: finishCurrentActivityLocked r=" + r +
2722                     " destroy returned removed=" + activityRemoved);
2723             return activityRemoved ? null : r;
2724         }
2725
2726         // Need to go through the full pause cycle to get this
2727         // activity into the stopped state and then finish it.
2728         if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
2729         mStackSupervisor.mFinishingActivities.add(r);
2730         r.resumeKeyDispatchingLocked();
2731         mStackSupervisor.getFocusedStack().resumeTopActivityLocked(null);
2732         return r;
2733     }
2734
2735     void finishAllActivitiesLocked() {
2736         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
2737             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
2738             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
2739                 final ActivityRecord r = activities.get(activityNdx);
2740                 if (r.finishing) {
2741                     continue;
2742                 }
2743                 Slog.d(TAG, "finishAllActivitiesLocked: finishing " + r);
2744                 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
2745             }
2746         }
2747     }
2748
2749     final boolean navigateUpToLocked(IBinder token, Intent destIntent, int resultCode,
2750             Intent resultData) {
2751         final ActivityRecord srec = ActivityRecord.forToken(token);
2752         final TaskRecord task = srec.task;
2753         final ArrayList<ActivityRecord> activities = task.mActivities;
2754         final int start = activities.indexOf(srec);
2755         if (!mTaskHistory.contains(task) || (start < 0)) {
2756             return false;
2757         }
2758         int finishTo = start - 1;
2759         ActivityRecord parent = finishTo < 0 ? null : activities.get(finishTo);
2760         boolean foundParentInTask = false;
2761         final ComponentName dest = destIntent.getComponent();
2762         if (start > 0 && dest != null) {
2763             for (int i = finishTo; i >= 0; i--) {
2764                 ActivityRecord r = activities.get(i);
2765                 if (r.info.packageName.equals(dest.getPackageName()) &&
2766                         r.info.name.equals(dest.getClassName())) {
2767                     finishTo = i;
2768                     parent = r;
2769                     foundParentInTask = true;
2770                     break;
2771                 }
2772             }
2773         }
2774
2775         IActivityController controller = mService.mController;
2776         if (controller != null) {
2777             ActivityRecord next = topRunningActivityLocked(srec.appToken, 0);
2778             if (next != null) {
2779                 // ask watcher if this is allowed
2780                 boolean resumeOK = true;
2781                 try {
2782                     resumeOK = controller.activityResuming(next.packageName);
2783                 } catch (RemoteException e) {
2784                     mService.mController = null;
2785                     Watchdog.getInstance().setActivityController(null);
2786                 }
2787
2788                 if (!resumeOK) {
2789                     return false;
2790                 }
2791             }
2792         }
2793         final long origId = Binder.clearCallingIdentity();
2794         for (int i = start; i > finishTo; i--) {
2795             ActivityRecord r = activities.get(i);
2796             requestFinishActivityLocked(r.appToken, resultCode, resultData, "navigate-up", true);
2797             // Only return the supplied result for the first activity finished
2798             resultCode = Activity.RESULT_CANCELED;
2799             resultData = null;
2800         }
2801
2802         if (parent != null && foundParentInTask) {
2803             final int parentLaunchMode = parent.info.launchMode;
2804             final int destIntentFlags = destIntent.getFlags();
2805             if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE ||
2806                     parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
2807                     parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
2808                     (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
2809                 parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent);
2810             } else {
2811                 try {
2812                     ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
2813                             destIntent.getComponent(), 0, srec.userId);
2814                     int res = mStackSupervisor.startActivityLocked(srec.app.thread, destIntent,
2815                             null, aInfo, null, null, parent.appToken, null,
2816                             0, -1, parent.launchedFromUid, parent.launchedFromPackage,
2817                             0, null, true, null, null);
2818                     foundParentInTask = res == ActivityManager.START_SUCCESS;
2819                 } catch (RemoteException e) {
2820                     foundParentInTask = false;
2821                 }
2822                 requestFinishActivityLocked(parent.appToken, resultCode,
2823                         resultData, "navigate-up", true);
2824             }
2825         }
2826         Binder.restoreCallingIdentity(origId);
2827         return foundParentInTask;
2828     }
2829     /**
2830      * Perform the common clean-up of an activity record.  This is called both
2831      * as part of destroyActivityLocked() (when destroying the client-side
2832      * representation) and cleaning things up as a result of its hosting
2833      * processing going away, in which case there is no remaining client-side
2834      * state to destroy so only the cleanup here is needed.
2835      */
2836     final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices,
2837             boolean setState) {
2838         if (mResumedActivity == r) {
2839             mResumedActivity = null;
2840         }
2841         if (mPausingActivity == r) {
2842             mPausingActivity = null;
2843         }
2844         mService.clearFocusedActivity(r);
2845
2846         r.configDestroy = false;
2847         r.frozenBeforeDestroy = false;
2848
2849         if (setState) {
2850             if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (cleaning up)");
2851             r.state = ActivityState.DESTROYED;
2852             if (DEBUG_APP) Slog.v(TAG, "Clearing app during cleanUp for activity " + r);
2853             r.app = null;
2854         }
2855
2856         // Make sure this record is no longer in the pending finishes list.
2857         // This could happen, for example, if we are trimming activities
2858         // down to the max limit while they are still waiting to finish.
2859         mStackSupervisor.mFinishingActivities.remove(r);
2860         mStackSupervisor.mWaitingVisibleActivities.remove(r);
2861
2862         // Remove any pending results.
2863         if (r.finishing && r.pendingResults != null) {
2864             for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
2865                 PendingIntentRecord rec = apr.get();
2866                 if (rec != null) {
2867                     mService.cancelIntentSenderLocked(rec, false);
2868                 }
2869             }
2870             r.pendingResults = null;
2871         }
2872
2873         if (cleanServices) {
2874             cleanUpActivityServicesLocked(r);
2875         }
2876
2877         // Get rid of any pending idle timeouts.
2878         removeTimeoutsForActivityLocked(r);
2879         if (getMediaPlayer() == r) {
2880             mStackSupervisor.setMediaPlayingLocked(r, false);
2881         }
2882     }
2883
2884     private void removeTimeoutsForActivityLocked(ActivityRecord r) {
2885         mStackSupervisor.removeTimeoutsForActivityLocked(r);
2886         mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
2887         mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
2888         mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
2889         r.finishLaunchTickingLocked();
2890     }
2891
2892     private void removeActivityFromHistoryLocked(ActivityRecord r) {
2893         mStackSupervisor.removeChildActivityContainers(r);
2894         finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
2895         r.makeFinishing();
2896         if (DEBUG_ADD_REMOVE) {
2897             RuntimeException here = new RuntimeException("here");
2898             here.fillInStackTrace();
2899             Slog.i(TAG, "Removing activity " + r + " from stack");
2900         }
2901         r.takeFromHistory();
2902         removeTimeoutsForActivityLocked(r);
2903         if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (removed from history)");
2904         r.state = ActivityState.DESTROYED;
2905         if (DEBUG_APP) Slog.v(TAG, "Clearing app during remove for activity " + r);
2906         r.app = null;
2907         mWindowManager.removeAppToken(r.appToken);
2908         if (VALIDATE_TOKENS) {
2909             validateAppTokensLocked();
2910         }
2911         final TaskRecord task = r.task;
2912         if (task != null && task.removeActivity(r)) {
2913             if (DEBUG_STACK) Slog.i(TAG,
2914                     "removeActivityFromHistoryLocked: last activity removed from " + this);
2915             if (mStackSupervisor.isFrontStack(this) && task == topTask() &&
2916                     task.isOverHomeStack()) {
2917                 mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo());
2918             }
2919             removeTask(task);
2920         }
2921         cleanUpActivityServicesLocked(r);
2922         r.removeUriPermissionsLocked();
2923     }
2924
2925     /**
2926      * Perform clean-up of service connections in an activity record.
2927      */
2928     final void cleanUpActivityServicesLocked(ActivityRecord r) {
2929         // Throw away any services that have been bound by this activity.
2930         if (r.connections != null) {
2931             Iterator<ConnectionRecord> it = r.connections.iterator();
2932             while (it.hasNext()) {
2933                 ConnectionRecord c = it.next();
2934                 mService.mServices.removeConnectionLocked(c, null, r);
2935             }
2936             r.connections = null;
2937         }
2938     }
2939
2940     final void scheduleDestroyActivities(ProcessRecord owner, String reason) {
2941         Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG);
2942         msg.obj = new ScheduleDestroyArgs(owner, reason);
2943         mHandler.sendMessage(msg);
2944     }
2945
2946     final void destroyActivitiesLocked(ProcessRecord owner, String reason) {
2947         boolean lastIsOpaque = false;
2948         boolean activityRemoved = false;
2949         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
2950             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
2951             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
2952                 final ActivityRecord r = activities.get(activityNdx);
2953                 if (r.finishing) {
2954                     continue;
2955                 }
2956                 if (r.fullscreen) {
2957                     lastIsOpaque = true;
2958                 }
2959                 if (owner != null && r.app != owner) {
2960                     continue;
2961                 }
2962                 if (!lastIsOpaque) {
2963                     continue;
2964                 }
2965                 // We can destroy this one if we have its icicle saved and
2966                 // it is not in the process of pausing/stopping/finishing.
2967                 if (r.app != null && r != mResumedActivity && r != mPausingActivity
2968                         && r.haveState && !r.visible && r.stopped
2969                         && r.state != ActivityState.DESTROYING
2970                         && r.state != ActivityState.DESTROYED) {
2971                     if (DEBUG_SWITCH) Slog.v(TAG, "Destroying " + r + " in state " + r.state
2972                             + " resumed=" + mResumedActivity
2973                             + " pausing=" + mPausingActivity);
2974                     if (destroyActivityLocked(r, true, reason)) {
2975                         activityRemoved = true;
2976                     }
2977                 }
2978             }
2979         }
2980         if (activityRemoved) {
2981             mStackSupervisor.resumeTopActivitiesLocked();
2982         }
2983     }
2984
2985     /**
2986      * Destroy the current CLIENT SIDE instance of an activity.  This may be
2987      * called both when actually finishing an activity, or when performing
2988      * a configuration switch where we destroy the current client-side object
2989      * but then create a new client-side object for this same HistoryRecord.
2990      */
2991     final boolean destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason) {
2992         if (DEBUG_SWITCH || DEBUG_CLEANUP) Slog.v(
2993             TAG, "Removing activity from " + reason + ": token=" + r
2994               + ", app=" + (r.app != null ? r.app.processName : "(null)"));
2995         EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
2996                 r.userId, System.identityHashCode(r),
2997                 r.task.taskId, r.shortComponentName, reason);
2998
2999         boolean removedFromHistory = false;
3000
3001         cleanUpActivityLocked(r, false, false);
3002
3003         final boolean hadApp = r.app != null;
3004
3005         if (hadApp) {
3006             if (removeFromApp) {
3007                 r.app.activities.remove(r);
3008                 if (mService.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
3009                     mService.mHeavyWeightProcess = null;
3010                     mService.mHandler.sendEmptyMessage(
3011                             ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG);
3012                 }
3013                 if (r.app.activities.isEmpty()) {
3014                     // No longer have activities, so update LRU list and oom adj.
3015                     mService.updateLruProcessLocked(r.app, false, null);
3016                     mService.updateOomAdjLocked();
3017                 }
3018             }
3019
3020             boolean skipDestroy = false;
3021
3022             try {
3023                 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
3024                 r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,
3025                         r.configChangeFlags);
3026             } catch (Exception e) {
3027                 // We can just ignore exceptions here...  if the process
3028                 // has crashed, our death notification will clean things
3029                 // up.
3030                 //Slog.w(TAG, "Exception thrown during finish", e);
3031                 if (r.finishing) {
3032                     removeActivityFromHistoryLocked(r);
3033                     removedFromHistory = true;
3034                     skipDestroy = true;
3035                 }
3036             }
3037
3038             r.nowVisible = false;
3039
3040             // If the activity is finishing, we need to wait on removing it
3041             // from the list to give it a chance to do its cleanup.  During
3042             // that time it may make calls back with its token so we need to
3043             // be able to find it on the list and so we don't want to remove
3044             // it from the list yet.  Otherwise, we can just immediately put
3045             // it in the destroyed state since we are not removing it from the
3046             // list.
3047             if (r.finishing && !skipDestroy) {
3048                 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYING: " + r
3049                         + " (destroy requested)");
3050                 r.state = ActivityState.DESTROYING;
3051                 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG, r);
3052                 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
3053             } else {
3054                 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (destroy skipped)");
3055                 r.state = ActivityState.DESTROYED;
3056                 if (DEBUG_APP) Slog.v(TAG, "Clearing app during destroy for activity " + r);
3057                 r.app = null;
3058             }
3059         } else {
3060             // remove this record from the history.
3061             if (r.finishing) {
3062                 removeActivityFromHistoryLocked(r);
3063                 removedFromHistory = true;
3064             } else {
3065                 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (no app)");
3066                 r.state = ActivityState.DESTROYED;
3067                 if (DEBUG_APP) Slog.v(TAG, "Clearing app during destroy for activity " + r);
3068                 r.app = null;
3069             }
3070         }
3071
3072         r.configChangeFlags = 0;
3073
3074         if (!mLRUActivities.remove(r) && hadApp) {
3075             Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
3076         }
3077
3078         return removedFromHistory;
3079     }
3080
3081     final void activityDestroyedLocked(IBinder token) {
3082         final long origId = Binder.clearCallingIdentity();
3083         try {
3084             ActivityRecord r = ActivityRecord.forToken(token);
3085             if (r != null) {
3086                 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
3087             }
3088             if (DEBUG_CONTAINERS) Slog.d(TAG, "activityDestroyedLocked: r=" + r);
3089
3090             if (isInStackLocked(token) != null) {
3091                 if (r.state == ActivityState.DESTROYING) {
3092                     cleanUpActivityLocked(r, true, false);
3093                     removeActivityFromHistoryLocked(r);
3094                 }
3095             }
3096             mStackSupervisor.resumeTopActivitiesLocked();
3097         } finally {
3098             Binder.restoreCallingIdentity(origId);
3099         }
3100     }
3101
3102     void releaseMediaResources() {
3103         if (isMediaPlaying() && !mHandler.hasMessages(STOP_MEDIA_PLAYING_TIMEOUT_MSG)) {
3104             final ActivityRecord r = getMediaPlayer();
3105             if (DEBUG_STATES) Slog.d(TAG, "releaseMediaResources activtyDisplay=" +
3106                     mActivityContainer.mActivityDisplay + " mediaPlayer=" + r + " app=" + r.app +
3107                     " thread=" + r.app.thread);
3108             if (r != null && r.app != null && r.app.thread != null) {
3109                 try {
3110                     r.app.thread.scheduleStopMediaPlaying(r.appToken);
3111                 } catch (RemoteException e) {
3112                 }
3113                 mHandler.sendEmptyMessageDelayed(STOP_MEDIA_PLAYING_TIMEOUT_MSG, 500);
3114             } else {
3115                 Slog.e(TAG, "releaseMediaResources: activity " + r + " no longer running");
3116                 mediaResourcesReleased(r.appToken);
3117             }
3118         }
3119     }
3120
3121     final void mediaResourcesReleased(IBinder token) {
3122         mHandler.removeMessages(STOP_MEDIA_PLAYING_TIMEOUT_MSG);
3123         final ActivityRecord r = getMediaPlayer();
3124         if (r != null) {
3125             mStackSupervisor.mStoppingActivities.add(r);
3126             setMediaPlayer(null);
3127         }
3128         mStackSupervisor.resumeTopActivitiesLocked();
3129     }
3130
3131     boolean isMediaPlaying() {
3132         return isAttached() && mActivityContainer.mActivityDisplay.isMediaPlaying();
3133     }
3134
3135     void setMediaPlayer(ActivityRecord r) {
3136         if (isAttached()) {
3137             mActivityContainer.mActivityDisplay.setMediaPlaying(r);
3138         }
3139     }
3140
3141     ActivityRecord getMediaPlayer() {
3142         return isAttached() ? mActivityContainer.mActivityDisplay.mMediaPlayingActivity : null;
3143     }
3144
3145     private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list,
3146             ProcessRecord app, String listName) {
3147         int i = list.size();
3148         if (DEBUG_CLEANUP) Slog.v(
3149             TAG, "Removing app " + app + " from list " + listName
3150             + " with " + i + " entries");
3151         while (i > 0) {
3152             i--;
3153             ActivityRecord r = list.get(i);
3154             if (DEBUG_CLEANUP) Slog.v(TAG, "Record #" + i + " " + r);
3155             if (r.app == app) {
3156                 if (DEBUG_CLEANUP) Slog.v(TAG, "---> REMOVING this entry!");
3157                 list.remove(i);
3158                 removeTimeoutsForActivityLocked(r);
3159             }
3160         }
3161     }
3162
3163     boolean removeHistoryRecordsForAppLocked(ProcessRecord app) {
3164         removeHistoryRecordsForAppLocked(mLRUActivities, app, "mLRUActivities");
3165         removeHistoryRecordsForAppLocked(mStackSupervisor.mStoppingActivities, app,
3166                 "mStoppingActivities");
3167         removeHistoryRecordsForAppLocked(mStackSupervisor.mGoingToSleepActivities, app,
3168                 "mGoingToSleepActivities");
3169         removeHistoryRecordsForAppLocked(mStackSupervisor.mWaitingVisibleActivities, app,
3170                 "mWaitingVisibleActivities");
3171         removeHistoryRecordsForAppLocked(mStackSupervisor.mFinishingActivities, app,
3172                 "mFinishingActivities");
3173
3174         boolean hasVisibleActivities = false;
3175
3176         // Clean out the history list.
3177         int i = numActivities();
3178         if (DEBUG_CLEANUP) Slog.v(
3179             TAG, "Removing app " + app + " from history with " + i + " entries");
3180         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3181             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3182             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3183                 final ActivityRecord r = activities.get(activityNdx);
3184                 --i;
3185                 if (DEBUG_CLEANUP) Slog.v(
3186                     TAG, "Record #" + i + " " + r + ": app=" + r.app);
3187                 if (r.app == app) {
3188                     boolean remove;
3189                     if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
3190                         // Don't currently have state for the activity, or
3191                         // it is finishing -- always remove it.
3192                         remove = true;
3193                     } else if (r.launchCount > 2 &&
3194                             r.lastLaunchTime > (SystemClock.uptimeMillis()-60000)) {
3195                         // We have launched this activity too many times since it was
3196                         // able to run, so give up and remove it.
3197                         remove = true;
3198                     } else {
3199                         // The process may be gone, but the activity lives on!
3200                         remove = false;
3201                     }
3202                     if (remove) {
3203                         if (DEBUG_ADD_REMOVE || DEBUG_CLEANUP) {
3204                             RuntimeException here = new RuntimeException("here");
3205                             here.fillInStackTrace();
3206                             Slog.i(TAG, "Removing activity " + r + " from stack at " + i
3207                                     + ": haveState=" + r.haveState
3208                                     + " stateNotNeeded=" + r.stateNotNeeded
3209                                     + " finishing=" + r.finishing
3210                                     + " state=" + r.state, here);
3211                         }
3212                         if (!r.finishing) {
3213                             Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
3214                             EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
3215                                     r.userId, System.identityHashCode(r),
3216                                     r.task.taskId, r.shortComponentName,
3217                                     "proc died without state saved");
3218                             if (r.state == ActivityState.RESUMED) {
3219                                 mService.updateUsageStats(r, false);
3220                             }
3221                         }
3222                         removeActivityFromHistoryLocked(r);
3223
3224                     } else {
3225                         // We have the current state for this activity, so
3226                         // it can be restarted later when needed.
3227                         if (localLOGV) Slog.v(
3228                             TAG, "Keeping entry, setting app to null");
3229                         if (r.visible) {
3230                             hasVisibleActivities = true;
3231                         }
3232                         if (DEBUG_APP) Slog.v(TAG, "Clearing app during removeHistory for activity "
3233                                 + r);
3234                         r.app = null;
3235                         r.nowVisible = false;
3236                         if (!r.haveState) {
3237                             if (DEBUG_SAVED_STATE) Slog.i(TAG,
3238                                     "App died, clearing saved state of " + r);
3239                             r.icicle = null;
3240                         }
3241                     }
3242
3243                     cleanUpActivityLocked(r, true, true);
3244                 }
3245             }
3246         }
3247
3248         return hasVisibleActivities;
3249     }
3250
3251     final void updateTransitLocked(int transit, Bundle options) {
3252         if (options != null) {
3253             ActivityRecord r = topRunningActivityLocked(null);
3254             if (r != null && r.state != ActivityState.RESUMED) {
3255                 r.updateOptionsLocked(options);
3256             } else {
3257                 ActivityOptions.abort(options);
3258             }
3259         }
3260         mWindowManager.prepareAppTransition(transit, false);
3261     }
3262
3263     void updateTaskMovement(TaskRecord task, boolean toFront) {
3264         if (task.isPersistable) {
3265             task.mLastTimeMoved = System.currentTimeMillis();
3266             // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most
3267             // recently will be most negative, tasks sent to the bottom before that will be less
3268             // negative. Similarly for recent tasks moved to the top which will be most positive.
3269             if (!toFront) {
3270                 task.mLastTimeMoved *= -1;
3271             }
3272         }
3273     }
3274
3275     void moveHomeStackTaskToTop(int homeStackTaskType) {
3276         final int top = mTaskHistory.size() - 1;
3277         for (int taskNdx = top; taskNdx >= 0; --taskNdx) {
3278             final TaskRecord task = mTaskHistory.get(taskNdx);
3279             if (task.taskType == homeStackTaskType) {
3280                 if (DEBUG_TASKS || DEBUG_STACK)
3281                     Slog.d(TAG, "moveHomeStackTaskToTop: moving " + task);
3282                 mTaskHistory.remove(taskNdx);
3283                 mTaskHistory.add(top, task);
3284                 updateTaskMovement(task, true);
3285                 mWindowManager.moveTaskToTop(task.taskId);
3286                 return;
3287             }
3288         }
3289     }
3290
3291     final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
3292         if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
3293
3294         final int numTasks = mTaskHistory.size();
3295         final int index = mTaskHistory.indexOf(tr);
3296         if (numTasks == 0 || index < 0)  {
3297             // nothing to do!
3298             if (reason != null &&
3299                     (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
3300                 ActivityOptions.abort(options);
3301             } else {
3302                 updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
3303             }
3304             return;
3305         }
3306
3307         moveToFront();
3308
3309         // Shift all activities with this task up to the top
3310         // of the stack, keeping them in the same internal order.
3311         insertTaskAtTop(tr);
3312
3313         if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare to front transition: task=" + tr);
3314         if (reason != null &&
3315                 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
3316             mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
3317             ActivityRecord r = topRunningActivityLocked(null);
3318             if (r != null) {
3319                 mNoAnimActivities.add(r);
3320             }
3321             ActivityOptions.abort(options);
3322         } else {
3323             updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
3324         }
3325
3326         mWindowManager.moveTaskToTop(tr.taskId);
3327
3328         mStackSupervisor.resumeTopActivitiesLocked();
3329         EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
3330
3331         if (VALIDATE_TOKENS) {
3332             validateAppTokensLocked();
3333         }
3334     }
3335
3336     /**
3337      * Worker method for rearranging history stack. Implements the function of moving all
3338      * activities for a specific task (gathering them if disjoint) into a single group at the
3339      * bottom of the stack.
3340      *
3341      * If a watcher is installed, the action is preflighted and the watcher has an opportunity
3342      * to premeptively cancel the move.
3343      *
3344      * @param taskId The taskId to collect and move to the bottom.
3345      * @return Returns true if the move completed, false if not.
3346      */
3347     final boolean moveTaskToBackLocked(int taskId, ActivityRecord reason) {
3348         final TaskRecord tr = taskForIdLocked(taskId);
3349         if (tr == null) {
3350             Slog.i(TAG, "moveTaskToBack: bad taskId=" + taskId);
3351             return false;
3352         }
3353
3354         Slog.i(TAG, "moveTaskToBack: " + tr);
3355
3356         mStackSupervisor.endLockTaskModeIfTaskEnding(tr);
3357
3358         // If we have a watcher, preflight the move before committing to it.  First check
3359         // for *other* available tasks, but if none are available, then try again allowing the
3360         // current task to be selected.
3361         if (mStackSupervisor.isFrontStack(this) && mService.mController != null) {
3362             ActivityRecord next = topRunningActivityLocked(null, taskId);
3363             if (next == null) {
3364                 next = topRunningActivityLocked(null, 0);
3365             }
3366             if (next != null) {
3367                 // ask watcher if this is allowed
3368                 boolean moveOK = true;
3369                 try {
3370                     moveOK = mService.mController.activityResuming(next.packageName);
3371                 } catch (RemoteException e) {
3372                     mService.mController = null;
3373                     Watchdog.getInstance().setActivityController(null);
3374                 }
3375                 if (!moveOK) {
3376                     return false;
3377                 }
3378             }
3379         }
3380
3381         if (DEBUG_TRANSITION) Slog.v(TAG,
3382                 "Prepare to back transition: task=" + taskId);
3383
3384         mTaskHistory.remove(tr);
3385         mTaskHistory.add(0, tr);
3386         updateTaskMovement(tr, false);
3387
3388         // There is an assumption that moving a task to the back moves it behind the home activity.
3389         // We make sure here that some activity in the stack will launch home.
3390         int numTasks = mTaskHistory.size();
3391         for (int taskNdx = numTasks - 1; taskNdx >= 1; --taskNdx) {
3392             final TaskRecord task = mTaskHistory.get(taskNdx);
3393             if (task.isOverHomeStack()) {
3394                 break;
3395             }
3396             if (taskNdx == 1) {
3397                 // Set the last task before tr to go to home.
3398                 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
3399             }
3400         }
3401
3402         if (reason != null &&
3403                 (reason.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
3404             mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
3405             ActivityRecord r = topRunningActivityLocked(null);
3406             if (r != null) {
3407                 mNoAnimActivities.add(r);
3408             }
3409         } else {
3410             mWindowManager.prepareAppTransition(AppTransition.TRANSIT_TASK_TO_BACK, false);
3411         }
3412         mWindowManager.moveTaskToBottom(taskId);
3413
3414         if (VALIDATE_TOKENS) {
3415             validateAppTokensLocked();
3416         }
3417
3418         final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null;
3419         if (task == tr && tr.isOverHomeStack() || numTasks <= 1 && isOnHomeDisplay()) {
3420             final int taskToReturnTo = tr.getTaskToReturnTo();
3421             tr.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
3422             return mStackSupervisor.resumeHomeStackTask(taskToReturnTo, null);
3423         }
3424
3425         mStackSupervisor.resumeTopActivitiesLocked();
3426         return true;
3427     }
3428
3429     static final void logStartActivity(int tag, ActivityRecord r,
3430             TaskRecord task) {
3431         final Uri data = r.intent.getData();
3432         final String strData = data != null ? data.toSafeString() : null;
3433
3434         EventLog.writeEvent(tag,
3435                 r.userId, System.identityHashCode(r), task.taskId,
3436                 r.shortComponentName, r.intent.getAction(),
3437                 r.intent.getType(), strData, r.intent.getFlags());
3438     }
3439
3440     /**
3441      * Make sure the given activity matches the current configuration.  Returns
3442      * false if the activity had to be destroyed.  Returns true if the
3443      * configuration is the same, or the activity will remain running as-is
3444      * for whatever reason.  Ensures the HistoryRecord is updated with the
3445      * correct configuration and all other bookkeeping is handled.
3446      */
3447     final boolean ensureActivityConfigurationLocked(ActivityRecord r,
3448             int globalChanges) {
3449         if (mConfigWillChange) {
3450             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3451                     "Skipping config check (will change): " + r);
3452             return true;
3453         }
3454
3455         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3456                 "Ensuring correct configuration: " + r);
3457
3458         // Short circuit: if the two configurations are the exact same
3459         // object (the common case), then there is nothing to do.
3460         Configuration newConfig = mService.mConfiguration;
3461         if (r.configuration == newConfig && !r.forceNewConfig) {
3462             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3463                     "Configuration unchanged in " + r);
3464             return true;
3465         }
3466
3467         // We don't worry about activities that are finishing.
3468         if (r.finishing) {
3469             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3470                     "Configuration doesn't matter in finishing " + r);
3471             r.stopFreezingScreenLocked(false);
3472             return true;
3473         }
3474
3475         // Okay we now are going to make this activity have the new config.
3476         // But then we need to figure out how it needs to deal with that.
3477         Configuration oldConfig = r.configuration;
3478         r.configuration = newConfig;
3479
3480         // Determine what has changed.  May be nothing, if this is a config
3481         // that has come back from the app after going idle.  In that case
3482         // we just want to leave the official config object now in the
3483         // activity and do nothing else.
3484         final int changes = oldConfig.diff(newConfig);
3485         if (changes == 0 && !r.forceNewConfig) {
3486             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3487                     "Configuration no differences in " + r);
3488             return true;
3489         }
3490
3491         // If the activity isn't currently running, just leave the new
3492         // configuration and it will pick that up next time it starts.
3493         if (r.app == null || r.app.thread == null) {
3494             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3495                     "Configuration doesn't matter not running " + r);
3496             r.stopFreezingScreenLocked(false);
3497             r.forceNewConfig = false;
3498             return true;
3499         }
3500
3501         // Figure out how to handle the changes between the configurations.
3502         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
3503             Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
3504                     + Integer.toHexString(changes) + ", handles=0x"
3505                     + Integer.toHexString(r.info.getRealConfigChanged())
3506                     + ", newConfig=" + newConfig);
3507         }
3508         if ((changes&(~r.info.getRealConfigChanged())) != 0 || r.forceNewConfig) {
3509             // Aha, the activity isn't handling the change, so DIE DIE DIE.
3510             r.configChangeFlags |= changes;
3511             r.startFreezingScreenLocked(r.app, globalChanges);
3512             r.forceNewConfig = false;
3513             if (r.app == null || r.app.thread == null) {
3514                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3515                         "Config is destroying non-running " + r);
3516                 destroyActivityLocked(r, true, "config");
3517             } else if (r.state == ActivityState.PAUSING) {
3518                 // A little annoying: we are waiting for this activity to
3519                 // finish pausing.  Let's not do anything now, but just
3520                 // flag that it needs to be restarted when done pausing.
3521                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3522                         "Config is skipping already pausing " + r);
3523                 r.configDestroy = true;
3524                 return true;
3525             } else if (r.state == ActivityState.RESUMED) {
3526                 // Try to optimize this case: the configuration is changing
3527                 // and we need to restart the top, resumed activity.
3528                 // Instead of doing the normal handshaking, just say
3529                 // "restart!".
3530                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3531                         "Config is relaunching resumed " + r);
3532                 relaunchActivityLocked(r, r.configChangeFlags, true);
3533                 r.configChangeFlags = 0;
3534             } else {
3535                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3536                         "Config is relaunching non-resumed " + r);
3537                 relaunchActivityLocked(r, r.configChangeFlags, false);
3538                 r.configChangeFlags = 0;
3539             }
3540
3541             // All done...  tell the caller we weren't able to keep this
3542             // activity around.
3543             return false;
3544         }
3545
3546         // Default case: the activity can handle this new configuration, so
3547         // hand it over.  Note that we don't need to give it the new
3548         // configuration, since we always send configuration changes to all
3549         // process when they happen so it can just use whatever configuration
3550         // it last got.
3551         if (r.app != null && r.app.thread != null) {
3552             try {
3553                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
3554                 r.app.thread.scheduleActivityConfigurationChanged(r.appToken);
3555             } catch (RemoteException e) {
3556                 // If process died, whatever.
3557             }
3558         }
3559         r.stopFreezingScreenLocked(false);
3560
3561         return true;
3562     }
3563
3564     private boolean relaunchActivityLocked(ActivityRecord r,
3565             int changes, boolean andResume) {
3566         List<ResultInfo> results = null;
3567         List<Intent> newIntents = null;
3568         if (andResume) {
3569             results = r.results;
3570             newIntents = r.newIntents;
3571         }
3572         if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
3573                 + " with results=" + results + " newIntents=" + newIntents
3574                 + " andResume=" + andResume);
3575         EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
3576                 : EventLogTags.AM_RELAUNCH_ACTIVITY, r.userId, System.identityHashCode(r),
3577                 r.task.taskId, r.shortComponentName);
3578
3579         r.startFreezingScreenLocked(r.app, 0);
3580
3581         mStackSupervisor.removeChildActivityContainers(r);
3582
3583         try {
3584             if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
3585                     (andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ")
3586                     + r);
3587             r.forceNewConfig = false;
3588             r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents,
3589                     changes, !andResume, new Configuration(mService.mConfiguration));
3590             // Note: don't need to call pauseIfSleepingLocked() here, because
3591             // the caller will only pass in 'andResume' if this activity is
3592             // currently resumed, which implies we aren't sleeping.
3593         } catch (RemoteException e) {
3594             if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG, "Relaunch failed", e);
3595         }
3596
3597         if (andResume) {
3598             r.results = null;
3599             r.newIntents = null;
3600             r.state = ActivityState.RESUMED;
3601         } else {
3602             mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
3603             r.state = ActivityState.PAUSED;
3604         }
3605
3606         return true;
3607     }
3608
3609     boolean willActivityBeVisibleLocked(IBinder token) {
3610         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3611             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3612             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3613                 final ActivityRecord r = activities.get(activityNdx);
3614                 if (r.appToken == token) {
3615                     return true;
3616                 }
3617                 if (r.fullscreen && !r.finishing) {
3618                     return false;
3619                 }
3620             }
3621         }
3622         final ActivityRecord r = ActivityRecord.forToken(token);
3623         if (r == null) {
3624             return false;
3625         }
3626         if (r.finishing) Slog.e(TAG, "willActivityBeVisibleLocked: Returning false,"
3627                 + " would have returned true for r=" + r);
3628         return !r.finishing;
3629     }
3630
3631     void closeSystemDialogsLocked() {
3632         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3633             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3634             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3635                 final ActivityRecord r = activities.get(activityNdx);
3636                 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
3637                     finishActivityLocked(r, Activity.RESULT_CANCELED, null, "close-sys", true);
3638                 }
3639             }
3640         }
3641     }
3642
3643     boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
3644         boolean didSomething = false;
3645         TaskRecord lastTask = null;
3646         ComponentName homeActivity = null;
3647         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3648             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3649             int numActivities = activities.size();
3650             for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
3651                 ActivityRecord r = activities.get(activityNdx);
3652                 final boolean samePackage = r.packageName.equals(name)
3653                         || (name == null && r.userId == userId);
3654                 if ((userId == UserHandle.USER_ALL || r.userId == userId)
3655                         && (samePackage || r.task == lastTask)
3656                         && (r.app == null || evenPersistent || !r.app.persistent)) {
3657                     if (!doit) {
3658                         if (r.finishing) {
3659                             // If this activity is just finishing, then it is not
3660                             // interesting as far as something to stop.
3661                             continue;
3662                         }
3663                         return true;
3664                     }
3665                     if (r.isHomeActivity()) {
3666                         if (homeActivity != null && homeActivity.equals(r.realActivity)) {
3667                             Slog.i(TAG, "Skip force-stop again " + r);
3668                             continue;
3669                         } else {
3670                             homeActivity = r.realActivity;
3671                         }
3672                     }
3673                     didSomething = true;
3674                     Slog.i(TAG, "  Force finishing activity " + r);
3675                     if (samePackage) {
3676                         if (r.app != null) {
3677                             r.app.removed = true;
3678                         }
3679                         r.app = null;
3680                     }
3681                     lastTask = r.task;
3682                     if (finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop",
3683                             true)) {
3684                         // r has been deleted from mActivities, accommodate.
3685                         --numActivities;
3686                         --activityNdx;
3687                     }
3688                 }
3689             }
3690         }
3691         return didSomething;
3692     }
3693
3694     void getTasksLocked(List<RunningTaskInfo> list, int callingUid, boolean allowed) {
3695         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3696             final TaskRecord task = mTaskHistory.get(taskNdx);
3697             ActivityRecord r = null;
3698             ActivityRecord top = null;
3699             int numActivities = 0;
3700             int numRunning = 0;
3701             final ArrayList<ActivityRecord> activities = task.mActivities;
3702             if (activities.isEmpty()) {
3703                 continue;
3704             }
3705             if (!allowed && !task.isHomeTask() && task.creatorUid != callingUid) {
3706                 continue;
3707             }
3708             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3709                 r = activities.get(activityNdx);
3710
3711                 // Initialize state for next task if needed.
3712                 if (top == null || (top.state == ActivityState.INITIALIZING)) {
3713                     top = r;
3714                     numActivities = numRunning = 0;
3715                 }
3716
3717                 // Add 'r' into the current task.
3718                 numActivities++;
3719                 if (r.app != null && r.app.thread != null) {
3720                     numRunning++;
3721                 }
3722
3723                 if (localLOGV) Slog.v(
3724                     TAG, r.intent.getComponent().flattenToShortString()
3725                     + ": task=" + r.task);
3726             }
3727
3728             RunningTaskInfo ci = new RunningTaskInfo();
3729             ci.id = task.taskId;
3730             ci.baseActivity = r.intent.getComponent();
3731             ci.topActivity = top.intent.getComponent();
3732             ci.lastActiveTime = task.lastActiveTime;
3733
3734             if (top.task != null) {
3735                 ci.description = top.task.lastDescription;
3736             }
3737             ci.numActivities = numActivities;
3738             ci.numRunning = numRunning;
3739             //System.out.println(
3740             //    "#" + maxNum + ": " + " descr=" + ci.description);
3741             list.add(ci);
3742         }
3743     }
3744
3745     public void unhandledBackLocked() {
3746         final int top = mTaskHistory.size() - 1;
3747         if (DEBUG_SWITCH) Slog.d(
3748             TAG, "Performing unhandledBack(): top activity at " + top);
3749         if (top >= 0) {
3750             final ArrayList<ActivityRecord> activities = mTaskHistory.get(top).mActivities;
3751             int activityTop = activities.size() - 1;
3752             if (activityTop > 0) {
3753                 finishActivityLocked(activities.get(activityTop), Activity.RESULT_CANCELED, null,
3754                         "unhandled-back", true);
3755             }
3756         }
3757     }
3758
3759     /**
3760      * Reset local parameters because an app's activity died.
3761      * @param app The app of the activity that died.
3762      * @return result from removeHistoryRecordsForAppLocked.
3763      */
3764     boolean handleAppDiedLocked(ProcessRecord app) {
3765         if (mPausingActivity != null && mPausingActivity.app == app) {
3766             if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG,
3767                     "App died while pausing: " + mPausingActivity);
3768             mPausingActivity = null;
3769         }
3770         if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
3771             mLastPausedActivity = null;
3772             mLastNoHistoryActivity = null;
3773         }
3774
3775         return removeHistoryRecordsForAppLocked(app);
3776     }
3777
3778     void handleAppCrashLocked(ProcessRecord app) {
3779         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3780             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3781             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3782                 final ActivityRecord r = activities.get(activityNdx);
3783                 if (r.app == app) {
3784                     Slog.w(TAG, "  Force finishing activity "
3785                             + r.intent.getComponent().flattenToShortString());
3786                     finishActivityLocked(r, Activity.RESULT_CANCELED, null, "crashed", false);
3787                 }
3788             }
3789         }
3790     }
3791
3792     boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
3793             boolean dumpClient, String dumpPackage, boolean needSep, String header) {
3794         boolean printed = false;
3795         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3796             final TaskRecord task = mTaskHistory.get(taskNdx);
3797             printed |= ActivityStackSupervisor.dumpHistoryList(fd, pw,
3798                     mTaskHistory.get(taskNdx).mActivities, "    ", "Hist", true, !dumpAll,
3799                     dumpClient, dumpPackage, needSep, header,
3800                     "    Task id #" + task.taskId);
3801             if (printed) {
3802                 header = null;
3803             }
3804         }
3805         return printed;
3806     }
3807
3808     ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
3809         ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
3810
3811         if ("all".equals(name)) {
3812             for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3813                 activities.addAll(mTaskHistory.get(taskNdx).mActivities);
3814             }
3815         } else if ("top".equals(name)) {
3816             final int top = mTaskHistory.size() - 1;
3817             if (top >= 0) {
3818                 final ArrayList<ActivityRecord> list = mTaskHistory.get(top).mActivities;
3819                 int listTop = list.size() - 1;
3820                 if (listTop >= 0) {
3821                     activities.add(list.get(listTop));
3822                 }
3823             }
3824         } else {
3825             ItemMatcher matcher = new ItemMatcher();
3826             matcher.build(name);
3827
3828             for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3829                 for (ActivityRecord r1 : mTaskHistory.get(taskNdx).mActivities) {
3830                     if (matcher.match(r1, r1.intent.getComponent())) {
3831                         activities.add(r1);
3832                     }
3833                 }
3834             }
3835         }
3836
3837         return activities;
3838     }
3839
3840     ActivityRecord restartPackage(String packageName) {
3841         ActivityRecord starting = topRunningActivityLocked(null);
3842
3843         // All activities that came from the package must be
3844         // restarted as if there was a config change.
3845         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3846             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3847             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3848                 final ActivityRecord a = activities.get(activityNdx);
3849                 if (a.info.packageName.equals(packageName)) {
3850                     a.forceNewConfig = true;
3851                     if (starting != null && a == starting && a.visible) {
3852                         a.startFreezingScreenLocked(starting.app,
3853                                 ActivityInfo.CONFIG_SCREEN_LAYOUT);
3854                     }
3855                 }
3856             }
3857         }
3858
3859         return starting;
3860     }
3861
3862     void removeTask(TaskRecord task) {
3863         mStackSupervisor.endLockTaskModeIfTaskEnding(task);
3864         mWindowManager.removeTask(task.taskId);
3865         final ActivityRecord r = mResumedActivity;
3866         if (r != null && r.task == task) {
3867             mResumedActivity = null;
3868         }
3869
3870         final int taskNdx = mTaskHistory.indexOf(task);
3871         final int topTaskNdx = mTaskHistory.size() - 1;
3872         if (task.isOverHomeStack() && taskNdx < topTaskNdx) {
3873             final TaskRecord nextTask = mTaskHistory.get(taskNdx + 1);
3874             if (!nextTask.isOverHomeStack()) {
3875                 nextTask.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
3876             }
3877         }
3878         mTaskHistory.remove(task);
3879         updateTaskMovement(task, true);
3880
3881         if (task.mActivities.isEmpty()) {
3882             final boolean isVoiceSession = task.voiceSession != null;
3883             if (isVoiceSession) {
3884                 try {
3885                     task.voiceSession.taskFinished(task.intent, task.taskId);
3886                 } catch (RemoteException e) {
3887                 }
3888             }
3889             if (task.autoRemoveFromRecents() || isVoiceSession) {
3890                 // Task creator asked to remove this when done, or this task was a voice
3891                 // interaction, so it should not remain on the recent tasks list.
3892                 mService.mRecentTasks.remove(task);
3893                 task.closeRecentsChain();
3894             }
3895         }
3896
3897         if (mTaskHistory.isEmpty()) {
3898             if (DEBUG_STACK) Slog.i(TAG, "removeTask: moving to back stack=" + this);
3899             if (isOnHomeDisplay()) {
3900                 mStackSupervisor.moveHomeStack(!isHomeStack());
3901             }
3902             if (mStacks != null) {
3903                 mStacks.remove(this);
3904                 mStacks.add(0, this);
3905             }
3906             mActivityContainer.onTaskListEmptyLocked();
3907         }
3908     }
3909
3910     TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
3911             IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
3912             boolean toTop) {
3913         TaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession,
3914                 voiceInteractor);
3915         addTask(task, toTop, false);
3916         return task;
3917     }
3918
3919     ArrayList<TaskRecord> getAllTasks() {
3920         return new ArrayList<TaskRecord>(mTaskHistory);
3921     }
3922
3923     void addTask(final TaskRecord task, final boolean toTop, boolean moving) {
3924         task.stack = this;
3925         if (toTop) {
3926             insertTaskAtTop(task);
3927         } else {
3928             mTaskHistory.add(0, task);
3929             updateTaskMovement(task, false);
3930         }
3931         if (!moving && task.voiceSession != null) {
3932             try {
3933                 task.voiceSession.taskStarted(task.intent, task.taskId);
3934             } catch (RemoteException e) {
3935             }
3936         }
3937     }
3938
3939     public int getStackId() {
3940         return mStackId;
3941     }
3942
3943     @Override
3944     public String toString() {
3945         return "ActivityStack{" + Integer.toHexString(System.identityHashCode(this))
3946                 + " stackId=" + mStackId + ", " + mTaskHistory.size() + " tasks}";
3947     }
3948 }