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