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