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