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