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