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