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