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 android.Manifest.permission.START_ANY_ACTIVITY;
     20 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
     21 
     22 import com.android.internal.app.HeavyWeightSwitcherActivity;
     23 import com.android.internal.os.BatteryStatsImpl;
     24 import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
     25 
     26 import android.app.Activity;
     27 import android.app.ActivityManager;
     28 import android.app.ActivityOptions;
     29 import android.app.AppGlobals;
     30 import android.app.IActivityManager;
     31 import android.app.IThumbnailRetriever;
     32 import android.app.IApplicationThread;
     33 import android.app.PendingIntent;
     34 import android.app.ResultInfo;
     35 import android.app.IActivityManager.WaitResult;
     36 import android.content.ComponentName;
     37 import android.content.Context;
     38 import android.content.IIntentSender;
     39 import android.content.Intent;
     40 import android.content.IntentSender;
     41 import android.content.pm.ActivityInfo;
     42 import android.content.pm.ApplicationInfo;
     43 import android.content.pm.PackageManager;
     44 import android.content.pm.ResolveInfo;
     45 import android.content.res.Configuration;
     46 import android.content.res.Resources;
     47 import android.graphics.Bitmap;
     48 import android.os.Binder;
     49 import android.os.Bundle;
     50 import android.os.Handler;
     51 import android.os.IBinder;
     52 import android.os.Message;
     53 import android.os.ParcelFileDescriptor;
     54 import android.os.PowerManager;
     55 import android.os.Process;
     56 import android.os.RemoteException;
     57 import android.os.SystemClock;
     58 import android.os.UserId;
     59 import android.util.EventLog;
     60 import android.util.Log;
     61 import android.util.Slog;
     62 import android.view.WindowManagerPolicy;
     63 
     64 import java.io.IOException;
     65 import java.lang.ref.WeakReference;
     66 import java.util.ArrayList;
     67 import java.util.Iterator;
     68 import java.util.List;
     69 
     70 /**
     71  * State and management of a single stack of activities.
     72  */
     73 final class ActivityStack {
     74     static final String TAG = ActivityManagerService.TAG;
     75     static final boolean localLOGV = ActivityManagerService.localLOGV;
     76     static final boolean DEBUG_SWITCH = ActivityManagerService.DEBUG_SWITCH;
     77     static final boolean DEBUG_PAUSE = ActivityManagerService.DEBUG_PAUSE;
     78     static final boolean DEBUG_VISBILITY = ActivityManagerService.DEBUG_VISBILITY;
     79     static final boolean DEBUG_USER_LEAVING = ActivityManagerService.DEBUG_USER_LEAVING;
     80     static final boolean DEBUG_TRANSITION = ActivityManagerService.DEBUG_TRANSITION;
     81     static final boolean DEBUG_RESULTS = ActivityManagerService.DEBUG_RESULTS;
     82     static final boolean DEBUG_CONFIGURATION = ActivityManagerService.DEBUG_CONFIGURATION;
     83     static final boolean DEBUG_TASKS = ActivityManagerService.DEBUG_TASKS;
     84 
     85     static final boolean DEBUG_STATES = false;
     86     static final boolean DEBUG_ADD_REMOVE = false;
     87     static final boolean DEBUG_SAVED_STATE = false;
     88 
     89     static final boolean VALIDATE_TOKENS = ActivityManagerService.VALIDATE_TOKENS;
     90 
     91     // How long we wait until giving up on the last activity telling us it
     92     // is idle.
     93     static final int IDLE_TIMEOUT = 10*1000;
     94 
     95     // Ticks during which we check progress while waiting for an app to launch.
     96     static final int LAUNCH_TICK = 500;
     97 
     98     // How long we wait until giving up on the last activity to pause.  This
     99     // is short because it directly impacts the responsiveness of starting the
    100     // next activity.
    101     static final int PAUSE_TIMEOUT = 500;
    102 
    103     // How long we wait for the activity to tell us it has stopped before
    104     // giving up.  This is a good amount of time because we really need this
    105     // from the application in order to get its saved state.
    106     static final int STOP_TIMEOUT = 10*1000;
    107 
    108     // How long we can hold the sleep wake lock before giving up.
    109     static final int SLEEP_TIMEOUT = 5*1000;
    110 
    111     // How long we can hold the launch wake lock before giving up.
    112     static final int LAUNCH_TIMEOUT = 10*1000;
    113 
    114     // How long we wait until giving up on an activity telling us it has
    115     // finished destroying itself.
    116     static final int DESTROY_TIMEOUT = 10*1000;
    117 
    118     // How long until we reset a task when the user returns to it.  Currently
    119     // disabled.
    120     static final long ACTIVITY_INACTIVE_RESET_TIME = 0;
    121 
    122     // How long between activity launches that we consider safe to not warn
    123     // the user about an unexpected activity being launched on top.
    124     static final long START_WARN_TIME = 5*1000;
    125 
    126     // Set to false to disable the preview that is shown while a new activity
    127     // is being started.
    128     static final boolean SHOW_APP_STARTING_PREVIEW = true;
    129 
    130     enum ActivityState {
    131         INITIALIZING,
    132         RESUMED,
    133         PAUSING,
    134         PAUSED,
    135         STOPPING,
    136         STOPPED,
    137         FINISHING,
    138         DESTROYING,
    139         DESTROYED
    140     }
    141 
    142     final ActivityManagerService mService;
    143     final boolean mMainStack;
    144 
    145     final Context mContext;
    146 
    147     /**
    148      * The back history of all previous (and possibly still
    149      * running) activities.  It contains HistoryRecord objects.
    150      */
    151     final ArrayList<ActivityRecord> mHistory = new ArrayList<ActivityRecord>();
    152 
    153     /**
    154      * Used for validating app tokens with window manager.
    155      */
    156     final ArrayList<IBinder> mValidateAppTokens = new ArrayList<IBinder>();
    157 
    158     /**
    159      * List of running activities, sorted by recent usage.
    160      * The first entry in the list is the least recently used.
    161      * It contains HistoryRecord objects.
    162      */
    163     final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<ActivityRecord>();
    164 
    165     /**
    166      * List of activities that are waiting for a new activity
    167      * to become visible before completing whatever operation they are
    168      * supposed to do.
    169      */
    170     final ArrayList<ActivityRecord> mWaitingVisibleActivities
    171             = new ArrayList<ActivityRecord>();
    172 
    173     /**
    174      * List of activities that are ready to be stopped, but waiting
    175      * for the next activity to settle down before doing so.  It contains
    176      * HistoryRecord objects.
    177      */
    178     final ArrayList<ActivityRecord> mStoppingActivities
    179             = new ArrayList<ActivityRecord>();
    180 
    181     /**
    182      * List of activities that are in the process of going to sleep.
    183      */
    184     final ArrayList<ActivityRecord> mGoingToSleepActivities
    185             = new ArrayList<ActivityRecord>();
    186 
    187     /**
    188      * Animations that for the current transition have requested not to
    189      * be considered for the transition animation.
    190      */
    191     final ArrayList<ActivityRecord> mNoAnimActivities
    192             = new ArrayList<ActivityRecord>();
    193 
    194     /**
    195      * List of activities that are ready to be finished, but waiting
    196      * for the previous activity to settle down before doing so.  It contains
    197      * HistoryRecord objects.
    198      */
    199     final ArrayList<ActivityRecord> mFinishingActivities
    200             = new ArrayList<ActivityRecord>();
    201 
    202     /**
    203      * List of people waiting to find out about the next launched activity.
    204      */
    205     final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
    206             = new ArrayList<IActivityManager.WaitResult>();
    207 
    208     /**
    209      * List of people waiting to find out about the next visible activity.
    210      */
    211     final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
    212             = new ArrayList<IActivityManager.WaitResult>();
    213 
    214     /**
    215      * Set when the system is going to sleep, until we have
    216      * successfully paused the current activity and released our wake lock.
    217      * At that point the system is allowed to actually sleep.
    218      */
    219     final PowerManager.WakeLock mGoingToSleep;
    220 
    221     /**
    222      * We don't want to allow the device to go to sleep while in the process
    223      * of launching an activity.  This is primarily to allow alarm intent
    224      * receivers to launch an activity and get that to run before the device
    225      * goes back to sleep.
    226      */
    227     final PowerManager.WakeLock mLaunchingActivity;
    228 
    229     /**
    230      * When we are in the process of pausing an activity, before starting the
    231      * next one, this variable holds the activity that is currently being paused.
    232      */
    233     ActivityRecord mPausingActivity = null;
    234 
    235     /**
    236      * This is the last activity that we put into the paused state.  This is
    237      * used to determine if we need to do an activity transition while sleeping,
    238      * when we normally hold the top activity paused.
    239      */
    240     ActivityRecord mLastPausedActivity = null;
    241 
    242     /**
    243      * Current activity that is resumed, or null if there is none.
    244      */
    245     ActivityRecord mResumedActivity = null;
    246 
    247     /**
    248      * This is the last activity that has been started.  It is only used to
    249      * identify when multiple activities are started at once so that the user
    250      * can be warned they may not be in the activity they think they are.
    251      */
    252     ActivityRecord mLastStartedActivity = null;
    253 
    254     /**
    255      * Set when we know we are going to be calling updateConfiguration()
    256      * soon, so want to skip intermediate config checks.
    257      */
    258     boolean mConfigWillChange;
    259 
    260     /**
    261      * Set to indicate whether to issue an onUserLeaving callback when a
    262      * newly launched activity is being brought in front of us.
    263      */
    264     boolean mUserLeaving = false;
    265 
    266     long mInitialStartTime = 0;
    267 
    268     /**
    269      * Set when we have taken too long waiting to go to sleep.
    270      */
    271     boolean mSleepTimeout = false;
    272 
    273     /**
    274      * Dismiss the keyguard after the next activity is displayed?
    275      */
    276     boolean mDismissKeyguardOnNextActivity = false;
    277 
    278     int mThumbnailWidth = -1;
    279     int mThumbnailHeight = -1;
    280 
    281     private int mCurrentUser;
    282 
    283     static final int SLEEP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG;
    284     static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
    285     static final int IDLE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
    286     static final int IDLE_NOW_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
    287     static final int LAUNCH_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 4;
    288     static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 5;
    289     static final int RESUME_TOP_ACTIVITY_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6;
    290     static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 7;
    291     static final int STOP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 8;
    292     static final int DESTROY_ACTIVITIES_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 9;
    293 
    294     static class ScheduleDestroyArgs {
    295         final ProcessRecord mOwner;
    296         final boolean mOomAdj;
    297         final String mReason;
    298         ScheduleDestroyArgs(ProcessRecord owner, boolean oomAdj, String reason) {
    299             mOwner = owner;
    300             mOomAdj = oomAdj;
    301             mReason = reason;
    302         }
    303     }
    304 
    305     final Handler mHandler = new Handler() {
    306         //public Handler() {
    307         //    if (localLOGV) Slog.v(TAG, "Handler started!");
    308         //}
    309 
    310         public void handleMessage(Message msg) {
    311             switch (msg.what) {
    312                 case SLEEP_TIMEOUT_MSG: {
    313                     synchronized (mService) {
    314                         if (mService.isSleeping()) {
    315                             Slog.w(TAG, "Sleep timeout!  Sleeping now.");
    316                             mSleepTimeout = true;
    317                             checkReadyForSleepLocked();
    318                         }
    319                     }
    320                 } break;
    321                 case PAUSE_TIMEOUT_MSG: {
    322                     ActivityRecord r = (ActivityRecord)msg.obj;
    323                     // We don't at this point know if the activity is fullscreen,
    324                     // so we need to be conservative and assume it isn't.
    325                     Slog.w(TAG, "Activity pause timeout for " + r);
    326                     synchronized (mService) {
    327                         if (r.app != null) {
    328                             mService.logAppTooSlow(r.app, r.pauseTime,
    329                                     "pausing " + r);
    330                         }
    331                     }
    332 
    333                     activityPaused(r != null ? r.appToken : null, true);
    334                 } break;
    335                 case IDLE_TIMEOUT_MSG: {
    336                     if (mService.mDidDexOpt) {
    337                         mService.mDidDexOpt = false;
    338                         Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
    339                         nmsg.obj = msg.obj;
    340                         mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
    341                         return;
    342                     }
    343                     // We don't at this point know if the activity is fullscreen,
    344                     // so we need to be conservative and assume it isn't.
    345                     ActivityRecord r = (ActivityRecord)msg.obj;
    346                     Slog.w(TAG, "Activity idle timeout for " + r);
    347                     activityIdleInternal(r != null ? r.appToken : null, true, null);
    348                 } break;
    349                 case LAUNCH_TICK_MSG: {
    350                     ActivityRecord r = (ActivityRecord)msg.obj;
    351                     synchronized (mService) {
    352                         if (r.continueLaunchTickingLocked()) {
    353                             mService.logAppTooSlow(r.app, r.launchTickTime,
    354                                     "launching " + r);
    355                         }
    356                     }
    357                 } break;
    358                 case DESTROY_TIMEOUT_MSG: {
    359                     ActivityRecord r = (ActivityRecord)msg.obj;
    360                     // We don't at this point know if the activity is fullscreen,
    361                     // so we need to be conservative and assume it isn't.
    362                     Slog.w(TAG, "Activity destroy timeout for " + r);
    363                     activityDestroyed(r != null ? r.appToken : null);
    364                 } break;
    365                 case IDLE_NOW_MSG: {
    366                     ActivityRecord r = (ActivityRecord)msg.obj;
    367                     activityIdleInternal(r != null ? r.appToken : null, false, null);
    368                 } break;
    369                 case LAUNCH_TIMEOUT_MSG: {
    370                     if (mService.mDidDexOpt) {
    371                         mService.mDidDexOpt = false;
    372                         Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
    373                         mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
    374                         return;
    375                     }
    376                     synchronized (mService) {
    377                         if (mLaunchingActivity.isHeld()) {
    378                             Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
    379                             mLaunchingActivity.release();
    380                         }
    381                     }
    382                 } break;
    383                 case RESUME_TOP_ACTIVITY_MSG: {
    384                     synchronized (mService) {
    385                         resumeTopActivityLocked(null);
    386                     }
    387                 } break;
    388                 case STOP_TIMEOUT_MSG: {
    389                     ActivityRecord r = (ActivityRecord)msg.obj;
    390                     // We don't at this point know if the activity is fullscreen,
    391                     // so we need to be conservative and assume it isn't.
    392                     Slog.w(TAG, "Activity stop timeout for " + r);
    393                     synchronized (mService) {
    394                         if (r.isInHistory()) {
    395                             activityStoppedLocked(r, null, null, null);
    396                         }
    397                     }
    398                 } break;
    399                 case DESTROY_ACTIVITIES_MSG: {
    400                     ScheduleDestroyArgs args = (ScheduleDestroyArgs)msg.obj;
    401                     synchronized (mService) {
    402                         destroyActivitiesLocked(args.mOwner, args.mOomAdj, args.mReason);
    403                     }
    404                 }
    405             }
    406         }
    407     };
    408 
    409     ActivityStack(ActivityManagerService service, Context context, boolean mainStack) {
    410         mService = service;
    411         mContext = context;
    412         mMainStack = mainStack;
    413         PowerManager pm =
    414             (PowerManager)context.getSystemService(Context.POWER_SERVICE);
    415         mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
    416         mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
    417         mLaunchingActivity.setReferenceCounted(false);
    418     }
    419 
    420     final ActivityRecord topRunningActivityLocked(ActivityRecord notTop) {
    421         // TODO: Don't look for any tasks from other users
    422         int i = mHistory.size()-1;
    423         while (i >= 0) {
    424             ActivityRecord r = mHistory.get(i);
    425             if (!r.finishing && r != notTop) {
    426                 return r;
    427             }
    428             i--;
    429         }
    430         return null;
    431     }
    432 
    433     final ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
    434         // TODO: Don't look for any tasks from other users
    435         int i = mHistory.size()-1;
    436         while (i >= 0) {
    437             ActivityRecord r = mHistory.get(i);
    438             if (!r.finishing && !r.delayedResume && r != notTop) {
    439                 return r;
    440             }
    441             i--;
    442         }
    443         return null;
    444     }
    445 
    446     /**
    447      * This is a simplified version of topRunningActivityLocked that provides a number of
    448      * optional skip-over modes.  It is intended for use with the ActivityController hook only.
    449      *
    450      * @param token If non-null, any history records matching this token will be skipped.
    451      * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
    452      *
    453      * @return Returns the HistoryRecord of the next activity on the stack.
    454      */
    455     final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) {
    456         // TODO: Don't look for any tasks from other users
    457         int i = mHistory.size()-1;
    458         while (i >= 0) {
    459             ActivityRecord r = mHistory.get(i);
    460             // Note: the taskId check depends on real taskId fields being non-zero
    461             if (!r.finishing && (token != r.appToken) && (taskId != r.task.taskId)) {
    462                 return r;
    463             }
    464             i--;
    465         }
    466         return null;
    467     }
    468 
    469     final int indexOfTokenLocked(IBinder token) {
    470         return mHistory.indexOf(ActivityRecord.forToken(token));
    471     }
    472 
    473     final int indexOfActivityLocked(ActivityRecord r) {
    474         return mHistory.indexOf(r);
    475     }
    476 
    477     final ActivityRecord isInStackLocked(IBinder token) {
    478         ActivityRecord r = ActivityRecord.forToken(token);
    479         if (mHistory.contains(r)) {
    480             return r;
    481         }
    482         return null;
    483     }
    484 
    485     private final boolean updateLRUListLocked(ActivityRecord r) {
    486         final boolean hadit = mLRUActivities.remove(r);
    487         mLRUActivities.add(r);
    488         return hadit;
    489     }
    490 
    491     /**
    492      * Returns the top activity in any existing task matching the given
    493      * Intent.  Returns null if no such task is found.
    494      */
    495     private ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
    496         ComponentName cls = intent.getComponent();
    497         if (info.targetActivity != null) {
    498             cls = new ComponentName(info.packageName, info.targetActivity);
    499         }
    500 
    501         TaskRecord cp = null;
    502 
    503         final int userId = UserId.getUserId(info.applicationInfo.uid);
    504         final int N = mHistory.size();
    505         for (int i=(N-1); i>=0; i--) {
    506             ActivityRecord r = mHistory.get(i);
    507             if (!r.finishing && r.task != cp && r.userId == userId
    508                     && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
    509                 cp = r.task;
    510                 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
    511                 //        + "/aff=" + r.task.affinity + " to new cls="
    512                 //        + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
    513                 if (r.task.affinity != null) {
    514                     if (r.task.affinity.equals(info.taskAffinity)) {
    515                         //Slog.i(TAG, "Found matching affinity!");
    516                         return r;
    517                     }
    518                 } else if (r.task.intent != null
    519                         && r.task.intent.getComponent().equals(cls)) {
    520                     //Slog.i(TAG, "Found matching class!");
    521                     //dump();
    522                     //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
    523                     return r;
    524                 } else if (r.task.affinityIntent != null
    525                         && r.task.affinityIntent.getComponent().equals(cls)) {
    526                     //Slog.i(TAG, "Found matching class!");
    527                     //dump();
    528                     //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
    529                     return r;
    530                 }
    531             }
    532         }
    533 
    534         return null;
    535     }
    536 
    537     /**
    538      * Returns the first activity (starting from the top of the stack) that
    539      * is the same as the given activity.  Returns null if no such activity
    540      * is found.
    541      */
    542     private ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
    543         ComponentName cls = intent.getComponent();
    544         if (info.targetActivity != null) {
    545             cls = new ComponentName(info.packageName, info.targetActivity);
    546         }
    547         final int userId = UserId.getUserId(info.applicationInfo.uid);
    548 
    549         final int N = mHistory.size();
    550         for (int i=(N-1); i>=0; i--) {
    551             ActivityRecord r = mHistory.get(i);
    552             if (!r.finishing) {
    553                 if (r.intent.getComponent().equals(cls) && r.userId == userId) {
    554                     //Slog.i(TAG, "Found matching class!");
    555                     //dump();
    556                     //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
    557                     return r;
    558                 }
    559             }
    560         }
    561 
    562         return null;
    563     }
    564 
    565     final void showAskCompatModeDialogLocked(ActivityRecord r) {
    566         Message msg = Message.obtain();
    567         msg.what = ActivityManagerService.SHOW_COMPAT_MODE_DIALOG_MSG;
    568         msg.obj = r.task.askedCompatMode ? null : r;
    569         mService.mHandler.sendMessage(msg);
    570     }
    571 
    572     /*
    573      * Move the activities around in the stack to bring a user to the foreground.
    574      * @return whether there are any activities for the specified user.
    575      */
    576     final boolean switchUser(int userId) {
    577         synchronized (mService) {
    578             mCurrentUser = userId;
    579 
    580             // Only one activity? Nothing to do...
    581             if (mHistory.size() < 2)
    582                 return false;
    583 
    584             boolean haveActivities = false;
    585             // Check if the top activity is from the new user.
    586             ActivityRecord top = mHistory.get(mHistory.size() - 1);
    587             if (top.userId == userId) return true;
    588             // Otherwise, move the user's activities to the top.
    589             int N = mHistory.size();
    590             int i = 0;
    591             while (i < N) {
    592                 ActivityRecord r = mHistory.get(i);
    593                 if (r.userId == userId) {
    594                     ActivityRecord moveToTop = mHistory.remove(i);
    595                     mHistory.add(moveToTop);
    596                     // No need to check the top one now
    597                     N--;
    598                     haveActivities = true;
    599                 } else {
    600                     i++;
    601                 }
    602             }
    603             // Transition from the old top to the new top
    604             resumeTopActivityLocked(top);
    605             return haveActivities;
    606         }
    607     }
    608 
    609     final boolean realStartActivityLocked(ActivityRecord r,
    610             ProcessRecord app, boolean andResume, boolean checkConfig)
    611             throws RemoteException {
    612 
    613         r.startFreezingScreenLocked(app, 0);
    614         mService.mWindowManager.setAppVisibility(r.appToken, true);
    615 
    616         // schedule launch ticks to collect information about slow apps.
    617         r.startLaunchTickingLocked();
    618 
    619         // Have the window manager re-evaluate the orientation of
    620         // the screen based on the new activity order.  Note that
    621         // as a result of this, it can call back into the activity
    622         // manager with a new orientation.  We don't care about that,
    623         // because the activity is not currently running so we are
    624         // just restarting it anyway.
    625         if (checkConfig) {
    626             Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
    627                     mService.mConfiguration,
    628                     r.mayFreezeScreenLocked(app) ? r.appToken : null);
    629             mService.updateConfigurationLocked(config, r, false, false);
    630         }
    631 
    632         r.app = app;
    633         app.waitingToKill = null;
    634 
    635         if (localLOGV) Slog.v(TAG, "Launching: " + r);
    636 
    637         int idx = app.activities.indexOf(r);
    638         if (idx < 0) {
    639             app.activities.add(r);
    640         }
    641         mService.updateLruProcessLocked(app, true, true);
    642 
    643         try {
    644             if (app.thread == null) {
    645                 throw new RemoteException();
    646             }
    647             List<ResultInfo> results = null;
    648             List<Intent> newIntents = null;
    649             if (andResume) {
    650                 results = r.results;
    651                 newIntents = r.newIntents;
    652             }
    653             if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
    654                     + " icicle=" + r.icicle
    655                     + " with results=" + results + " newIntents=" + newIntents
    656                     + " andResume=" + andResume);
    657             if (andResume) {
    658                 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
    659                         System.identityHashCode(r),
    660                         r.task.taskId, r.shortComponentName);
    661             }
    662             if (r.isHomeActivity) {
    663                 mService.mHomeProcess = app;
    664             }
    665             mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
    666             r.sleeping = false;
    667             r.forceNewConfig = false;
    668             showAskCompatModeDialogLocked(r);
    669             r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
    670             String profileFile = null;
    671             ParcelFileDescriptor profileFd = null;
    672             boolean profileAutoStop = false;
    673             if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
    674                 if (mService.mProfileProc == null || mService.mProfileProc == app) {
    675                     mService.mProfileProc = app;
    676                     profileFile = mService.mProfileFile;
    677                     profileFd = mService.mProfileFd;
    678                     profileAutoStop = mService.mAutoStopProfiler;
    679                 }
    680             }
    681             app.hasShownUi = true;
    682             app.pendingUiClean = true;
    683             if (profileFd != null) {
    684                 try {
    685                     profileFd = profileFd.dup();
    686                 } catch (IOException e) {
    687                     profileFd = null;
    688                 }
    689             }
    690             app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
    691                     System.identityHashCode(r), r.info,
    692                     new Configuration(mService.mConfiguration),
    693                     r.compat, r.icicle, results, newIntents, !andResume,
    694                     mService.isNextTransitionForward(), profileFile, profileFd,
    695                     profileAutoStop);
    696 
    697             if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
    698                 // This may be a heavy-weight process!  Note that the package
    699                 // manager will ensure that only activity can run in the main
    700                 // process of the .apk, which is the only thing that will be
    701                 // considered heavy-weight.
    702                 if (app.processName.equals(app.info.packageName)) {
    703                     if (mService.mHeavyWeightProcess != null
    704                             && mService.mHeavyWeightProcess != app) {
    705                         Log.w(TAG, "Starting new heavy weight process " + app
    706                                 + " when already running "
    707                                 + mService.mHeavyWeightProcess);
    708                     }
    709                     mService.mHeavyWeightProcess = app;
    710                     Message msg = mService.mHandler.obtainMessage(
    711                             ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
    712                     msg.obj = r;
    713                     mService.mHandler.sendMessage(msg);
    714                 }
    715             }
    716 
    717         } catch (RemoteException e) {
    718             if (r.launchFailed) {
    719                 // This is the second time we failed -- finish activity
    720                 // and give up.
    721                 Slog.e(TAG, "Second failure launching "
    722                       + r.intent.getComponent().flattenToShortString()
    723                       + ", giving up", e);
    724                 mService.appDiedLocked(app, app.pid, app.thread);
    725                 requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
    726                         "2nd-crash");
    727                 return false;
    728             }
    729 
    730             // This is the first time we failed -- restart process and
    731             // retry.
    732             app.activities.remove(r);
    733             throw e;
    734         }
    735 
    736         r.launchFailed = false;
    737         if (updateLRUListLocked(r)) {
    738             Slog.w(TAG, "Activity " + r
    739                   + " being launched, but already in LRU list");
    740         }
    741 
    742         if (andResume) {
    743             // As part of the process of launching, ActivityThread also performs
    744             // a resume.
    745             r.state = ActivityState.RESUMED;
    746             if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + r
    747                     + " (starting new instance)");
    748             r.stopped = false;
    749             mResumedActivity = r;
    750             r.task.touchActiveTime();
    751             if (mMainStack) {
    752                 mService.addRecentTaskLocked(r.task);
    753             }
    754             completeResumeLocked(r);
    755             checkReadyForSleepLocked();
    756             if (DEBUG_SAVED_STATE) Slog.i(TAG, "Launch completed; removing icicle of " + r.icicle);
    757             r.icicle = null;
    758             r.haveState = false;
    759         } else {
    760             // This activity is not starting in the resumed state... which
    761             // should look like we asked it to pause+stop (but remain visible),
    762             // and it has done so and reported back the current icicle and
    763             // other state.
    764             if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
    765                     + " (starting in stopped state)");
    766             r.state = ActivityState.STOPPED;
    767             r.stopped = true;
    768         }
    769 
    770         // Launch the new version setup screen if needed.  We do this -after-
    771         // launching the initial activity (that is, home), so that it can have
    772         // a chance to initialize itself while in the background, making the
    773         // switch back to it faster and look better.
    774         if (mMainStack) {
    775             mService.startSetupActivityLocked();
    776         }
    777 
    778         return true;
    779     }
    780 
    781     private final void startSpecificActivityLocked(ActivityRecord r,
    782             boolean andResume, boolean checkConfig) {
    783         // Is this activity's application already running?
    784         ProcessRecord app = mService.getProcessRecordLocked(r.processName,
    785                 r.info.applicationInfo.uid);
    786 
    787         if (r.launchTime == 0) {
    788             r.launchTime = SystemClock.uptimeMillis();
    789             if (mInitialStartTime == 0) {
    790                 mInitialStartTime = r.launchTime;
    791             }
    792         } else if (mInitialStartTime == 0) {
    793             mInitialStartTime = SystemClock.uptimeMillis();
    794         }
    795 
    796         if (app != null && app.thread != null) {
    797             try {
    798                 app.addPackage(r.info.packageName);
    799                 realStartActivityLocked(r, app, andResume, checkConfig);
    800                 return;
    801             } catch (RemoteException e) {
    802                 Slog.w(TAG, "Exception when starting activity "
    803                         + r.intent.getComponent().flattenToShortString(), e);
    804             }
    805 
    806             // If a dead object exception was thrown -- fall through to
    807             // restart the application.
    808         }
    809 
    810         mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
    811                 "activity", r.intent.getComponent(), false, false);
    812     }
    813 
    814     void stopIfSleepingLocked() {
    815         if (mService.isSleeping()) {
    816             if (!mGoingToSleep.isHeld()) {
    817                 mGoingToSleep.acquire();
    818                 if (mLaunchingActivity.isHeld()) {
    819                     mLaunchingActivity.release();
    820                     mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
    821                 }
    822             }
    823             mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
    824             Message msg = mHandler.obtainMessage(SLEEP_TIMEOUT_MSG);
    825             mHandler.sendMessageDelayed(msg, SLEEP_TIMEOUT);
    826             checkReadyForSleepLocked();
    827         }
    828     }
    829 
    830     void awakeFromSleepingLocked() {
    831         mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
    832         mSleepTimeout = false;
    833         if (mGoingToSleep.isHeld()) {
    834             mGoingToSleep.release();
    835         }
    836         // Ensure activities are no longer sleeping.
    837         for (int i=mHistory.size()-1; i>=0; i--) {
    838             ActivityRecord r = mHistory.get(i);
    839             r.setSleeping(false);
    840         }
    841         mGoingToSleepActivities.clear();
    842     }
    843 
    844     void activitySleptLocked(ActivityRecord r) {
    845         mGoingToSleepActivities.remove(r);
    846         checkReadyForSleepLocked();
    847     }
    848 
    849     void checkReadyForSleepLocked() {
    850         if (!mService.isSleeping()) {
    851             // Do not care.
    852             return;
    853         }
    854 
    855         if (!mSleepTimeout) {
    856             if (mResumedActivity != null) {
    857                 // Still have something resumed; can't sleep until it is paused.
    858                 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause " + mResumedActivity);
    859                 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
    860                 startPausingLocked(false, true);
    861                 return;
    862             }
    863             if (mPausingActivity != null) {
    864                 // Still waiting for something to pause; can't sleep yet.
    865                 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still waiting to pause " + mPausingActivity);
    866                 return;
    867             }
    868 
    869             if (mStoppingActivities.size() > 0) {
    870                 // Still need to tell some activities to stop; can't sleep yet.
    871                 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
    872                         + mStoppingActivities.size() + " activities");
    873                 scheduleIdleLocked();
    874                 return;
    875             }
    876 
    877             ensureActivitiesVisibleLocked(null, 0);
    878 
    879             // Make sure any stopped but visible activities are now sleeping.
    880             // This ensures that the activity's onStop() is called.
    881             for (int i=mHistory.size()-1; i>=0; i--) {
    882                 ActivityRecord r = mHistory.get(i);
    883                 if (r.state == ActivityState.STOPPING || r.state == ActivityState.STOPPED) {
    884                     r.setSleeping(true);
    885                 }
    886             }
    887 
    888             if (mGoingToSleepActivities.size() > 0) {
    889                 // Still need to tell some activities to sleep; can't sleep yet.
    890                 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
    891                         + mGoingToSleepActivities.size() + " activities");
    892                 return;
    893             }
    894         }
    895 
    896         mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
    897 
    898         if (mGoingToSleep.isHeld()) {
    899             mGoingToSleep.release();
    900         }
    901         if (mService.mShuttingDown) {
    902             mService.notifyAll();
    903         }
    904     }
    905 
    906     public final Bitmap screenshotActivities(ActivityRecord who) {
    907         if (who.noDisplay) {
    908             return null;
    909         }
    910 
    911         Resources res = mService.mContext.getResources();
    912         int w = mThumbnailWidth;
    913         int h = mThumbnailHeight;
    914         if (w < 0) {
    915             mThumbnailWidth = w =
    916                 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
    917             mThumbnailHeight = h =
    918                 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
    919         }
    920 
    921         if (w > 0) {
    922             return mService.mWindowManager.screenshotApplications(who.appToken, w, h);
    923         }
    924         return null;
    925     }
    926 
    927     private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
    928         if (mPausingActivity != null) {
    929             RuntimeException e = new RuntimeException();
    930             Slog.e(TAG, "Trying to pause when pause is already pending for "
    931                   + mPausingActivity, e);
    932         }
    933         ActivityRecord prev = mResumedActivity;
    934         if (prev == null) {
    935             RuntimeException e = new RuntimeException();
    936             Slog.e(TAG, "Trying to pause when nothing is resumed", e);
    937             resumeTopActivityLocked(null);
    938             return;
    939         }
    940         if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev);
    941         else if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
    942         mResumedActivity = null;
    943         mPausingActivity = prev;
    944         mLastPausedActivity = prev;
    945         prev.state = ActivityState.PAUSING;
    946         prev.task.touchActiveTime();
    947         prev.updateThumbnail(screenshotActivities(prev), null);
    948 
    949         mService.updateCpuStats();
    950 
    951         if (prev.app != null && prev.app.thread != null) {
    952             if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
    953             try {
    954                 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
    955                         System.identityHashCode(prev),
    956                         prev.shortComponentName);
    957                 prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
    958                         userLeaving, prev.configChangeFlags);
    959                 if (mMainStack) {
    960                     mService.updateUsageStats(prev, false);
    961                 }
    962             } catch (Exception e) {
    963                 // Ignore exception, if process died other code will cleanup.
    964                 Slog.w(TAG, "Exception thrown during pause", e);
    965                 mPausingActivity = null;
    966                 mLastPausedActivity = null;
    967             }
    968         } else {
    969             mPausingActivity = null;
    970             mLastPausedActivity = null;
    971         }
    972 
    973         // If we are not going to sleep, we want to ensure the device is
    974         // awake until the next activity is started.
    975         if (!mService.mSleeping && !mService.mShuttingDown) {
    976             mLaunchingActivity.acquire();
    977             if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
    978                 // To be safe, don't allow the wake lock to be held for too long.
    979                 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
    980                 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
    981             }
    982         }
    983 
    984 
    985         if (mPausingActivity != null) {
    986             // Have the window manager pause its key dispatching until the new
    987             // activity has started.  If we're pausing the activity just because
    988             // the screen is being turned off and the UI is sleeping, don't interrupt
    989             // key dispatch; the same activity will pick it up again on wakeup.
    990             if (!uiSleeping) {
    991                 prev.pauseKeyDispatchingLocked();
    992             } else {
    993                 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
    994             }
    995 
    996             // Schedule a pause timeout in case the app doesn't respond.
    997             // We don't give it much time because this directly impacts the
    998             // responsiveness seen by the user.
    999             Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
   1000             msg.obj = prev;
   1001             prev.pauseTime = SystemClock.uptimeMillis();
   1002             mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
   1003             if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
   1004         } else {
   1005             // This activity failed to schedule the
   1006             // pause, so just treat it as being paused now.
   1007             if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
   1008             resumeTopActivityLocked(null);
   1009         }
   1010     }
   1011 
   1012     final void activityPaused(IBinder token, boolean timeout) {
   1013         if (DEBUG_PAUSE) Slog.v(
   1014             TAG, "Activity paused: token=" + token + ", timeout=" + timeout);
   1015 
   1016         ActivityRecord r = null;
   1017 
   1018         synchronized (mService) {
   1019             int index = indexOfTokenLocked(token);
   1020             if (index >= 0) {
   1021                 r = mHistory.get(index);
   1022                 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
   1023                 if (mPausingActivity == r) {
   1024                     if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r
   1025                             + (timeout ? " (due to timeout)" : " (pause complete)"));
   1026                     r.state = ActivityState.PAUSED;
   1027                     completePauseLocked();
   1028                 } else {
   1029                     EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
   1030                             System.identityHashCode(r), r.shortComponentName,
   1031                             mPausingActivity != null
   1032                                 ? mPausingActivity.shortComponentName : "(none)");
   1033                 }
   1034             }
   1035         }
   1036     }
   1037 
   1038     final void activityStoppedLocked(ActivityRecord r, Bundle icicle, Bitmap thumbnail,
   1039             CharSequence description) {
   1040         if (r.state != ActivityState.STOPPING) {
   1041             Slog.i(TAG, "Activity reported stop, but no longer stopping: " + r);
   1042             mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
   1043             return;
   1044         }
   1045         if (DEBUG_SAVED_STATE) Slog.i(TAG, "Saving icicle of " + r + ": " + icicle);
   1046         if (icicle != null) {
   1047             // If icicle is null, this is happening due to a timeout, so we
   1048             // haven't really saved the state.
   1049             r.icicle = icicle;
   1050             r.haveState = true;
   1051             r.updateThumbnail(thumbnail, description);
   1052         }
   1053         if (!r.stopped) {
   1054             if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r + " (stop complete)");
   1055             mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
   1056             r.stopped = true;
   1057             r.state = ActivityState.STOPPED;
   1058             if (r.finishing) {
   1059                 r.clearOptionsLocked();
   1060             } else {
   1061                 if (r.configDestroy) {
   1062                     destroyActivityLocked(r, true, false, "stop-config");
   1063                     resumeTopActivityLocked(null);
   1064                 } else {
   1065                     // Now that this process has stopped, we may want to consider
   1066                     // it to be the previous app to try to keep around in case
   1067                     // the user wants to return to it.
   1068                     ProcessRecord fgApp = null;
   1069                     if (mResumedActivity != null) {
   1070                         fgApp = mResumedActivity.app;
   1071                     } else if (mPausingActivity != null) {
   1072                         fgApp = mPausingActivity.app;
   1073                     }
   1074                     if (r.app != null && fgApp != null && r.app != fgApp
   1075                             && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
   1076                             && r.app != mService.mHomeProcess) {
   1077                         mService.mPreviousProcess = r.app;
   1078                         mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
   1079                     }
   1080                 }
   1081             }
   1082         }
   1083     }
   1084 
   1085     private final void completePauseLocked() {
   1086         ActivityRecord prev = mPausingActivity;
   1087         if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
   1088 
   1089         if (prev != null) {
   1090             if (prev.finishing) {
   1091                 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
   1092                 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
   1093             } else if (prev.app != null) {
   1094                 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
   1095                 if (prev.waitingVisible) {
   1096                     prev.waitingVisible = false;
   1097                     mWaitingVisibleActivities.remove(prev);
   1098                     if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
   1099                             TAG, "Complete pause, no longer waiting: " + prev);
   1100                 }
   1101                 if (prev.configDestroy) {
   1102                     // The previous is being paused because the configuration
   1103                     // is changing, which means it is actually stopping...
   1104                     // To juggle the fact that we are also starting a new
   1105                     // instance right now, we need to first completely stop
   1106                     // the current instance before starting the new one.
   1107                     if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
   1108                     destroyActivityLocked(prev, true, false, "pause-config");
   1109                 } else {
   1110                     mStoppingActivities.add(prev);
   1111                     if (mStoppingActivities.size() > 3) {
   1112                         // If we already have a few activities waiting to stop,
   1113                         // then give up on things going idle and start clearing
   1114                         // them out.
   1115                         if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
   1116                         scheduleIdleLocked();
   1117                     } else {
   1118                         checkReadyForSleepLocked();
   1119                     }
   1120                 }
   1121             } else {
   1122                 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
   1123                 prev = null;
   1124             }
   1125             mPausingActivity = null;
   1126         }
   1127 
   1128         if (!mService.isSleeping()) {
   1129             resumeTopActivityLocked(prev);
   1130         } else {
   1131             checkReadyForSleepLocked();
   1132             if (topRunningActivityLocked(null) == null) {
   1133                 // If there are no more activities available to run, then
   1134                 // do resume anyway to start something.
   1135                 resumeTopActivityLocked(null);
   1136             }
   1137         }
   1138 
   1139         if (prev != null) {
   1140             prev.resumeKeyDispatchingLocked();
   1141         }
   1142 
   1143         if (prev.app != null && prev.cpuTimeAtResume > 0
   1144                 && mService.mBatteryStatsService.isOnBattery()) {
   1145             long diff = 0;
   1146             synchronized (mService.mProcessStatsThread) {
   1147                 diff = mService.mProcessStats.getCpuTimeForPid(prev.app.pid)
   1148                         - prev.cpuTimeAtResume;
   1149             }
   1150             if (diff > 0) {
   1151                 BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics();
   1152                 synchronized (bsi) {
   1153                     BatteryStatsImpl.Uid.Proc ps =
   1154                             bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
   1155                             prev.info.packageName);
   1156                     if (ps != null) {
   1157                         ps.addForegroundTimeLocked(diff);
   1158                     }
   1159                 }
   1160             }
   1161         }
   1162         prev.cpuTimeAtResume = 0; // reset it
   1163     }
   1164 
   1165     /**
   1166      * Once we know that we have asked an application to put an activity in
   1167      * the resumed state (either by launching it or explicitly telling it),
   1168      * this function updates the rest of our state to match that fact.
   1169      */
   1170     private final void completeResumeLocked(ActivityRecord next) {
   1171         next.idle = false;
   1172         next.results = null;
   1173         next.newIntents = null;
   1174 
   1175         // schedule an idle timeout in case the app doesn't do it for us.
   1176         Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
   1177         msg.obj = next;
   1178         mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
   1179 
   1180         if (false) {
   1181             // The activity was never told to pause, so just keep
   1182             // things going as-is.  To maintain our own state,
   1183             // we need to emulate it coming back and saying it is
   1184             // idle.
   1185             msg = mHandler.obtainMessage(IDLE_NOW_MSG);
   1186             msg.obj = next;
   1187             mHandler.sendMessage(msg);
   1188         }
   1189 
   1190         if (mMainStack) {
   1191             mService.reportResumedActivityLocked(next);
   1192         }
   1193 
   1194         next.clearThumbnail();
   1195         if (mMainStack) {
   1196             mService.setFocusedActivityLocked(next);
   1197         }
   1198         next.resumeKeyDispatchingLocked();
   1199         ensureActivitiesVisibleLocked(null, 0);
   1200         mService.mWindowManager.executeAppTransition();
   1201         mNoAnimActivities.clear();
   1202 
   1203         // Mark the point when the activity is resuming
   1204         // TODO: To be more accurate, the mark should be before the onCreate,
   1205         //       not after the onResume. But for subsequent starts, onResume is fine.
   1206         if (next.app != null) {
   1207             synchronized (mService.mProcessStatsThread) {
   1208                 next.cpuTimeAtResume = mService.mProcessStats.getCpuTimeForPid(next.app.pid);
   1209             }
   1210         } else {
   1211             next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
   1212         }
   1213     }
   1214 
   1215     /**
   1216      * Make sure that all activities that need to be visible (that is, they
   1217      * currently can be seen by the user) actually are.
   1218      */
   1219     final void ensureActivitiesVisibleLocked(ActivityRecord top,
   1220             ActivityRecord starting, String onlyThisProcess, int configChanges) {
   1221         if (DEBUG_VISBILITY) Slog.v(
   1222                 TAG, "ensureActivitiesVisible behind " + top
   1223                 + " configChanges=0x" + Integer.toHexString(configChanges));
   1224 
   1225         // If the top activity is not fullscreen, then we need to
   1226         // make sure any activities under it are now visible.
   1227         final int count = mHistory.size();
   1228         int i = count-1;
   1229         while (mHistory.get(i) != top) {
   1230             i--;
   1231         }
   1232         ActivityRecord r;
   1233         boolean behindFullscreen = false;
   1234         for (; i>=0; i--) {
   1235             r = mHistory.get(i);
   1236             if (DEBUG_VISBILITY) Slog.v(
   1237                     TAG, "Make visible? " + r + " finishing=" + r.finishing
   1238                     + " state=" + r.state);
   1239             if (r.finishing) {
   1240                 continue;
   1241             }
   1242 
   1243             final boolean doThisProcess = onlyThisProcess == null
   1244                     || onlyThisProcess.equals(r.processName);
   1245 
   1246             // First: if this is not the current activity being started, make
   1247             // sure it matches the current configuration.
   1248             if (r != starting && doThisProcess) {
   1249                 ensureActivityConfigurationLocked(r, 0);
   1250             }
   1251 
   1252             if (r.app == null || r.app.thread == null) {
   1253                 if (onlyThisProcess == null
   1254                         || onlyThisProcess.equals(r.processName)) {
   1255                     // This activity needs to be visible, but isn't even
   1256                     // running...  get it started, but don't resume it
   1257                     // at this point.
   1258                     if (DEBUG_VISBILITY) Slog.v(
   1259                             TAG, "Start and freeze screen for " + r);
   1260                     if (r != starting) {
   1261                         r.startFreezingScreenLocked(r.app, configChanges);
   1262                     }
   1263                     if (!r.visible) {
   1264                         if (DEBUG_VISBILITY) Slog.v(
   1265                                 TAG, "Starting and making visible: " + r);
   1266                         mService.mWindowManager.setAppVisibility(r.appToken, true);
   1267                     }
   1268                     if (r != starting) {
   1269                         startSpecificActivityLocked(r, false, false);
   1270                     }
   1271                 }
   1272 
   1273             } else if (r.visible) {
   1274                 // If this activity is already visible, then there is nothing
   1275                 // else to do here.
   1276                 if (DEBUG_VISBILITY) Slog.v(
   1277                         TAG, "Skipping: already visible at " + r);
   1278                 r.stopFreezingScreenLocked(false);
   1279 
   1280             } else if (onlyThisProcess == null) {
   1281                 // This activity is not currently visible, but is running.
   1282                 // Tell it to become visible.
   1283                 r.visible = true;
   1284                 if (r.state != ActivityState.RESUMED && r != starting) {
   1285                     // If this activity is paused, tell it
   1286                     // to now show its window.
   1287                     if (DEBUG_VISBILITY) Slog.v(
   1288                             TAG, "Making visible and scheduling visibility: " + r);
   1289                     try {
   1290                         mService.mWindowManager.setAppVisibility(r.appToken, true);
   1291                         r.sleeping = false;
   1292                         r.app.pendingUiClean = true;
   1293                         r.app.thread.scheduleWindowVisibility(r.appToken, true);
   1294                         r.stopFreezingScreenLocked(false);
   1295                     } catch (Exception e) {
   1296                         // Just skip on any failure; we'll make it
   1297                         // visible when it next restarts.
   1298                         Slog.w(TAG, "Exception thrown making visibile: "
   1299                                 + r.intent.getComponent(), e);
   1300                     }
   1301                 }
   1302             }
   1303 
   1304             // Aggregate current change flags.
   1305             configChanges |= r.configChangeFlags;
   1306 
   1307             if (r.fullscreen) {
   1308                 // At this point, nothing else needs to be shown
   1309                 if (DEBUG_VISBILITY) Slog.v(
   1310                         TAG, "Stopping: fullscreen at " + r);
   1311                 behindFullscreen = true;
   1312                 i--;
   1313                 break;
   1314             }
   1315         }
   1316 
   1317         // Now for any activities that aren't visible to the user, make
   1318         // sure they no longer are keeping the screen frozen.
   1319         while (i >= 0) {
   1320             r = mHistory.get(i);
   1321             if (DEBUG_VISBILITY) Slog.v(
   1322                     TAG, "Make invisible? " + r + " finishing=" + r.finishing
   1323                     + " state=" + r.state
   1324                     + " behindFullscreen=" + behindFullscreen);
   1325             if (!r.finishing) {
   1326                 if (behindFullscreen) {
   1327                     if (r.visible) {
   1328                         if (DEBUG_VISBILITY) Slog.v(
   1329                                 TAG, "Making invisible: " + r);
   1330                         r.visible = false;
   1331                         try {
   1332                             mService.mWindowManager.setAppVisibility(r.appToken, false);
   1333                             if ((r.state == ActivityState.STOPPING
   1334                                     || r.state == ActivityState.STOPPED)
   1335                                     && r.app != null && r.app.thread != null) {
   1336                                 if (DEBUG_VISBILITY) Slog.v(
   1337                                         TAG, "Scheduling invisibility: " + r);
   1338                                 r.app.thread.scheduleWindowVisibility(r.appToken, false);
   1339                             }
   1340                         } catch (Exception e) {
   1341                             // Just skip on any failure; we'll make it
   1342                             // visible when it next restarts.
   1343                             Slog.w(TAG, "Exception thrown making hidden: "
   1344                                     + r.intent.getComponent(), e);
   1345                         }
   1346                     } else {
   1347                         if (DEBUG_VISBILITY) Slog.v(
   1348                                 TAG, "Already invisible: " + r);
   1349                     }
   1350                 } else if (r.fullscreen) {
   1351                     if (DEBUG_VISBILITY) Slog.v(
   1352                             TAG, "Now behindFullscreen: " + r);
   1353                     behindFullscreen = true;
   1354                 }
   1355             }
   1356             i--;
   1357         }
   1358     }
   1359 
   1360     /**
   1361      * Version of ensureActivitiesVisible that can easily be called anywhere.
   1362      */
   1363     final void ensureActivitiesVisibleLocked(ActivityRecord starting,
   1364             int configChanges) {
   1365         ActivityRecord r = topRunningActivityLocked(null);
   1366         if (r != null) {
   1367             ensureActivitiesVisibleLocked(r, starting, null, configChanges);
   1368         }
   1369     }
   1370 
   1371     /**
   1372      * Ensure that the top activity in the stack is resumed.
   1373      *
   1374      * @param prev The previously resumed activity, for when in the process
   1375      * of pausing; can be null to call from elsewhere.
   1376      *
   1377      * @return Returns true if something is being resumed, or false if
   1378      * nothing happened.
   1379      */
   1380     final boolean resumeTopActivityLocked(ActivityRecord prev) {
   1381         return resumeTopActivityLocked(prev, null);
   1382     }
   1383 
   1384     final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
   1385         // Find the first activity that is not finishing.
   1386         ActivityRecord next = topRunningActivityLocked(null);
   1387 
   1388         // Remember how we'll process this pause/resume situation, and ensure
   1389         // that the state is reset however we wind up proceeding.
   1390         final boolean userLeaving = mUserLeaving;
   1391         mUserLeaving = false;
   1392 
   1393         if (next == null) {
   1394             // There are no more activities!  Let's just start up the
   1395             // Launcher...
   1396             if (mMainStack) {
   1397                 ActivityOptions.abort(options);
   1398                 return mService.startHomeActivityLocked(0);
   1399             }
   1400         }
   1401 
   1402         next.delayedResume = false;
   1403 
   1404         // If the top activity is the resumed one, nothing to do.
   1405         if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
   1406             // Make sure we have executed any pending transitions, since there
   1407             // should be nothing left to do at this point.
   1408             mService.mWindowManager.executeAppTransition();
   1409             mNoAnimActivities.clear();
   1410             ActivityOptions.abort(options);
   1411             return false;
   1412         }
   1413 
   1414         // If we are sleeping, and there is no resumed activity, and the top
   1415         // activity is paused, well that is the state we want.
   1416         if ((mService.mSleeping || mService.mShuttingDown)
   1417                 && mLastPausedActivity == next
   1418                 && (next.state == ActivityState.PAUSED
   1419                     || next.state == ActivityState.STOPPED
   1420                     || next.state == ActivityState.STOPPING)) {
   1421             // Make sure we have executed any pending transitions, since there
   1422             // should be nothing left to do at this point.
   1423             mService.mWindowManager.executeAppTransition();
   1424             mNoAnimActivities.clear();
   1425             ActivityOptions.abort(options);
   1426             return false;
   1427         }
   1428 
   1429         // The activity may be waiting for stop, but that is no longer
   1430         // appropriate for it.
   1431         mStoppingActivities.remove(next);
   1432         mGoingToSleepActivities.remove(next);
   1433         next.sleeping = false;
   1434         mWaitingVisibleActivities.remove(next);
   1435 
   1436         next.updateOptionsLocked(options);
   1437 
   1438         if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
   1439 
   1440         // If we are currently pausing an activity, then don't do anything
   1441         // until that is done.
   1442         if (mPausingActivity != null) {
   1443             if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
   1444             return false;
   1445         }
   1446 
   1447         // Okay we are now going to start a switch, to 'next'.  We may first
   1448         // have to pause the current activity, but this is an important point
   1449         // where we have decided to go to 'next' so keep track of that.
   1450         // XXX "App Redirected" dialog is getting too many false positives
   1451         // at this point, so turn off for now.
   1452         if (false) {
   1453             if (mLastStartedActivity != null && !mLastStartedActivity.finishing) {
   1454                 long now = SystemClock.uptimeMillis();
   1455                 final boolean inTime = mLastStartedActivity.startTime != 0
   1456                         && (mLastStartedActivity.startTime + START_WARN_TIME) >= now;
   1457                 final int lastUid = mLastStartedActivity.info.applicationInfo.uid;
   1458                 final int nextUid = next.info.applicationInfo.uid;
   1459                 if (inTime && lastUid != nextUid
   1460                         && lastUid != next.launchedFromUid
   1461                         && mService.checkPermission(
   1462                                 android.Manifest.permission.STOP_APP_SWITCHES,
   1463                                 -1, next.launchedFromUid)
   1464                         != PackageManager.PERMISSION_GRANTED) {
   1465                     mService.showLaunchWarningLocked(mLastStartedActivity, next);
   1466                 } else {
   1467                     next.startTime = now;
   1468                     mLastStartedActivity = next;
   1469                 }
   1470             } else {
   1471                 next.startTime = SystemClock.uptimeMillis();
   1472                 mLastStartedActivity = next;
   1473             }
   1474         }
   1475 
   1476         // We need to start pausing the current activity so the top one
   1477         // can be resumed...
   1478         if (mResumedActivity != null) {
   1479             if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
   1480             startPausingLocked(userLeaving, false);
   1481             return true;
   1482         }
   1483 
   1484         // If the most recent activity was noHistory but was only stopped rather
   1485         // than stopped+finished because the device went to sleep, we need to make
   1486         // sure to finish it as we're making a new activity topmost.
   1487         final ActivityRecord last = mLastPausedActivity;
   1488         if (mService.mSleeping && last != null && !last.finishing) {
   1489             if ((last.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
   1490                     || (last.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
   1491                 if (DEBUG_STATES) {
   1492                     Slog.d(TAG, "no-history finish of " + last + " on new resume");
   1493                 }
   1494                 requestFinishActivityLocked(last.appToken, Activity.RESULT_CANCELED, null,
   1495                 "no-history");
   1496             }
   1497         }
   1498 
   1499         if (prev != null && prev != next) {
   1500             if (!prev.waitingVisible && next != null && !next.nowVisible) {
   1501                 prev.waitingVisible = true;
   1502                 mWaitingVisibleActivities.add(prev);
   1503                 if (DEBUG_SWITCH) Slog.v(
   1504                         TAG, "Resuming top, waiting visible to hide: " + prev);
   1505             } else {
   1506                 // The next activity is already visible, so hide the previous
   1507                 // activity's windows right now so we can show the new one ASAP.
   1508                 // We only do this if the previous is finishing, which should mean
   1509                 // it is on top of the one being resumed so hiding it quickly
   1510                 // is good.  Otherwise, we want to do the normal route of allowing
   1511                 // the resumed activity to be shown so we can decide if the
   1512                 // previous should actually be hidden depending on whether the
   1513                 // new one is found to be full-screen or not.
   1514                 if (prev.finishing) {
   1515                     mService.mWindowManager.setAppVisibility(prev.appToken, false);
   1516                     if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
   1517                             + prev + ", waitingVisible="
   1518                             + (prev != null ? prev.waitingVisible : null)
   1519                             + ", nowVisible=" + next.nowVisible);
   1520                 } else {
   1521                     if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
   1522                         + prev + ", waitingVisible="
   1523                         + (prev != null ? prev.waitingVisible : null)
   1524                         + ", nowVisible=" + next.nowVisible);
   1525                 }
   1526             }
   1527         }
   1528 
   1529         // Launching this app's activity, make sure the app is no longer
   1530         // considered stopped.
   1531         try {
   1532             AppGlobals.getPackageManager().setPackageStoppedState(
   1533                     next.packageName, false, next.userId); /* TODO: Verify if correct userid */
   1534         } catch (RemoteException e1) {
   1535         } catch (IllegalArgumentException e) {
   1536             Slog.w(TAG, "Failed trying to unstop package "
   1537                     + next.packageName + ": " + e);
   1538         }
   1539 
   1540         // We are starting up the next activity, so tell the window manager
   1541         // that the previous one will be hidden soon.  This way it can know
   1542         // to ignore it when computing the desired screen orientation.
   1543         boolean noAnim = false;
   1544         if (prev != null) {
   1545             if (prev.finishing) {
   1546                 if (DEBUG_TRANSITION) Slog.v(TAG,
   1547                         "Prepare close transition: prev=" + prev);
   1548                 if (mNoAnimActivities.contains(prev)) {
   1549                     mService.mWindowManager.prepareAppTransition(
   1550                             WindowManagerPolicy.TRANSIT_NONE, false);
   1551                 } else {
   1552                     mService.mWindowManager.prepareAppTransition(prev.task == next.task
   1553                             ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
   1554                             : WindowManagerPolicy.TRANSIT_TASK_CLOSE, false);
   1555                 }
   1556                 mService.mWindowManager.setAppWillBeHidden(prev.appToken);
   1557                 mService.mWindowManager.setAppVisibility(prev.appToken, false);
   1558             } else {
   1559                 if (DEBUG_TRANSITION) Slog.v(TAG,
   1560                         "Prepare open transition: prev=" + prev);
   1561                 if (mNoAnimActivities.contains(next)) {
   1562                     noAnim = true;
   1563                     mService.mWindowManager.prepareAppTransition(
   1564                             WindowManagerPolicy.TRANSIT_NONE, false);
   1565                 } else {
   1566                     mService.mWindowManager.prepareAppTransition(prev.task == next.task
   1567                             ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
   1568                             : WindowManagerPolicy.TRANSIT_TASK_OPEN, false);
   1569                 }
   1570             }
   1571             if (false) {
   1572                 mService.mWindowManager.setAppWillBeHidden(prev.appToken);
   1573                 mService.mWindowManager.setAppVisibility(prev.appToken, false);
   1574             }
   1575         } else if (mHistory.size() > 1) {
   1576             if (DEBUG_TRANSITION) Slog.v(TAG,
   1577                     "Prepare open transition: no previous");
   1578             if (mNoAnimActivities.contains(next)) {
   1579                 noAnim = true;
   1580                 mService.mWindowManager.prepareAppTransition(
   1581                         WindowManagerPolicy.TRANSIT_NONE, false);
   1582             } else {
   1583                 mService.mWindowManager.prepareAppTransition(
   1584                         WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN, false);
   1585             }
   1586         }
   1587         if (!noAnim) {
   1588             next.applyOptionsLocked();
   1589         } else {
   1590             next.clearOptionsLocked();
   1591         }
   1592 
   1593         if (next.app != null && next.app.thread != null) {
   1594             if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
   1595 
   1596             // This activity is now becoming visible.
   1597             mService.mWindowManager.setAppVisibility(next.appToken, true);
   1598 
   1599             // schedule launch ticks to collect information about slow apps.
   1600             next.startLaunchTickingLocked();
   1601 
   1602             ActivityRecord lastResumedActivity = mResumedActivity;
   1603             ActivityState lastState = next.state;
   1604 
   1605             mService.updateCpuStats();
   1606 
   1607             if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + next + " (in existing)");
   1608             next.state = ActivityState.RESUMED;
   1609             mResumedActivity = next;
   1610             next.task.touchActiveTime();
   1611             if (mMainStack) {
   1612                 mService.addRecentTaskLocked(next.task);
   1613             }
   1614             mService.updateLruProcessLocked(next.app, true, true);
   1615             updateLRUListLocked(next);
   1616 
   1617             // Have the window manager re-evaluate the orientation of
   1618             // the screen based on the new activity order.
   1619             boolean updated = false;
   1620             if (mMainStack) {
   1621                 synchronized (mService) {
   1622                     Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
   1623                             mService.mConfiguration,
   1624                             next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
   1625                     if (config != null) {
   1626                         next.frozenBeforeDestroy = true;
   1627                     }
   1628                     updated = mService.updateConfigurationLocked(config, next, false, false);
   1629                 }
   1630             }
   1631             if (!updated) {
   1632                 // The configuration update wasn't able to keep the existing
   1633                 // instance of the activity, and instead started a new one.
   1634                 // We should be all done, but let's just make sure our activity
   1635                 // is still at the top and schedule another run if something
   1636                 // weird happened.
   1637                 ActivityRecord nextNext = topRunningActivityLocked(null);
   1638                 if (DEBUG_SWITCH) Slog.i(TAG,
   1639                         "Activity config changed during resume: " + next
   1640                         + ", new next: " + nextNext);
   1641                 if (nextNext != next) {
   1642                     // Do over!
   1643                     mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
   1644                 }
   1645                 if (mMainStack) {
   1646                     mService.setFocusedActivityLocked(next);
   1647                 }
   1648                 ensureActivitiesVisibleLocked(null, 0);
   1649                 mService.mWindowManager.executeAppTransition();
   1650                 mNoAnimActivities.clear();
   1651                 return true;
   1652             }
   1653 
   1654             try {
   1655                 // Deliver all pending results.
   1656                 ArrayList a = next.results;
   1657                 if (a != null) {
   1658                     final int N = a.size();
   1659                     if (!next.finishing && N > 0) {
   1660                         if (DEBUG_RESULTS) Slog.v(
   1661                                 TAG, "Delivering results to " + next
   1662                                 + ": " + a);
   1663                         next.app.thread.scheduleSendResult(next.appToken, a);
   1664                     }
   1665                 }
   1666 
   1667                 if (next.newIntents != null) {
   1668                     next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
   1669                 }
   1670 
   1671                 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
   1672                         System.identityHashCode(next),
   1673                         next.task.taskId, next.shortComponentName);
   1674 
   1675                 next.sleeping = false;
   1676                 showAskCompatModeDialogLocked(next);
   1677                 next.app.pendingUiClean = true;
   1678                 next.app.thread.scheduleResumeActivity(next.appToken,
   1679                         mService.isNextTransitionForward());
   1680 
   1681                 checkReadyForSleepLocked();
   1682 
   1683             } catch (Exception e) {
   1684                 // Whoops, need to restart this activity!
   1685                 if (DEBUG_STATES) Slog.v(TAG, "Resume failed; resetting state to "
   1686                         + lastState + ": " + next);
   1687                 next.state = lastState;
   1688                 mResumedActivity = lastResumedActivity;
   1689                 Slog.i(TAG, "Restarting because process died: " + next);
   1690                 if (!next.hasBeenLaunched) {
   1691                     next.hasBeenLaunched = true;
   1692                 } else {
   1693                     if (SHOW_APP_STARTING_PREVIEW && mMainStack) {
   1694                         mService.mWindowManager.setAppStartingWindow(
   1695                                 next.appToken, next.packageName, next.theme,
   1696                                 mService.compatibilityInfoForPackageLocked(
   1697                                         next.info.applicationInfo),
   1698                                 next.nonLocalizedLabel,
   1699                                 next.labelRes, next.icon, next.windowFlags,
   1700                                 null, true);
   1701                     }
   1702                 }
   1703                 startSpecificActivityLocked(next, true, false);
   1704                 return true;
   1705             }
   1706 
   1707             // From this point on, if something goes wrong there is no way
   1708             // to recover the activity.
   1709             try {
   1710                 next.visible = true;
   1711                 completeResumeLocked(next);
   1712             } catch (Exception e) {
   1713                 // If any exception gets thrown, toss away this
   1714                 // activity and try the next one.
   1715                 Slog.w(TAG, "Exception thrown during resume of " + next, e);
   1716                 requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
   1717                         "resume-exception");
   1718                 return true;
   1719             }
   1720 
   1721             // Didn't need to use the icicle, and it is now out of date.
   1722             if (DEBUG_SAVED_STATE) Slog.i(TAG, "Resumed activity; didn't need icicle of: " + next);
   1723             next.icicle = null;
   1724             next.haveState = false;
   1725             next.stopped = false;
   1726 
   1727         } else {
   1728             // Whoops, need to restart this activity!
   1729             if (!next.hasBeenLaunched) {
   1730                 next.hasBeenLaunched = true;
   1731             } else {
   1732                 if (SHOW_APP_STARTING_PREVIEW) {
   1733                     mService.mWindowManager.setAppStartingWindow(
   1734                             next.appToken, next.packageName, next.theme,
   1735                             mService.compatibilityInfoForPackageLocked(
   1736                                     next.info.applicationInfo),
   1737                             next.nonLocalizedLabel,
   1738                             next.labelRes, next.icon, next.windowFlags,
   1739                             null, true);
   1740                 }
   1741                 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
   1742             }
   1743             startSpecificActivityLocked(next, true, true);
   1744         }
   1745 
   1746         return true;
   1747     }
   1748 
   1749     private final void startActivityLocked(ActivityRecord r, boolean newTask,
   1750             boolean doResume, boolean keepCurTransition, Bundle options) {
   1751         final int NH = mHistory.size();
   1752 
   1753         int addPos = -1;
   1754 
   1755         if (!newTask) {
   1756             // If starting in an existing task, find where that is...
   1757             boolean startIt = true;
   1758             for (int i = NH-1; i >= 0; i--) {
   1759                 ActivityRecord p = mHistory.get(i);
   1760                 if (p.finishing) {
   1761                     continue;
   1762                 }
   1763                 if (p.task == r.task) {
   1764                     // Here it is!  Now, if this is not yet visible to the
   1765                     // user, then just add it without starting; it will
   1766                     // get started when the user navigates back to it.
   1767                     addPos = i+1;
   1768                     if (!startIt) {
   1769                         if (DEBUG_ADD_REMOVE) {
   1770                             RuntimeException here = new RuntimeException("here");
   1771                             here.fillInStackTrace();
   1772                             Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos,
   1773                                     here);
   1774                         }
   1775                         mHistory.add(addPos, r);
   1776                         r.putInHistory();
   1777                         mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
   1778                                 r.info.screenOrientation, r.fullscreen);
   1779                         if (VALIDATE_TOKENS) {
   1780                             validateAppTokensLocked();
   1781                         }
   1782                         ActivityOptions.abort(options);
   1783                         return;
   1784                     }
   1785                     break;
   1786                 }
   1787                 if (p.fullscreen) {
   1788                     startIt = false;
   1789                 }
   1790             }
   1791         }
   1792 
   1793         // Place a new activity at top of stack, so it is next to interact
   1794         // with the user.
   1795         if (addPos < 0) {
   1796             addPos = NH;
   1797         }
   1798 
   1799         // If we are not placing the new activity frontmost, we do not want
   1800         // to deliver the onUserLeaving callback to the actual frontmost
   1801         // activity
   1802         if (addPos < NH) {
   1803             mUserLeaving = false;
   1804             if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
   1805         }
   1806 
   1807         // Slot the activity into the history stack and proceed
   1808         if (DEBUG_ADD_REMOVE) {
   1809             RuntimeException here = new RuntimeException("here");
   1810             here.fillInStackTrace();
   1811             Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos, here);
   1812         }
   1813         mHistory.add(addPos, r);
   1814         r.putInHistory();
   1815         r.frontOfTask = newTask;
   1816         if (NH > 0) {
   1817             // We want to show the starting preview window if we are
   1818             // switching to a new task, or the next activity's process is
   1819             // not currently running.
   1820             boolean showStartingIcon = newTask;
   1821             ProcessRecord proc = r.app;
   1822             if (proc == null) {
   1823                 proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
   1824             }
   1825             if (proc == null || proc.thread == null) {
   1826                 showStartingIcon = true;
   1827             }
   1828             if (DEBUG_TRANSITION) Slog.v(TAG,
   1829                     "Prepare open transition: starting " + r);
   1830             if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
   1831                 mService.mWindowManager.prepareAppTransition(
   1832                         WindowManagerPolicy.TRANSIT_NONE, keepCurTransition);
   1833                 mNoAnimActivities.add(r);
   1834             } else {
   1835                 mService.mWindowManager.prepareAppTransition(newTask
   1836                         ? WindowManagerPolicy.TRANSIT_TASK_OPEN
   1837                         : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
   1838                 mNoAnimActivities.remove(r);
   1839             }
   1840             r.updateOptionsLocked(options);
   1841             mService.mWindowManager.addAppToken(
   1842                     addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen);
   1843             boolean doShow = true;
   1844             if (newTask) {
   1845                 // Even though this activity is starting fresh, we still need
   1846                 // to reset it to make sure we apply affinities to move any
   1847                 // existing activities from other tasks in to it.
   1848                 // If the caller has requested that the target task be
   1849                 // reset, then do so.
   1850                 if ((r.intent.getFlags()
   1851                         &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
   1852                     resetTaskIfNeededLocked(r, r);
   1853                     doShow = topRunningNonDelayedActivityLocked(null) == r;
   1854                 }
   1855             }
   1856             if (SHOW_APP_STARTING_PREVIEW && doShow) {
   1857                 // Figure out if we are transitioning from another activity that is
   1858                 // "has the same starting icon" as the next one.  This allows the
   1859                 // window manager to keep the previous window it had previously
   1860                 // created, if it still had one.
   1861                 ActivityRecord prev = mResumedActivity;
   1862                 if (prev != null) {
   1863                     // We don't want to reuse the previous starting preview if:
   1864                     // (1) The current activity is in a different task.
   1865                     if (prev.task != r.task) prev = null;
   1866                     // (2) The current activity is already displayed.
   1867                     else if (prev.nowVisible) prev = null;
   1868                 }
   1869                 mService.mWindowManager.setAppStartingWindow(
   1870                         r.appToken, r.packageName, r.theme,
   1871                         mService.compatibilityInfoForPackageLocked(
   1872                                 r.info.applicationInfo), r.nonLocalizedLabel,
   1873                         r.labelRes, r.icon, r.windowFlags,
   1874                         prev != null ? prev.appToken : null, showStartingIcon);
   1875             }
   1876         } else {
   1877             // If this is the first activity, don't do any fancy animations,
   1878             // because there is nothing for it to animate on top of.
   1879             mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
   1880                     r.info.screenOrientation, r.fullscreen);
   1881             ActivityOptions.abort(options);
   1882         }
   1883         if (VALIDATE_TOKENS) {
   1884             validateAppTokensLocked();
   1885         }
   1886 
   1887         if (doResume) {
   1888             resumeTopActivityLocked(null);
   1889         }
   1890     }
   1891 
   1892     final void validateAppTokensLocked() {
   1893         mValidateAppTokens.clear();
   1894         mValidateAppTokens.ensureCapacity(mHistory.size());
   1895         for (int i=0; i<mHistory.size(); i++) {
   1896             mValidateAppTokens.add(mHistory.get(i).appToken);
   1897         }
   1898         mService.mWindowManager.validateAppTokens(mValidateAppTokens);
   1899     }
   1900 
   1901     /**
   1902      * Perform a reset of the given task, if needed as part of launching it.
   1903      * Returns the new HistoryRecord at the top of the task.
   1904      */
   1905     private final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
   1906             ActivityRecord newActivity) {
   1907         boolean forceReset = (newActivity.info.flags
   1908                 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
   1909         if (ACTIVITY_INACTIVE_RESET_TIME > 0
   1910                 && taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
   1911             if ((newActivity.info.flags
   1912                     &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
   1913                 forceReset = true;
   1914             }
   1915         }
   1916 
   1917         final TaskRecord task = taskTop.task;
   1918 
   1919         // We are going to move through the history list so that we can look
   1920         // at each activity 'target' with 'below' either the interesting
   1921         // activity immediately below it in the stack or null.
   1922         ActivityRecord target = null;
   1923         int targetI = 0;
   1924         int taskTopI = -1;
   1925         int replyChainEnd = -1;
   1926         int lastReparentPos = -1;
   1927         for (int i=mHistory.size()-1; i>=-1; i--) {
   1928             ActivityRecord below = i >= 0 ? mHistory.get(i) : null;
   1929 
   1930             if (below != null && below.finishing) {
   1931                 continue;
   1932             }
   1933             // Don't check any lower in the stack if we're crossing a user boundary.
   1934             if (below != null && below.userId != taskTop.userId) {
   1935                 break;
   1936             }
   1937             if (target == null) {
   1938                 target = below;
   1939                 targetI = i;
   1940                 // If we were in the middle of a reply chain before this
   1941                 // task, it doesn't appear like the root of the chain wants
   1942                 // anything interesting, so drop it.
   1943                 replyChainEnd = -1;
   1944                 continue;
   1945             }
   1946 
   1947             final int flags = target.info.flags;
   1948 
   1949             final boolean finishOnTaskLaunch =
   1950                 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
   1951             final boolean allowTaskReparenting =
   1952                 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
   1953 
   1954             if (target.task == task) {
   1955                 // We are inside of the task being reset...  we'll either
   1956                 // finish this activity, push it out for another task,
   1957                 // or leave it as-is.  We only do this
   1958                 // for activities that are not the root of the task (since
   1959                 // if we finish the root, we may no longer have the task!).
   1960                 if (taskTopI < 0) {
   1961                     taskTopI = targetI;
   1962                 }
   1963                 if (below != null && below.task == task) {
   1964                     final boolean clearWhenTaskReset =
   1965                             (target.intent.getFlags()
   1966                                     &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
   1967                     if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
   1968                         // If this activity is sending a reply to a previous
   1969                         // activity, we can't do anything with it now until
   1970                         // we reach the start of the reply chain.
   1971                         // XXX note that we are assuming the result is always
   1972                         // to the previous activity, which is almost always
   1973                         // the case but we really shouldn't count on.
   1974                         if (replyChainEnd < 0) {
   1975                             replyChainEnd = targetI;
   1976                         }
   1977                     } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
   1978                             && target.taskAffinity != null
   1979                             && !target.taskAffinity.equals(task.affinity)) {
   1980                         // If this activity has an affinity for another
   1981                         // task, then we need to move it out of here.  We will
   1982                         // move it as far out of the way as possible, to the
   1983                         // bottom of the activity stack.  This also keeps it
   1984                         // correctly ordered with any activities we previously
   1985                         // moved.
   1986                         ActivityRecord p = mHistory.get(0);
   1987                         if (target.taskAffinity != null
   1988                                 && target.taskAffinity.equals(p.task.affinity)) {
   1989                             // If the activity currently at the bottom has the
   1990                             // same task affinity as the one we are moving,
   1991                             // then merge it into the same task.
   1992                             target.setTask(p.task, p.thumbHolder, false);
   1993                             if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
   1994                                     + " out to bottom task " + p.task);
   1995                         } else {
   1996                             mService.mCurTask++;
   1997                             if (mService.mCurTask <= 0) {
   1998                                 mService.mCurTask = 1;
   1999                             }
   2000                             target.setTask(new TaskRecord(mService.mCurTask, target.info, null),
   2001                                     null, false);
   2002                             target.task.affinityIntent = target.intent;
   2003                             if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
   2004                                     + " out to new task " + target.task);
   2005                         }
   2006                         mService.mWindowManager.setAppGroupId(target.appToken, task.taskId);
   2007                         if (replyChainEnd < 0) {
   2008                             replyChainEnd = targetI;
   2009                         }
   2010                         int dstPos = 0;
   2011                         ThumbnailHolder curThumbHolder = target.thumbHolder;
   2012                         for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
   2013                             p = mHistory.get(srcPos);
   2014                             if (p.finishing) {
   2015                                 continue;
   2016                             }
   2017                             if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
   2018                                     + " out to target's task " + target.task);
   2019                             p.setTask(target.task, curThumbHolder, false);
   2020                             curThumbHolder = p.thumbHolder;
   2021                             if (DEBUG_ADD_REMOVE) {
   2022                                 RuntimeException here = new RuntimeException("here");
   2023                                 here.fillInStackTrace();
   2024                                 Slog.i(TAG, "Removing and adding activity " + p + " to stack at "
   2025                                         + dstPos, here);
   2026                             }
   2027                             mHistory.remove(srcPos);
   2028                             mHistory.add(dstPos, p);
   2029                             mService.mWindowManager.moveAppToken(dstPos, p.appToken);
   2030                             mService.mWindowManager.setAppGroupId(p.appToken, p.task.taskId);
   2031                             dstPos++;
   2032                             if (VALIDATE_TOKENS) {
   2033                                 validateAppTokensLocked();
   2034                             }
   2035                             i++;
   2036                         }
   2037                         if (taskTop == p) {
   2038                             taskTop = below;
   2039                         }
   2040                         if (taskTopI == replyChainEnd) {
   2041                             taskTopI = -1;
   2042                         }
   2043                         replyChainEnd = -1;
   2044                     } else if (forceReset || finishOnTaskLaunch
   2045                             || clearWhenTaskReset) {
   2046                         // If the activity should just be removed -- either
   2047                         // because it asks for it, or the task should be
   2048                         // cleared -- then finish it and anything that is
   2049                         // part of its reply chain.
   2050                         if (clearWhenTaskReset) {
   2051                             // In this case, we want to finish this activity
   2052                             // and everything above it, so be sneaky and pretend
   2053                             // like these are all in the reply chain.
   2054                             replyChainEnd = targetI+1;
   2055                             while (replyChainEnd < mHistory.size() &&
   2056                                     (mHistory.get(
   2057                                                 replyChainEnd)).task == task) {
   2058                                 replyChainEnd++;
   2059                             }
   2060                             replyChainEnd--;
   2061                         } else if (replyChainEnd < 0) {
   2062                             replyChainEnd = targetI;
   2063                         }
   2064                         ActivityRecord p = null;
   2065                         for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
   2066                             p = mHistory.get(srcPos);
   2067                             if (p.finishing) {
   2068                                 continue;
   2069                             }
   2070                             if (finishActivityLocked(p, srcPos,
   2071                                     Activity.RESULT_CANCELED, null, "reset")) {
   2072                                 replyChainEnd--;
   2073                                 srcPos--;
   2074                             }
   2075                         }
   2076                         if (taskTop == p) {
   2077                             taskTop = below;
   2078                         }
   2079                         if (taskTopI == replyChainEnd) {
   2080                             taskTopI = -1;
   2081                         }
   2082                         replyChainEnd = -1;
   2083                     } else {
   2084                         // If we were in the middle of a chain, well the
   2085                         // activity that started it all doesn't want anything
   2086                         // special, so leave it all as-is.
   2087                         replyChainEnd = -1;
   2088                     }
   2089                 } else {
   2090                     // Reached the bottom of the task -- any reply chain
   2091                     // should be left as-is.
   2092                     replyChainEnd = -1;
   2093                 }
   2094 
   2095             } else if (target.resultTo != null && (below == null
   2096                     || below.task == target.task)) {
   2097                 // If this activity is sending a reply to a previous
   2098                 // activity, we can't do anything with it now until
   2099                 // we reach the start of the reply chain.
   2100                 // XXX note that we are assuming the result is always
   2101                 // to the previous activity, which is almost always
   2102                 // the case but we really shouldn't count on.
   2103                 if (replyChainEnd < 0) {
   2104                     replyChainEnd = targetI;
   2105                 }
   2106 
   2107             } else if (taskTopI >= 0 && allowTaskReparenting
   2108                     && task.affinity != null
   2109                     && task.affinity.equals(target.taskAffinity)) {
   2110                 // We are inside of another task...  if this activity has
   2111                 // an affinity for our task, then either remove it if we are
   2112                 // clearing or move it over to our task.  Note that
   2113                 // we currently punt on the case where we are resetting a
   2114                 // task that is not at the top but who has activities above
   2115                 // with an affinity to it...  this is really not a normal
   2116                 // case, and we will need to later pull that task to the front
   2117                 // and usually at that point we will do the reset and pick
   2118                 // up those remaining activities.  (This only happens if
   2119                 // someone starts an activity in a new task from an activity
   2120                 // in a task that is not currently on top.)
   2121                 if (forceReset || finishOnTaskLaunch) {
   2122                     if (replyChainEnd < 0) {
   2123                         replyChainEnd = targetI;
   2124                     }
   2125                     ActivityRecord p = null;
   2126                     if (DEBUG_TASKS) Slog.v(TAG, "Finishing task at index "
   2127                             + targetI + " to " + replyChainEnd);
   2128                     for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
   2129                         p = mHistory.get(srcPos);
   2130                         if (p.finishing) {
   2131                             continue;
   2132                         }
   2133                         if (finishActivityLocked(p, srcPos,
   2134                                 Activity.RESULT_CANCELED, null, "reset")) {
   2135                             taskTopI--;
   2136                             lastReparentPos--;
   2137                             replyChainEnd--;
   2138                             srcPos--;
   2139                         }
   2140                     }
   2141                     replyChainEnd = -1;
   2142                 } else {
   2143                     if (replyChainEnd < 0) {
   2144                         replyChainEnd = targetI;
   2145                     }
   2146                     if (DEBUG_TASKS) Slog.v(TAG, "Reparenting task at index "
   2147                             + targetI + " to " + replyChainEnd);
   2148                     for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
   2149                         ActivityRecord p = mHistory.get(srcPos);
   2150                         if (p.finishing) {
   2151                             continue;
   2152                         }
   2153                         if (lastReparentPos < 0) {
   2154                             lastReparentPos = taskTopI;
   2155                             taskTop = p;
   2156                         } else {
   2157                             lastReparentPos--;
   2158                         }
   2159                         if (DEBUG_ADD_REMOVE) {
   2160                             RuntimeException here = new RuntimeException("here");
   2161                             here.fillInStackTrace();
   2162                             Slog.i(TAG, "Removing and adding activity " + p + " to stack at "
   2163                                     + lastReparentPos, here);
   2164                         }
   2165                         mHistory.remove(srcPos);
   2166                         p.setTask(task, null, false);
   2167                         mHistory.add(lastReparentPos, p);
   2168                         if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
   2169                                 + " from " + srcPos + " to " + lastReparentPos
   2170                                 + " in to resetting task " + task);
   2171                         mService.mWindowManager.moveAppToken(lastReparentPos, p.appToken);
   2172                         mService.mWindowManager.setAppGroupId(p.appToken, p.task.taskId);
   2173                         if (VALIDATE_TOKENS) {
   2174                             validateAppTokensLocked();
   2175                         }
   2176                     }
   2177                     replyChainEnd = -1;
   2178 
   2179                     // Now we've moved it in to place...  but what if this is
   2180                     // a singleTop activity and we have put it on top of another
   2181                     // instance of the same activity?  Then we drop the instance
   2182                     // below so it remains singleTop.
   2183                     if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
   2184                         for (int j=lastReparentPos-1; j>=0; j--) {
   2185                             ActivityRecord p = mHistory.get(j);
   2186                             if (p.finishing) {
   2187                                 continue;
   2188                             }
   2189                             if (p.intent.getComponent().equals(target.intent.getComponent())) {
   2190                                 if (finishActivityLocked(p, j,
   2191                                         Activity.RESULT_CANCELED, null, "replace")) {
   2192                                     taskTopI--;
   2193                                     lastReparentPos--;
   2194                                 }
   2195                             }
   2196                         }
   2197                     }
   2198                 }
   2199 
   2200             } else if (below != null && below.task != target.task) {
   2201                 // We hit the botton of a task; the reply chain can't
   2202                 // pass through it.
   2203                 replyChainEnd = -1;
   2204             }
   2205 
   2206             target = below;
   2207             targetI = i;
   2208         }
   2209 
   2210         return taskTop;
   2211     }
   2212 
   2213     /**
   2214      * Perform clear operation as requested by
   2215      * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
   2216      * stack to the given task, then look for
   2217      * an instance of that activity in the stack and, if found, finish all
   2218      * activities on top of it and return the instance.
   2219      *
   2220      * @param newR Description of the new activity being started.
   2221      * @return Returns the old activity that should be continued to be used,
   2222      * or null if none was found.
   2223      */
   2224     private final ActivityRecord performClearTaskLocked(int taskId,
   2225             ActivityRecord newR, int launchFlags) {
   2226         int i = mHistory.size();
   2227 
   2228         // First find the requested task.
   2229         while (i > 0) {
   2230             i--;
   2231             ActivityRecord r = mHistory.get(i);
   2232             if (r.task.taskId == taskId) {
   2233                 i++;
   2234                 break;
   2235             }
   2236         }
   2237 
   2238         // Now clear it.
   2239         while (i > 0) {
   2240             i--;
   2241             ActivityRecord r = mHistory.get(i);
   2242             if (r.finishing) {
   2243                 continue;
   2244             }
   2245             if (r.task.taskId != taskId) {
   2246                 return null;
   2247             }
   2248             if (r.realActivity.equals(newR.realActivity)) {
   2249                 // Here it is!  Now finish everything in front...
   2250                 ActivityRecord ret = r;
   2251                 while (i < (mHistory.size()-1)) {
   2252                     i++;
   2253                     r = mHistory.get(i);
   2254                     if (r.task.taskId != taskId) {
   2255                         break;
   2256                     }
   2257                     if (r.finishing) {
   2258                         continue;
   2259                     }
   2260                     if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
   2261                             null, "clear")) {
   2262                         i--;
   2263                     }
   2264                 }
   2265 
   2266                 // Finally, if this is a normal launch mode (that is, not
   2267                 // expecting onNewIntent()), then we will finish the current
   2268                 // instance of the activity so a new fresh one can be started.
   2269                 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
   2270                         && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
   2271                     if (!ret.finishing) {
   2272                         int index = indexOfTokenLocked(ret.appToken);
   2273                         if (index >= 0) {
   2274                             finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
   2275                                     null, "clear");
   2276                         }
   2277                         return null;
   2278                     }
   2279                 }
   2280 
   2281                 return ret;
   2282             }
   2283         }
   2284 
   2285         return null;
   2286     }
   2287 
   2288     /**
   2289      * Completely remove all activities associated with an existing
   2290      * task starting at a specified index.
   2291      */
   2292     private final void performClearTaskAtIndexLocked(int taskId, int i) {
   2293         while (i < mHistory.size()) {
   2294             ActivityRecord r = mHistory.get(i);
   2295             if (r.task.taskId != taskId) {
   2296                 // Whoops hit the end.
   2297                 return;
   2298             }
   2299             if (r.finishing) {
   2300                 i++;
   2301                 continue;
   2302             }
   2303             if (!finishActivityLocked(r, i, Activity.RESULT_CANCELED,
   2304                     null, "clear")) {
   2305                 i++;
   2306             }
   2307         }
   2308     }
   2309 
   2310     /**
   2311      * Completely remove all activities associated with an existing task.
   2312      */
   2313     private final void performClearTaskLocked(int taskId) {
   2314         int i = mHistory.size();
   2315 
   2316         // First find the requested task.
   2317         while (i > 0) {
   2318             i--;
   2319             ActivityRecord r = mHistory.get(i);
   2320             if (r.task.taskId == taskId) {
   2321                 i++;
   2322                 break;
   2323             }
   2324         }
   2325 
   2326         // Now find the start and clear it.
   2327         while (i > 0) {
   2328             i--;
   2329             ActivityRecord r = mHistory.get(i);
   2330             if (r.finishing) {
   2331                 continue;
   2332             }
   2333             if (r.task.taskId != taskId) {
   2334                 // We hit the bottom.  Now finish it all...
   2335                 performClearTaskAtIndexLocked(taskId, i+1);
   2336                 return;
   2337             }
   2338         }
   2339     }
   2340 
   2341     /**
   2342      * Find the activity in the history stack within the given task.  Returns
   2343      * the index within the history at which it's found, or < 0 if not found.
   2344      */
   2345     private final int findActivityInHistoryLocked(ActivityRecord r, int task) {
   2346         int i = mHistory.size();
   2347         while (i > 0) {
   2348             i--;
   2349             ActivityRecord candidate = mHistory.get(i);
   2350             if (candidate.finishing) {
   2351                 continue;
   2352             }
   2353             if (candidate.task.taskId != task) {
   2354                 break;
   2355             }
   2356             if (candidate.realActivity.equals(r.realActivity)) {
   2357                 return i;
   2358             }
   2359         }
   2360 
   2361         return -1;
   2362     }
   2363 
   2364     /**
   2365      * Reorder the history stack so that the activity at the given index is
   2366      * brought to the front.
   2367      */
   2368     private final ActivityRecord moveActivityToFrontLocked(int where) {
   2369         ActivityRecord newTop = mHistory.remove(where);
   2370         int top = mHistory.size();
   2371         ActivityRecord oldTop = mHistory.get(top-1);
   2372         if (DEBUG_ADD_REMOVE) {
   2373             RuntimeException here = new RuntimeException("here");
   2374             here.fillInStackTrace();
   2375             Slog.i(TAG, "Removing and adding activity " + newTop + " to stack at "
   2376                     + top, here);
   2377         }
   2378         mHistory.add(top, newTop);
   2379         oldTop.frontOfTask = false;
   2380         newTop.frontOfTask = true;
   2381         return newTop;
   2382     }
   2383 
   2384     final int startActivityLocked(IApplicationThread caller,
   2385             Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
   2386             String resultWho, int requestCode,
   2387             int callingPid, int callingUid, int startFlags, Bundle options,
   2388             boolean componentSpecified, ActivityRecord[] outActivity) {
   2389 
   2390         int err = ActivityManager.START_SUCCESS;
   2391 
   2392         ProcessRecord callerApp = null;
   2393         if (caller != null) {
   2394             callerApp = mService.getRecordForAppLocked(caller);
   2395             if (callerApp != null) {
   2396                 callingPid = callerApp.pid;
   2397                 callingUid = callerApp.info.uid;
   2398             } else {
   2399                 Slog.w(TAG, "Unable to find app for caller " + caller
   2400                       + " (pid=" + callingPid + ") when starting: "
   2401                       + intent.toString());
   2402                 err = ActivityManager.START_PERMISSION_DENIED;
   2403             }
   2404         }
   2405 
   2406         if (err == ActivityManager.START_SUCCESS) {
   2407             final int userId = aInfo != null ? UserId.getUserId(aInfo.applicationInfo.uid) : 0;
   2408             Slog.i(TAG, "START {" + intent.toShortString(true, true, true, false)
   2409                     + " u=" + userId + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
   2410         }
   2411 
   2412         ActivityRecord sourceRecord = null;
   2413         ActivityRecord resultRecord = null;
   2414         if (resultTo != null) {
   2415             int index = indexOfTokenLocked(resultTo);
   2416             if (DEBUG_RESULTS) Slog.v(
   2417                 TAG, "Will send result to " + resultTo + " (index " + index + ")");
   2418             if (index >= 0) {
   2419                 sourceRecord = mHistory.get(index);
   2420                 if (requestCode >= 0 && !sourceRecord.finishing) {
   2421                     resultRecord = sourceRecord;
   2422                 }
   2423             }
   2424         }
   2425 
   2426         int launchFlags = intent.getFlags();
   2427 
   2428         if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
   2429                 && sourceRecord != null) {
   2430             // Transfer the result target from the source activity to the new
   2431             // one being started, including any failures.
   2432             if (requestCode >= 0) {
   2433                 ActivityOptions.abort(options);
   2434                 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
   2435             }
   2436             resultRecord = sourceRecord.resultTo;
   2437             resultWho = sourceRecord.resultWho;
   2438             requestCode = sourceRecord.requestCode;
   2439             sourceRecord.resultTo = null;
   2440             if (resultRecord != null) {
   2441                 resultRecord.removeResultsLocked(
   2442                     sourceRecord, resultWho, requestCode);
   2443             }
   2444         }
   2445 
   2446         if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
   2447             // We couldn't find a class that can handle the given Intent.
   2448             // That's the end of that!
   2449             err = ActivityManager.START_INTENT_NOT_RESOLVED;
   2450         }
   2451 
   2452         if (err == ActivityManager.START_SUCCESS && aInfo == null) {
   2453             // We couldn't find the specific class specified in the Intent.
   2454             // Also the end of the line.
   2455             err = ActivityManager.START_CLASS_NOT_FOUND;
   2456         }
   2457 
   2458         if (err != ActivityManager.START_SUCCESS) {
   2459             if (resultRecord != null) {
   2460                 sendActivityResultLocked(-1,
   2461                     resultRecord, resultWho, requestCode,
   2462                     Activity.RESULT_CANCELED, null);
   2463             }
   2464             mDismissKeyguardOnNextActivity = false;
   2465             ActivityOptions.abort(options);
   2466             return err;
   2467         }
   2468 
   2469         final int startAnyPerm = mService.checkPermission(
   2470                 START_ANY_ACTIVITY, callingPid, callingUid);
   2471         final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
   2472                 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
   2473         if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
   2474             if (resultRecord != null) {
   2475                 sendActivityResultLocked(-1,
   2476                     resultRecord, resultWho, requestCode,
   2477                     Activity.RESULT_CANCELED, null);
   2478             }
   2479             mDismissKeyguardOnNextActivity = false;
   2480             String msg;
   2481             if (!aInfo.exported) {
   2482                 msg = "Permission Denial: starting " + intent.toString()
   2483                         + " from " + callerApp + " (pid=" + callingPid
   2484                         + ", uid=" + callingUid + ")"
   2485                         + " not exported from uid " + aInfo.applicationInfo.uid;
   2486             } else {
   2487                 msg = "Permission Denial: starting " + intent.toString()
   2488                         + " from " + callerApp + " (pid=" + callingPid
   2489                         + ", uid=" + callingUid + ")"
   2490                         + " requires " + aInfo.permission;
   2491             }
   2492             Slog.w(TAG, msg);
   2493             throw new SecurityException(msg);
   2494         }
   2495 
   2496         if (mMainStack) {
   2497             if (mService.mController != null) {
   2498                 boolean abort = false;
   2499                 try {
   2500                     // The Intent we give to the watcher has the extra data
   2501                     // stripped off, since it can contain private information.
   2502                     Intent watchIntent = intent.cloneFilter();
   2503                     abort = !mService.mController.activityStarting(watchIntent,
   2504                             aInfo.applicationInfo.packageName);
   2505                 } catch (RemoteException e) {
   2506                     mService.mController = null;
   2507                 }
   2508 
   2509                 if (abort) {
   2510                     if (resultRecord != null) {
   2511                         sendActivityResultLocked(-1,
   2512                             resultRecord, resultWho, requestCode,
   2513                             Activity.RESULT_CANCELED, null);
   2514                     }
   2515                     // We pretend to the caller that it was really started, but
   2516                     // they will just get a cancel result.
   2517                     mDismissKeyguardOnNextActivity = false;
   2518                     ActivityOptions.abort(options);
   2519                     return ActivityManager.START_SUCCESS;
   2520                 }
   2521             }
   2522         }
   2523 
   2524         ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid,
   2525                 intent, resolvedType, aInfo, mService.mConfiguration,
   2526                 resultRecord, resultWho, requestCode, componentSpecified);
   2527         if (outActivity != null) {
   2528             outActivity[0] = r;
   2529         }
   2530 
   2531         if (mMainStack) {
   2532             if (mResumedActivity == null
   2533                     || mResumedActivity.info.applicationInfo.uid != callingUid) {
   2534                 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
   2535                     PendingActivityLaunch pal = new PendingActivityLaunch();
   2536                     pal.r = r;
   2537                     pal.sourceRecord = sourceRecord;
   2538                     pal.startFlags = startFlags;
   2539                     mService.mPendingActivityLaunches.add(pal);
   2540                     mDismissKeyguardOnNextActivity = false;
   2541                     ActivityOptions.abort(options);
   2542                     return ActivityManager.START_SWITCHES_CANCELED;
   2543                 }
   2544             }
   2545 
   2546             if (mService.mDidAppSwitch) {
   2547                 // This is the second allowed switch since we stopped switches,
   2548                 // so now just generally allow switches.  Use case: user presses
   2549                 // home (switches disabled, switch to home, mDidAppSwitch now true);
   2550                 // user taps a home icon (coming from home so allowed, we hit here
   2551                 // and now allow anyone to switch again).
   2552                 mService.mAppSwitchesAllowedTime = 0;
   2553             } else {
   2554                 mService.mDidAppSwitch = true;
   2555             }
   2556 
   2557             mService.doPendingActivityLaunchesLocked(false);
   2558         }
   2559 
   2560         err = startActivityUncheckedLocked(r, sourceRecord,
   2561                 startFlags, true, options);
   2562         if (mDismissKeyguardOnNextActivity && mPausingActivity == null) {
   2563             // Someone asked to have the keyguard dismissed on the next
   2564             // activity start, but we are not actually doing an activity
   2565             // switch...  just dismiss the keyguard now, because we
   2566             // probably want to see whatever is behind it.
   2567             mDismissKeyguardOnNextActivity = false;
   2568             mService.mWindowManager.dismissKeyguard();
   2569         }
   2570         return err;
   2571     }
   2572 
   2573     final void moveHomeToFrontFromLaunchLocked(int launchFlags) {
   2574         if ((launchFlags &
   2575                 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
   2576                 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
   2577             // Caller wants to appear on home activity, so before starting
   2578             // their own activity we will bring home to the front.
   2579             moveHomeToFrontLocked();
   2580         }
   2581     }
   2582 
   2583     final int startActivityUncheckedLocked(ActivityRecord r,
   2584             ActivityRecord sourceRecord, int startFlags, boolean doResume,
   2585             Bundle options) {
   2586         final Intent intent = r.intent;
   2587         final int callingUid = r.launchedFromUid;
   2588         final int userId = r.userId;
   2589 
   2590         int launchFlags = intent.getFlags();
   2591 
   2592         // We'll invoke onUserLeaving before onPause only if the launching
   2593         // activity did not explicitly state that this is an automated launch.
   2594         mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
   2595         if (DEBUG_USER_LEAVING) Slog.v(TAG,
   2596                 "startActivity() => mUserLeaving=" + mUserLeaving);
   2597 
   2598         // If the caller has asked not to resume at this point, we make note
   2599         // of this in the record so that we can skip it when trying to find
   2600         // the top running activity.
   2601         if (!doResume) {
   2602             r.delayedResume = true;
   2603         }
   2604 
   2605         ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
   2606                 != 0 ? r : null;
   2607 
   2608         // If the onlyIfNeeded flag is set, then we can do this if the activity
   2609         // being launched is the same as the one making the call...  or, as
   2610         // a special case, if we do not know the caller then we count the
   2611         // current top activity as the caller.
   2612         if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
   2613             ActivityRecord checkedCaller = sourceRecord;
   2614             if (checkedCaller == null) {
   2615                 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
   2616             }
   2617             if (!checkedCaller.realActivity.equals(r.realActivity)) {
   2618                 // Caller is not the same as launcher, so always needed.
   2619                 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
   2620             }
   2621         }
   2622 
   2623         if (sourceRecord == null) {
   2624             // This activity is not being started from another...  in this
   2625             // case we -always- start a new task.
   2626             if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
   2627                 Slog.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
   2628                       + intent);
   2629                 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
   2630             }
   2631         } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
   2632             // The original activity who is starting us is running as a single
   2633             // instance...  this new activity it is starting must go on its
   2634             // own task.
   2635             launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
   2636         } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
   2637                 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
   2638             // The activity being started is a single instance...  it always
   2639             // gets launched into its own task.
   2640             launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
   2641         }
   2642 
   2643         if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
   2644             // For whatever reason this activity is being launched into a new
   2645             // task...  yet the caller has requested a result back.  Well, that
   2646             // is pretty messed up, so instead immediately send back a cancel
   2647             // and let the new task continue launched as normal without a
   2648             // dependency on its originator.
   2649             Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
   2650             sendActivityResultLocked(-1,
   2651                     r.resultTo, r.resultWho, r.requestCode,
   2652                 Activity.RESULT_CANCELED, null);
   2653             r.resultTo = null;
   2654         }
   2655 
   2656         boolean addingToTask = false;
   2657         boolean movedHome = false;
   2658         TaskRecord reuseTask = null;
   2659         if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
   2660                 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
   2661                 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
   2662                 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
   2663             // If bring to front is requested, and no result is requested, and
   2664             // we can find a task that was started with this same
   2665             // component, then instead of launching bring that one to the front.
   2666             if (r.resultTo == null) {
   2667                 // See if there is a task to bring to the front.  If this is
   2668                 // a SINGLE_INSTANCE activity, there can be one and only one
   2669                 // instance of it in the history, and it is always in its own
   2670                 // unique task, so we do a special search.
   2671                 ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
   2672                         ? findTaskLocked(intent, r.info)
   2673                         : findActivityLocked(intent, r.info);
   2674                 if (taskTop != null) {
   2675                     if (taskTop.task.intent == null) {
   2676                         // This task was started because of movement of
   2677                         // the activity based on affinity...  now that we
   2678                         // are actually launching it, we can assign the
   2679                         // base intent.
   2680                         taskTop.task.setIntent(intent, r.info);
   2681                     }
   2682                     // If the target task is not in the front, then we need
   2683                     // to bring it to the front...  except...  well, with
   2684                     // SINGLE_TASK_LAUNCH it's not entirely clear.  We'd like
   2685                     // to have the same behavior as if a new instance was
   2686                     // being started, which means not bringing it to the front
   2687                     // if the caller is not itself in the front.
   2688                     ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop);
   2689                     if (curTop != null && curTop.task != taskTop.task) {
   2690                         r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
   2691                         boolean callerAtFront = sourceRecord == null
   2692                                 || curTop.task == sourceRecord.task;
   2693                         if (callerAtFront) {
   2694                             // We really do want to push this one into the
   2695                             // user's face, right now.
   2696                             movedHome = true;
   2697                             moveHomeToFrontFromLaunchLocked(launchFlags);
   2698                             moveTaskToFrontLocked(taskTop.task, r, options);
   2699                             options = null;
   2700                         }
   2701                     }
   2702                     // If the caller has requested that the target task be
   2703                     // reset, then do so.
   2704                     if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
   2705                         taskTop = resetTaskIfNeededLocked(taskTop, r);
   2706                     }
   2707                     if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED)  != 0) {
   2708                         // We don't need to start a new activity, and
   2709                         // the client said not to do anything if that
   2710                         // is the case, so this is it!  And for paranoia, make
   2711                         // sure we have correctly resumed the top activity.
   2712                         if (doResume) {
   2713                             resumeTopActivityLocked(null, options);
   2714                         } else {
   2715                             ActivityOptions.abort(options);
   2716                         }
   2717                         return ActivityManager.START_RETURN_INTENT_TO_CALLER;
   2718                     }
   2719                     if ((launchFlags &
   2720                             (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
   2721                             == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
   2722                         // The caller has requested to completely replace any
   2723                         // existing task with its new activity.  Well that should
   2724                         // not be too hard...
   2725                         reuseTask = taskTop.task;
   2726                         performClearTaskLocked(taskTop.task.taskId);
   2727                         reuseTask.setIntent(r.intent, r.info);
   2728                     } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
   2729                             || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
   2730                             || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
   2731                         // In this situation we want to remove all activities
   2732                         // from the task up to the one being started.  In most
   2733                         // cases this means we are resetting the task to its
   2734                         // initial state.
   2735                         ActivityRecord top = performClearTaskLocked(
   2736                                 taskTop.task.taskId, r, launchFlags);
   2737                         if (top != null) {
   2738                             if (top.frontOfTask) {
   2739                                 // Activity aliases may mean we use different
   2740                                 // intents for the top activity, so make sure
   2741                                 // the task now has the identity of the new
   2742                                 // intent.
   2743                                 top.task.setIntent(r.intent, r.info);
   2744                             }
   2745                             logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
   2746                             top.deliverNewIntentLocked(callingUid, r.intent);
   2747                         } else {
   2748                             // A special case: we need to
   2749                             // start the activity because it is not currently
   2750                             // running, and the caller has asked to clear the
   2751                             // current task to have this activity at the top.
   2752                             addingToTask = true;
   2753                             // Now pretend like this activity is being started
   2754                             // by the top of its task, so it is put in the
   2755                             // right place.
   2756                             sourceRecord = taskTop;
   2757                         }
   2758                     } else if (r.realActivity.equals(taskTop.task.realActivity)) {
   2759                         // In this case the top activity on the task is the
   2760                         // same as the one being launched, so we take that
   2761                         // as a request to bring the task to the foreground.
   2762                         // If the top activity in the task is the root
   2763                         // activity, deliver this new intent to it if it
   2764                         // desires.
   2765                         if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
   2766                                 && taskTop.realActivity.equals(r.realActivity)) {
   2767                             logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
   2768                             if (taskTop.frontOfTask) {
   2769                                 taskTop.task.setIntent(r.intent, r.info);
   2770                             }
   2771                             taskTop.deliverNewIntentLocked(callingUid, r.intent);
   2772                         } else if (!r.intent.filterEquals(taskTop.task.intent)) {
   2773                             // In this case we are launching the root activity
   2774                             // of the task, but with a different intent.  We
   2775                             // should start a new instance on top.
   2776                             addingToTask = true;
   2777                             sourceRecord = taskTop;
   2778                         }
   2779                     } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
   2780                         // In this case an activity is being launched in to an
   2781                         // existing task, without resetting that task.  This
   2782                         // is typically the situation of launching an activity
   2783                         // from a notification or shortcut.  We want to place
   2784                         // the new activity on top of the current task.
   2785                         addingToTask = true;
   2786                         sourceRecord = taskTop;
   2787                     } else if (!taskTop.task.rootWasReset) {
   2788                         // In this case we are launching in to an existing task
   2789                         // that has not yet been started from its front door.
   2790                         // The current task has been brought to the front.
   2791                         // Ideally, we'd probably like to place this new task
   2792                         // at the bottom of its stack, but that's a little hard
   2793                         // to do with the current organization of the code so
   2794                         // for now we'll just drop it.
   2795                         taskTop.task.setIntent(r.intent, r.info);
   2796                     }
   2797                     if (!addingToTask && reuseTask == null) {
   2798                         // We didn't do anything...  but it was needed (a.k.a., client
   2799                         // don't use that intent!)  And for paranoia, make
   2800                         // sure we have correctly resumed the top activity.
   2801                         if (doResume) {
   2802                             resumeTopActivityLocked(null, options);
   2803                         } else {
   2804                             ActivityOptions.abort(options);
   2805                         }
   2806                         return ActivityManager.START_TASK_TO_FRONT;
   2807                     }
   2808                 }
   2809             }
   2810         }
   2811 
   2812         //String uri = r.intent.toURI();
   2813         //Intent intent2 = new Intent(uri);
   2814         //Slog.i(TAG, "Given intent: " + r.intent);
   2815         //Slog.i(TAG, "URI is: " + uri);
   2816         //Slog.i(TAG, "To intent: " + intent2);
   2817 
   2818         if (r.packageName != null) {
   2819             // If the activity being launched is the same as the one currently
   2820             // at the top, then we need to check if it should only be launched
   2821             // once.
   2822             ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);
   2823             if (top != null && r.resultTo == null) {
   2824                 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
   2825                     if (top.app != null && top.app.thread != null) {
   2826                         if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
   2827                             || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
   2828                             || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
   2829                             logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
   2830                             // For paranoia, make sure we have correctly
   2831                             // resumed the top activity.
   2832                             if (doResume) {
   2833                                 resumeTopActivityLocked(null);
   2834                             }
   2835                             ActivityOptions.abort(options);
   2836                             if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
   2837                                 // We don't need to start a new activity, and
   2838                                 // the client said not to do anything if that
   2839                                 // is the case, so this is it!
   2840                                 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
   2841                             }
   2842                             top.deliverNewIntentLocked(callingUid, r.intent);
   2843                             return ActivityManager.START_DELIVERED_TO_TOP;
   2844                         }
   2845                     }
   2846                 }
   2847             }
   2848 
   2849         } else {
   2850             if (r.resultTo != null) {
   2851                 sendActivityResultLocked(-1,
   2852                         r.resultTo, r.resultWho, r.requestCode,
   2853                     Activity.RESULT_CANCELED, null);
   2854             }
   2855             ActivityOptions.abort(options);
   2856             return ActivityManager.START_CLASS_NOT_FOUND;
   2857         }
   2858 
   2859         boolean newTask = false;
   2860         boolean keepCurTransition = false;
   2861 
   2862         // Should this be considered a new task?
   2863         if (r.resultTo == null && !addingToTask
   2864                 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
   2865             if (reuseTask == null) {
   2866                 // todo: should do better management of integers.
   2867                 mService.mCurTask++;
   2868                 if (mService.mCurTask <= 0) {
   2869                     mService.mCurTask = 1;
   2870                 }
   2871                 r.setTask(new TaskRecord(mService.mCurTask, r.info, intent), null, true);
   2872                 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
   2873                         + " in new task " + r.task);
   2874             } else {
   2875                 r.setTask(reuseTask, reuseTask, true);
   2876             }
   2877             newTask = true;
   2878             if (!movedHome) {
   2879                 moveHomeToFrontFromLaunchLocked(launchFlags);
   2880             }
   2881 
   2882         } else if (sourceRecord != null) {
   2883             if (!addingToTask &&
   2884                     (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
   2885                 // In this case, we are adding the activity to an existing
   2886                 // task, but the caller has asked to clear that task if the
   2887                 // activity is already running.
   2888                 ActivityRecord top = performClearTaskLocked(
   2889                         sourceRecord.task.taskId, r, launchFlags);
   2890                 keepCurTransition = true;
   2891                 if (top != null) {
   2892                     logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
   2893                     top.deliverNewIntentLocked(callingUid, r.intent);
   2894                     // For paranoia, make sure we have correctly
   2895                     // resumed the top activity.
   2896                     if (doResume) {
   2897                         resumeTopActivityLocked(null);
   2898                     }
   2899                     ActivityOptions.abort(options);
   2900                     return ActivityManager.START_DELIVERED_TO_TOP;
   2901                 }
   2902             } else if (!addingToTask &&
   2903                     (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
   2904                 // In this case, we are launching an activity in our own task
   2905                 // that may already be running somewhere in the history, and
   2906                 // we want to shuffle it to the front of the stack if so.
   2907                 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
   2908                 if (where >= 0) {
   2909                     ActivityRecord top = moveActivityToFrontLocked(where);
   2910                     logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
   2911                     top.updateOptionsLocked(options);
   2912                     top.deliverNewIntentLocked(callingUid, r.intent);
   2913                     if (doResume) {
   2914                         resumeTopActivityLocked(null);
   2915                     }
   2916                     return ActivityManager.START_DELIVERED_TO_TOP;
   2917                 }
   2918             }
   2919             // An existing activity is starting this new activity, so we want
   2920             // to keep the new one in the same task as the one that is starting
   2921             // it.
   2922             r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
   2923             if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
   2924                     + " in existing task " + r.task);
   2925 
   2926         } else {
   2927             // This not being started from an existing activity, and not part
   2928             // of a new task...  just put it in the top task, though these days
   2929             // this case should never happen.
   2930             final int N = mHistory.size();
   2931             ActivityRecord prev =
   2932                 N > 0 ? mHistory.get(N-1) : null;
   2933             r.setTask(prev != null
   2934                     ? prev.task
   2935                     : new TaskRecord(mService.mCurTask, r.info, intent), null, true);
   2936             if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
   2937                     + " in new guessed " + r.task);
   2938         }
   2939 
   2940         mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
   2941                 intent, r.getUriPermissionsLocked());
   2942 
   2943         if (newTask) {
   2944             EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
   2945         }
   2946         logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
   2947         startActivityLocked(r, newTask, doResume, keepCurTransition, options);
   2948         return ActivityManager.START_SUCCESS;
   2949     }
   2950 
   2951     ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
   2952             String profileFile, ParcelFileDescriptor profileFd, int userId) {
   2953         // Collect information about the target of the Intent.
   2954         ActivityInfo aInfo;
   2955         try {
   2956             ResolveInfo rInfo =
   2957                 AppGlobals.getPackageManager().resolveIntent(
   2958                         intent, resolvedType,
   2959                         PackageManager.MATCH_DEFAULT_ONLY
   2960                                     | ActivityManagerService.STOCK_PM_FLAGS, userId);
   2961             aInfo = rInfo != null ? rInfo.activityInfo : null;
   2962         } catch (RemoteException e) {
   2963             aInfo = null;
   2964         }
   2965 
   2966         if (aInfo != null) {
   2967             // Store the found target back into the intent, because now that
   2968             // we have it we never want to do this again.  For example, if the
   2969             // user navigates back to this point in the history, we should
   2970             // always restart the exact same activity.
   2971             intent.setComponent(new ComponentName(
   2972                     aInfo.applicationInfo.packageName, aInfo.name));
   2973 
   2974             // Don't debug things in the system process
   2975             if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
   2976                 if (!aInfo.processName.equals("system")) {
   2977                     mService.setDebugApp(aInfo.processName, true, false);
   2978                 }
   2979             }
   2980 
   2981             if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
   2982                 if (!aInfo.processName.equals("system")) {
   2983                     mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
   2984                 }
   2985             }
   2986 
   2987             if (profileFile != null) {
   2988                 if (!aInfo.processName.equals("system")) {
   2989                     mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
   2990                             profileFile, profileFd,
   2991                             (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
   2992                 }
   2993             }
   2994         }
   2995         return aInfo;
   2996     }
   2997 
   2998     final int startActivityMayWait(IApplicationThread caller, int callingUid,
   2999             Intent intent, String resolvedType, IBinder resultTo,
   3000             String resultWho, int requestCode, int startFlags, String profileFile,
   3001             ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
   3002             Bundle options, int userId) {
   3003         // Refuse possible leaked file descriptors
   3004         if (intent != null && intent.hasFileDescriptors()) {
   3005             throw new IllegalArgumentException("File descriptors passed in Intent");
   3006         }
   3007         boolean componentSpecified = intent.getComponent() != null;
   3008 
   3009         // Don't modify the client's object!
   3010         intent = new Intent(intent);
   3011 
   3012         // Collect information about the target of the Intent.
   3013         ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
   3014                 profileFile, profileFd, userId);
   3015         if (aInfo != null && mService.isSingleton(aInfo.processName, aInfo.applicationInfo)) {
   3016             userId = 0;
   3017         }
   3018         aInfo = mService.getActivityInfoForUser(aInfo, userId);
   3019 
   3020         synchronized (mService) {
   3021             int callingPid;
   3022             if (callingUid >= 0) {
   3023                 callingPid = -1;
   3024             } else if (caller == null) {
   3025                 callingPid = Binder.getCallingPid();
   3026                 callingUid = Binder.getCallingUid();
   3027             } else {
   3028                 callingPid = callingUid = -1;
   3029             }
   3030 
   3031             mConfigWillChange = config != null
   3032                     && mService.mConfiguration.diff(config) != 0;
   3033             if (DEBUG_CONFIGURATION) Slog.v(TAG,
   3034                     "Starting activity when config will change = " + mConfigWillChange);
   3035 
   3036             final long origId = Binder.clearCallingIdentity();
   3037 
   3038             if (mMainStack && aInfo != null &&
   3039                     (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
   3040                 // This may be a heavy-weight process!  Check to see if we already
   3041                 // have another, different heavy-weight process running.
   3042                 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
   3043                     if (mService.mHeavyWeightProcess != null &&
   3044                             (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
   3045                             !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
   3046                         int realCallingPid = callingPid;
   3047                         int realCallingUid = callingUid;
   3048                         if (caller != null) {
   3049                             ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
   3050                             if (callerApp != null) {
   3051                                 realCallingPid = callerApp.pid;
   3052                                 realCallingUid = callerApp.info.uid;
   3053                             } else {
   3054                                 Slog.w(TAG, "Unable to find app for caller " + caller
   3055                                       + " (pid=" + realCallingPid + ") when starting: "
   3056                                       + intent.toString());
   3057                                 ActivityOptions.abort(options);
   3058                                 return ActivityManager.START_PERMISSION_DENIED;
   3059                             }
   3060                         }
   3061 
   3062                         IIntentSender target = mService.getIntentSenderLocked(
   3063                                 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
   3064                                 realCallingUid, null, null, 0, new Intent[] { intent },
   3065                                 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
   3066                                 | PendingIntent.FLAG_ONE_SHOT, null);
   3067 
   3068                         Intent newIntent = new Intent();
   3069                         if (requestCode >= 0) {
   3070                             // Caller is requesting a result.
   3071                             newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
   3072                         }
   3073                         newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
   3074                                 new IntentSender(target));
   3075                         if (mService.mHeavyWeightProcess.activities.size() > 0) {
   3076                             ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
   3077                             newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
   3078                                     hist.packageName);
   3079                             newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
   3080                                     hist.task.taskId);
   3081                         }
   3082                         newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
   3083                                 aInfo.packageName);
   3084                         newIntent.setFlags(intent.getFlags());
   3085                         newIntent.setClassName("android",
   3086                                 HeavyWeightSwitcherActivity.class.getName());
   3087                         intent = newIntent;
   3088                         resolvedType = null;
   3089                         caller = null;
   3090                         callingUid = Binder.getCallingUid();
   3091                         callingPid = Binder.getCallingPid();
   3092                         componentSpecified = true;
   3093                         try {
   3094                             ResolveInfo rInfo =
   3095                                 AppGlobals.getPackageManager().resolveIntent(
   3096                                         intent, null,
   3097                                         PackageManager.MATCH_DEFAULT_ONLY
   3098                                         | ActivityManagerService.STOCK_PM_FLAGS, userId);
   3099                             aInfo = rInfo != null ? rInfo.activityInfo : null;
   3100                             aInfo = mService.getActivityInfoForUser(aInfo, userId);
   3101                         } catch (RemoteException e) {
   3102                             aInfo = null;
   3103                         }
   3104                     }
   3105                 }
   3106             }
   3107 
   3108             int res = startActivityLocked(caller, intent, resolvedType,
   3109                     aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
   3110                     startFlags, options, componentSpecified, null);
   3111 
   3112             if (mConfigWillChange && mMainStack) {
   3113                 // If the caller also wants to switch to a new configuration,
   3114                 // do so now.  This allows a clean switch, as we are waiting
   3115                 // for the current activity to pause (so we will not destroy
   3116                 // it), and have not yet started the next activity.
   3117                 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
   3118                         "updateConfiguration()");
   3119                 mConfigWillChange = false;
   3120                 if (DEBUG_CONFIGURATION) Slog.v(TAG,
   3121                         "Updating to new configuration after starting activity.");
   3122                 mService.updateConfigurationLocked(config, null, false, false);
   3123             }
   3124 
   3125             Binder.restoreCallingIdentity(origId);
   3126 
   3127             if (outResult != null) {
   3128                 outResult.result = res;
   3129                 if (res == ActivityManager.START_SUCCESS) {
   3130                     mWaitingActivityLaunched.add(outResult);
   3131                     do {
   3132                         try {
   3133                             mService.wait();
   3134                         } catch (InterruptedException e) {
   3135                         }
   3136                     } while (!outResult.timeout && outResult.who == null);
   3137                 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
   3138                     ActivityRecord r = this.topRunningActivityLocked(null);
   3139                     if (r.nowVisible) {
   3140                         outResult.timeout = false;
   3141                         outResult.who = new ComponentName(r.info.packageName, r.info.name);
   3142                         outResult.totalTime = 0;
   3143                         outResult.thisTime = 0;
   3144                     } else {
   3145                         outResult.thisTime = SystemClock.uptimeMillis();
   3146                         mWaitingActivityVisible.add(outResult);
   3147                         do {
   3148                             try {
   3149                                 mService.wait();
   3150                             } catch (InterruptedException e) {
   3151                             }
   3152                         } while (!outResult.timeout && outResult.who == null);
   3153                     }
   3154                 }
   3155             }
   3156 
   3157             return res;
   3158         }
   3159     }
   3160 
   3161     final int startActivities(IApplicationThread caller, int callingUid,
   3162             Intent[] intents, String[] resolvedTypes, IBinder resultTo,
   3163             Bundle options, int userId) {
   3164         if (intents == null) {
   3165             throw new NullPointerException("intents is null");
   3166         }
   3167         if (resolvedTypes == null) {
   3168             throw new NullPointerException("resolvedTypes is null");
   3169         }
   3170         if (intents.length != resolvedTypes.length) {
   3171             throw new IllegalArgumentException("intents are length different than resolvedTypes");
   3172         }
   3173 
   3174         ActivityRecord[] outActivity = new ActivityRecord[1];
   3175 
   3176         int callingPid;
   3177         if (callingUid >= 0) {
   3178             callingPid = -1;
   3179         } else if (caller == null) {
   3180             callingPid = Binder.getCallingPid();
   3181             callingUid = Binder.getCallingUid();
   3182         } else {
   3183             callingPid = callingUid = -1;
   3184         }
   3185         final long origId = Binder.clearCallingIdentity();
   3186         try {
   3187             synchronized (mService) {
   3188 
   3189                 for (int i=0; i<intents.length; i++) {
   3190                     Intent intent = intents[i];
   3191                     if (intent == null) {
   3192                         continue;
   3193                     }
   3194 
   3195                     // Refuse possible leaked file descriptors
   3196                     if (intent != null && intent.hasFileDescriptors()) {
   3197                         throw new IllegalArgumentException("File descriptors passed in Intent");
   3198                     }
   3199 
   3200                     boolean componentSpecified = intent.getComponent() != null;
   3201 
   3202                     // Don't modify the client's object!
   3203                     intent = new Intent(intent);
   3204 
   3205                     // Collect information about the target of the Intent.
   3206                     ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
   3207                             0, null, null, userId);
   3208                     // TODO: New, check if this is correct
   3209                     aInfo = mService.getActivityInfoForUser(aInfo, userId);
   3210 
   3211                     if (mMainStack && aInfo != null && (aInfo.applicationInfo.flags
   3212                             & ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
   3213                         throw new IllegalArgumentException(
   3214                                 "FLAG_CANT_SAVE_STATE not supported here");
   3215                     }
   3216 
   3217                     Bundle theseOptions;
   3218                     if (options != null && i == intents.length-1) {
   3219                         theseOptions = options;
   3220                     } else {
   3221                         theseOptions = null;
   3222                     }
   3223                     int res = startActivityLocked(caller, intent, resolvedTypes[i],
   3224                             aInfo, resultTo, null, -1, callingPid, callingUid,
   3225                             0, theseOptions, componentSpecified, outActivity);
   3226                     if (res < 0) {
   3227                         return res;
   3228                     }
   3229 
   3230                     resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
   3231                 }
   3232             }
   3233         } finally {
   3234             Binder.restoreCallingIdentity(origId);
   3235         }
   3236 
   3237         return ActivityManager.START_SUCCESS;
   3238     }
   3239 
   3240     void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
   3241             long thisTime, long totalTime) {
   3242         for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
   3243             WaitResult w = mWaitingActivityLaunched.get(i);
   3244             w.timeout = timeout;
   3245             if (r != null) {
   3246                 w.who = new ComponentName(r.info.packageName, r.info.name);
   3247             }
   3248             w.thisTime = thisTime;
   3249             w.totalTime = totalTime;
   3250         }
   3251         mService.notifyAll();
   3252     }
   3253 
   3254     void reportActivityVisibleLocked(ActivityRecord r) {
   3255         for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
   3256             WaitResult w = mWaitingActivityVisible.get(i);
   3257             w.timeout = false;
   3258             if (r != null) {
   3259                 w.who = new ComponentName(r.info.packageName, r.info.name);
   3260             }
   3261             w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
   3262             w.thisTime = w.totalTime;
   3263         }
   3264         mService.notifyAll();
   3265 
   3266         if (mDismissKeyguardOnNextActivity) {
   3267             mDismissKeyguardOnNextActivity = false;
   3268             mService.mWindowManager.dismissKeyguard();
   3269         }
   3270     }
   3271 
   3272     void sendActivityResultLocked(int callingUid, ActivityRecord r,
   3273             String resultWho, int requestCode, int resultCode, Intent data) {
   3274 
   3275         if (callingUid > 0) {
   3276             mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
   3277                     data, r.getUriPermissionsLocked());
   3278         }
   3279 
   3280         if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
   3281                 + " : who=" + resultWho + " req=" + requestCode
   3282                 + " res=" + resultCode + " data=" + data);
   3283         if (mResumedActivity == r && r.app != null && r.app.thread != null) {
   3284             try {
   3285                 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
   3286                 list.add(new ResultInfo(resultWho, requestCode,
   3287                         resultCode, data));
   3288                 r.app.thread.scheduleSendResult(r.appToken, list);
   3289                 return;
   3290             } catch (Exception e) {
   3291                 Slog.w(TAG, "Exception thrown sending result to " + r, e);
   3292             }
   3293         }
   3294 
   3295         r.addResultLocked(null, resultWho, requestCode, resultCode, data);
   3296     }
   3297 
   3298     private final void stopActivityLocked(ActivityRecord r) {
   3299         if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
   3300         if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
   3301                 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
   3302             if (!r.finishing) {
   3303                 if (!mService.mSleeping) {
   3304                     if (DEBUG_STATES) {
   3305                         Slog.d(TAG, "no-history finish of " + r);
   3306                     }
   3307                     requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
   3308                             "no-history");
   3309                 } else {
   3310                     if (DEBUG_STATES) Slog.d(TAG, "Not finishing noHistory " + r
   3311                             + " on stop because we're just sleeping");
   3312                 }
   3313             }
   3314         }
   3315 
   3316         if (r.app != null && r.app.thread != null) {
   3317             if (mMainStack) {
   3318                 if (mService.mFocusedActivity == r) {
   3319                     mService.setFocusedActivityLocked(topRunningActivityLocked(null));
   3320                 }
   3321             }
   3322             r.resumeKeyDispatchingLocked();
   3323             try {
   3324                 r.stopped = false;
   3325                 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
   3326                         + " (stop requested)");
   3327                 r.state = ActivityState.STOPPING;
   3328                 if (DEBUG_VISBILITY) Slog.v(
   3329                         TAG, "Stopping visible=" + r.visible + " for " + r);
   3330                 if (!r.visible) {
   3331                     mService.mWindowManager.setAppVisibility(r.appToken, false);
   3332                 }
   3333                 r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
   3334                 if (mService.isSleeping()) {
   3335                     r.setSleeping(true);
   3336                 }
   3337                 Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG);
   3338                 msg.obj = r;
   3339                 mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
   3340             } catch (Exception e) {
   3341                 // Maybe just ignore exceptions here...  if the process
   3342                 // has crashed, our death notification will clean things
   3343                 // up.
   3344                 Slog.w(TAG, "Exception thrown during pause", e);
   3345                 // Just in case, assume it to be stopped.
   3346                 r.stopped = true;
   3347                 if (DEBUG_STATES) Slog.v(TAG, "Stop failed; moving to STOPPED: " + r);
   3348                 r.state = ActivityState.STOPPED;
   3349                 if (r.configDestroy) {
   3350                     destroyActivityLocked(r, true, false, "stop-except");
   3351                 }
   3352             }
   3353         }
   3354     }
   3355 
   3356     final ArrayList<ActivityRecord> processStoppingActivitiesLocked(
   3357             boolean remove) {
   3358         int N = mStoppingActivities.size();
   3359         if (N <= 0) return null;
   3360 
   3361         ArrayList<ActivityRecord> stops = null;
   3362 
   3363         final boolean nowVisible = mResumedActivity != null
   3364                 && mResumedActivity.nowVisible
   3365                 && !mResumedActivity.waitingVisible;
   3366         for (int i=0; i<N; i++) {
   3367             ActivityRecord s = mStoppingActivities.get(i);
   3368             if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
   3369                     + nowVisible + " waitingVisible=" + s.waitingVisible
   3370                     + " finishing=" + s.finishing);
   3371             if (s.waitingVisible && nowVisible) {
   3372                 mWaitingVisibleActivities.remove(s);
   3373                 s.waitingVisible = false;
   3374                 if (s.finishing) {
   3375                     // If this activity is finishing, it is sitting on top of
   3376                     // everyone else but we now know it is no longer needed...
   3377                     // so get rid of it.  Otherwise, we need to go through the
   3378                     // normal flow and hide it once we determine that it is
   3379                     // hidden by the activities in front of it.
   3380                     if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
   3381                     mService.mWindowManager.setAppVisibility(s.appToken, false);
   3382                 }
   3383             }
   3384             if ((!s.waitingVisible || mService.isSleeping()) && remove) {
   3385                 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
   3386                 if (stops == null) {
   3387                     stops = new ArrayList<ActivityRecord>();
   3388                 }
   3389                 stops.add(s);
   3390                 mStoppingActivities.remove(i);
   3391                 N--;
   3392                 i--;
   3393             }
   3394         }
   3395 
   3396         return stops;
   3397     }
   3398 
   3399     final void scheduleIdleLocked() {
   3400         Message msg = Message.obtain();
   3401         msg.what = IDLE_NOW_MSG;
   3402         mHandler.sendMessage(msg);
   3403     }
   3404 
   3405     final ActivityRecord activityIdleInternal(IBinder token, boolean fromTimeout,
   3406             Configuration config) {
   3407         if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
   3408 
   3409         ActivityRecord res = null;
   3410 
   3411         ArrayList<ActivityRecord> stops = null;
   3412         ArrayList<ActivityRecord> finishes = null;
   3413         ArrayList<ActivityRecord> thumbnails = null;
   3414         int NS = 0;
   3415         int NF = 0;
   3416         int NT = 0;
   3417         IApplicationThread sendThumbnail = null;
   3418         boolean booting = false;
   3419         boolean enableScreen = false;
   3420         boolean activityRemoved = false;
   3421 
   3422         synchronized (mService) {
   3423             ActivityRecord r = ActivityRecord.forToken(token);
   3424             if (r != null) {
   3425                 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
   3426                 r.finishLaunchTickingLocked();
   3427             }
   3428 
   3429             // Get the activity record.
   3430             int index = indexOfActivityLocked(r);
   3431             if (index >= 0) {
   3432                 res = r;
   3433 
   3434                 if (fromTimeout) {
   3435                     reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
   3436                 }
   3437 
   3438                 // This is a hack to semi-deal with a race condition
   3439                 // in the client where it can be constructed with a
   3440                 // newer configuration from when we asked it to launch.
   3441                 // We'll update with whatever configuration it now says
   3442                 // it used to launch.
   3443                 if (config != null) {
   3444                     r.configuration = config;
   3445                 }
   3446 
   3447                 // No longer need to keep the device awake.
   3448                 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
   3449                     mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
   3450                     mLaunchingActivity.release();
   3451                 }
   3452 
   3453                 // We are now idle.  If someone is waiting for a thumbnail from
   3454                 // us, we can now deliver.
   3455                 r.idle = true;
   3456                 mService.scheduleAppGcsLocked();
   3457                 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
   3458                     sendThumbnail = r.app.thread;
   3459                     r.thumbnailNeeded = false;
   3460                 }
   3461 
   3462                 // If this activity is fullscreen, set up to hide those under it.
   3463 
   3464                 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
   3465                 ensureActivitiesVisibleLocked(null, 0);
   3466 
   3467                 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
   3468                 if (mMainStack) {
   3469                     if (!mService.mBooted) {
   3470                         mService.mBooted = true;
   3471                         enableScreen = true;
   3472                     }
   3473                 }
   3474 
   3475             } else if (fromTimeout) {
   3476                 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
   3477             }
   3478 
   3479             // Atomically retrieve all of the other things to do.
   3480             stops = processStoppingActivitiesLocked(true);
   3481             NS = stops != null ? stops.size() : 0;
   3482             if ((NF=mFinishingActivities.size()) > 0) {
   3483                 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
   3484                 mFinishingActivities.clear();
   3485             }
   3486             if ((NT=mService.mCancelledThumbnails.size()) > 0) {
   3487                 thumbnails = new ArrayList<ActivityRecord>(mService.mCancelledThumbnails);
   3488                 mService.mCancelledThumbnails.clear();
   3489             }
   3490 
   3491             if (mMainStack) {
   3492                 booting = mService.mBooting;
   3493                 mService.mBooting = false;
   3494             }
   3495         }
   3496 
   3497         int i;
   3498 
   3499         // Send thumbnail if requested.
   3500         if (sendThumbnail != null) {
   3501             try {
   3502                 sendThumbnail.requestThumbnail(token);
   3503             } catch (Exception e) {
   3504                 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
   3505                 mService.sendPendingThumbnail(null, token, null, null, true);
   3506             }
   3507         }
   3508 
   3509         // Stop any activities that are scheduled to do so but have been
   3510         // waiting for the next one to start.
   3511         for (i=0; i<NS; i++) {
   3512             ActivityRecord r = (ActivityRecord)stops.get(i);
   3513             synchronized (mService) {
   3514                 if (r.finishing) {
   3515                     finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
   3516                 } else {
   3517                     stopActivityLocked(r);
   3518                 }
   3519             }
   3520         }
   3521 
   3522         // Finish any activities that are scheduled to do so but have been
   3523         // waiting for the next one to start.
   3524         for (i=0; i<NF; i++) {
   3525             ActivityRecord r = (ActivityRecord)finishes.get(i);
   3526             synchronized (mService) {
   3527                 activityRemoved = destroyActivityLocked(r, true, false, "finish-idle");
   3528             }
   3529         }
   3530 
   3531         // Report back to any thumbnail receivers.
   3532         for (i=0; i<NT; i++) {
   3533             ActivityRecord r = (ActivityRecord)thumbnails.get(i);
   3534             mService.sendPendingThumbnail(r, null, null, null, true);
   3535         }
   3536 
   3537         if (booting) {
   3538             mService.finishBooting();
   3539         }
   3540 
   3541         mService.trimApplications();
   3542         //dump();
   3543         //mWindowManager.dump();
   3544 
   3545         if (enableScreen) {
   3546             mService.enableScreenAfterBoot();
   3547         }
   3548 
   3549         if (activityRemoved) {
   3550             resumeTopActivityLocked(null);
   3551         }
   3552 
   3553         return res;
   3554     }
   3555 
   3556     /**
   3557      * @return Returns true if the activity is being finished, false if for
   3558      * some reason it is being left as-is.
   3559      */
   3560     final boolean requestFinishActivityLocked(IBinder token, int resultCode,
   3561             Intent resultData, String reason) {
   3562         int index = indexOfTokenLocked(token);
   3563         if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(
   3564                 TAG, "Finishing activity @" + index + ": token=" + token
   3565                 + ", result=" + resultCode + ", data=" + resultData
   3566                 + ", reason=" + reason);
   3567         if (index < 0) {
   3568             return false;
   3569         }
   3570         ActivityRecord r = mHistory.get(index);
   3571 
   3572         finishActivityLocked(r, index, resultCode, resultData, reason);
   3573         return true;
   3574     }
   3575 
   3576     final void finishSubActivityLocked(IBinder token, String resultWho, int requestCode) {
   3577         ActivityRecord self = isInStackLocked(token);
   3578         if (self == null) {
   3579             return;
   3580         }
   3581 
   3582         int i;
   3583         for (i=mHistory.size()-1; i>=0; i--) {
   3584             ActivityRecord r = (ActivityRecord)mHistory.get(i);
   3585             if (r.resultTo == self && r.requestCode == requestCode) {
   3586                 if ((r.resultWho == null && resultWho == null) ||
   3587                     (r.resultWho != null && r.resultWho.equals(resultWho))) {
   3588                     finishActivityLocked(r, i,
   3589                             Activity.RESULT_CANCELED, null, "request-sub");
   3590                 }
   3591             }
   3592         }
   3593     }
   3594 
   3595     final boolean finishActivityAffinityLocked(IBinder token) {
   3596         int index = indexOfTokenLocked(token);
   3597         if (DEBUG_RESULTS) Slog.v(
   3598                 TAG, "Finishing activity affinity @" + index + ": token=" + token);
   3599         if (index < 0) {
   3600             return false;
   3601         }
   3602         ActivityRecord r = mHistory.get(index);
   3603 
   3604         while (index >= 0) {
   3605             ActivityRecord cur = mHistory.get(index);
   3606             if (cur.task != r.task) {
   3607                 break;
   3608             }
   3609             if (cur.taskAffinity == null && r.taskAffinity != null) {
   3610                 break;
   3611             }
   3612             if (cur.taskAffinity != null && !cur.taskAffinity.equals(r.taskAffinity)) {
   3613                 break;
   3614             }
   3615             finishActivityLocked(cur, index, Activity.RESULT_CANCELED, null, "request-affinity");
   3616             index--;
   3617         }
   3618         return true;
   3619     }
   3620 
   3621     final void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
   3622         // send the result
   3623         ActivityRecord resultTo = r.resultTo;
   3624         if (resultTo != null) {
   3625             if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
   3626                     + " who=" + r.resultWho + " req=" + r.requestCode
   3627                     + " res=" + resultCode + " data=" + resultData);
   3628             if (r.info.applicationInfo.uid > 0) {
   3629                 mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
   3630                         resultTo.packageName, resultData,
   3631                         resultTo.getUriPermissionsLocked());
   3632             }
   3633             resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
   3634                                      resultData);
   3635             r.resultTo = null;
   3636         }
   3637         else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
   3638 
   3639         // Make sure this HistoryRecord is not holding on to other resources,
   3640         // because clients have remote IPC references to this object so we
   3641         // can't assume that will go away and want to avoid circular IPC refs.
   3642         r.results = null;
   3643         r.pendingResults = null;
   3644         r.newIntents = null;
   3645         r.icicle = null;
   3646     }
   3647 
   3648     /**
   3649      * @return Returns true if this activity has been removed from the history
   3650      * list, or false if it is still in the list and will be removed later.
   3651      */
   3652     final boolean finishActivityLocked(ActivityRecord r, int index,
   3653             int resultCode, Intent resultData, String reason) {
   3654         return finishActivityLocked(r, index, resultCode, resultData, reason, false);
   3655     }
   3656 
   3657     /**
   3658      * @return Returns true if this activity has been removed from the history
   3659      * list, or false if it is still in the list and will be removed later.
   3660      */
   3661     final boolean finishActivityLocked(ActivityRecord r, int index,
   3662             int resultCode, Intent resultData, String reason, boolean immediate) {
   3663         if (r.finishing) {
   3664             Slog.w(TAG, "Duplicate finish request for " + r);
   3665             return false;
   3666         }
   3667 
   3668         r.makeFinishing();
   3669         EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
   3670                 System.identityHashCode(r),
   3671                 r.task.taskId, r.shortComponentName, reason);
   3672         if (index < (mHistory.size()-1)) {
   3673             ActivityRecord next = mHistory.get(index+1);
   3674             if (next.task == r.task) {
   3675                 if (r.frontOfTask) {
   3676                     // The next activity is now the front of the task.
   3677                     next.frontOfTask = true;
   3678                 }
   3679                 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
   3680                     // If the caller asked that this activity (and all above it)
   3681                     // be cleared when the task is reset, don't lose that information,
   3682                     // but propagate it up to the next activity.
   3683                     next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
   3684                 }
   3685             }
   3686         }
   3687 
   3688         r.pauseKeyDispatchingLocked();
   3689         if (mMainStack) {
   3690             if (mService.mFocusedActivity == r) {
   3691                 mService.setFocusedActivityLocked(topRunningActivityLocked(null));
   3692             }
   3693         }
   3694 
   3695         finishActivityResultsLocked(r, resultCode, resultData);
   3696 
   3697         if (mService.mPendingThumbnails.size() > 0) {
   3698             // There are clients waiting to receive thumbnails so, in case
   3699             // this is an activity that someone is waiting for, add it
   3700             // to the pending list so we can correctly update the clients.
   3701             mService.mCancelledThumbnails.add(r);
   3702         }
   3703 
   3704         if (immediate) {
   3705             return finishCurrentActivityLocked(r, index,
   3706                     FINISH_IMMEDIATELY) == null;
   3707         } else if (mResumedActivity == r) {
   3708             boolean endTask = index <= 0
   3709                     || (mHistory.get(index-1)).task != r.task;
   3710             if (DEBUG_TRANSITION) Slog.v(TAG,
   3711                     "Prepare close transition: finishing " + r);
   3712             mService.mWindowManager.prepareAppTransition(endTask
   3713                     ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
   3714                     : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE, false);
   3715 
   3716             // Tell window manager to prepare for this one to be removed.
   3717             mService.mWindowManager.setAppVisibility(r.appToken, false);
   3718 
   3719             if (mPausingActivity == null) {
   3720                 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
   3721                 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
   3722                 startPausingLocked(false, false);
   3723             }
   3724 
   3725         } else if (r.state != ActivityState.PAUSING) {
   3726             // If the activity is PAUSING, we will complete the finish once
   3727             // it is done pausing; else we can just directly finish it here.
   3728             if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
   3729             return finishCurrentActivityLocked(r, index,
   3730                     FINISH_AFTER_PAUSE) == null;
   3731         } else {
   3732             if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
   3733         }
   3734 
   3735         return false;
   3736     }
   3737 
   3738     private static final int FINISH_IMMEDIATELY = 0;
   3739     private static final int FINISH_AFTER_PAUSE = 1;
   3740     private static final int FINISH_AFTER_VISIBLE = 2;
   3741 
   3742     private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
   3743             int mode) {
   3744         final int index = indexOfActivityLocked(r);
   3745         if (index < 0) {
   3746             return null;
   3747         }
   3748 
   3749         return finishCurrentActivityLocked(r, index, mode);
   3750     }
   3751 
   3752     private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
   3753             int index, int mode) {
   3754         // First things first: if this activity is currently visible,
   3755         // and the resumed activity is not yet visible, then hold off on
   3756         // finishing until the resumed one becomes visible.
   3757         if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
   3758             if (!mStoppingActivities.contains(r)) {
   3759                 mStoppingActivities.add(r);
   3760                 if (mStoppingActivities.size() > 3) {
   3761                     // If we already have a few activities waiting to stop,
   3762                     // then give up on things going idle and start clearing
   3763                     // them out.
   3764                     scheduleIdleLocked();
   3765                 } else {
   3766                     checkReadyForSleepLocked();
   3767                 }
   3768             }
   3769             if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
   3770                     + " (finish requested)");
   3771             r.state = ActivityState.STOPPING;
   3772             mService.updateOomAdjLocked();
   3773             return r;
   3774         }
   3775 
   3776         // make sure the record is cleaned out of other places.
   3777         mStoppingActivities.remove(r);
   3778         mGoingToSleepActivities.remove(r);
   3779         mWaitingVisibleActivities.remove(r);
   3780         if (mResumedActivity == r) {
   3781             mResumedActivity = null;
   3782         }
   3783         final ActivityState prevState = r.state;
   3784         if (DEBUG_STATES) Slog.v(TAG, "Moving to FINISHING: " + r);
   3785         r.state = ActivityState.FINISHING;
   3786 
   3787         if (mode == FINISH_IMMEDIATELY
   3788                 || prevState == ActivityState.STOPPED
   3789                 || prevState == ActivityState.INITIALIZING) {
   3790             // If this activity is already stopped, we can just finish
   3791             // it right now.
   3792             boolean activityRemoved = destroyActivityLocked(r, true, true, "finish-imm");
   3793             if (activityRemoved) {
   3794                 resumeTopActivityLocked(null);
   3795             }
   3796             return activityRemoved ? null : r;
   3797         } else {
   3798             // Need to go through the full pause cycle to get this
   3799             // activity into the stopped state and then finish it.
   3800             if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
   3801             mFinishingActivities.add(r);
   3802             resumeTopActivityLocked(null);
   3803         }
   3804         return r;
   3805     }
   3806 
   3807     /**
   3808      * Perform the common clean-up of an activity record.  This is called both
   3809      * as part of destroyActivityLocked() (when destroying the client-side
   3810      * representation) and cleaning things up as a result of its hosting
   3811      * processing going away, in which case there is no remaining client-side
   3812      * state to destroy so only the cleanup here is needed.
   3813      */
   3814     final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices,
   3815             boolean setState) {
   3816         if (mResumedActivity == r) {
   3817             mResumedActivity = null;
   3818         }
   3819         if (mService.mFocusedActivity == r) {
   3820             mService.mFocusedActivity = null;
   3821         }
   3822 
   3823         r.configDestroy = false;
   3824         r.frozenBeforeDestroy = false;
   3825 
   3826         if (setState) {
   3827             if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (cleaning up)");
   3828             r.state = ActivityState.DESTROYED;
   3829         }
   3830 
   3831         // Make sure this record is no longer in the pending finishes list.
   3832         // This could happen, for example, if we are trimming activities
   3833         // down to the max limit while they are still waiting to finish.
   3834         mFinishingActivities.remove(r);
   3835         mWaitingVisibleActivities.remove(r);
   3836 
   3837         // Remove any pending results.
   3838         if (r.finishing && r.pendingResults != null) {
   3839             for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
   3840                 PendingIntentRecord rec = apr.get();
   3841                 if (rec != null) {
   3842                     mService.cancelIntentSenderLocked(rec, false);
   3843                 }
   3844             }
   3845             r.pendingResults = null;
   3846         }
   3847 
   3848         if (cleanServices) {
   3849             cleanUpActivityServicesLocked(r);
   3850         }
   3851 
   3852         if (mService.mPendingThumbnails.size() > 0) {
   3853             // There are clients waiting to receive thumbnails so, in case
   3854             // this is an activity that someone is waiting for, add it
   3855             // to the pending list so we can correctly update the clients.
   3856             mService.mCancelledThumbnails.add(r);
   3857         }
   3858 
   3859         // Get rid of any pending idle timeouts.
   3860         removeTimeoutsForActivityLocked(r);
   3861     }
   3862 
   3863     private void removeTimeoutsForActivityLocked(ActivityRecord r) {
   3864         mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
   3865         mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
   3866         mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
   3867         mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
   3868         r.finishLaunchTickingLocked();
   3869     }
   3870 
   3871     final void removeActivityFromHistoryLocked(ActivityRecord r) {
   3872         if (r.state != ActivityState.DESTROYED) {
   3873             finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
   3874             r.makeFinishing();
   3875             if (DEBUG_ADD_REMOVE) {
   3876                 RuntimeException here = new RuntimeException("here");
   3877                 here.fillInStackTrace();
   3878                 Slog.i(TAG, "Removing activity " + r + " from stack");
   3879             }
   3880             mHistory.remove(r);
   3881             r.takeFromHistory();
   3882             if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
   3883                     + " (removed from history)");
   3884             r.state = ActivityState.DESTROYED;
   3885             mService.mWindowManager.removeAppToken(r.appToken);
   3886             if (VALIDATE_TOKENS) {
   3887                 validateAppTokensLocked();
   3888             }
   3889             cleanUpActivityServicesLocked(r);
   3890             r.removeUriPermissionsLocked();
   3891         }
   3892     }
   3893 
   3894     /**
   3895      * Perform clean-up of service connections in an activity record.
   3896      */
   3897     final void cleanUpActivityServicesLocked(ActivityRecord r) {
   3898         // Throw away any services that have been bound by this activity.
   3899         if (r.connections != null) {
   3900             Iterator<ConnectionRecord> it = r.connections.iterator();
   3901             while (it.hasNext()) {
   3902                 ConnectionRecord c = it.next();
   3903                 mService.removeConnectionLocked(c, null, r);
   3904             }
   3905             r.connections = null;
   3906         }
   3907     }
   3908 
   3909     final void scheduleDestroyActivities(ProcessRecord owner, boolean oomAdj, String reason) {
   3910         Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG);
   3911         msg.obj = new ScheduleDestroyArgs(owner, oomAdj, reason);
   3912         mHandler.sendMessage(msg);
   3913     }
   3914 
   3915     final void destroyActivitiesLocked(ProcessRecord owner, boolean oomAdj, String reason) {
   3916         boolean lastIsOpaque = false;
   3917         boolean activityRemoved = false;
   3918         for (int i=mHistory.size()-1; i>=0; i--) {
   3919             ActivityRecord r = mHistory.get(i);
   3920             if (r.finishing) {
   3921                 continue;
   3922             }
   3923             if (r.fullscreen) {
   3924                 lastIsOpaque = true;
   3925             }
   3926             if (owner != null && r.app != owner) {
   3927                 continue;
   3928             }
   3929             if (!lastIsOpaque) {
   3930                 continue;
   3931             }
   3932             // We can destroy this one if we have its icicle saved and
   3933             // it is not in the process of pausing/stopping/finishing.
   3934             if (r.app != null && r != mResumedActivity && r != mPausingActivity
   3935                     && r.haveState && !r.visible && r.stopped
   3936                     && r.state != ActivityState.DESTROYING
   3937                     && r.state != ActivityState.DESTROYED) {
   3938                 if (DEBUG_SWITCH) Slog.v(TAG, "Destroying " + r + " in state " + r.state
   3939                         + " resumed=" + mResumedActivity
   3940                         + " pausing=" + mPausingActivity);
   3941                 if (destroyActivityLocked(r, true, oomAdj, reason)) {
   3942                     activityRemoved = true;
   3943                 }
   3944             }
   3945         }
   3946         if (activityRemoved) {
   3947             resumeTopActivityLocked(null);
   3948         }
   3949     }
   3950 
   3951     /**
   3952      * Destroy the current CLIENT SIDE instance of an activity.  This may be
   3953      * called both when actually finishing an activity, or when performing
   3954      * a configuration switch where we destroy the current client-side object
   3955      * but then create a new client-side object for this same HistoryRecord.
   3956      */
   3957     final boolean destroyActivityLocked(ActivityRecord r,
   3958             boolean removeFromApp, boolean oomAdj, String reason) {
   3959         if (DEBUG_SWITCH) Slog.v(
   3960             TAG, "Removing activity from " + reason + ": token=" + r
   3961               + ", app=" + (r.app != null ? r.app.processName : "(null)"));
   3962         EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
   3963                 System.identityHashCode(r),
   3964                 r.task.taskId, r.shortComponentName, reason);
   3965 
   3966         boolean removedFromHistory = false;
   3967 
   3968         cleanUpActivityLocked(r, false, false);
   3969 
   3970         final boolean hadApp = r.app != null;
   3971 
   3972         if (hadApp) {
   3973             if (removeFromApp) {
   3974                 int idx = r.app.activities.indexOf(r);
   3975                 if (idx >= 0) {
   3976                     r.app.activities.remove(idx);
   3977                 }
   3978                 if (mService.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
   3979                     mService.mHeavyWeightProcess = null;
   3980                     mService.mHandler.sendEmptyMessage(
   3981                             ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG);
   3982                 }
   3983                 if (r.app.activities.size() == 0) {
   3984                     // No longer have activities, so update location in
   3985                     // LRU list.
   3986                     mService.updateLruProcessLocked(r.app, oomAdj, false);
   3987                 }
   3988             }
   3989 
   3990             boolean skipDestroy = false;
   3991 
   3992             try {
   3993                 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
   3994                 r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,
   3995                         r.configChangeFlags);
   3996             } catch (Exception e) {
   3997                 // We can just ignore exceptions here...  if the process
   3998                 // has crashed, our death notification will clean things
   3999                 // up.
   4000                 //Slog.w(TAG, "Exception thrown during finish", e);
   4001                 if (r.finishing) {
   4002                     removeActivityFromHistoryLocked(r);
   4003                     removedFromHistory = true;
   4004                     skipDestroy = true;
   4005                 }
   4006             }
   4007 
   4008             r.app = null;
   4009             r.nowVisible = false;
   4010 
   4011             // If the activity is finishing, we need to wait on removing it
   4012             // from the list to give it a chance to do its cleanup.  During
   4013             // that time it may make calls back with its token so we need to
   4014             // be able to find it on the list and so we don't want to remove
   4015             // it from the list yet.  Otherwise, we can just immediately put
   4016             // it in the destroyed state since we are not removing it from the
   4017             // list.
   4018             if (r.finishing && !skipDestroy) {
   4019                 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYING: " + r
   4020                         + " (destroy requested)");
   4021                 r.state = ActivityState.DESTROYING;
   4022                 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
   4023                 msg.obj = r;
   4024                 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
   4025             } else {
   4026                 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
   4027                         + " (destroy skipped)");
   4028                 r.state = ActivityState.DESTROYED;
   4029             }
   4030         } else {
   4031             // remove this record from the history.
   4032             if (r.finishing) {
   4033                 removeActivityFromHistoryLocked(r);
   4034                 removedFromHistory = true;
   4035             } else {
   4036                 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
   4037                         + " (no app)");
   4038                 r.state = ActivityState.DESTROYED;
   4039             }
   4040         }
   4041 
   4042         r.configChangeFlags = 0;
   4043 
   4044         if (!mLRUActivities.remove(r) && hadApp) {
   4045             Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
   4046         }
   4047 
   4048         return removedFromHistory;
   4049     }
   4050 
   4051     final void activityDestroyed(IBinder token) {
   4052         synchronized (mService) {
   4053             final long origId = Binder.clearCallingIdentity();
   4054             try {
   4055                 ActivityRecord r = ActivityRecord.forToken(token);
   4056                 if (r != null) {
   4057                     mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
   4058                 }
   4059 
   4060                 int index = indexOfActivityLocked(r);
   4061                 if (index >= 0) {
   4062                     if (r.state == ActivityState.DESTROYING) {
   4063                         cleanUpActivityLocked(r, true, false);
   4064                         removeActivityFromHistoryLocked(r);
   4065                     }
   4066                 }
   4067                 resumeTopActivityLocked(null);
   4068             } finally {
   4069                 Binder.restoreCallingIdentity(origId);
   4070             }
   4071         }
   4072     }
   4073 
   4074     private void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
   4075         int i = list.size();
   4076         if (localLOGV) Slog.v(
   4077             TAG, "Removing app " + app + " from list " + list
   4078             + " with " + i + " entries");
   4079         while (i > 0) {
   4080             i--;
   4081             ActivityRecord r = (ActivityRecord)list.get(i);
   4082             if (localLOGV) Slog.v(
   4083                 TAG, "Record #" + i + " " + r + ": app=" + r.app);
   4084             if (r.app == app) {
   4085                 if (localLOGV) Slog.v(TAG, "Removing this entry!");
   4086                 list.remove(i);
   4087                 removeTimeoutsForActivityLocked(r);
   4088             }
   4089         }
   4090     }
   4091 
   4092     void removeHistoryRecordsForAppLocked(ProcessRecord app) {
   4093         removeHistoryRecordsForAppLocked(mLRUActivities, app);
   4094         removeHistoryRecordsForAppLocked(mStoppingActivities, app);
   4095         removeHistoryRecordsForAppLocked(mGoingToSleepActivities, app);
   4096         removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
   4097         removeHistoryRecordsForAppLocked(mFinishingActivities, app);
   4098     }
   4099 
   4100     /**
   4101      * Move the current home activity's task (if one exists) to the front
   4102      * of the stack.
   4103      */
   4104     final void moveHomeToFrontLocked() {
   4105         TaskRecord homeTask = null;
   4106         for (int i=mHistory.size()-1; i>=0; i--) {
   4107             ActivityRecord hr = mHistory.get(i);
   4108             if (hr.isHomeActivity) {
   4109                 homeTask = hr.task;
   4110                 break;
   4111             }
   4112         }
   4113         if (homeTask != null) {
   4114             moveTaskToFrontLocked(homeTask, null, null);
   4115         }
   4116     }
   4117 
   4118     final void updateTransitLocked(int transit, Bundle options) {
   4119         if (options != null) {
   4120             ActivityRecord r = topRunningActivityLocked(null);
   4121             if (r != null && r.state != ActivityState.RESUMED) {
   4122                 r.updateOptionsLocked(options);
   4123             } else {
   4124                 ActivityOptions.abort(options);
   4125             }
   4126         }
   4127         mService.mWindowManager.prepareAppTransition(transit, false);
   4128     }
   4129 
   4130     final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
   4131         if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
   4132 
   4133         final int task = tr.taskId;
   4134         int top = mHistory.size()-1;
   4135 
   4136         if (top < 0 || (mHistory.get(top)).task.taskId == task) {
   4137             // nothing to do!
   4138             if (reason != null &&
   4139                     (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
   4140                 ActivityOptions.abort(options);
   4141             } else {
   4142                 updateTransitLocked(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT, options);
   4143             }
   4144             return;
   4145         }
   4146 
   4147         ArrayList<IBinder> moved = new ArrayList<IBinder>();
   4148 
   4149         // Applying the affinities may have removed entries from the history,
   4150         // so get the size again.
   4151         top = mHistory.size()-1;
   4152         int pos = top;
   4153 
   4154         // Shift all activities with this task up to the top
   4155         // of the stack, keeping them in the same internal order.
   4156         while (pos >= 0) {
   4157             ActivityRecord r = mHistory.get(pos);
   4158             if (localLOGV) Slog.v(
   4159                 TAG, "At " + pos + " ckp " + r.task + ": " + r);
   4160             if (r.task.taskId == task) {
   4161                 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
   4162                 if (DEBUG_ADD_REMOVE) {
   4163                     RuntimeException here = new RuntimeException("here");
   4164                     here.fillInStackTrace();
   4165                     Slog.i(TAG, "Removing and adding activity " + r + " to stack at " + top, here);
   4166                 }
   4167                 mHistory.remove(pos);
   4168                 mHistory.add(top, r);
   4169                 moved.add(0, r.appToken);
   4170                 top--;
   4171             }
   4172             pos--;
   4173         }
   4174 
   4175         if (DEBUG_TRANSITION) Slog.v(TAG,
   4176                 "Prepare to front transition: task=" + tr);
   4177         if (reason != null &&
   4178                 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
   4179             mService.mWindowManager.prepareAppTransition(
   4180                     WindowManagerPolicy.TRANSIT_NONE, false);
   4181             ActivityRecord r = topRunningActivityLocked(null);
   4182             if (r != null) {
   4183                 mNoAnimActivities.add(r);
   4184             }
   4185             ActivityOptions.abort(options);
   4186         } else {
   4187             updateTransitLocked(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT, options);
   4188         }
   4189 
   4190         mService.mWindowManager.moveAppTokensToTop(moved);
   4191         if (VALIDATE_TOKENS) {
   4192             validateAppTokensLocked();
   4193         }
   4194 
   4195         finishTaskMoveLocked(task);
   4196         EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
   4197     }
   4198 
   4199     private final void finishTaskMoveLocked(int task) {
   4200         resumeTopActivityLocked(null);
   4201     }
   4202 
   4203     /**
   4204      * Worker method for rearranging history stack.  Implements the function of moving all
   4205      * activities for a specific task (gathering them if disjoint) into a single group at the
   4206      * bottom of the stack.
   4207      *
   4208      * If a watcher is installed, the action is preflighted and the watcher has an opportunity
   4209      * to premeptively cancel the move.
   4210      *
   4211      * @param task The taskId to collect and move to the bottom.
   4212      * @return Returns true if the move completed, false if not.
   4213      */
   4214     final boolean moveTaskToBackLocked(int task, ActivityRecord reason) {
   4215         Slog.i(TAG, "moveTaskToBack: " + task);
   4216 
   4217         // If we have a watcher, preflight the move before committing to it.  First check
   4218         // for *other* available tasks, but if none are available, then try again allowing the
   4219         // current task to be selected.
   4220         if (mMainStack && mService.mController != null) {
   4221             ActivityRecord next = topRunningActivityLocked(null, task);
   4222             if (next == null) {
   4223                 next = topRunningActivityLocked(null, 0);
   4224             }
   4225             if (next != null) {
   4226                 // ask watcher if this is allowed
   4227                 boolean moveOK = true;
   4228                 try {
   4229                     moveOK = mService.mController.activityResuming(next.packageName);
   4230                 } catch (RemoteException e) {
   4231                     mService.mController = null;
   4232                 }
   4233                 if (!moveOK) {
   4234                     return false;
   4235                 }
   4236             }
   4237         }
   4238 
   4239         ArrayList<IBinder> moved = new ArrayList<IBinder>();
   4240 
   4241         if (DEBUG_TRANSITION) Slog.v(TAG,
   4242                 "Prepare to back transition: task=" + task);
   4243 
   4244         final int N = mHistory.size();
   4245         int bottom = 0;
   4246         int pos = 0;
   4247 
   4248         // Shift all activities with this task down to the bottom
   4249         // of the stack, keeping them in the same internal order.
   4250         while (pos < N) {
   4251             ActivityRecord r = mHistory.get(pos);
   4252             if (localLOGV) Slog.v(
   4253                 TAG, "At " + pos + " ckp " + r.task + ": " + r);
   4254             if (r.task.taskId == task) {
   4255                 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
   4256                 if (DEBUG_ADD_REMOVE) {
   4257                     RuntimeException here = new RuntimeException("here");
   4258                     here.fillInStackTrace();
   4259                     Slog.i(TAG, "Removing and adding activity " + r + " to stack at "
   4260                             + bottom, here);
   4261                 }
   4262                 mHistory.remove(pos);
   4263                 mHistory.add(bottom, r);
   4264                 moved.add(r.appToken);
   4265                 bottom++;
   4266             }
   4267             pos++;
   4268         }
   4269 
   4270         if (reason != null &&
   4271                 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
   4272             mService.mWindowManager.prepareAppTransition(
   4273                     WindowManagerPolicy.TRANSIT_NONE, false);
   4274             ActivityRecord r = topRunningActivityLocked(null);
   4275             if (r != null) {
   4276                 mNoAnimActivities.add(r);
   4277             }
   4278         } else {
   4279             mService.mWindowManager.prepareAppTransition(
   4280                     WindowManagerPolicy.TRANSIT_TASK_TO_BACK, false);
   4281         }
   4282         mService.mWindowManager.moveAppTokensToBottom(moved);
   4283         if (VALIDATE_TOKENS) {
   4284             validateAppTokensLocked();
   4285         }
   4286 
   4287         finishTaskMoveLocked(task);
   4288         return true;
   4289     }
   4290 
   4291     public ActivityManager.TaskThumbnails getTaskThumbnailsLocked(TaskRecord tr) {
   4292         TaskAccessInfo info = getTaskAccessInfoLocked(tr.taskId, true);
   4293         ActivityRecord resumed = mResumedActivity;
   4294         if (resumed != null && resumed.thumbHolder == tr) {
   4295             info.mainThumbnail = resumed.stack.screenshotActivities(resumed);
   4296         } else {
   4297             info.mainThumbnail = tr.lastThumbnail;
   4298         }
   4299         return info;
   4300     }
   4301 
   4302     public ActivityRecord removeTaskActivitiesLocked(int taskId, int subTaskIndex,
   4303             boolean taskRequired) {
   4304         TaskAccessInfo info = getTaskAccessInfoLocked(taskId, false);
   4305         if (info.root == null) {
   4306             if (taskRequired) {
   4307                 Slog.w(TAG, "removeTaskLocked: unknown taskId " + taskId);
   4308             }
   4309             return null;
   4310         }
   4311 
   4312         if (subTaskIndex < 0) {
   4313             // Just remove the entire task.
   4314             performClearTaskAtIndexLocked(taskId, info.rootIndex);
   4315             return info.root;
   4316         }
   4317 
   4318         if (subTaskIndex >= info.subtasks.size()) {
   4319             if (taskRequired) {
   4320                 Slog.w(TAG, "removeTaskLocked: unknown subTaskIndex " + subTaskIndex);
   4321             }
   4322             return null;
   4323         }
   4324 
   4325         // Remove all of this task's activies starting at the sub task.
   4326         TaskAccessInfo.SubTask subtask = info.subtasks.get(subTaskIndex);
   4327         performClearTaskAtIndexLocked(taskId, subtask.index);
   4328         return subtask.activity;
   4329     }
   4330 
   4331     public TaskAccessInfo getTaskAccessInfoLocked(int taskId, boolean inclThumbs) {
   4332         ActivityRecord resumed = mResumedActivity;
   4333         final TaskAccessInfo thumbs = new TaskAccessInfo();
   4334         // How many different sub-thumbnails?
   4335         final int NA = mHistory.size();
   4336         int j = 0;
   4337         ThumbnailHolder holder = null;
   4338         while (j < NA) {
   4339             ActivityRecord ar = mHistory.get(j);
   4340             if (!ar.finishing && ar.task.taskId == taskId) {
   4341                 holder = ar.thumbHolder;
   4342                 break;
   4343             }
   4344             j++;
   4345         }
   4346 
   4347         if (j >= NA) {
   4348             return thumbs;
   4349         }
   4350 
   4351         thumbs.root = mHistory.get(j);
   4352         thumbs.rootIndex = j;
   4353 
   4354         ArrayList<TaskAccessInfo.SubTask> subtasks = new ArrayList<TaskAccessInfo.SubTask>();
   4355         thumbs.subtasks = subtasks;
   4356         ActivityRecord lastActivity = null;
   4357         while (j < NA) {
   4358             ActivityRecord ar = mHistory.get(j);
   4359             j++;
   4360             if (ar.finishing) {
   4361                 continue;
   4362             }
   4363             if (ar.task.taskId != taskId) {
   4364                 break;
   4365             }
   4366             lastActivity = ar;
   4367             if (ar.thumbHolder != holder && holder != null) {
   4368                 thumbs.numSubThumbbails++;
   4369                 holder = ar.thumbHolder;
   4370                 TaskAccessInfo.SubTask sub = new TaskAccessInfo.SubTask();
   4371                 sub.thumbnail = holder.lastThumbnail;
   4372                 sub.activity = ar;
   4373                 sub.index = j-1;
   4374                 subtasks.add(sub);
   4375             }
   4376         }
   4377         if (lastActivity != null && subtasks.size() > 0) {
   4378             if (resumed == lastActivity) {
   4379                 TaskAccessInfo.SubTask sub = subtasks.get(subtasks.size()-1);
   4380                 sub.thumbnail = lastActivity.stack.screenshotActivities(lastActivity);
   4381             }
   4382         }
   4383         if (thumbs.numSubThumbbails > 0) {
   4384             thumbs.retriever = new IThumbnailRetriever.Stub() {
   4385                 public Bitmap getThumbnail(int index) {
   4386                     if (index < 0 || index >= thumbs.subtasks.size()) {
   4387                         return null;
   4388                     }
   4389                     return thumbs.subtasks.get(index).thumbnail;
   4390                 }
   4391             };
   4392         }
   4393         return thumbs;
   4394     }
   4395 
   4396     private final void logStartActivity(int tag, ActivityRecord r,
   4397             TaskRecord task) {
   4398         EventLog.writeEvent(tag,
   4399                 System.identityHashCode(r), task.taskId,
   4400                 r.shortComponentName, r.intent.getAction(),
   4401                 r.intent.getType(), r.intent.getDataString(),
   4402                 r.intent.getFlags());
   4403     }
   4404 
   4405     /**
   4406      * Make sure the given activity matches the current configuration.  Returns
   4407      * false if the activity had to be destroyed.  Returns true if the
   4408      * configuration is the same, or the activity will remain running as-is
   4409      * for whatever reason.  Ensures the HistoryRecord is updated with the
   4410      * correct configuration and all other bookkeeping is handled.
   4411      */
   4412     final boolean ensureActivityConfigurationLocked(ActivityRecord r,
   4413             int globalChanges) {
   4414         if (mConfigWillChange) {
   4415             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   4416                     "Skipping config check (will change): " + r);
   4417             return true;
   4418         }
   4419 
   4420         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   4421                 "Ensuring correct configuration: " + r);
   4422 
   4423         // Short circuit: if the two configurations are the exact same
   4424         // object (the common case), then there is nothing to do.
   4425         Configuration newConfig = mService.mConfiguration;
   4426         if (r.configuration == newConfig && !r.forceNewConfig) {
   4427             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   4428                     "Configuration unchanged in " + r);
   4429             return true;
   4430         }
   4431 
   4432         // We don't worry about activities that are finishing.
   4433         if (r.finishing) {
   4434             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   4435                     "Configuration doesn't matter in finishing " + r);
   4436             r.stopFreezingScreenLocked(false);
   4437             return true;
   4438         }
   4439 
   4440         // Okay we now are going to make this activity have the new config.
   4441         // But then we need to figure out how it needs to deal with that.
   4442         Configuration oldConfig = r.configuration;
   4443         r.configuration = newConfig;
   4444 
   4445         // Determine what has changed.  May be nothing, if this is a config
   4446         // that has come back from the app after going idle.  In that case
   4447         // we just want to leave the official config object now in the
   4448         // activity and do nothing else.
   4449         final int changes = oldConfig.diff(newConfig);
   4450         if (changes == 0 && !r.forceNewConfig) {
   4451             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   4452                     "Configuration no differences in " + r);
   4453             return true;
   4454         }
   4455 
   4456         // If the activity isn't currently running, just leave the new
   4457         // configuration and it will pick that up next time it starts.
   4458         if (r.app == null || r.app.thread == null) {
   4459             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   4460                     "Configuration doesn't matter not running " + r);
   4461             r.stopFreezingScreenLocked(false);
   4462             r.forceNewConfig = false;
   4463             return true;
   4464         }
   4465 
   4466         // Figure out how to handle the changes between the configurations.
   4467         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
   4468             Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
   4469                     + Integer.toHexString(changes) + ", handles=0x"
   4470                     + Integer.toHexString(r.info.getRealConfigChanged())
   4471                     + ", newConfig=" + newConfig);
   4472         }
   4473         if ((changes&(~r.info.getRealConfigChanged())) != 0 || r.forceNewConfig) {
   4474             // Aha, the activity isn't handling the change, so DIE DIE DIE.
   4475             r.configChangeFlags |= changes;
   4476             r.startFreezingScreenLocked(r.app, globalChanges);
   4477             r.forceNewConfig = false;
   4478             if (r.app == null || r.app.thread == null) {
   4479                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   4480                         "Config is destroying non-running " + r);
   4481                 destroyActivityLocked(r, true, false, "config");
   4482             } else if (r.state == ActivityState.PAUSING) {
   4483                 // A little annoying: we are waiting for this activity to
   4484                 // finish pausing.  Let's not do anything now, but just
   4485                 // flag that it needs to be restarted when done pausing.
   4486                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   4487                         "Config is skipping already pausing " + r);
   4488                 r.configDestroy = true;
   4489                 return true;
   4490             } else if (r.state == ActivityState.RESUMED) {
   4491                 // Try to optimize this case: the configuration is changing
   4492                 // and we need to restart the top, resumed activity.
   4493                 // Instead of doing the normal handshaking, just say
   4494                 // "restart!".
   4495                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   4496                         "Config is relaunching resumed " + r);
   4497                 relaunchActivityLocked(r, r.configChangeFlags, true);
   4498                 r.configChangeFlags = 0;
   4499             } else {
   4500                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
   4501                         "Config is relaunching non-resumed " + r);
   4502                 relaunchActivityLocked(r, r.configChangeFlags, false);
   4503                 r.configChangeFlags = 0;
   4504             }
   4505 
   4506             // All done...  tell the caller we weren't able to keep this
   4507             // activity around.
   4508             return false;
   4509         }
   4510 
   4511         // Default case: the activity can handle this new configuration, so
   4512         // hand it over.  Note that we don't need to give it the new
   4513         // configuration, since we always send configuration changes to all
   4514         // process when they happen so it can just use whatever configuration
   4515         // it last got.
   4516         if (r.app != null && r.app.thread != null) {
   4517             try {
   4518                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
   4519                 r.app.thread.scheduleActivityConfigurationChanged(r.appToken);
   4520             } catch (RemoteException e) {
   4521                 // If process died, whatever.
   4522             }
   4523         }
   4524         r.stopFreezingScreenLocked(false);
   4525 
   4526         return true;
   4527     }
   4528 
   4529     private final boolean relaunchActivityLocked(ActivityRecord r,
   4530             int changes, boolean andResume) {
   4531         List<ResultInfo> results = null;
   4532         List<Intent> newIntents = null;
   4533         if (andResume) {
   4534             results = r.results;
   4535             newIntents = r.newIntents;
   4536         }
   4537         if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
   4538                 + " with results=" + results + " newIntents=" + newIntents
   4539                 + " andResume=" + andResume);
   4540         EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
   4541                 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
   4542                 r.task.taskId, r.shortComponentName);
   4543 
   4544         r.startFreezingScreenLocked(r.app, 0);
   4545 
   4546         try {
   4547             if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
   4548                     (andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ")
   4549                     + r);
   4550             r.forceNewConfig = false;
   4551             r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents,
   4552                     changes, !andResume, new Configuration(mService.mConfiguration));
   4553             // Note: don't need to call pauseIfSleepingLocked() here, because
   4554             // the caller will only pass in 'andResume' if this activity is
   4555             // currently resumed, which implies we aren't sleeping.
   4556         } catch (RemoteException e) {
   4557             if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG, "Relaunch failed", e);
   4558         }
   4559 
   4560         if (andResume) {
   4561             r.results = null;
   4562             r.newIntents = null;
   4563             if (mMainStack) {
   4564                 mService.reportResumedActivityLocked(r);
   4565             }
   4566             r.state = ActivityState.RESUMED;
   4567         } else {
   4568             mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
   4569             r.state = ActivityState.PAUSED;
   4570         }
   4571 
   4572         return true;
   4573     }
   4574 
   4575     public void dismissKeyguardOnNextActivityLocked() {
   4576         mDismissKeyguardOnNextActivity = true;
   4577     }
   4578 }
   4579