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