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