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