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