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