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