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