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