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                                 mWindowManager.setAppVisibility(r.appToken, true);
   1098                             }
   1099                             if (r != starting) {
   1100                                 mStackSupervisor.startSpecificActivityLocked(r, false, false);
   1101                             }
   1102                         }
   1103 
   1104                     } else if (r.visible) {
   1105                         // If this activity is already visible, then there is nothing
   1106                         // else to do here.
   1107                         if (DEBUG_VISBILITY) Slog.v(TAG, "Skipping: already visible at " + r);
   1108                         r.stopFreezingScreenLocked(false);
   1109 
   1110                     } else if (onlyThisProcess == null) {
   1111                         // This activity is not currently visible, but is running.
   1112                         // Tell it to become visible.
   1113                         r.visible = true;
   1114                         if (r.state != ActivityState.RESUMED && r != starting) {
   1115                             // If this activity is paused, tell it
   1116                             // to now show its window.
   1117                             if (DEBUG_VISBILITY) Slog.v(
   1118                                     TAG, "Making visible and scheduling visibility: " + r);
   1119                             try {
   1120                                 if (mTranslucentActivityWaiting != null) {
   1121                                     mUndrawnActivitiesBelowTopTranslucent.add(r);
   1122                                 }
   1123                                 mWindowManager.setAppVisibility(r.appToken, true);
   1124                                 r.sleeping = false;
   1125                                 r.app.pendingUiClean = true;
   1126                                 r.app.thread.scheduleWindowVisibility(r.appToken, true);
   1127                                 r.stopFreezingScreenLocked(false);
   1128                             } catch (Exception e) {
   1129                                 // Just skip on any failure; we'll make it
   1130                                 // visible when it next restarts.
   1131                                 Slog.w(TAG, "Exception thrown making visibile: "
   1132                                         + r.intent.getComponent(), e);
   1133                             }
   1134                         }
   1135                     }
   1136 
   1137                     // Aggregate current change flags.
   1138                     configChanges |= r.configChangeFlags;
   1139 
   1140                     if (r.fullscreen) {
   1141                         // At this point, nothing else needs to be shown
   1142                         if (DEBUG_VISBILITY) Slog.v(TAG, "Fullscreen: at " + r);
   1143                         behindFullscreen = true;
   1144                     } else if (isActivityOverHome(r)) {
   1145                         if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r);
   1146                         showHomeBehindStack = true;
   1147                         behindFullscreen = !isHomeStack();
   1148                     }
   1149                 } else {
   1150                     if (DEBUG_VISBILITY) Slog.v(
   1151                         TAG, "Make invisible? " + r + " finishing=" + r.finishing
   1152                         + " state=" + r.state
   1153                         + " behindFullscreen=" + behindFullscreen);
   1154                     // Now for any activities that aren't visible to the user, make
   1155                     // sure they no longer are keeping the screen frozen.
   1156                     if (r.visible) {
   1157                         if (DEBUG_VISBILITY) Slog.v(TAG, "Making invisible: " + r);
   1158                         r.visible = false;
   1159                         try {
   1160                             mWindowManager.setAppVisibility(r.appToken, false);
   1161                             switch (r.state) {
   1162                                 case STOPPING:
   1163                                 case STOPPED:
   1164                                     if (r.app != null && r.app.thread != null) {
   1165                                         if (DEBUG_VISBILITY) Slog.v(
   1166                                                 TAG, "Scheduling invisibility: " + r);
   1167                                         r.app.thread.scheduleWindowVisibility(r.appToken, false);
   1168                                     }
   1169                                     break;
   1170 
   1171                                 case INITIALIZING:
   1172                                 case RESUMED:
   1173                                 case PAUSING:
   1174                                 case PAUSED:
   1175                                     // This case created for transitioning activities from
   1176                                     // translucent to opaque {@link Activity#convertToOpaque}.
   1177                                     if (!mStackSupervisor.mStoppingActivities.contains(r)) {
   1178                                         mStackSupervisor.mStoppingActivities.add(r);
   1179                                     }
   1180                                     mStackSupervisor.scheduleIdleLocked();
   1181                                     break;
   1182 
   1183                                 default:
   1184                                     break;
   1185                             }
   1186                         } catch (Exception e) {
   1187                             // Just skip on any failure; we'll make it
   1188                             // visible when it next restarts.
   1189                             Slog.w(TAG, "Exception thrown making hidden: "
   1190                                     + r.intent.getComponent(), e);
   1191                         }
   1192                     } else {
   1193                         if (DEBUG_VISBILITY) Slog.v(TAG, "Already invisible: " + r);
   1194                     }
   1195                 }
   1196             }
   1197         }
   1198         return showHomeBehindStack;
   1199     }
   1200 
   1201     void convertToTranslucent(ActivityRecord r) {
   1202         mTranslucentActivityWaiting = r;
   1203         mUndrawnActivitiesBelowTopTranslucent.clear();
   1204         mHandler.sendEmptyMessageDelayed(TRANSLUCENT_TIMEOUT_MSG, TRANSLUCENT_CONVERSION_TIMEOUT);
   1205     }
   1206 
   1207     /**
   1208      * Called as activities below the top translucent activity are redrawn. When the last one is
   1209      * redrawn notify the top activity by calling
   1210      * {@link Activity#onTranslucentConversionComplete}.
   1211      *
   1212      * @param r The most recent background activity to be drawn. Or, if r is null then a timeout
   1213      * occurred and the activity will be notified immediately.
   1214      */
   1215     void notifyActivityDrawnLocked(ActivityRecord r) {
   1216         if ((r == null)
   1217                 || (mUndrawnActivitiesBelowTopTranslucent.remove(r) &&
   1218                         mUndrawnActivitiesBelowTopTranslucent.isEmpty())) {
   1219             // The last undrawn activity below the top has just been drawn. If there is an
   1220             // opaque activity at the top, notify it that it can become translucent safely now.
   1221             final ActivityRecord waitingActivity = mTranslucentActivityWaiting;
   1222             mTranslucentActivityWaiting = null;
   1223             mUndrawnActivitiesBelowTopTranslucent.clear();
   1224             mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG);
   1225 
   1226             if (waitingActivity != null && waitingActivity.app != null &&
   1227                     waitingActivity.app.thread != null) {
   1228                 try {
   1229                     waitingActivity.app.thread.scheduleTranslucentConversionComplete(
   1230                             waitingActivity.appToken, r != null);
   1231                 } catch (RemoteException e) {
   1232                 }
   1233             }
   1234         }
   1235     }
   1236 
   1237     /**
   1238      * Ensure that the top activity in the stack is resumed.
   1239      *
   1240      * @param prev The previously resumed activity, for when in the process
   1241      * of pausing; can be null to call from elsewhere.
   1242      *
   1243      * @return Returns true if something is being resumed, or false if
   1244      * nothing happened.
   1245      */
   1246     final boolean resumeTopActivityLocked(ActivityRecord prev) {
   1247         return resumeTopActivityLocked(prev, null);
   1248     }
   1249 
   1250     final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
   1251         if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
   1252 
   1253         // Find the first activity that is not finishing.
   1254         ActivityRecord next = topRunningActivityLocked(null);
   1255 
   1256         // Remember how we'll process this pause/resume situation, and ensure
   1257         // that the state is reset however we wind up proceeding.
   1258         final boolean userLeaving = mStackSupervisor.mUserLeaving;
   1259         mStackSupervisor.mUserLeaving = false;
   1260 
   1261         if (next == null) {
   1262             // There are no more activities!  Let's just start up the
   1263             // Launcher...
   1264             ActivityOptions.abort(options);
   1265             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
   1266             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
   1267             return mStackSupervisor.resumeHomeActivity(prev);
   1268         }
   1269 
   1270         next.delayedResume = false;
   1271 
   1272         // If the top activity is the resumed one, nothing to do.
   1273         if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
   1274                     mStackSupervisor.allResumedActivitiesComplete()) {
   1275             // Make sure we have executed any pending transitions, since there
   1276             // should be nothing left to do at this point.
   1277             mWindowManager.executeAppTransition();
   1278             mNoAnimActivities.clear();
   1279             ActivityOptions.abort(options);
   1280             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Top activity resumed " + next);
   1281             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
   1282             return false;
   1283         }
   1284 
   1285         final TaskRecord nextTask = next.task;
   1286         final TaskRecord prevTask = prev != null ? prev.task : null;
   1287         if (prevTask != null && prevTask.mOnTopOfHome && prev.finishing && prev.frontOfTask) {
   1288             if (DEBUG_STACK)  mStackSupervisor.validateTopActivitiesLocked();
   1289             if (prevTask == nextTask) {
   1290                 ArrayList<ActivityRecord> activities = prevTask.mActivities;
   1291                 final int numActivities = activities.size();
   1292                 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
   1293                     final ActivityRecord r = activities.get(activityNdx);
   1294                     // r is usually the same as next, but what if two activities were launched
   1295                     // before prev finished?
   1296                     if (!r.finishing) {
   1297                         r.frontOfTask = true;
   1298                         break;
   1299                     }
   1300                 }
   1301             } else if (prevTask != topTask()) {
   1302                 // This task is going away but it was supposed to return to the home task.
   1303                 // Now the task above it has to return to the home task instead.
   1304                 final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
   1305                 mTaskHistory.get(taskNdx).mOnTopOfHome = true;
   1306             } else {
   1307                 if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Launching home next");
   1308                 return mStackSupervisor.resumeHomeActivity(prev);
   1309             }
   1310         }
   1311 
   1312         // If we are sleeping, and there is no resumed activity, and the top
   1313         // activity is paused, well that is the state we want.
   1314         if (mService.isSleepingOrShuttingDown()
   1315                 && mLastPausedActivity == next
   1316                 && mStackSupervisor.allPausedActivitiesComplete()) {
   1317             // Make sure we have executed any pending transitions, since there
   1318             // should be nothing left to do at this point.
   1319             mWindowManager.executeAppTransition();
   1320             mNoAnimActivities.clear();
   1321             ActivityOptions.abort(options);
   1322             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Going to sleep and all paused");
   1323             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
   1324             return false;
   1325         }
   1326 
   1327         // Make sure that the user who owns this activity is started.  If not,
   1328         // we will just leave it as is because someone should be bringing
   1329         // another user's activities to the top of the stack.
   1330         if (mService.mStartedUsers.get(next.userId) == null) {
   1331             Slog.w(TAG, "Skipping resume of top activity " + next
   1332                     + ": user " + next.userId + " is stopped");
   1333             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
   1334             return false;
   1335         }
   1336 
   1337         // The activity may be waiting for stop, but that is no longer
   1338         // appropriate for it.
   1339         mStackSupervisor.mStoppingActivities.remove(next);
   1340         mStackSupervisor.mGoingToSleepActivities.remove(next);
   1341         next.sleeping = false;
   1342         mStackSupervisor.mWaitingVisibleActivities.remove(next);
   1343 
   1344         next.updateOptionsLocked(options);
   1345 
   1346         if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
   1347 
   1348         // If we are currently pausing an activity, then don't do anything
   1349         // until that is done.
   1350         if (!mStackSupervisor.allPausedActivitiesComplete()) {
   1351             if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG,
   1352                     "resumeTopActivityLocked: Skip resume: some activity pausing.");
   1353             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
   1354             return false;
   1355         }
   1356 
   1357         // Okay we are now going to start a switch, to 'next'.  We may first
   1358         // have to pause the current activity, but this is an important point
   1359         // where we have decided to go to 'next' so keep track of that.
   1360         // XXX "App Redirected" dialog is getting too many false positives
   1361         // at this point, so turn off for now.
   1362         if (false) {
   1363             if (mLastStartedActivity != null && !mLastStartedActivity.finishing) {
   1364                 long now = SystemClock.uptimeMillis();
   1365                 final boolean inTime = mLastStartedActivity.startTime != 0
   1366                         && (mLastStartedActivity.startTime + START_WARN_TIME) >= now;
   1367                 final int lastUid = mLastStartedActivity.info.applicationInfo.uid;
   1368                 final int nextUid = next.info.applicationInfo.uid;
   1369                 if (inTime && lastUid != nextUid
   1370                         && lastUid != next.launchedFromUid
   1371                         && mService.checkPermission(
   1372                                 android.Manifest.permission.STOP_APP_SWITCHES,
   1373                                 -1, next.launchedFromUid)
   1374                         != PackageManager.PERMISSION_GRANTED) {
   1375                     mService.showLaunchWarningLocked(mLastStartedActivity, next);
   1376                 } else {
   1377                     next.startTime = now;
   1378                     mLastStartedActivity = next;
   1379                 }
   1380             } else {
   1381                 next.startTime = SystemClock.uptimeMillis();
   1382                 mLastStartedActivity = next;
   1383             }
   1384         }
   1385 
   1386         // We need to start pausing the current activity so the top one
   1387         // can be resumed...
   1388         boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving);
   1389         if (mResumedActivity != null) {
   1390             pausing = true;
   1391             startPausingLocked(userLeaving, false);
   1392             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);
   1393         }
   1394         if (pausing) {
   1395             if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG,
   1396                     "resumeTopActivityLocked: Skip resume: need to start pausing");
   1397             // At this point we want to put the upcoming activity's process
   1398             // at the top of the LRU list, since we know we will be needing it
   1399             // very soon and it would be a waste to let it get killed if it
   1400             // happens to be sitting towards the end.
   1401             if (next.app != null && next.app.thread != null) {
   1402                 // No reason to do full oom adj update here; we'll let that
   1403                 // happen whenever it needs to later.
   1404                 mService.updateLruProcessLocked(next.app, true, null);
   1405             }
   1406             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
   1407             return true;
   1408         }
   1409 
   1410         // If the most recent activity was noHistory but was only stopped rather
   1411         // than stopped+finished because the device went to sleep, we need to make
   1412         // sure to finish it as we're making a new activity topmost.
   1413         if (mService.mSleeping && mLastNoHistoryActivity != null &&
   1414                 !mLastNoHistoryActivity.finishing) {
   1415             if (DEBUG_STATES) Slog.d(TAG, "no-history finish of " + mLastNoHistoryActivity +
   1416                     " on new resume");
   1417             requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
   1418                     null, "no-history", false);
   1419             mLastNoHistoryActivity = null;
   1420         }
   1421 
   1422         if (prev != null && prev != next) {
   1423             if (!prev.waitingVisible && next != null && !next.nowVisible) {
   1424                 prev.waitingVisible = true;
   1425                 mStackSupervisor.mWaitingVisibleActivities.add(prev);
   1426                 if (DEBUG_SWITCH) Slog.v(
   1427                         TAG, "Resuming top, waiting visible to hide: " + prev);
   1428             } else {
   1429                 // The next activity is already visible, so hide the previous
   1430                 // activity's windows right now so we can show the new one ASAP.
   1431                 // We only do this if the previous is finishing, which should mean
   1432                 // it is on top of the one being resumed so hiding it quickly
   1433                 // is good.  Otherwise, we want to do the normal route of allowing
   1434                 // the resumed activity to be shown so we can decide if the
   1435                 // previous should actually be hidden depending on whether the
   1436                 // new one is found to be full-screen or not.
   1437                 if (prev.finishing) {
   1438                     mWindowManager.setAppVisibility(prev.appToken, false);
   1439                     if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
   1440                             + prev + ", waitingVisible="
   1441                             + (prev != null ? prev.waitingVisible : null)
   1442                             + ", nowVisible=" + next.nowVisible);
   1443                 } else {
   1444                     if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
   1445                         + prev + ", waitingVisible="
   1446                         + (prev != null ? prev.waitingVisible : null)
   1447                         + ", nowVisible=" + next.nowVisible);
   1448                 }
   1449             }
   1450         }
   1451 
   1452         // Launching this app's activity, make sure the app is no longer
   1453         // considered stopped.
   1454         try {
   1455             AppGlobals.getPackageManager().setPackageStoppedState(
   1456                     next.packageName, false, next.userId); /* TODO: Verify if correct userid */
   1457         } catch (RemoteException e1) {
   1458         } catch (IllegalArgumentException e) {
   1459             Slog.w(TAG, "Failed trying to unstop package "
   1460                     + next.packageName + ": " + e);
   1461         }
   1462 
   1463         // We are starting up the next activity, so tell the window manager
   1464         // that the previous one will be hidden soon.  This way it can know
   1465         // to ignore it when computing the desired screen orientation.
   1466         boolean anim = true;
   1467         if (prev != null) {
   1468             if (prev.finishing) {
   1469                 if (DEBUG_TRANSITION) Slog.v(TAG,
   1470                         "Prepare close transition: prev=" + prev);
   1471                 if (mNoAnimActivities.contains(prev)) {
   1472                     anim = false;
   1473                     mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
   1474                 } else {
   1475                     mWindowManager.prepareAppTransition(prev.task == next.task
   1476                             ? AppTransition.TRANSIT_ACTIVITY_CLOSE
   1477                             : AppTransition.TRANSIT_TASK_CLOSE, false);
   1478                 }
   1479                 mWindowManager.setAppWillBeHidden(prev.appToken);
   1480                 mWindowManager.setAppVisibility(prev.appToken, false);
   1481             } else {
   1482                 if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: prev=" + prev);
   1483                 if (mNoAnimActivities.contains(next)) {
   1484                     anim = false;
   1485                     mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
   1486                 } else {
   1487                     mWindowManager.prepareAppTransition(prev.task == next.task
   1488                             ? AppTransition.TRANSIT_ACTIVITY_OPEN
   1489                             : AppTransition.TRANSIT_TASK_OPEN, false);
   1490                 }
   1491             }
   1492             if (false) {
   1493                 mWindowManager.setAppWillBeHidden(prev.appToken);
   1494                 mWindowManager.setAppVisibility(prev.appToken, false);
   1495             }
   1496         } else {
   1497             if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: no previous");
   1498             if (mNoAnimActivities.contains(next)) {
   1499                 anim = false;
   1500                 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
   1501             } else {
   1502                 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_OPEN, false);
   1503             }
   1504         }
   1505         if (anim) {
   1506             next.applyOptionsLocked();
   1507         } else {
   1508             next.clearOptionsLocked();
   1509         }
   1510 
   1511         ActivityStack lastStack = mStackSupervisor.getLastStack();
   1512         if (next.app != null && next.app.thread != null) {
   1513             if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
   1514 
   1515             // This activity is now becoming visible.
   1516             mWindowManager.setAppVisibility(next.appToken, true);
   1517 
   1518             // schedule launch ticks to collect information about slow apps.
   1519             next.startLaunchTickingLocked();
   1520 
   1521             ActivityRecord lastResumedActivity =
   1522                     lastStack == null ? null :lastStack.mResumedActivity;
   1523             ActivityState lastState = next.state;
   1524 
   1525             mService.updateCpuStats();
   1526 
   1527             if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + next + " (in existing)");
   1528             next.state = ActivityState.RESUMED;
   1529             mResumedActivity = next;
   1530             next.task.touchActiveTime();
   1531             mService.addRecentTaskLocked(next.task);
   1532             mService.updateLruProcessLocked(next.app, true, null);
   1533             updateLRUListLocked(next);
   1534             mService.updateOomAdjLocked();
   1535 
   1536             // Have the window manager re-evaluate the orientation of
   1537             // the screen based on the new activity order.
   1538             boolean notUpdated = true;
   1539             if (mStackSupervisor.isFrontStack(this)) {
   1540                 Configuration config = mWindowManager.updateOrientationFromAppTokens(
   1541                         mService.mConfiguration,
   1542                         next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
   1543                 if (config != null) {
   1544                     next.frozenBeforeDestroy = true;
   1545                 }
   1546                 notUpdated = !mService.updateConfigurationLocked(config, next, false, false);
   1547             }
   1548 
   1549             if (notUpdated) {
   1550                 // The configuration update wasn't able to keep the existing
   1551                 // instance of the activity, and instead started a new one.
   1552                 // We should be all done, but let's just make sure our activity
   1553                 // is still at the top and schedule another run if something
   1554                 // weird happened.
   1555                 ActivityRecord nextNext = topRunningActivityLocked(null);
   1556                 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
   1557                         "Activity config changed during resume: " + next
   1558                         + ", new next: " + nextNext);
   1559                 if (nextNext != next) {
   1560                     // Do over!
   1561                     mStackSupervisor.scheduleResumeTopActivities();
   1562                 }
   1563                 if (mStackSupervisor.reportResumedActivityLocked(next)) {
   1564                     mNoAnimActivities.clear();
   1565                     if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
   1566                     return true;
   1567                 }
   1568                 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
   1569                 return false;
   1570             }
   1571 
   1572             try {
   1573                 // Deliver all pending results.
   1574                 ArrayList<ResultInfo> a = next.results;
   1575                 if (a != null) {
   1576                     final int N = a.size();
   1577                     if (!next.finishing && N > 0) {
   1578                         if (DEBUG_RESULTS) Slog.v(
   1579                                 TAG, "Delivering results to " + next
   1580                                 + ": " + a);
   1581                         next.app.thread.scheduleSendResult(next.appToken, a);
   1582                     }
   1583                 }
   1584 
   1585                 if (next.newIntents != null) {
   1586                     next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
   1587                 }
   1588 
   1589                 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
   1590                         next.userId, System.identityHashCode(next),
   1591                         next.task.taskId, next.shortComponentName);
   1592 
   1593                 next.sleeping = false;
   1594                 mService.showAskCompatModeDialogLocked(next);
   1595                 next.app.pendingUiClean = true;
   1596                 next.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
   1597                 next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
   1598                         mService.isNextTransitionForward());
   1599 
   1600                 mStackSupervisor.checkReadyForSleepLocked();
   1601 
   1602                 if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Resumed " + next);
   1603             } catch (Exception e) {
   1604                 // Whoops, need to restart this activity!
   1605                 if (DEBUG_STATES) Slog.v(TAG, "Resume failed; resetting state to "
   1606                         + lastState + ": " + next);
   1607                 next.state = lastState;
   1608                 if (lastStack != null) {
   1609                     lastStack.mResumedActivity = lastResumedActivity;
   1610                 }
   1611                 Slog.i(TAG, "Restarting because process died: " + next);
   1612                 if (!next.hasBeenLaunched) {
   1613                     next.hasBeenLaunched = true;
   1614                 } else  if (SHOW_APP_STARTING_PREVIEW && lastStack != null &&
   1615                         mStackSupervisor.isFrontStack(lastStack)) {
   1616                     mWindowManager.setAppStartingWindow(
   1617                             next.appToken, next.packageName, next.theme,
   1618                             mService.compatibilityInfoForPackageLocked(next.info.applicationInfo),
   1619                             next.nonLocalizedLabel, next.labelRes, next.icon, next.logo,
   1620                             next.windowFlags, null, true);
   1621                 }
   1622                 mStackSupervisor.startSpecificActivityLocked(next, true, false);
   1623                 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
   1624                 return true;
   1625             }
   1626 
   1627             // From this point on, if something goes wrong there is no way
   1628             // to recover the activity.
   1629             try {
   1630                 next.visible = true;
   1631                 completeResumeLocked(next);
   1632             } catch (Exception e) {
   1633                 // If any exception gets thrown, toss away this
   1634                 // activity and try the next one.
   1635                 Slog.w(TAG, "Exception thrown during resume of " + next, e);
   1636                 requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
   1637                         "resume-exception", true);
   1638                 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
   1639                 return true;
   1640             }
   1641             next.stopped = false;
   1642 
   1643         } else {
   1644             // Whoops, need to restart this activity!
   1645             if (!next.hasBeenLaunched) {
   1646                 next.hasBeenLaunched = true;
   1647             } else {
   1648                 if (SHOW_APP_STARTING_PREVIEW) {
   1649                     mWindowManager.setAppStartingWindow(
   1650                             next.appToken, next.packageName, next.theme,
   1651                             mService.compatibilityInfoForPackageLocked(
   1652                                     next.info.applicationInfo),
   1653                             next.nonLocalizedLabel,
   1654                             next.labelRes, next.icon, next.logo, next.windowFlags,
   1655                             null, true);
   1656                 }
   1657                 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
   1658             }
   1659             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Restarting " + next);
   1660             mStackSupervisor.startSpecificActivityLocked(next, true, true);
   1661         }
   1662 
   1663         if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
   1664         return true;
   1665     }
   1666 
   1667     private void insertTaskAtTop(TaskRecord task) {
   1668         // If this is being moved to the top by another activity or being launched from the home
   1669         // activity, set mOnTopOfHome accordingly.
   1670         ActivityStack lastStack = mStackSupervisor.getLastStack();
   1671         final boolean fromHome = lastStack == null ? true : lastStack.isHomeStack();
   1672         if (!isHomeStack() && (fromHome || topTask() != task)) {
   1673             task.mOnTopOfHome = fromHome;
   1674         }
   1675 
   1676         mTaskHistory.remove(task);
   1677         // Now put task at top.
   1678         int stackNdx = mTaskHistory.size();
   1679         if (task.userId != mCurrentUser) {
   1680             // Put non-current user tasks below current user tasks.
   1681             while (--stackNdx >= 0) {
   1682                 if (mTaskHistory.get(stackNdx).userId != mCurrentUser) {
   1683                     break;
   1684                 }
   1685             }
   1686             ++stackNdx;
   1687         }
   1688         mTaskHistory.add(stackNdx, task);
   1689     }
   1690 
   1691     final void startActivityLocked(ActivityRecord r, boolean newTask,
   1692             boolean doResume, boolean keepCurTransition, Bundle options) {
   1693         TaskRecord rTask = r.task;
   1694         final int taskId = rTask.taskId;
   1695         if (taskForIdLocked(taskId) == null || newTask) {
   1696             // Last activity in task had been removed or ActivityManagerService is reusing task.
   1697             // Insert or replace.
   1698             // Might not even be in.
   1699             insertTaskAtTop(rTask);
   1700             mWindowManager.moveTaskToTop(taskId);
   1701         }
   1702         TaskRecord task = null;
   1703         if (!newTask) {
   1704             // If starting in an existing task, find where that is...
   1705             boolean startIt = true;
   1706             for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
   1707                 task = mTaskHistory.get(taskNdx);
   1708                 if (task == r.task) {
   1709                     // Here it is!  Now, if this is not yet visible to the
   1710                     // user, then just add it without starting; it will
   1711                     // get started when the user navigates back to it.
   1712                     if (!startIt) {
   1713                         if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
   1714                                 + task, new RuntimeException("here").fillInStackTrace());
   1715                         task.addActivityToTop(r);
   1716                         r.putInHistory();
   1717                         mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
   1718                                 r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
   1719                                 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
   1720                                 r.userId, r.info.configChanges);
   1721                         if (VALIDATE_TOKENS) {
   1722                             validateAppTokensLocked();
   1723                         }
   1724                         ActivityOptions.abort(options);
   1725                         return;
   1726                     }
   1727                     break;
   1728                 } else if (task.numFullscreen > 0) {
   1729                     startIt = false;
   1730                 }
   1731             }
   1732         }
   1733 
   1734         // Place a new activity at top of stack, so it is next to interact
   1735         // with the user.
   1736 
   1737         // If we are not placing the new activity frontmost, we do not want
   1738         // to deliver the onUserLeaving callback to the actual frontmost
   1739         // activity
   1740         if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
   1741             mStackSupervisor.mUserLeaving = false;
   1742             if (DEBUG_USER_LEAVING) Slog.v(TAG,
   1743                     "startActivity() behind front, mUserLeaving=false");
   1744         }
   1745 
   1746         task = r.task;
   1747 
   1748         // Slot the activity into the history stack and proceed
   1749         if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
   1750                 new RuntimeException("here").fillInStackTrace());
   1751         task.addActivityToTop(r);
   1752 
   1753         r.putInHistory();
   1754         r.frontOfTask = newTask;
   1755         if (!isHomeStack() || numActivities() > 0) {
   1756             // We want to show the starting preview window if we are
   1757             // switching to a new task, or the next activity's process is
   1758             // not currently running.
   1759             boolean showStartingIcon = newTask;
   1760             ProcessRecord proc = r.app;
   1761             if (proc == null) {
   1762                 proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
   1763             }
   1764             if (proc == null || proc.thread == null) {
   1765                 showStartingIcon = true;
   1766             }
   1767             if (DEBUG_TRANSITION) Slog.v(TAG,
   1768                     "Prepare open transition: starting " + r);
   1769             if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
   1770                 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, keepCurTransition);
   1771                 mNoAnimActivities.add(r);
   1772             } else {
   1773                 mWindowManager.prepareAppTransition(newTask
   1774                         ? AppTransition.TRANSIT_TASK_OPEN
   1775                         : AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
   1776                 mNoAnimActivities.remove(r);
   1777             }
   1778             r.updateOptionsLocked(options);
   1779             mWindowManager.addAppToken(task.mActivities.indexOf(r),
   1780                     r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
   1781                     (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId,
   1782                     r.info.configChanges);
   1783             boolean doShow = true;
   1784             if (newTask) {
   1785                 // Even though this activity is starting fresh, we still need
   1786                 // to reset it to make sure we apply affinities to move any
   1787                 // existing activities from other tasks in to it.
   1788                 // If the caller has requested that the target task be
   1789                 // reset, then do so.
   1790                 if ((r.intent.getFlags()
   1791                         &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
   1792                     resetTaskIfNeededLocked(r, r);
   1793                     doShow = topRunningNonDelayedActivityLocked(null) == r;
   1794                 }
   1795             }
   1796             if (SHOW_APP_STARTING_PREVIEW && doShow) {
   1797                 // Figure out if we are transitioning from another activity that is
   1798                 // "has the same starting icon" as the next one.  This allows the
   1799                 // window manager to keep the previous window it had previously
   1800                 // created, if it still had one.
   1801                 ActivityRecord prev = mResumedActivity;
   1802                 if (prev != null) {
   1803                     // We don't want to reuse the previous starting preview if:
   1804                     // (1) The current activity is in a different task.
   1805                     if (prev.task != r.task) {
   1806                         prev = null;
   1807                     }
   1808                     // (2) The current activity is already displayed.
   1809                     else if (prev.nowVisible) {
   1810                         prev = null;
   1811                     }
   1812                 }
   1813                 mWindowManager.setAppStartingWindow(
   1814                         r.appToken, r.packageName, r.theme,
   1815                         mService.compatibilityInfoForPackageLocked(
   1816                                 r.info.applicationInfo), r.nonLocalizedLabel,
   1817                         r.labelRes, r.icon, r.logo, r.windowFlags,
   1818                         prev != null ? prev.appToken : null, showStartingIcon);
   1819             }
   1820         } else {
   1821             // If this is the first activity, don't do any fancy animations,
   1822             // because there is nothing for it to animate on top of.
   1823             mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
   1824                     r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
   1825                     (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId,
   1826                     r.info.configChanges);
   1827             ActivityOptions.abort(options);
   1828         }
   1829         if (VALIDATE_TOKENS) {
   1830             validateAppTokensLocked();
   1831         }
   1832 
   1833         if (doResume) {
   1834             mStackSupervisor.resumeTopActivitiesLocked();
   1835         }
   1836     }
   1837 
   1838     final void validateAppTokensLocked() {
   1839         mValidateAppTokens.clear();
   1840         mValidateAppTokens.ensureCapacity(numActivities());
   1841         final int numTasks = mTaskHistory.size();
   1842         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
   1843             TaskRecord task = mTaskHistory.get(taskNdx);
   1844             final ArrayList<ActivityRecord> activities = task.mActivities;
   1845             if (activities.isEmpty()) {
   1846                 continue;
   1847             }
   1848             TaskGroup group = new TaskGroup();
   1849             group.taskId = task.taskId;
   1850             mValidateAppTokens.add(group);
   1851             final int numActivities = activities.size();
   1852             for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
   1853                 final ActivityRecord r = activities.get(activityNdx);
   1854                 group.tokens.add(r.appToken);
   1855             }
   1856         }
   1857         mWindowManager.validateAppTokens(mStackId, mValidateAppTokens);
   1858     }
   1859 
   1860     /**
   1861      * Perform a reset of the given task, if needed as part of launching it.
   1862      * Returns the new HistoryRecord at the top of the task.
   1863      */
   1864     /**
   1865      * Helper method for #resetTaskIfNeededLocked.
   1866      * We are inside of the task being reset...  we'll either finish this activity, push it out
   1867      * for another task, or leave it as-is.
   1868      * @param task The task containing the Activity (taskTop) that might be reset.
   1869      * @param forceReset
   1870      * @return An ActivityOptions that needs to be processed.
   1871      */
   1872     final ActivityOptions resetTargetTaskIfNeededLocked(TaskRecord task, boolean forceReset) {
   1873         ActivityOptions topOptions = null;
   1874 
   1875         int replyChainEnd = -1;
   1876         boolean canMoveOptions = true;
   1877 
   1878         // We only do this for activities that are not the root of the task (since if we finish
   1879         // the root, we may no longer have the task!).
   1880         final ArrayList<ActivityRecord> activities = task.mActivities;
   1881         final int numActivities = activities.size();
   1882         for (int i = numActivities - 1; i > 0; --i ) {
   1883             ActivityRecord target = activities.get(i);
   1884 
   1885             final int flags = target.info.flags;
   1886             final boolean finishOnTaskLaunch =
   1887                     (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
   1888             final boolean allowTaskReparenting =
   1889                     (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
   1890             final boolean clearWhenTaskReset =
   1891                     (target.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
   1892 
   1893             if (!finishOnTaskLaunch
   1894                     && !clearWhenTaskReset
   1895                     && target.resultTo != null) {
   1896                 // If this activity is sending a reply to a previous
   1897                 // activity, we can't do anything with it now until
   1898                 // we reach the start of the reply chain.
   1899                 // XXX note that we are assuming the result is always
   1900                 // to the previous activity, which is almost always
   1901                 // the case but we really shouldn't count on.
   1902                 if (replyChainEnd < 0) {
   1903                     replyChainEnd = i;
   1904                 }
   1905             } else if (!finishOnTaskLaunch
   1906                     && !clearWhenTaskReset
   1907                     && allowTaskReparenting
   1908                     && target.taskAffinity != null
   1909                     && !target.taskAffinity.equals(task.affinity)) {
   1910                 // If this activity has an affinity for another
   1911                 // task, then we need to move it out of here.  We will
   1912                 // move it as far out of the way as possible, to the
   1913                 // bottom of the activity stack.  This also keeps it
   1914                 // correctly ordered with any activities we previously
   1915                 // moved.
   1916                 final ThumbnailHolder newThumbHolder;
   1917                 final TaskRecord targetTask;
   1918                 final ActivityRecord bottom =
   1919                         !mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ?
   1920                                 mTaskHistory.get(0).mActivities.get(0) : null;
   1921                 if (bottom != null && target.taskAffinity != null
   1922                         && target.taskAffinity.equals(bottom.task.affinity)) {
   1923                     // If the activity currently at the bottom has the
   1924                     // same task affinity as the one we are moving,
   1925                     // then merge it into the same task.
   1926                     targetTask = bottom.task;
   1927                     newThumbHolder = bottom.thumbHolder == null ? targetTask : bottom.thumbHolder;
   1928                     if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
   1929                             + " out to bottom task " + bottom.task);
   1930                 } else {
   1931                     targetTask = createTaskRecord(mStackSupervisor.getNextTaskId(), target.info,
   1932                             null, false);
   1933                     newThumbHolder = targetTask;
   1934                     targetTask.affinityIntent = target.intent;
   1935                     if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
   1936                             + " out to new task " + target.task);
   1937                 }
   1938 
   1939                 if (clearWhenTaskReset) {
   1940                     // This is the start of a new sub-task.
   1941                     if (target.thumbHolder == null) {
   1942                         target.thumbHolder = new ThumbnailHolder();
   1943                     }
   1944                 } else {
   1945                     target.thumbHolder = newThumbHolder;
   1946                 }
   1947 
   1948                 final int targetTaskId = targetTask.taskId;
   1949                 mWindowManager.setAppGroupId(target.appToken, targetTaskId);
   1950 
   1951                 boolean noOptions = canMoveOptions;
   1952                 final int start = replyChainEnd < 0 ? i : replyChainEnd;
   1953                 for (int srcPos = start; srcPos >= i; --srcPos) {
   1954                     final ActivityRecord p = activities.get(srcPos);
   1955                     if (p.finishing) {
   1956                         continue;
   1957                     }
   1958 
   1959                     ThumbnailHolder curThumbHolder = p.thumbHolder;
   1960                     canMoveOptions = false;
   1961                     if (noOptions && topOptions == null) {
   1962                         topOptions = p.takeOptionsLocked();
   1963                         if (topOptions != null) {
   1964                             noOptions = false;
   1965                         }
   1966                     }
   1967                     if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing activity " + p + " from task="
   1968                             + task + " adding to task=" + targetTask
   1969                             + " Callers=" + Debug.getCallers(4));
   1970                     if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
   1971                             + " out to target's task " + target.task);
   1972                     p.setTask(targetTask, curThumbHolder, false);
   1973                     targetTask.addActivityAtBottom(p);
   1974 
   1975                     mWindowManager.setAppGroupId(p.appToken, targetTaskId);
   1976                 }
   1977 
   1978                 mWindowManager.moveTaskToBottom(targetTaskId);
   1979                 if (VALIDATE_TOKENS) {
   1980                     validateAppTokensLocked();
   1981                 }
   1982 
   1983                 replyChainEnd = -1;
   1984             } else if (forceReset || finishOnTaskLaunch || clearWhenTaskReset) {
   1985                 // If the activity should just be removed -- either
   1986                 // because it asks for it, or the task should be
   1987                 // cleared -- then finish it and anything that is
   1988                 // part of its reply chain.
   1989                 int end;
   1990                 if (clearWhenTaskReset) {
   1991                     // In this case, we want to finish this activity
   1992                     // and everything above it, so be sneaky and pretend
   1993                     // like these are all in the reply chain.
   1994                     end = numActivities - 1;
   1995                 } else if (replyChainEnd < 0) {
   1996                     end = i;
   1997                 } else {
   1998                     end = replyChainEnd;
   1999                 }
   2000                 boolean noOptions = canMoveOptions;
   2001                 for (int srcPos = i; srcPos <= end; srcPos++) {
   2002                     ActivityRecord p = activities.get(srcPos);
   2003                     if (p.finishing) {
   2004                         continue;
   2005                     }
   2006                     canMoveOptions = false;
   2007                     if (noOptions && topOptions == null) {
   2008                         topOptions = p.takeOptionsLocked();
   2009                         if (topOptions != null) {
   2010                             noOptions = false;
   2011                         }
   2012                     }
   2013                     if (DEBUG_TASKS) Slog.w(TAG,
   2014                             "resetTaskIntendedTask: calling finishActivity on " + p);
   2015                     if (finishActivityLocked(p, Activity.RESULT_CANCELED, null, "reset", false)) {
   2016                         end--;
   2017                         srcPos--;
   2018                     }
   2019                 }
   2020                 replyChainEnd = -1;
   2021             } else {
   2022                 // If we were in the middle of a chain, well the
   2023                 // activity that started it all doesn't want anything
   2024                 // special, so leave it all as-is.
   2025                 replyChainEnd = -1;
   2026             }
   2027         }
   2028 
   2029         return topOptions;
   2030     }
   2031 
   2032     /**
   2033      * Helper method for #resetTaskIfNeededLocked. Processes all of the activities in a given
   2034      * TaskRecord looking for an affinity with the task of resetTaskIfNeededLocked.taskTop.
   2035      * @param affinityTask The task we are looking for an affinity to.
   2036      * @param task Task that resetTaskIfNeededLocked.taskTop belongs to.
   2037      * @param topTaskIsHigher True if #task has already been processed by resetTaskIfNeededLocked.
   2038      * @param forceReset Flag passed in to resetTaskIfNeededLocked.
   2039      */
   2040     private int resetAffinityTaskIfNeededLocked(TaskRecord affinityTask, TaskRecord task,
   2041             boolean topTaskIsHigher, boolean forceReset, int taskInsertionPoint) {
   2042         int replyChainEnd = -1;
   2043         final int taskId = task.taskId;
   2044         final String taskAffinity = task.affinity;
   2045 
   2046         final ArrayList<ActivityRecord> activities = affinityTask.mActivities;
   2047         final int numActivities = activities.size();
   2048         // Do not operate on the root Activity.
   2049         for (int i = numActivities - 1; i > 0; --i) {
   2050             ActivityRecord target = activities.get(i);
   2051 
   2052             final int flags = target.info.flags;
   2053             boolean finishOnTaskLaunch = (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
   2054             boolean allowTaskReparenting = (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
   2055 
   2056             if (target.resultTo != null) {
   2057                 // If this activity is sending a reply to a previous
   2058                 // activity, we can't do anything with it now until
   2059                 // we reach the start of the reply chain.
   2060                 // XXX note that we are assuming the result is always
   2061                 // to the previous activity, which is almost always
   2062                 // the case but we really shouldn't count on.
   2063                 if (replyChainEnd < 0) {
   2064                     replyChainEnd = i;
   2065                 }
   2066             } else if (topTaskIsHigher
   2067                     && allowTaskReparenting
   2068                     && taskAffinity != null
   2069                     && taskAffinity.equals(target.taskAffinity)) {
   2070                 // This activity has an affinity for our task. Either remove it if we are
   2071                 // clearing or move it over to our task.  Note that
   2072                 // we currently punt on the case where we are resetting a
   2073                 // task that is not at the top but who has activities above
   2074                 // with an affinity to it...  this is really not a normal
   2075                 // case, and we will need to later pull that task to the front
   2076                 // and usually at that point we will do the reset and pick
   2077                 // up those remaining activities.  (This only happens if
   2078                 // someone starts an activity in a new task from an activity
   2079                 // in a task that is not currently on top.)
   2080                 if (forceReset || finishOnTaskLaunch) {
   2081                     final int start = replyChainEnd >= 0 ? replyChainEnd : i;
   2082                     if (DEBUG_TASKS) Slog.v(TAG, "Finishing task at index " + start + " to " + i);
   2083                     for (int srcPos = start; srcPos >= i; --srcPos) {
   2084                         final ActivityRecord p = activities.get(srcPos);
   2085                         if (p.finishing) {
   2086                             continue;
   2087                         }
   2088                         finishActivityLocked(p, Activity.RESULT_CANCELED, null, "reset", false);
   2089                     }
   2090                 } else {
   2091                     if (taskInsertionPoint < 0) {
   2092                         taskInsertionPoint = task.mActivities.size();
   2093 
   2094                     }
   2095 
   2096                     final int start = replyChainEnd >= 0 ? replyChainEnd : i;
   2097                     if (DEBUG_TASKS) Slog.v(TAG, "Reparenting from task=" + affinityTask + ":"
   2098                             + start + "-" + i + " to task=" + task + ":" + taskInsertionPoint);
   2099                     for (int srcPos = start; srcPos >= i; --srcPos) {
   2100                         final ActivityRecord p = activities.get(srcPos);
   2101                         p.setTask(task, null, false);
   2102                         task.addActivityAtIndex(taskInsertionPoint, p);
   2103 
   2104                         if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing and adding activity " + p
   2105                                 + " to stack at " + task,
   2106                                 new RuntimeException("here").fillInStackTrace());
   2107                         if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p + " from " + srcPos
   2108                                 + " in to resetting task " + task);
   2109                         mWindowManager.setAppGroupId(p.appToken, taskId);
   2110                     }
   2111                     mWindowManager.moveTaskToTop(taskId);
   2112                     if (VALIDATE_TOKENS) {
   2113                         validateAppTokensLocked();
   2114                     }
   2115 
   2116                     // Now we've moved it in to place...  but what if this is
   2117                     // a singleTop activity and we have put it on top of another
   2118                     // instance of the same activity?  Then we drop the instance
   2119                     // below so it remains singleTop.
   2120                     if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
   2121                         ArrayList<ActivityRecord> taskActivities = task.mActivities;
   2122                         int targetNdx = taskActivities.indexOf(target);
   2123                         if (targetNdx > 0) {
   2124                             ActivityRecord p = taskActivities.get(targetNdx - 1);
   2125                             if (p.intent.getComponent().equals(target.intent.getComponent())) {
   2126                                 finishActivityLocked(p, Activity.RESULT_CANCELED, null, "replace",
   2127                                         false);
   2128                             }
   2129                         }
   2130                     }
   2131                 }
   2132 
   2133                 replyChainEnd = -1;
   2134             }
   2135         }
   2136         return taskInsertionPoint;
   2137     }
   2138 
   2139     final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
   2140             ActivityRecord newActivity) {
   2141         boolean forceReset =
   2142                 (newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
   2143         if (ACTIVITY_INACTIVE_RESET_TIME > 0
   2144                 && taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
   2145             if ((newActivity.info.flags & ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
   2146                 forceReset = true;
   2147             }
   2148         }
   2149 
   2150         final TaskRecord task = taskTop.task;
   2151 
   2152         /** False until we evaluate the TaskRecord associated with taskTop. Switches to true
   2153          * for remaining tasks. Used for later tasks to reparent to task. */
   2154         boolean taskFound = false;
   2155 
   2156         /** If ActivityOptions are moved out and need to be aborted or moved to taskTop. */
   2157         ActivityOptions topOptions = null;
   2158 
   2159         // Preserve the location for reparenting in the new task.
   2160         int reparentInsertionPoint = -1;
   2161 
   2162         for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
   2163             final TaskRecord targetTask = mTaskHistory.get(i);
   2164 
   2165             if (targetTask == task) {
   2166                 topOptions = resetTargetTaskIfNeededLocked(task, forceReset);
   2167                 taskFound = true;
   2168             } else {
   2169                 reparentInsertionPoint = resetAffinityTaskIfNeededLocked(targetTask, task,
   2170                         taskFound, forceReset, reparentInsertionPoint);
   2171             }
   2172         }
   2173 
   2174         int taskNdx = mTaskHistory.indexOf(task);
   2175         do {
   2176             taskTop = mTaskHistory.get(taskNdx--).getTopActivity();
   2177         } while (taskTop == null && taskNdx >= 0);
   2178 
   2179         if (topOptions != null) {
   2180             // If we got some ActivityOptions from an activity on top that
   2181             // was removed from the task, propagate them to the new real top.
   2182             if (taskTop != null) {
   2183                 taskTop.updateOptionsLocked(topOptions);
   2184             } else {
   2185                 topOptions.abort();
   2186             }
   2187         }
   2188 
   2189         return taskTop;
   2190     }
   2191 
   2192     void sendActivityResultLocked(int callingUid, ActivityRecord r,
   2193             String resultWho, int requestCode, int resultCode, Intent data) {
   2194 
   2195         if (callingUid > 0) {
   2196             mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
   2197                     data, r.getUriPermissionsLocked());
   2198         }
   2199 
   2200         if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
   2201                 + " : who=" + resultWho + " req=" + requestCode
   2202                 + " res=" + resultCode + " data=" + data);
   2203         if (mResumedActivity == r && r.app != null && r.app.thread != null) {
   2204             try {
   2205                 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
   2206                 list.add(new ResultInfo(resultWho, requestCode,
   2207                         resultCode, data));
   2208                 r.app.thread.scheduleSendResult(r.appToken, list);
   2209                 return;
   2210             } catch (Exception e) {
   2211                 Slog.w(TAG, "Exception thrown sending result to " + r, e);
   2212             }
   2213         }
   2214 
   2215         r.addResultLocked(null, resultWho, requestCode, resultCode, data);
   2216     }
   2217 
   2218     private void adjustFocusedActivityLocked(ActivityRecord r) {
   2219         if (mStackSupervisor.isFrontStack(this) && mService.mFocusedActivity == r) {
   2220             ActivityRecord next = topRunningActivityLocked(null);
   2221             if (next != r) {
   2222                 final TaskRecord task = r.task;
   2223                 if (r.frontOfTask && task == topTask() && task.mOnTopOfHome) {
   2224                     mStackSupervisor.moveHomeToTop();
   2225                 }
   2226             }
   2227             mService.setFocusedActivityLocked(mStackSupervisor.topRunningActivityLocked());
   2228         }
   2229     }
   2230 
   2231     final void stopActivityLocked(ActivityRecord r) {
   2232         if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
   2233         if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
   2234                 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
   2235             if (!r.finishing) {
   2236                 if (!mService.mSleeping) {
   2237                     if (DEBUG_STATES) {
   2238                         Slog.d(TAG, "no-history finish of " + r);
   2239                     }
   2240                     requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
   2241                             "no-history", false);
   2242                 } else {
   2243                     if (DEBUG_STATES) Slog.d(TAG, "Not finishing noHistory " + r
   2244                             + " on stop because we're just sleeping");
   2245                 }
   2246             }
   2247         }
   2248 
   2249         if (r.app != null && r.app.thread != null) {
   2250             adjustFocusedActivityLocked(r);
   2251             r.resumeKeyDispatchingLocked();
   2252             try {
   2253                 r.stopped = false;
   2254                 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
   2255                         + " (stop requested)");
   2256                 r.state = ActivityState.STOPPING;
   2257                 if (DEBUG_VISBILITY) Slog.v(
   2258                         TAG, "Stopping visible=" + r.visible + " for " + r);
   2259                 if (!r.visible) {
   2260                     mWindowManager.setAppVisibility(r.appToken, false);
   2261                 }
   2262                 r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
   2263                 if (mService.isSleepingOrShuttingDown()) {
   2264                     r.setSleeping(true);
   2265                 }
   2266                 Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r);
   2267                 mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
   2268             } catch (Exception e) {
   2269                 // Maybe just ignore exceptions here...  if the process
   2270                 // has crashed, our death notification will clean things
   2271                 // up.
   2272                 Slog.w(TAG, "Exception thrown during pause", e);
   2273                 // Just in case, assume it to be stopped.
   2274                 r.stopped = true;
   2275                 if (DEBUG_STATES) Slog.v(TAG, "Stop failed; moving to STOPPED: " + r);
   2276                 r.state = ActivityState.STOPPED;
   2277                 if (r.configDestroy) {
   2278                     destroyActivityLocked(r, true, false, "stop-except");
   2279                 }
   2280             }
   2281         }
   2282     }
   2283 
   2284     /**
   2285      * @return Returns true if the activity is being finished, false if for
   2286      * some reason it is being left as-is.
   2287      */
   2288     final boolean requestFinishActivityLocked(IBinder token, int resultCode,
   2289             Intent resultData, String reason, boolean oomAdj) {
   2290         ActivityRecord r = isInStackLocked(token);
   2291         if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(
   2292                 TAG, "Finishing activity token=" + token + " r="
   2293                 + ", result=" + resultCode + ", data=" + resultData
   2294                 + ", reason=" + reason);
   2295         if (r == null) {
   2296             return false;
   2297         }
   2298 
   2299         finishActivityLocked(r, resultCode, resultData, reason, oomAdj);
   2300         return true;
   2301     }
   2302 
   2303     final void finishSubActivityLocked(ActivityRecord self, String resultWho, int requestCode) {
   2304         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
   2305             ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
   2306             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
   2307                 ActivityRecord r = activities.get(activityNdx);
   2308                 if (r.resultTo == self && r.requestCode == requestCode) {
   2309                     if ((r.resultWho == null && resultWho == null) ||
   2310                         (r.resultWho != null && r.resultWho.equals(resultWho))) {
   2311                         finishActivityLocked(r, Activity.RESULT_CANCELED, null, "request-sub",
   2312                                 false);
   2313                     }
   2314                 }
   2315             }
   2316         }
   2317         mService.updateOomAdjLocked();
   2318     }
   2319 
   2320     final void finishTopRunningActivityLocked(ProcessRecord app) {
   2321         ActivityRecord r = topRunningActivityLocked(null);
   2322         if (r != null && r.app == app) {
   2323             // If the top running activity is from this crashing
   2324             // process, then terminate it to avoid getting in a loop.
   2325             Slog.w(TAG, "  Force finishing activity "
   2326                     + r.intent.getComponent().flattenToShortString());
   2327             int taskNdx = mTaskHistory.indexOf(r.task);
   2328             int activityNdx = r.task.mActivities.indexOf(r);
   2329             finishActivityLocked(r, Activity.RESULT_CANCELED, null, "crashed", false);
   2330             // Also terminate any activities below it that aren't yet
   2331             // stopped, to avoid a situation where one will get
   2332             // re-start our crashing activity once it gets resumed again.
   2333             --activityNdx;
   2334             if (activityNdx < 0) {
   2335                 do {
   2336                     --taskNdx;
   2337                     if (taskNdx < 0) {
   2338                         break;
   2339                     }
   2340                     activityNdx = mTaskHistory.get(taskNdx).mActivities.size() - 1;
   2341                 } while (activityNdx < 0);
   2342             }
   2343             if (activityNdx >= 0) {
   2344                 r = mTaskHistory.get(taskNdx).mActivities.get(activityNdx);
   2345                 if (r.state == ActivityState.RESUMED
   2346                         || r.state == ActivityState.PAUSING
   2347                         || r.state == ActivityState.PAUSED) {
   2348                     if (!r.isHomeActivity() || mService.mHomeProcess != r.app) {
   2349                         Slog.w(TAG, "  Force finishing activity "
   2350                                 + r.intent.getComponent().flattenToShortString());
   2351                         finishActivityLocked(r, Activity.RESULT_CANCELED, null, "crashed", false);
   2352                     }
   2353                 }
   2354             }
   2355         }
   2356     }
   2357 
   2358     final boolean finishActivityAffinityLocked(ActivityRecord r) {
   2359         ArrayList<ActivityRecord> activities = r.task.mActivities;
   2360         for (int index = activities.indexOf(r); index >= 0; --index) {
   2361             ActivityRecord cur = activities.get(index);
   2362             if (!Objects.equal(cur.taskAffinity, r.taskAffinity)) {
   2363                 break;
   2364             }
   2365             finishActivityLocked(cur, Activity.RESULT_CANCELED, null, "request-affinity", true);
   2366         }
   2367         return true;
   2368     }
   2369 
   2370     final void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
   2371         // send the result
   2372         ActivityRecord resultTo = r.resultTo;
   2373         if (resultTo != null) {
   2374             if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
   2375                     + " who=" + r.resultWho + " req=" + r.requestCode
   2376                     + " res=" + resultCode + " data=" + resultData);
   2377             if (r.info.applicationInfo.uid > 0) {
   2378                 mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
   2379                         resultTo.packageName, resultData,
   2380                         resultTo.getUriPermissionsLocked());
   2381             }
   2382             resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
   2383                                      resultData);
   2384             r.resultTo = null;
   2385         }
   2386         else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
   2387 
   2388         // Make sure this HistoryRecord is not holding on to other resources,
   2389         // because clients have remote IPC references to this object so we
   2390         // can't assume that will go away and want to avoid circular IPC refs.
   2391         r.results = null;
   2392         r.pendingResults = null;
   2393         r.newIntents = null;
   2394         r.icicle = null;
   2395     }
   2396 
   2397     /**
   2398      * @return Returns true if this activity has been removed from the history
   2399      * list, or false if it is still in the list and will be removed later.
   2400      */
   2401     final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
   2402             String reason, boolean oomAdj) {
   2403         if (r.finishing) {
   2404             Slog.w(TAG, "Duplicate finish request for " + r);
   2405             return false;
   2406         }
   2407 
   2408         r.makeFinishing();
   2409         EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
   2410                 r.userId, System.identityHashCode(r),
   2411                 r.task.taskId, r.shortComponentName, reason);
   2412         final ArrayList<ActivityRecord> activities = r.task.mActivities;
   2413         final int index = activities.indexOf(r);
   2414         if (index < (activities.size() - 1)) {
   2415             ActivityRecord next = activities.get(index+1);
   2416             if (r.frontOfTask) {
   2417                 // The next activity is now the front of the task.
   2418                 next.frontOfTask = true;
   2419             }
   2420             if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
   2421                 // If the caller asked that this activity (and all above it)
   2422                 // be cleared when the task is reset, don't lose that information,
   2423                 // but propagate it up to the next activity.
   2424                 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
   2425             }
   2426         }
   2427 
   2428         r.pauseKeyDispatchingLocked();
   2429 
   2430         adjustFocusedActivityLocked(r);
   2431 
   2432         finishActivityResultsLocked(r, resultCode, resultData);
   2433 
   2434         if (!mService.mPendingThumbnails.isEmpty()) {
   2435             // There are clients waiting to receive thumbnails so, in case
   2436             // this is an activity that someone is waiting for, add it
   2437             // to the pending list so we can correctly update the clients.
   2438             mStackSupervisor.mCancelledThumbnails.add(r);
   2439         }
   2440 
   2441         if (mResumedActivity == r) {
   2442             boolean endTask = index <= 0;
   2443             if (DEBUG_VISBILITY || DEBUG_TRANSITION) Slog.v(TAG,
   2444                     "Prepare close transition: finishing " + r);
   2445             mWindowManager.prepareAppTransition(endTask
   2446                     ? AppTransition.TRANSIT_TASK_CLOSE
   2447                     : AppTransition.TRANSIT_ACTIVITY_CLOSE, false);
   2448 
   2449             // Tell window manager to prepare for this one to be removed.
   2450             mWindowManager.setAppVisibility(r.appToken, false);
   2451 
   2452             if (mPausingActivity == null) {
   2453                 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
   2454                 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
   2455                 startPausingLocked(false, false);
   2456             }
   2457 
   2458         } else if (r.state != ActivityState.PAUSING) {
   2459             // If the activity is PAUSING, we will complete the finish once
   2460             // it is done pausing; else we can just directly finish it here.
   2461             if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
   2462             return finishCurrentActivityLocked(r, FINISH_AFTER_PAUSE, oomAdj) == null;
   2463         } else {
   2464             if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
   2465         }
   2466 
   2467         return false;
   2468     }
   2469 
   2470     static final int FINISH_IMMEDIATELY = 0;
   2471     static final int FINISH_AFTER_PAUSE = 1;
   2472     static final int FINISH_AFTER_VISIBLE = 2;
   2473 
   2474     final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj) {
   2475         // First things first: if this activity is currently visible,
   2476         // and the resumed activity is not yet visible, then hold off on
   2477         // finishing until the resumed one becomes visible.
   2478         if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
   2479             if (!mStackSupervisor.mStoppingActivities.contains(r)) {
   2480                 mStackSupervisor.mStoppingActivities.add(r);
   2481                 if (mStackSupervisor.mStoppingActivities.size() > 3
   2482                         || r.frontOfTask && mTaskHistory.size() <= 1) {
   2483                     // If we already have a few activities waiting to stop,
   2484                     // then give up on things going idle and start clearing
   2485                     // them out. Or if r is the last of activity of the last task the stack
   2486                     // will be empty and must be cleared immediately.
   2487                     mStackSupervisor.scheduleIdleLocked();
   2488                 } else {
   2489                     mStackSupervisor.checkReadyForSleepLocked();
   2490                 }
   2491             }
   2492             if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
   2493                     + " (finish requested)");
   2494             r.state = ActivityState.STOPPING;
   2495             if (oomAdj) {
   2496                 mService.updateOomAdjLocked();
   2497             }
   2498             return r;
   2499         }
   2500 
   2501         // make sure the record is cleaned out of other places.
   2502         mStackSupervisor.mStoppingActivities.remove(r);
   2503         mStackSupervisor.mGoingToSleepActivities.remove(r);
   2504         mStackSupervisor.mWaitingVisibleActivities.remove(r);
   2505         if (mResumedActivity == r) {
   2506             mResumedActivity = null;
   2507         }
   2508         final ActivityState prevState = r.state;
   2509         if (DEBUG_STATES) Slog.v(TAG, "Moving to FINISHING: " + r);
   2510         r.state = ActivityState.FINISHING;
   2511 
   2512         if (mode == FINISH_IMMEDIATELY
   2513                 || prevState == ActivityState.STOPPED
   2514                 || prevState == ActivityState.INITIALIZING) {
   2515             // If this activity is already stopped, we can just finish
   2516             // it right now.
   2517             boolean activityRemoved = destroyActivityLocked(r, true,
   2518                     oomAdj, "finish-imm");
   2519             if (activityRemoved) {
   2520                 mStackSupervisor.resumeTopActivitiesLocked();
   2521             }
   2522             return activityRemoved ? null : r;
   2523         }
   2524 
   2525         // Need to go through the full pause cycle to get this
   2526         // activity into the stopped state and then finish it.
   2527         if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
   2528         mStackSupervisor.mFinishingActivities.add(r);
   2529         mStackSupervisor.getFocusedStack().resumeTopActivityLocked(null);
   2530         return r;
   2531     }
   2532 
   2533     final boolean navigateUpToLocked(IBinder token, Intent destIntent, int resultCode,
   2534             Intent resultData) {
   2535         final ActivityRecord srec = ActivityRecord.forToken(token);
   2536         final TaskRecord task = srec.task;
   2537         final ArrayList<ActivityRecord> activities = task.mActivities;
   2538         final int start = activities.indexOf(srec);
   2539         if (!mTaskHistory.contains(task) || (start < 0)) {
   2540             return false;
   2541         }
   2542         int finishTo = start - 1;
   2543         ActivityRecord parent = finishTo < 0 ? null : activities.get(finishTo);
   2544         boolean foundParentInTask = false;
   2545         final ComponentName dest = destIntent.getComponent();
   2546         if (start > 0 && dest != null) {
   2547             for (int i = finishTo; i >= 0; i--) {
   2548                 ActivityRecord r = activities.get(i);
   2549                 if (r.info.packageName.equals(dest.getPackageName()) &&
   2550                         r.info.name.equals(dest.getClassName())) {
   2551                     finishTo = i;
   2552                     parent = r;
   2553                     foundParentInTask = true;
   2554                     break;
   2555                 }
   2556             }
   2557         }
   2558 
   2559         IActivityController controller = mService.mController;
   2560         if (controller != null) {
   2561             ActivityRecord next = topRunningActivityLocked(srec.appToken, 0);
   2562             if (next != null) {
   2563                 // ask watcher if this is allowed
   2564                 boolean resumeOK = true;
   2565                 try {
   2566                     resumeOK = controller.activityResuming(next.packageName);
   2567                 } catch (RemoteException e) {
   2568                     mService.mController = null;
   2569                     Watchdog.getInstance().setActivityController(null);
   2570                 }
   2571 
   2572                 if (!resumeOK) {
   2573                     return false;
   2574                 }
   2575             }
   2576         }
   2577         final long origId = Binder.clearCallingIdentity();
   2578         for (int i = start; i > finishTo; i--) {
   2579             ActivityRecord r = activities.get(i);
   2580             requestFinishActivityLocked(r.appToken, resultCode, resultData, "navigate-up", true);
   2581             // Only return the supplied result for the first activity finished
   2582             resultCode = Activity.RESULT_CANCELED;
   2583             resultData = null;
   2584         }
   2585 
   2586         if (parent != null && foundParentInTask) {
   2587             final int parentLaunchMode = parent.info.launchMode;
   2588             final int destIntentFlags = destIntent.getFlags();
   2589             if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE ||
   2590                     parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
   2591                     parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
   2592                     (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
   2593                 parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent);
   2594             } else {
   2595                 try {
   2596                     ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
   2597                             destIntent.getComponent(), 0, srec.userId);
   2598                     int res = mStackSupervisor.startActivityLocked(srec.app.thread, destIntent,
   2599                             null, aInfo, parent.appToken, null,
   2600                             0, -1, parent.launchedFromUid, parent.launchedFromPackage,
   2601                             0, null, true, null);
   2602                     foundParentInTask = res == ActivityManager.START_SUCCESS;
   2603                 } catch (RemoteException e) {
   2604                     foundParentInTask = false;
   2605                 }
   2606                 requestFinishActivityLocked(parent.appToken, resultCode,
   2607                         resultData, "navigate-up", true);
   2608             }
   2609         }
   2610         Binder.restoreCallingIdentity(origId);
   2611         return foundParentInTask;
   2612     }
   2613     /**
   2614      * Perform the common clean-up of an activity record.  This is called both
   2615      * as part of destroyActivityLocked() (when destroying the client-side
   2616      * representation) and cleaning things up as a result of its hosting
   2617      * processing going away, in which case there is no remaining client-side
   2618      * state to destroy so only the cleanup here is needed.
   2619      */
   2620     final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices,
   2621             boolean setState) {
   2622         if (mResumedActivity == r) {
   2623             mResumedActivity = null;
   2624         }
   2625         if (mService.mFocusedActivity == r) {
   2626             mService.mFocusedActivity = null;
   2627         }
   2628 
   2629         r.configDestroy = false;
   2630         r.frozenBeforeDestroy = false;
   2631 
   2632         if (setState) {
   2633             if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (cleaning up)");
   2634             r.state = ActivityState.DESTROYED;
   2635             if (DEBUG_APP) Slog.v(TAG, "Clearing app during cleanUp for activity " + r);
   2636             r.app = null;
   2637         }
   2638 
   2639         // Make sure this record is no longer in the pending finishes list.
   2640         // This could happen, for example, if we are trimming activities
   2641         // down to the max limit while they are still waiting to finish.
   2642         mStackSupervisor.mFinishingActivities.remove(r);
   2643         mStackSupervisor.mWaitingVisibleActivities.remove(r);
   2644 
   2645         // Remove any pending results.
   2646         if (r.finishing && r.pendingResults != null) {
   2647             for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
   2648                 PendingIntentRecord rec = apr.get();
   2649                 if (rec != null) {
   2650                     mService.cancelIntentSenderLocked(rec, false);
   2651                 }
   2652             }
   2653             r.pendingResults = null;
   2654         }
   2655 
   2656         if (cleanServices) {
   2657             cleanUpActivityServicesLocked(r);
   2658         }
   2659 
   2660         if (!mService.mPendingThumbnails.isEmpty()) {
   2661             // There are clients waiting to receive thumbnails so, in case
   2662             // this is an activity that someone is waiting for, add it
   2663             // to the pending list so we can correctly update the clients.
   2664             mStackSupervisor.mCancelledThumbnails.add(r);
   2665         }
   2666 
   2667         // Get rid of any pending idle timeouts.
   2668         removeTimeoutsForActivityLocked(r);
   2669     }
   2670 
   2671     private void removeTimeoutsForActivityLocked(ActivityRecord r) {
   2672         mStackSupervisor.removeTimeoutsForActivityLocked(r);
   2673         mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
   2674         mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
   2675         mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
   2676         r.finishLaunchTickingLocked();
   2677     }
   2678 
   2679     final void removeActivityFromHistoryLocked(ActivityRecord r) {
   2680         finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
   2681         r.makeFinishing();
   2682         if (DEBUG_ADD_REMOVE) {
   2683             RuntimeException here = new RuntimeException("here");
   2684             here.fillInStackTrace();
   2685             Slog.i(TAG, "Removing activity " + r + " from stack");
   2686         }
   2687         final TaskRecord task = r.task;
   2688         if (task != null && task.removeActivity(r)) {
   2689             if (DEBUG_STACK) Slog.i(TAG,
   2690                     "removeActivityFromHistoryLocked: last activity removed from " + this);
   2691             if (mStackSupervisor.isFrontStack(this) && task == topTask() && task.mOnTopOfHome) {
   2692                 mStackSupervisor.moveHomeToTop();
   2693             }
   2694             mStackSupervisor.removeTask(task);
   2695         }
   2696         r.takeFromHistory();
   2697         removeTimeoutsForActivityLocked(r);
   2698         if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (removed from history)");
   2699         r.state = ActivityState.DESTROYED;
   2700         if (DEBUG_APP) Slog.v(TAG, "Clearing app during remove for activity " + r);
   2701         r.app = null;
   2702         mWindowManager.removeAppToken(r.appToken);
   2703         if (VALIDATE_TOKENS) {
   2704             validateAppTokensLocked();
   2705         }
   2706         cleanUpActivityServicesLocked(r);
   2707         r.removeUriPermissionsLocked();
   2708     }
   2709 
   2710     /**
   2711      * Perform clean-up of service connections in an activity record.
   2712      */
   2713     final void cleanUpActivityServicesLocked(ActivityRecord r) {
   2714         // Throw away any services that have been bound by this activity.
   2715         if (r.connections != null) {
   2716             Iterator<ConnectionRecord> it = r.connections.iterator();
   2717             while (it.hasNext()) {
   2718                 ConnectionRecord c = it.next();
   2719                 mService.mServices.removeConnectionLocked(c, null, r);
   2720             }
   2721             r.connections = null;
   2722         }
   2723     }
   2724 
   2725     final void scheduleDestroyActivities(ProcessRecord owner, boolean oomAdj, String reason) {
   2726         Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG);
   2727         msg.obj = new ScheduleDestroyArgs(owner, oomAdj, reason);
   2728         mHandler.sendMessage(msg);
   2729     }
   2730 
   2731     final void destroyActivitiesLocked(ProcessRecord owner, boolean oomAdj, String reason) {
   2732         boolean lastIsOpaque = false;
   2733         boolean activityRemoved = false;
   2734         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
   2735             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
   2736             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
   2737                 final ActivityRecord r = activities.get(activityNdx);
   2738                 if (r.finishing) {
   2739                     continue;
   2740                 }
   2741                 if (r.fullscreen) {
   2742                     lastIsOpaque = true;
   2743                 }
   2744                 if (owner != null && r.app != owner) {
   2745                     continue;
   2746                 }
   2747                 if (!lastIsOpaque) {
   2748                     continue;
   2749                 }
   2750                 // We can destroy this one if we have its icicle saved and
   2751                 // it is not in the process of pausing/stopping/finishing.
   2752                 if (r.app != null && r != mResumedActivity && r != mPausingActivity
   2753                         && r.haveState && !r.visible && r.stopped
   2754                         && r.state != ActivityState.DESTROYING
   2755                         && r.state != ActivityState.DESTROYED) {
   2756                     if (DEBUG_SWITCH) Slog.v(TAG, "Destroying " + r + " in state " + r.state
   2757                             + " resumed=" + mResumedActivity
   2758                             + " pausing=" + mPausingActivity);
   2759                     if (destroyActivityLocked(r, true, oomAdj, reason)) {
   2760                         activityRemoved = true;
   2761                     }
   2762                 }
   2763             }
   2764         }
   2765         if (activityRemoved) {
   2766             mStackSupervisor.resumeTopActivitiesLocked();
   2767 
   2768         }
   2769     }
   2770 
   2771     /**
   2772      * Destroy the current CLIENT SIDE instance of an activity.  This may be
   2773      * called both when actually finishing an activity, or when performing
   2774      * a configuration switch where we destroy the current client-side object
   2775      * but then create a new client-side object for this same HistoryRecord.
   2776      */
   2777     final boolean destroyActivityLocked(ActivityRecord r,
   2778             boolean removeFromApp, boolean oomAdj, String reason) {
   2779         if (DEBUG_SWITCH || DEBUG_CLEANUP) Slog.v(
   2780             TAG, "Removing activity from " + reason + ": token=" + r
   2781               + ", app=" + (r.app != null ? r.app.processName : "(null)"));
   2782         EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
   2783                 r.userId, System.identityHashCode(r),
   2784                 r.task.taskId, r.shortComponentName, reason);
   2785 
   2786         boolean removedFromHistory = false;
   2787 
   2788         cleanUpActivityLocked(r, false, false);
   2789 
   2790         final boolean hadApp = r.app != null;
   2791 
   2792         if (hadApp) {
   2793             if (removeFromApp) {
   2794                 r.app.activities.remove(r);
   2795                 if (mService.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
   2796                     mService.mHeavyWeightProcess = null;
   2797                     mService.mHandler.sendEmptyMessage(
   2798                             ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG);
   2799                 }
   2800                 if (r.app.activities.isEmpty()) {
   2801                     // No longer have activities, so update LRU list and oom adj.
   2802                     mService.updateLruProcessLocked(r.app, false, null);
   2803                     mService.updateOomAdjLocked();
   2804                 }
   2805             }
   2806 
   2807             boolean skipDestroy = false;
   2808 
   2809             try {
   2810                 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
   2811                 r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,
   2812                         r.configChangeFlags);
   2813             } catch (Exception e) {
   2814                 // We can just ignore exceptions here...  if the process
   2815                 // has crashed, our death notification will clean things
   2816                 // up.
   2817                 //Slog.w(TAG, "Exception thrown during finish", e);
   2818                 if (r.finishing) {
   2819                     removeActivityFromHistoryLocked(r);
   2820                     removedFromHistory = true;
   2821                     skipDestroy = true;
   2822                 }
   2823             }
   2824 
   2825             r.nowVisible = false;
   2826 
   2827             // If the activity is finishing, we need to wait on removing it
   2828             // from the list to give it a chance to do its cleanup.  During
   2829             // that time it may make calls back with its token so we need to
   2830             // be able to find it on the list and so we don't want to remove
   2831             // it from the list yet.  Otherwise, we can just immediately put
   2832             // it in the destroyed state since we are not removing it from the
   2833             // list.
   2834             if (r.finishing && !skipDestroy) {
   2835                 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYING: " + r
   2836                         + " (destroy requested)");
   2837                 r.state = ActivityState.DESTROYING;
   2838                 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG, r);
   2839                 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
   2840             } else {
   2841                 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (destroy skipped)");
   2842                 r.state = ActivityState.DESTROYED;
   2843                 if (DEBUG_APP) Slog.v(TAG, "Clearing app during destroy for activity " + r);
   2844                 r.app = null;
   2845             }
   2846         } else {
   2847             // remove this record from the history.
   2848             if (r.finishing) {
   2849                 removeActivityFromHistoryLocked(r);
   2850                 removedFromHistory = true;
   2851             } else {
   2852                 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (no app)");
   2853                 r.state = ActivityState.DESTROYED;
   2854                 if (DEBUG_APP) Slog.v(TAG, "Clearing app during destroy for activity " + r);
   2855                 r.app = null;
   2856             }
   2857         }
   2858 
   2859         r.configChangeFlags = 0;
   2860 
   2861         if (!mLRUActivities.remove(r) && hadApp) {
   2862             Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
   2863         }
   2864 
   2865         return removedFromHistory;
   2866     }
   2867 
   2868     final void activityDestroyedLocked(IBinder token) {
   2869         final long origId = Binder.clearCallingIdentity();
   2870         try {
   2871             ActivityRecord r = ActivityRecord.forToken(token);
   2872             if (r != null) {
   2873                 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
   2874             }
   2875 
   2876             if (isInStackLocked(token) != null) {
   2877                 if (r.state == ActivityState.DESTROYING) {
   2878                     cleanUpActivityLocked(r, true, false);
   2879                     removeActivityFromHistoryLocked(r);
   2880                 }
   2881             }
   2882             mStackSupervisor.resumeTopActivitiesLocked();
   2883         } finally {
   2884             Binder.restoreCallingIdentity(origId);
   2885         }
   2886     }
   2887 
   2888     private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list,
   2889             ProcessRecord app, String listName) {
   2890         int i = list.size();
   2891         if (DEBUG_CLEANUP) Slog.v(
   2892             TAG, "Removing app " + app + " from list " + listName
   2893             + " with " + i + " entries");
   2894         while (i > 0) {
   2895             i--;
   2896             ActivityRecord r = list.get(i);
   2897             if (DEBUG_CLEANUP) Slog.v(TAG, "Record #" + i + " " + r);
   2898             if (r.app == app) {
   2899                 if (DEBUG_CLEANUP) Slog.v(TAG, "---> REMOVING this entry!");
   2900                 list.remove(i);
   2901                 removeTimeoutsForActivityLocked(r);
   2902             }
   2903         }
   2904     }
   2905 
   2906     boolean removeHistoryRecordsForAppLocked(ProcessRecord app) {
   2907         removeHistoryRecordsForAppLocked(mLRUActivities, app, "mLRUActivities");
   2908         removeHistoryRecordsForAppLocked(mStackSupervisor.mStoppingActivities, app,
   2909                 "mStoppingActivities");
   2910         removeHistoryRecordsForAppLocked(mStackSupervisor.mGoingToSleepActivities, app,
   2911                 "mGoingToSleepActivities");
   2912         removeHistoryRecordsForAppLocked(mStackSupervisor.mWaitingVisibleActivities, app,
   2913                 "mWaitingVisibleActivities");
   2914         removeHistoryRecordsForAppLocked(mStackSupervisor.mFinishingActivities, app,
   2915                 "mFinishingActivities");
   2916 
   2917         boolean hasVisibleActivities = false;
   2918 
   2919         // Clean out the history list.
   2920         int i = numActivities();
   2921         if (DEBUG_CLEANUP) Slog.v(
   2922             TAG, "Removing app " + app + " from history with " + i + " entries");
   2923         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
   2924             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
   2925             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
   2926                 final ActivityRecord r = activities.get(activityNdx);
   2927                 --i;
   2928                 if (DEBUG_CLEANUP) Slog.v(
   2929                     TAG, "Record #" + i + " " + r + ": app=" + r.app);
   2930                 if (r.app == app) {
   2931                     boolean remove;
   2932                     if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
   2933                         // Don't currently have state for the activity, or
   2934                         // it is finishing -- always remove it.
   2935                         remove = true;
   2936                     } else if (r.launchCount > 2 &&
   2937                             r.lastLaunchTime > (SystemClock.uptimeMillis()-60000)) {
   2938                         // We have launched this activity too many times since it was
   2939                         // able to run, so give up and remove it.
   2940                         remove = true;
   2941                     } else {
   2942                         // The process may be gone, but the activity lives on!
   2943                         remove = false;
   2944                     }
   2945                     if (remove) {
   2946                         if (DEBUG_ADD_REMOVE || DEBUG_CLEANUP) {
   2947                             RuntimeException here = new RuntimeException("here");
   2948                             here.fillInStackTrace();
   2949                             Slog.i(TAG, "Removing activity " + r + " from stack at " + i
   2950                                     + ": haveState=" + r.haveState
   2951                                     + " stateNotNeeded=" + r.stateNotNeeded
   2952                                     + " finishing=" + r.finishing
   2953                                     + " state=" + r.state, here);
   2954                         }
   2955                         if (!r.finishing) {
   2956                             Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
   2957                             EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
   2958                                     r.userId, System.identityHashCode(r),
   2959                                     r.task.taskId, r.shortComponentName,
   2960                                     "proc died without state saved");
   2961                             if (r.state == ActivityState.RESUMED) {
   2962                                 mService.updateUsageStats(r, false);
   2963                             }
   2964                         }
   2965                         removeActivityFromHistoryLocked(r);
   2966 
   2967                     } else {
   2968                         // We have the current state for this activity, so
   2969                         // it can be restarted later when needed.
   2970                         if (localLOGV) Slog.v(
   2971                             TAG, "Keeping entry, setting app to null");
   2972                         if (r.visible) {
   2973                             hasVisibleActivities = true;
   2974                         }
   2975                         if (DEBUG_APP) Slog.v(TAG, "Clearing app during removeHistory for activity "
   2976                                 + r);
   2977                         r.app = null;
   2978                         r.nowVisible = false;
   2979                         if (!r.haveState) {
   2980                             if (DEBUG_SAVED_STATE) Slog.i(TAG,
   2981                                     "App died, clearing saved state of " + r);
   2982                             r.icicle = null;
   2983                         }
   2984                     }
   2985 
   2986                     cleanUpActivityLocked(r, true, true);
   2987                 }
   2988             }
   2989         }
   2990 
   2991         return hasVisibleActivities;
   2992     }
   2993 
   2994     final void updateTransitLocked(int transit, Bundle options) {
   2995         if (options != null) {
   2996             ActivityRecord r = topRunningActivityLocked(null);
   2997             if (r != null && r.state != ActivityState.RESUMED) {
   2998                 r.updateOptionsLocked(options);
   2999             } else {
   3000                 ActivityOptions.abort(options);
   3001             }
   3002         }
   3003         mWindowManager.prepareAppTransition(transit, false);
   3004     }
   3005 
   3006     void moveHomeTaskToTop() {
   3007         final int top = mTaskHistory.size() - 1;
   3008         for (int taskNdx = top; taskNdx >= 0; --taskNdx) {
   3009             final TaskRecord task = mTaskHistory.get(taskNdx);
   3010             if (task.isHomeTask()) {
   3011                 if (DEBUG_TASKS || DEBUG_STACK) Slog.d(TAG, "moveHomeTaskToTop: moving " + task);
   3012                 mTaskHistory.remove(taskNdx);
   3013                 mTaskHistory.add(top, task);
   3014                 mWindowManager.moveTaskToTop(task.taskId);
   3015                 return;
   3016             }
   3017         }
   3018     }
   3019 
   3020     final boolean findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
   3021         final TaskRecord task = taskForIdLocked(taskId);
   3022         if (task != null) {
   3023             if ((flags & ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
   3024                 mStackSupervisor.mUserLeaving = true;
   3025             }
   3026             if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
   3027                 // Caller wants the home activity moved with it.  To accomplish this,
   3028                 // we'll just indicate that this task returns to the home task.
   3029                 task.mOnTopOfHome = true;
   3030             }
   3031             moveTaskToFrontLocked(task, null, options);
   3032             return true;
   3033         }
   3034         return false;
   3035     }
   3036 
   3037     final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
   3038         if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
   3039 
   3040         final int numTasks = mTaskHistory.size();
   3041         final int index = mTaskHistory.indexOf(tr);
   3042         if (numTasks == 0 || index < 0)  {
   3043             // nothing to do!
   3044             if (reason != null &&
   3045                     (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
   3046                 ActivityOptions.abort(options);
   3047             } else {
   3048                 updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
   3049             }
   3050             return;
   3051         }
   3052 
   3053         mStackSupervisor.moveHomeStack(isHomeStack());
   3054 
   3055         // Shift all activities with this task up to the top
   3056         // of the stack, keeping them in the same internal order.
   3057         insertTaskAtTop(tr);
   3058 
   3059         if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare to front transition: task=" + tr);
   3060         if (reason != null &&
   3061                 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
   3062             mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
   3063             ActivityRecord r = topRunningActivityLocked(null);
   3064             if (r != null) {
   3065                 mNoAnimActivities.add(r);
   3066             }
   3067             ActivityOptions.abort(options);
   3068         } else {
   3069             updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
   3070         }
   3071 
   3072         mWindowManager.moveTaskToTop(tr.taskId);
   3073 
   3074         mStackSupervisor.resumeTopActivitiesLocked();
   3075         EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
   3076 
   3077         if (VALIDATE_TOKENS) {
   3078             validateAppTokensLocked();
   3079         }
   3080     }
   3081 
   3082     /**
   3083      * Worker method for rearranging history stack. Implements the function of moving all
   3084      * activities for a specific task (gathering them if disjoint) into a single group at the
   3085      * bottom of the stack.
   3086      *
   3087      * If a watcher is installed, the action is preflighted and the watcher has an opportunity
   3088      * to premeptively cancel the move.
   3089      *
   3090      * @param taskId The taskId to collect and move to the bottom.
   3091      * @return Returns true if the move completed, false if not.
   3092      */
   3093     final boolean moveTaskToBackLocked(int taskId, ActivityRecord reason) {
   3094         Slog.i(TAG, "moveTaskToBack: " + taskId);
   3095 
   3096         // If we have a watcher, preflight the move before committing to it.  First check
   3097         // for *other* available tasks, but if none are available, then try again allowing the
   3098         // current task to be selected.
   3099         if (mStackSupervisor.isFrontStack(this) && mService.mController != null) {
   3100             ActivityRecord next = topRunningActivityLocked(null, taskId);
   3101             if (next == null) {
   3102                 next = topRunningActivityLocked(null, 0);
   3103             }
   3104             if (next != null) {
   3105                 // ask watcher if this is allowed
   3106                 boolean moveOK = true;
   3107                 try {
   3108                     moveOK = mService.mController.activityResuming(next.packageName);
   3109                 } catch (RemoteException e) {
   3110                     mService.mController = null;
   3111                     Watchdog.getInstance().setActivityController(null);
   3112                 }
   3113                 if (!moveOK) {
   3114                     return false;
   3115                 }
   3116             }
   3117         }
   3118 
   3119         if (DEBUG_TRANSITION) Slog.v(TAG,
   3120                 "Prepare to back transition: task=" + taskId);
   3121 
   3122         final TaskRecord tr = taskForIdLocked(taskId);
   3123         if (tr == null) {
   3124             return false;
   3125         }
   3126 
   3127         mTaskHistory.remove(tr);
   3128         mTaskHistory.add(0, tr);
   3129 
   3130         // There is an assumption that moving a task to the back moves it behind the home activity.
   3131         // We make sure here that some activity in the stack will launch home.
   3132         ActivityRecord lastActivity = null;
   3133         int numTasks = mTaskHistory.size();
   3134         for (int taskNdx = numTasks - 1; taskNdx >= 1; --taskNdx) {
   3135             final TaskRecord task = mTaskHistory.get(taskNdx);
   3136             if (task.mOnTopOfHome) {
   3137                 break;
   3138             }
   3139             if (taskNdx == 1) {
   3140                 // Set the last task before tr to go to home.
   3141                 task.mOnTopOfHome = true;
   3142             }
   3143         }
   3144 
   3145         if (reason != null &&
   3146                 (reason.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
   3147             mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
   3148             ActivityRecord r = topRunningActivityLocked(null);
   3149             if (r != null) {
   3150                 mNoAnimActivities.add(r);
   3151             }
   3152         } else {
   3153             mWindowManager.prepareAppTransition(AppTransition.TRANSIT_TASK_TO_BACK, false);
   3154         }
   3155         mWindowManager.moveTaskToBottom(taskId);
   3156 
   3157         if (VALIDATE_TOKENS) {
   3158             validateAppTokensLocked();
   3159         }
   3160 
   3161         final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null;
   3162         if (task == tr && task.mOnTopOfHome || numTasks <= 1) {
   3163             if (task != null) {
   3164                 task.mOnTopOfHome = false;
   3165             }
   3166             return mStackSupervisor.resumeHomeActivity(null);
   3167         }
   3168 
   3169         mStackSupervisor.resumeTopActivitiesLocked();
   3170         return true;
   3171     }
   3172 
   3173     static final void logStartActivity(int tag, ActivityRecord r,
   3174             TaskRecord task) {
   3175         final Uri data = r.intent.getData();
   3176         final String strData = data != null ? data.toSafeString() : null;
   3177 
   3178         EventLog.writeEvent(tag,
   3179                 r.userId, System.identityHashCode(r), task.taskId,
   3180                 r.shortComponentName, r.intent.getAction(),
   3181                 r.intent.getType(), strData, r.intent.getFlags());
   3182     }
   3183 
   3184     /**
   3185      * Make sure the given activity matches the current configuration.  Returns
   3186      * false if the activity had to be destroyed.  Returns true if the
   3187      * configuration is the same, or the activity will remain running as-is
   3188      * for whatever reason.  Ensures the HistoryRecord is updated with the
   3189      * correct configuration and all other bookkeeping is handled.
   3190      */
   3191     final boolean ensureActivityConfigurationLocked(ActivityRecord r,
   3192             int globalChanges) {
   3193         if (mConfigWillChange) {
   3194             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   3195                     "Skipping config check (will change): " + r);
   3196             return true;
   3197         }
   3198 
   3199         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   3200                 "Ensuring correct configuration: " + r);
   3201 
   3202         // Short circuit: if the two configurations are the exact same
   3203         // object (the common case), then there is nothing to do.
   3204         Configuration newConfig = mService.mConfiguration;
   3205         if (r.configuration == newConfig && !r.forceNewConfig) {
   3206             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   3207                     "Configuration unchanged in " + r);
   3208             return true;
   3209         }
   3210 
   3211         // We don't worry about activities that are finishing.
   3212         if (r.finishing) {
   3213             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   3214                     "Configuration doesn't matter in finishing " + r);
   3215             r.stopFreezingScreenLocked(false);
   3216             return true;
   3217         }
   3218 
   3219         // Okay we now are going to make this activity have the new config.
   3220         // But then we need to figure out how it needs to deal with that.
   3221         Configuration oldConfig = r.configuration;
   3222         r.configuration = newConfig;
   3223 
   3224         // Determine what has changed.  May be nothing, if this is a config
   3225         // that has come back from the app after going idle.  In that case
   3226         // we just want to leave the official config object now in the
   3227         // activity and do nothing else.
   3228         final int changes = oldConfig.diff(newConfig);
   3229         if (changes == 0 && !r.forceNewConfig) {
   3230             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   3231                     "Configuration no differences in " + r);
   3232             return true;
   3233         }
   3234 
   3235         // If the activity isn't currently running, just leave the new
   3236         // configuration and it will pick that up next time it starts.
   3237         if (r.app == null || r.app.thread == null) {
   3238             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   3239                     "Configuration doesn't matter not running " + r);
   3240             r.stopFreezingScreenLocked(false);
   3241             r.forceNewConfig = false;
   3242             return true;
   3243         }
   3244 
   3245         // Figure out how to handle the changes between the configurations.
   3246         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
   3247             Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
   3248                     + Integer.toHexString(changes) + ", handles=0x"
   3249                     + Integer.toHexString(r.info.getRealConfigChanged())
   3250                     + ", newConfig=" + newConfig);
   3251         }
   3252         if ((changes&(~r.info.getRealConfigChanged())) != 0 || r.forceNewConfig) {
   3253             // Aha, the activity isn't handling the change, so DIE DIE DIE.
   3254             r.configChangeFlags |= changes;
   3255             r.startFreezingScreenLocked(r.app, globalChanges);
   3256             r.forceNewConfig = false;
   3257             if (r.app == null || r.app.thread == null) {
   3258                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   3259                         "Config is destroying non-running " + r);
   3260                 destroyActivityLocked(r, true, false, "config");
   3261             } else if (r.state == ActivityState.PAUSING) {
   3262                 // A little annoying: we are waiting for this activity to
   3263                 // finish pausing.  Let's not do anything now, but just
   3264                 // flag that it needs to be restarted when done pausing.
   3265                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   3266                         "Config is skipping already pausing " + r);
   3267                 r.configDestroy = true;
   3268                 return true;
   3269             } else if (r.state == ActivityState.RESUMED) {
   3270                 // Try to optimize this case: the configuration is changing
   3271                 // and we need to restart the top, resumed activity.
   3272                 // Instead of doing the normal handshaking, just say
   3273                 // "restart!".
   3274                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   3275                         "Config is relaunching resumed " + r);
   3276                 relaunchActivityLocked(r, r.configChangeFlags, true);
   3277                 r.configChangeFlags = 0;
   3278             } else {
   3279                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   3280                         "Config is relaunching non-resumed " + r);
   3281                 relaunchActivityLocked(r, r.configChangeFlags, false);
   3282                 r.configChangeFlags = 0;
   3283             }
   3284 
   3285             // All done...  tell the caller we weren't able to keep this
   3286             // activity around.
   3287             return false;
   3288         }
   3289 
   3290         // Default case: the activity can handle this new configuration, so
   3291         // hand it over.  Note that we don't need to give it the new
   3292         // configuration, since we always send configuration changes to all
   3293         // process when they happen so it can just use whatever configuration
   3294         // it last got.
   3295         if (r.app != null && r.app.thread != null) {
   3296             try {
   3297                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
   3298                 r.app.thread.scheduleActivityConfigurationChanged(r.appToken);
   3299             } catch (RemoteException e) {
   3300                 // If process died, whatever.
   3301             }
   3302         }
   3303         r.stopFreezingScreenLocked(false);
   3304 
   3305         return true;
   3306     }
   3307 
   3308     private boolean relaunchActivityLocked(ActivityRecord r,
   3309             int changes, boolean andResume) {
   3310         List<ResultInfo> results = null;
   3311         List<Intent> newIntents = null;
   3312         if (andResume) {
   3313             results = r.results;
   3314             newIntents = r.newIntents;
   3315         }
   3316         if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
   3317                 + " with results=" + results + " newIntents=" + newIntents
   3318                 + " andResume=" + andResume);
   3319         EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
   3320                 : EventLogTags.AM_RELAUNCH_ACTIVITY, r.userId, System.identityHashCode(r),
   3321                 r.task.taskId, r.shortComponentName);
   3322 
   3323         r.startFreezingScreenLocked(r.app, 0);
   3324 
   3325         try {
   3326             if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
   3327                     (andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ")
   3328                     + r);
   3329             r.forceNewConfig = false;
   3330             r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents,
   3331                     changes, !andResume, new Configuration(mService.mConfiguration));
   3332             // Note: don't need to call pauseIfSleepingLocked() here, because
   3333             // the caller will only pass in 'andResume' if this activity is
   3334             // currently resumed, which implies we aren't sleeping.
   3335         } catch (RemoteException e) {
   3336             if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG, "Relaunch failed", e);
   3337         }
   3338 
   3339         if (andResume) {
   3340             r.results = null;
   3341             r.newIntents = null;
   3342             r.state = ActivityState.RESUMED;
   3343         } else {
   3344             mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
   3345             r.state = ActivityState.PAUSED;
   3346         }
   3347 
   3348         return true;
   3349     }
   3350 
   3351     boolean willActivityBeVisibleLocked(IBinder token) {
   3352         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
   3353             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
   3354             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
   3355                 final ActivityRecord r = activities.get(activityNdx);
   3356                 if (r.appToken == token) {
   3357                         return true;
   3358                 }
   3359                 if (r.fullscreen && !r.finishing) {
   3360                     return false;
   3361                 }
   3362             }
   3363         }
   3364         return true;
   3365     }
   3366 
   3367     void closeSystemDialogsLocked() {
   3368         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
   3369             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
   3370             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
   3371                 final ActivityRecord r = activities.get(activityNdx);
   3372                 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
   3373                     finishActivityLocked(r, Activity.RESULT_CANCELED, null, "close-sys", true);
   3374                 }
   3375             }
   3376         }
   3377     }
   3378 
   3379     boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
   3380         boolean didSomething = false;
   3381         TaskRecord lastTask = null;
   3382         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
   3383             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
   3384             int numActivities = activities.size();
   3385             for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
   3386                 ActivityRecord r = activities.get(activityNdx);
   3387                 final boolean samePackage = r.packageName.equals(name)
   3388                         || (name == null && r.userId == userId);
   3389                 if ((userId == UserHandle.USER_ALL || r.userId == userId)
   3390                         && (samePackage || r.task == lastTask)
   3391                         && (r.app == null || evenPersistent || !r.app.persistent)) {
   3392                     if (!doit) {
   3393                         if (r.finishing) {
   3394                             // If this activity is just finishing, then it is not
   3395                             // interesting as far as something to stop.
   3396                             continue;
   3397                         }
   3398                         return true;
   3399                     }
   3400                     didSomething = true;
   3401                     Slog.i(TAG, "  Force finishing activity " + r);
   3402                     if (samePackage) {
   3403                         if (r.app != null) {
   3404                             r.app.removed = true;
   3405                         }
   3406                         r.app = null;
   3407                     }
   3408                     lastTask = r.task;
   3409                     if (finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop",
   3410                             true)) {
   3411                         // r has been deleted from mActivities, accommodate.
   3412                         --numActivities;
   3413                         --activityNdx;
   3414                     }
   3415                 }
   3416             }
   3417         }
   3418         return didSomething;
   3419     }
   3420 
   3421     ActivityRecord getTasksLocked(IThumbnailReceiver receiver,
   3422             PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
   3423         ActivityRecord topRecord = null;
   3424         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
   3425             final TaskRecord task = mTaskHistory.get(taskNdx);
   3426             ActivityRecord r = null;
   3427             ActivityRecord top = null;
   3428             int numActivities = 0;
   3429             int numRunning = 0;
   3430             final ArrayList<ActivityRecord> activities = task.mActivities;
   3431             if (activities.isEmpty()) {
   3432                 continue;
   3433             }
   3434             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
   3435                 r = activities.get(activityNdx);
   3436 
   3437                 // Initialize state for next task if needed.
   3438                 if (top == null || (top.state == ActivityState.INITIALIZING)) {
   3439                     top = r;
   3440                     numActivities = numRunning = 0;
   3441                 }
   3442 
   3443                 // Add 'r' into the current task.
   3444                 numActivities++;
   3445                 if (r.app != null && r.app.thread != null) {
   3446                     numRunning++;
   3447                 }
   3448 
   3449                 if (localLOGV) Slog.v(
   3450                     TAG, r.intent.getComponent().flattenToShortString()
   3451                     + ": task=" + r.task);
   3452             }
   3453 
   3454             RunningTaskInfo ci = new RunningTaskInfo();
   3455             ci.id = task.taskId;
   3456             ci.baseActivity = r.intent.getComponent();
   3457             ci.topActivity = top.intent.getComponent();
   3458             ci.lastActiveTime = task.lastActiveTime;
   3459 
   3460             if (top.thumbHolder != null) {
   3461                 ci.description = top.thumbHolder.lastDescription;
   3462             }
   3463             ci.numActivities = numActivities;
   3464             ci.numRunning = numRunning;
   3465             //System.out.println(
   3466             //    "#" + maxNum + ": " + " descr=" + ci.description);
   3467             if (receiver != null) {
   3468                 if (localLOGV) Slog.v(
   3469                     TAG, "State=" + top.state + "Idle=" + top.idle
   3470                     + " app=" + top.app
   3471                     + " thr=" + (top.app != null ? top.app.thread : null));
   3472                 if (top.state == ActivityState.RESUMED || top.state == ActivityState.PAUSING) {
   3473                     if (top.idle && top.app != null && top.app.thread != null) {
   3474                         topRecord = top;
   3475                     } else {
   3476                         top.thumbnailNeeded = true;
   3477                     }
   3478                 }
   3479                 pending.pendingRecords.add(top);
   3480             }
   3481             list.add(ci);
   3482         }
   3483         return topRecord;
   3484     }
   3485 
   3486     public void unhandledBackLocked() {
   3487         final int top = mTaskHistory.size() - 1;
   3488         if (DEBUG_SWITCH) Slog.d(
   3489             TAG, "Performing unhandledBack(): top activity at " + top);
   3490         if (top >= 0) {
   3491             final ArrayList<ActivityRecord> activities = mTaskHistory.get(top).mActivities;
   3492             int activityTop = activities.size() - 1;
   3493             if (activityTop > 0) {
   3494                 finishActivityLocked(activities.get(activityTop), Activity.RESULT_CANCELED, null,
   3495                         "unhandled-back", true);
   3496             }
   3497         }
   3498     }
   3499 
   3500     /**
   3501      * Reset local parameters because an app's activity died.
   3502      * @param app The app of the activity that died.
   3503      * @return result from removeHistoryRecordsForAppLocked.
   3504      */
   3505     boolean handleAppDiedLocked(ProcessRecord app) {
   3506         if (mPausingActivity != null && mPausingActivity.app == app) {
   3507             if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG,
   3508                     "App died while pausing: " + mPausingActivity);
   3509             mPausingActivity = null;
   3510         }
   3511         if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
   3512             mLastPausedActivity = null;
   3513             mLastNoHistoryActivity = null;
   3514         }
   3515 
   3516         return removeHistoryRecordsForAppLocked(app);
   3517     }
   3518 
   3519     void handleAppCrashLocked(ProcessRecord app) {
   3520         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
   3521             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
   3522             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
   3523                 final ActivityRecord r = activities.get(activityNdx);
   3524                 if (r.app == app) {
   3525                     Slog.w(TAG, "  Force finishing activity "
   3526                             + r.intent.getComponent().flattenToShortString());
   3527                     finishActivityLocked(r, Activity.RESULT_CANCELED, null, "crashed", false);
   3528                 }
   3529             }
   3530         }
   3531     }
   3532 
   3533     boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
   3534             boolean dumpClient, String dumpPackage, boolean needSep, String header) {
   3535         boolean printed = false;
   3536         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
   3537             final TaskRecord task = mTaskHistory.get(taskNdx);
   3538             printed |= ActivityStackSupervisor.dumpHistoryList(fd, pw,
   3539                     mTaskHistory.get(taskNdx).mActivities, "    ", "Hist", true, !dumpAll,
   3540                     dumpClient, dumpPackage, needSep, header,
   3541                     "    Task id #" + task.taskId);
   3542             if (printed) {
   3543                 header = null;
   3544             }
   3545         }
   3546         return printed;
   3547     }
   3548 
   3549     ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
   3550         ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
   3551 
   3552         if ("all".equals(name)) {
   3553             for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
   3554                 activities.addAll(mTaskHistory.get(taskNdx).mActivities);
   3555             }
   3556         } else if ("top".equals(name)) {
   3557             final int top = mTaskHistory.size() - 1;
   3558             if (top >= 0) {
   3559                 final ArrayList<ActivityRecord> list = mTaskHistory.get(top).mActivities;
   3560                 int listTop = list.size() - 1;
   3561                 if (listTop >= 0) {
   3562                     activities.add(list.get(listTop));
   3563                 }
   3564             }
   3565         } else {
   3566             ItemMatcher matcher = new ItemMatcher();
   3567             matcher.build(name);
   3568 
   3569             for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
   3570                 for (ActivityRecord r1 : mTaskHistory.get(taskNdx).mActivities) {
   3571                     if (matcher.match(r1, r1.intent.getComponent())) {
   3572                         activities.add(r1);
   3573                     }
   3574                 }
   3575             }
   3576         }
   3577 
   3578         return activities;
   3579     }
   3580 
   3581     ActivityRecord restartPackage(String packageName) {
   3582         ActivityRecord starting = topRunningActivityLocked(null);
   3583 
   3584         // All activities that came from the package must be
   3585         // restarted as if there was a config change.
   3586         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
   3587             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
   3588             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
   3589                 final ActivityRecord a = activities.get(activityNdx);
   3590                 if (a.info.packageName.equals(packageName)) {
   3591                     a.forceNewConfig = true;
   3592                     if (starting != null && a == starting && a.visible) {
   3593                         a.startFreezingScreenLocked(starting.app,
   3594                                 ActivityInfo.CONFIG_SCREEN_LAYOUT);
   3595                     }
   3596                 }
   3597             }
   3598         }
   3599 
   3600         return starting;
   3601     }
   3602 
   3603     boolean removeTask(TaskRecord task) {
   3604         final int taskNdx = mTaskHistory.indexOf(task);
   3605         final int topTaskNdx = mTaskHistory.size() - 1;
   3606         if (task.mOnTopOfHome && taskNdx < topTaskNdx) {
   3607             mTaskHistory.get(taskNdx + 1).mOnTopOfHome = true;
   3608         }
   3609         mTaskHistory.remove(task);
   3610         return mTaskHistory.isEmpty();
   3611     }
   3612 
   3613     TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent, boolean toTop) {
   3614         TaskRecord task = new TaskRecord(taskId, info, intent);
   3615         addTask(task, toTop);
   3616         return task;
   3617     }
   3618 
   3619     ArrayList<TaskRecord> getAllTasks() {
   3620         return new ArrayList<TaskRecord>(mTaskHistory);
   3621     }
   3622 
   3623     void addTask(final TaskRecord task, final boolean toTop) {
   3624         task.stack = this;
   3625         if (toTop) {
   3626             insertTaskAtTop(task);
   3627         } else {
   3628             mTaskHistory.add(0, task);
   3629         }
   3630     }
   3631 
   3632     public int getStackId() {
   3633         return mStackId;
   3634     }
   3635 
   3636     @Override
   3637     public String toString() {
   3638         return "ActivityStack{" + Integer.toHexString(System.identityHashCode(this))
   3639                 + " stackId=" + mStackId + ", " + mTaskHistory.size() + " tasks}";
   3640     }
   3641 }
   3642