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