ActivityStack.java revision 1927ae8a56a010919a7535231fa0f7db70f7e152
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        }
1133
1134        if (prev != null) {
1135            prev.resumeKeyDispatchingLocked();
1136        }
1137
1138        if (prev.app != null && prev.cpuTimeAtResume > 0
1139                && mService.mBatteryStatsService.isOnBattery()) {
1140            long diff = 0;
1141            synchronized (mService.mProcessStatsThread) {
1142                diff = mService.mProcessStats.getCpuTimeForPid(prev.app.pid)
1143                        - prev.cpuTimeAtResume;
1144            }
1145            if (diff > 0) {
1146                BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics();
1147                synchronized (bsi) {
1148                    BatteryStatsImpl.Uid.Proc ps =
1149                            bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
1150                            prev.info.packageName);
1151                    if (ps != null) {
1152                        ps.addForegroundTimeLocked(diff);
1153                    }
1154                }
1155            }
1156        }
1157        prev.cpuTimeAtResume = 0; // reset it
1158    }
1159
1160    /**
1161     * Once we know that we have asked an application to put an activity in
1162     * the resumed state (either by launching it or explicitly telling it),
1163     * this function updates the rest of our state to match that fact.
1164     */
1165    private final void completeResumeLocked(ActivityRecord next) {
1166        next.idle = false;
1167        next.results = null;
1168        next.newIntents = null;
1169
1170        // schedule an idle timeout in case the app doesn't do it for us.
1171        Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1172        msg.obj = next;
1173        mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
1174
1175        if (false) {
1176            // The activity was never told to pause, so just keep
1177            // things going as-is.  To maintain our own state,
1178            // we need to emulate it coming back and saying it is
1179            // idle.
1180            msg = mHandler.obtainMessage(IDLE_NOW_MSG);
1181            msg.obj = next;
1182            mHandler.sendMessage(msg);
1183        }
1184
1185        if (mMainStack) {
1186            mService.reportResumedActivityLocked(next);
1187        }
1188
1189        next.clearThumbnail();
1190        if (mMainStack) {
1191            mService.setFocusedActivityLocked(next);
1192        }
1193        next.resumeKeyDispatchingLocked();
1194        ensureActivitiesVisibleLocked(null, 0);
1195        mService.mWindowManager.executeAppTransition();
1196        mNoAnimActivities.clear();
1197
1198        // Mark the point when the activity is resuming
1199        // TODO: To be more accurate, the mark should be before the onCreate,
1200        //       not after the onResume. But for subsequent starts, onResume is fine.
1201        if (next.app != null) {
1202            synchronized (mService.mProcessStatsThread) {
1203                next.cpuTimeAtResume = mService.mProcessStats.getCpuTimeForPid(next.app.pid);
1204            }
1205        } else {
1206            next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
1207        }
1208    }
1209
1210    /**
1211     * Make sure that all activities that need to be visible (that is, they
1212     * currently can be seen by the user) actually are.
1213     */
1214    final void ensureActivitiesVisibleLocked(ActivityRecord top,
1215            ActivityRecord starting, String onlyThisProcess, int configChanges) {
1216        if (DEBUG_VISBILITY) Slog.v(
1217                TAG, "ensureActivitiesVisible behind " + top
1218                + " configChanges=0x" + Integer.toHexString(configChanges));
1219
1220        // If the top activity is not fullscreen, then we need to
1221        // make sure any activities under it are now visible.
1222        final int count = mHistory.size();
1223        int i = count-1;
1224        while (mHistory.get(i) != top) {
1225            i--;
1226        }
1227        ActivityRecord r;
1228        boolean behindFullscreen = false;
1229        for (; i>=0; i--) {
1230            r = mHistory.get(i);
1231            if (DEBUG_VISBILITY) Slog.v(
1232                    TAG, "Make visible? " + r + " finishing=" + r.finishing
1233                    + " state=" + r.state);
1234            if (r.finishing) {
1235                continue;
1236            }
1237
1238            final boolean doThisProcess = onlyThisProcess == null
1239                    || onlyThisProcess.equals(r.processName);
1240
1241            // First: if this is not the current activity being started, make
1242            // sure it matches the current configuration.
1243            if (r != starting && doThisProcess) {
1244                ensureActivityConfigurationLocked(r, 0);
1245            }
1246
1247            if (r.app == null || r.app.thread == null) {
1248                if (onlyThisProcess == null
1249                        || onlyThisProcess.equals(r.processName)) {
1250                    // This activity needs to be visible, but isn't even
1251                    // running...  get it started, but don't resume it
1252                    // at this point.
1253                    if (DEBUG_VISBILITY) Slog.v(
1254                            TAG, "Start and freeze screen for " + r);
1255                    if (r != starting) {
1256                        r.startFreezingScreenLocked(r.app, configChanges);
1257                    }
1258                    if (!r.visible) {
1259                        if (DEBUG_VISBILITY) Slog.v(
1260                                TAG, "Starting and making visible: " + r);
1261                        mService.mWindowManager.setAppVisibility(r.appToken, true);
1262                    }
1263                    if (r != starting) {
1264                        startSpecificActivityLocked(r, false, false);
1265                    }
1266                }
1267
1268            } else if (r.visible) {
1269                // If this activity is already visible, then there is nothing
1270                // else to do here.
1271                if (DEBUG_VISBILITY) Slog.v(
1272                        TAG, "Skipping: already visible at " + r);
1273                r.stopFreezingScreenLocked(false);
1274
1275            } else if (onlyThisProcess == null) {
1276                // This activity is not currently visible, but is running.
1277                // Tell it to become visible.
1278                r.visible = true;
1279                if (r.state != ActivityState.RESUMED && r != starting) {
1280                    // If this activity is paused, tell it
1281                    // to now show its window.
1282                    if (DEBUG_VISBILITY) Slog.v(
1283                            TAG, "Making visible and scheduling visibility: " + r);
1284                    try {
1285                        mService.mWindowManager.setAppVisibility(r.appToken, true);
1286                        r.sleeping = false;
1287                        r.app.pendingUiClean = true;
1288                        r.app.thread.scheduleWindowVisibility(r.appToken, true);
1289                        r.stopFreezingScreenLocked(false);
1290                    } catch (Exception e) {
1291                        // Just skip on any failure; we'll make it
1292                        // visible when it next restarts.
1293                        Slog.w(TAG, "Exception thrown making visibile: "
1294                                + r.intent.getComponent(), e);
1295                    }
1296                }
1297            }
1298
1299            // Aggregate current change flags.
1300            configChanges |= r.configChangeFlags;
1301
1302            if (r.fullscreen) {
1303                // At this point, nothing else needs to be shown
1304                if (DEBUG_VISBILITY) Slog.v(
1305                        TAG, "Stopping: fullscreen at " + r);
1306                behindFullscreen = true;
1307                i--;
1308                break;
1309            }
1310        }
1311
1312        // Now for any activities that aren't visible to the user, make
1313        // sure they no longer are keeping the screen frozen.
1314        while (i >= 0) {
1315            r = mHistory.get(i);
1316            if (DEBUG_VISBILITY) Slog.v(
1317                    TAG, "Make invisible? " + r + " finishing=" + r.finishing
1318                    + " state=" + r.state
1319                    + " behindFullscreen=" + behindFullscreen);
1320            if (!r.finishing) {
1321                if (behindFullscreen) {
1322                    if (r.visible) {
1323                        if (DEBUG_VISBILITY) Slog.v(
1324                                TAG, "Making invisible: " + r);
1325                        r.visible = false;
1326                        try {
1327                            mService.mWindowManager.setAppVisibility(r.appToken, false);
1328                            if ((r.state == ActivityState.STOPPING
1329                                    || r.state == ActivityState.STOPPED)
1330                                    && r.app != null && r.app.thread != null) {
1331                                if (DEBUG_VISBILITY) Slog.v(
1332                                        TAG, "Scheduling invisibility: " + r);
1333                                r.app.thread.scheduleWindowVisibility(r.appToken, false);
1334                            }
1335                        } catch (Exception e) {
1336                            // Just skip on any failure; we'll make it
1337                            // visible when it next restarts.
1338                            Slog.w(TAG, "Exception thrown making hidden: "
1339                                    + r.intent.getComponent(), e);
1340                        }
1341                    } else {
1342                        if (DEBUG_VISBILITY) Slog.v(
1343                                TAG, "Already invisible: " + r);
1344                    }
1345                } else if (r.fullscreen) {
1346                    if (DEBUG_VISBILITY) Slog.v(
1347                            TAG, "Now behindFullscreen: " + r);
1348                    behindFullscreen = true;
1349                }
1350            }
1351            i--;
1352        }
1353    }
1354
1355    /**
1356     * Version of ensureActivitiesVisible that can easily be called anywhere.
1357     */
1358    final void ensureActivitiesVisibleLocked(ActivityRecord starting,
1359            int configChanges) {
1360        ActivityRecord r = topRunningActivityLocked(null);
1361        if (r != null) {
1362            ensureActivitiesVisibleLocked(r, starting, null, configChanges);
1363        }
1364    }
1365
1366    /**
1367     * Ensure that the top activity in the stack is resumed.
1368     *
1369     * @param prev The previously resumed activity, for when in the process
1370     * of pausing; can be null to call from elsewhere.
1371     *
1372     * @return Returns true if something is being resumed, or false if
1373     * nothing happened.
1374     */
1375    final boolean resumeTopActivityLocked(ActivityRecord prev) {
1376        return resumeTopActivityLocked(prev, null);
1377    }
1378
1379    final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
1380        // Find the first activity that is not finishing.
1381        ActivityRecord next = topRunningActivityLocked(null);
1382
1383        // Remember how we'll process this pause/resume situation, and ensure
1384        // that the state is reset however we wind up proceeding.
1385        final boolean userLeaving = mUserLeaving;
1386        mUserLeaving = false;
1387
1388        if (next == null) {
1389            // There are no more activities!  Let's just start up the
1390            // Launcher...
1391            if (mMainStack) {
1392                ActivityOptions.abort(options);
1393                return mService.startHomeActivityLocked(0);
1394            }
1395        }
1396
1397        next.delayedResume = false;
1398
1399        // If the top activity is the resumed one, nothing to do.
1400        if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
1401            // Make sure we have executed any pending transitions, since there
1402            // should be nothing left to do at this point.
1403            mService.mWindowManager.executeAppTransition();
1404            mNoAnimActivities.clear();
1405            ActivityOptions.abort(options);
1406            return false;
1407        }
1408
1409        // If we are sleeping, and there is no resumed activity, and the top
1410        // activity is paused, well that is the state we want.
1411        if ((mService.mSleeping || mService.mShuttingDown)
1412                && mLastPausedActivity == next
1413                && (next.state == ActivityState.PAUSED
1414                    || next.state == ActivityState.STOPPED
1415                    || next.state == ActivityState.STOPPING)) {
1416            // Make sure we have executed any pending transitions, since there
1417            // should be nothing left to do at this point.
1418            mService.mWindowManager.executeAppTransition();
1419            mNoAnimActivities.clear();
1420            ActivityOptions.abort(options);
1421            return false;
1422        }
1423
1424        // The activity may be waiting for stop, but that is no longer
1425        // appropriate for it.
1426        mStoppingActivities.remove(next);
1427        mGoingToSleepActivities.remove(next);
1428        next.sleeping = false;
1429        mWaitingVisibleActivities.remove(next);
1430
1431        next.updateOptionsLocked(options);
1432
1433        if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
1434
1435        // If we are currently pausing an activity, then don't do anything
1436        // until that is done.
1437        if (mPausingActivity != null) {
1438            if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
1439            return false;
1440        }
1441
1442        // Okay we are now going to start a switch, to 'next'.  We may first
1443        // have to pause the current activity, but this is an important point
1444        // where we have decided to go to 'next' so keep track of that.
1445        // XXX "App Redirected" dialog is getting too many false positives
1446        // at this point, so turn off for now.
1447        if (false) {
1448            if (mLastStartedActivity != null && !mLastStartedActivity.finishing) {
1449                long now = SystemClock.uptimeMillis();
1450                final boolean inTime = mLastStartedActivity.startTime != 0
1451                        && (mLastStartedActivity.startTime + START_WARN_TIME) >= now;
1452                final int lastUid = mLastStartedActivity.info.applicationInfo.uid;
1453                final int nextUid = next.info.applicationInfo.uid;
1454                if (inTime && lastUid != nextUid
1455                        && lastUid != next.launchedFromUid
1456                        && mService.checkPermission(
1457                                android.Manifest.permission.STOP_APP_SWITCHES,
1458                                -1, next.launchedFromUid)
1459                        != PackageManager.PERMISSION_GRANTED) {
1460                    mService.showLaunchWarningLocked(mLastStartedActivity, next);
1461                } else {
1462                    next.startTime = now;
1463                    mLastStartedActivity = next;
1464                }
1465            } else {
1466                next.startTime = SystemClock.uptimeMillis();
1467                mLastStartedActivity = next;
1468            }
1469        }
1470
1471        // We need to start pausing the current activity so the top one
1472        // can be resumed...
1473        if (mResumedActivity != null) {
1474            if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
1475            startPausingLocked(userLeaving, false);
1476            return true;
1477        }
1478
1479        // If the most recent activity was noHistory but was only stopped rather
1480        // than stopped+finished because the device went to sleep, we need to make
1481        // sure to finish it as we're making a new activity topmost.
1482        final ActivityRecord last = mLastPausedActivity;
1483        if (mService.mSleeping && last != null && !last.finishing) {
1484            if ((last.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
1485                    || (last.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
1486                if (DEBUG_STATES) {
1487                    Slog.d(TAG, "no-history finish of " + last + " on new resume");
1488                }
1489                requestFinishActivityLocked(last.appToken, Activity.RESULT_CANCELED, null,
1490                "no-history");
1491            }
1492        }
1493
1494        if (prev != null && prev != next) {
1495            if (!prev.waitingVisible && next != null && !next.nowVisible) {
1496                prev.waitingVisible = true;
1497                mWaitingVisibleActivities.add(prev);
1498                if (DEBUG_SWITCH) Slog.v(
1499                        TAG, "Resuming top, waiting visible to hide: " + prev);
1500            } else {
1501                // The next activity is already visible, so hide the previous
1502                // activity's windows right now so we can show the new one ASAP.
1503                // We only do this if the previous is finishing, which should mean
1504                // it is on top of the one being resumed so hiding it quickly
1505                // is good.  Otherwise, we want to do the normal route of allowing
1506                // the resumed activity to be shown so we can decide if the
1507                // previous should actually be hidden depending on whether the
1508                // new one is found to be full-screen or not.
1509                if (prev.finishing) {
1510                    mService.mWindowManager.setAppVisibility(prev.appToken, false);
1511                    if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
1512                            + prev + ", waitingVisible="
1513                            + (prev != null ? prev.waitingVisible : null)
1514                            + ", nowVisible=" + next.nowVisible);
1515                } else {
1516                    if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
1517                        + prev + ", waitingVisible="
1518                        + (prev != null ? prev.waitingVisible : null)
1519                        + ", nowVisible=" + next.nowVisible);
1520                }
1521            }
1522        }
1523
1524        // Launching this app's activity, make sure the app is no longer
1525        // considered stopped.
1526        try {
1527            AppGlobals.getPackageManager().setPackageStoppedState(
1528                    next.packageName, false, next.userId); /* TODO: Verify if correct userid */
1529        } catch (RemoteException e1) {
1530        } catch (IllegalArgumentException e) {
1531            Slog.w(TAG, "Failed trying to unstop package "
1532                    + next.packageName + ": " + e);
1533        }
1534
1535        // We are starting up the next activity, so tell the window manager
1536        // that the previous one will be hidden soon.  This way it can know
1537        // to ignore it when computing the desired screen orientation.
1538        boolean noAnim = false;
1539        if (prev != null) {
1540            if (prev.finishing) {
1541                if (DEBUG_TRANSITION) Slog.v(TAG,
1542                        "Prepare close transition: prev=" + prev);
1543                if (mNoAnimActivities.contains(prev)) {
1544                    mService.mWindowManager.prepareAppTransition(
1545                            WindowManagerPolicy.TRANSIT_NONE, false);
1546                } else {
1547                    mService.mWindowManager.prepareAppTransition(prev.task == next.task
1548                            ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
1549                            : WindowManagerPolicy.TRANSIT_TASK_CLOSE, false);
1550                }
1551                mService.mWindowManager.setAppWillBeHidden(prev.appToken);
1552                mService.mWindowManager.setAppVisibility(prev.appToken, false);
1553            } else {
1554                if (DEBUG_TRANSITION) Slog.v(TAG,
1555                        "Prepare open transition: prev=" + prev);
1556                if (mNoAnimActivities.contains(next)) {
1557                    noAnim = true;
1558                    mService.mWindowManager.prepareAppTransition(
1559                            WindowManagerPolicy.TRANSIT_NONE, false);
1560                } else {
1561                    mService.mWindowManager.prepareAppTransition(prev.task == next.task
1562                            ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1563                            : WindowManagerPolicy.TRANSIT_TASK_OPEN, false);
1564                }
1565            }
1566            if (false) {
1567                mService.mWindowManager.setAppWillBeHidden(prev.appToken);
1568                mService.mWindowManager.setAppVisibility(prev.appToken, false);
1569            }
1570        } else if (mHistory.size() > 1) {
1571            if (DEBUG_TRANSITION) Slog.v(TAG,
1572                    "Prepare open transition: no previous");
1573            if (mNoAnimActivities.contains(next)) {
1574                noAnim = true;
1575                mService.mWindowManager.prepareAppTransition(
1576                        WindowManagerPolicy.TRANSIT_NONE, false);
1577            } else {
1578                mService.mWindowManager.prepareAppTransition(
1579                        WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN, false);
1580            }
1581        }
1582        if (!noAnim) {
1583            next.applyOptionsLocked();
1584        } else {
1585            next.clearOptionsLocked();
1586        }
1587
1588        if (next.app != null && next.app.thread != null) {
1589            if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
1590
1591            // This activity is now becoming visible.
1592            mService.mWindowManager.setAppVisibility(next.appToken, true);
1593
1594            // schedule launch ticks to collect information about slow apps.
1595            next.startLaunchTickingLocked();
1596
1597            ActivityRecord lastResumedActivity = mResumedActivity;
1598            ActivityState lastState = next.state;
1599
1600            mService.updateCpuStats();
1601
1602            if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + next + " (in existing)");
1603            next.state = ActivityState.RESUMED;
1604            mResumedActivity = next;
1605            next.task.touchActiveTime();
1606            if (mMainStack) {
1607                mService.addRecentTaskLocked(next.task);
1608            }
1609            mService.updateLruProcessLocked(next.app, true, true);
1610            updateLRUListLocked(next);
1611
1612            // Have the window manager re-evaluate the orientation of
1613            // the screen based on the new activity order.
1614            boolean updated = false;
1615            if (mMainStack) {
1616                synchronized (mService) {
1617                    Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
1618                            mService.mConfiguration,
1619                            next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
1620                    if (config != null) {
1621                        next.frozenBeforeDestroy = true;
1622                    }
1623                    updated = mService.updateConfigurationLocked(config, next, false, false);
1624                }
1625            }
1626            if (!updated) {
1627                // The configuration update wasn't able to keep the existing
1628                // instance of the activity, and instead started a new one.
1629                // We should be all done, but let's just make sure our activity
1630                // is still at the top and schedule another run if something
1631                // weird happened.
1632                ActivityRecord nextNext = topRunningActivityLocked(null);
1633                if (DEBUG_SWITCH) Slog.i(TAG,
1634                        "Activity config changed during resume: " + next
1635                        + ", new next: " + nextNext);
1636                if (nextNext != next) {
1637                    // Do over!
1638                    mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
1639                }
1640                if (mMainStack) {
1641                    mService.setFocusedActivityLocked(next);
1642                }
1643                ensureActivitiesVisibleLocked(null, 0);
1644                mService.mWindowManager.executeAppTransition();
1645                mNoAnimActivities.clear();
1646                return true;
1647            }
1648
1649            try {
1650                // Deliver all pending results.
1651                ArrayList a = next.results;
1652                if (a != null) {
1653                    final int N = a.size();
1654                    if (!next.finishing && N > 0) {
1655                        if (DEBUG_RESULTS) Slog.v(
1656                                TAG, "Delivering results to " + next
1657                                + ": " + a);
1658                        next.app.thread.scheduleSendResult(next.appToken, a);
1659                    }
1660                }
1661
1662                if (next.newIntents != null) {
1663                    next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
1664                }
1665
1666                EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
1667                        System.identityHashCode(next),
1668                        next.task.taskId, next.shortComponentName);
1669
1670                next.sleeping = false;
1671                showAskCompatModeDialogLocked(next);
1672                next.app.pendingUiClean = true;
1673                next.app.thread.scheduleResumeActivity(next.appToken,
1674                        mService.isNextTransitionForward());
1675
1676                checkReadyForSleepLocked();
1677
1678            } catch (Exception e) {
1679                // Whoops, need to restart this activity!
1680                if (DEBUG_STATES) Slog.v(TAG, "Resume failed; resetting state to "
1681                        + lastState + ": " + next);
1682                next.state = lastState;
1683                mResumedActivity = lastResumedActivity;
1684                Slog.i(TAG, "Restarting because process died: " + next);
1685                if (!next.hasBeenLaunched) {
1686                    next.hasBeenLaunched = true;
1687                } else {
1688                    if (SHOW_APP_STARTING_PREVIEW && mMainStack) {
1689                        mService.mWindowManager.setAppStartingWindow(
1690                                next.appToken, next.packageName, next.theme,
1691                                mService.compatibilityInfoForPackageLocked(
1692                                        next.info.applicationInfo),
1693                                next.nonLocalizedLabel,
1694                                next.labelRes, next.icon, next.windowFlags,
1695                                null, true);
1696                    }
1697                }
1698                startSpecificActivityLocked(next, true, false);
1699                return true;
1700            }
1701
1702            // From this point on, if something goes wrong there is no way
1703            // to recover the activity.
1704            try {
1705                next.visible = true;
1706                completeResumeLocked(next);
1707            } catch (Exception e) {
1708                // If any exception gets thrown, toss away this
1709                // activity and try the next one.
1710                Slog.w(TAG, "Exception thrown during resume of " + next, e);
1711                requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
1712                        "resume-exception");
1713                return true;
1714            }
1715
1716            // Didn't need to use the icicle, and it is now out of date.
1717            if (DEBUG_SAVED_STATE) Slog.i(TAG, "Resumed activity; didn't need icicle of: " + next);
1718            next.icicle = null;
1719            next.haveState = false;
1720            next.stopped = false;
1721
1722        } else {
1723            // Whoops, need to restart this activity!
1724            if (!next.hasBeenLaunched) {
1725                next.hasBeenLaunched = true;
1726            } else {
1727                if (SHOW_APP_STARTING_PREVIEW) {
1728                    mService.mWindowManager.setAppStartingWindow(
1729                            next.appToken, next.packageName, next.theme,
1730                            mService.compatibilityInfoForPackageLocked(
1731                                    next.info.applicationInfo),
1732                            next.nonLocalizedLabel,
1733                            next.labelRes, next.icon, next.windowFlags,
1734                            null, true);
1735                }
1736                if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
1737            }
1738            startSpecificActivityLocked(next, true, true);
1739        }
1740
1741        return true;
1742    }
1743
1744    private final void startActivityLocked(ActivityRecord r, boolean newTask,
1745            boolean doResume, boolean keepCurTransition, Bundle options) {
1746        final int NH = mHistory.size();
1747
1748        int addPos = -1;
1749
1750        if (!newTask) {
1751            // If starting in an existing task, find where that is...
1752            boolean startIt = true;
1753            for (int i = NH-1; i >= 0; i--) {
1754                ActivityRecord p = mHistory.get(i);
1755                if (p.finishing) {
1756                    continue;
1757                }
1758                if (p.task == r.task) {
1759                    // Here it is!  Now, if this is not yet visible to the
1760                    // user, then just add it without starting; it will
1761                    // get started when the user navigates back to it.
1762                    addPos = i+1;
1763                    if (!startIt) {
1764                        if (DEBUG_ADD_REMOVE) {
1765                            RuntimeException here = new RuntimeException("here");
1766                            here.fillInStackTrace();
1767                            Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos,
1768                                    here);
1769                        }
1770                        mHistory.add(addPos, r);
1771                        r.putInHistory();
1772                        mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
1773                                r.info.screenOrientation, r.fullscreen);
1774                        if (VALIDATE_TOKENS) {
1775                            validateAppTokensLocked();
1776                        }
1777                        ActivityOptions.abort(options);
1778                        return;
1779                    }
1780                    break;
1781                }
1782                if (p.fullscreen) {
1783                    startIt = false;
1784                }
1785            }
1786        }
1787
1788        // Place a new activity at top of stack, so it is next to interact
1789        // with the user.
1790        if (addPos < 0) {
1791            addPos = NH;
1792        }
1793
1794        // If we are not placing the new activity frontmost, we do not want
1795        // to deliver the onUserLeaving callback to the actual frontmost
1796        // activity
1797        if (addPos < NH) {
1798            mUserLeaving = false;
1799            if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
1800        }
1801
1802        // Slot the activity into the history stack and proceed
1803        if (DEBUG_ADD_REMOVE) {
1804            RuntimeException here = new RuntimeException("here");
1805            here.fillInStackTrace();
1806            Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos, here);
1807        }
1808        mHistory.add(addPos, r);
1809        r.putInHistory();
1810        r.frontOfTask = newTask;
1811        if (NH > 0) {
1812            // We want to show the starting preview window if we are
1813            // switching to a new task, or the next activity's process is
1814            // not currently running.
1815            boolean showStartingIcon = newTask;
1816            ProcessRecord proc = r.app;
1817            if (proc == null) {
1818                proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
1819            }
1820            if (proc == null || proc.thread == null) {
1821                showStartingIcon = true;
1822            }
1823            if (DEBUG_TRANSITION) Slog.v(TAG,
1824                    "Prepare open transition: starting " + r);
1825            if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
1826                mService.mWindowManager.prepareAppTransition(
1827                        WindowManagerPolicy.TRANSIT_NONE, keepCurTransition);
1828                mNoAnimActivities.add(r);
1829            } else {
1830                mService.mWindowManager.prepareAppTransition(newTask
1831                        ? WindowManagerPolicy.TRANSIT_TASK_OPEN
1832                        : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
1833                mNoAnimActivities.remove(r);
1834            }
1835            r.updateOptionsLocked(options);
1836            mService.mWindowManager.addAppToken(
1837                    addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen);
1838            boolean doShow = true;
1839            if (newTask) {
1840                // Even though this activity is starting fresh, we still need
1841                // to reset it to make sure we apply affinities to move any
1842                // existing activities from other tasks in to it.
1843                // If the caller has requested that the target task be
1844                // reset, then do so.
1845                if ((r.intent.getFlags()
1846                        &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1847                    resetTaskIfNeededLocked(r, r);
1848                    doShow = topRunningNonDelayedActivityLocked(null) == r;
1849                }
1850            }
1851            if (SHOW_APP_STARTING_PREVIEW && doShow) {
1852                // Figure out if we are transitioning from another activity that is
1853                // "has the same starting icon" as the next one.  This allows the
1854                // window manager to keep the previous window it had previously
1855                // created, if it still had one.
1856                ActivityRecord prev = mResumedActivity;
1857                if (prev != null) {
1858                    // We don't want to reuse the previous starting preview if:
1859                    // (1) The current activity is in a different task.
1860                    if (prev.task != r.task) prev = null;
1861                    // (2) The current activity is already displayed.
1862                    else if (prev.nowVisible) prev = null;
1863                }
1864                mService.mWindowManager.setAppStartingWindow(
1865                        r.appToken, r.packageName, r.theme,
1866                        mService.compatibilityInfoForPackageLocked(
1867                                r.info.applicationInfo), r.nonLocalizedLabel,
1868                        r.labelRes, r.icon, r.windowFlags,
1869                        prev != null ? prev.appToken : null, showStartingIcon);
1870            }
1871        } else {
1872            // If this is the first activity, don't do any fancy animations,
1873            // because there is nothing for it to animate on top of.
1874            mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
1875                    r.info.screenOrientation, r.fullscreen);
1876            ActivityOptions.abort(options);
1877        }
1878        if (VALIDATE_TOKENS) {
1879            validateAppTokensLocked();
1880        }
1881
1882        if (doResume) {
1883            resumeTopActivityLocked(null);
1884        }
1885    }
1886
1887    final void validateAppTokensLocked() {
1888        mValidateAppTokens.clear();
1889        mValidateAppTokens.ensureCapacity(mHistory.size());
1890        for (int i=0; i<mHistory.size(); i++) {
1891            mValidateAppTokens.add(mHistory.get(i).appToken);
1892        }
1893        mService.mWindowManager.validateAppTokens(mValidateAppTokens);
1894    }
1895
1896    /**
1897     * Perform a reset of the given task, if needed as part of launching it.
1898     * Returns the new HistoryRecord at the top of the task.
1899     */
1900    private final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
1901            ActivityRecord newActivity) {
1902        boolean forceReset = (newActivity.info.flags
1903                &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
1904        if (ACTIVITY_INACTIVE_RESET_TIME > 0
1905                && taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
1906            if ((newActivity.info.flags
1907                    &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
1908                forceReset = true;
1909            }
1910        }
1911
1912        final TaskRecord task = taskTop.task;
1913
1914        // We are going to move through the history list so that we can look
1915        // at each activity 'target' with 'below' either the interesting
1916        // activity immediately below it in the stack or null.
1917        ActivityRecord target = null;
1918        int targetI = 0;
1919        int taskTopI = -1;
1920        int replyChainEnd = -1;
1921        int lastReparentPos = -1;
1922        for (int i=mHistory.size()-1; i>=-1; i--) {
1923            ActivityRecord below = i >= 0 ? mHistory.get(i) : null;
1924
1925            if (below != null && below.finishing) {
1926                continue;
1927            }
1928            // Don't check any lower in the stack if we're crossing a user boundary.
1929            if (below != null && below.userId != taskTop.userId) {
1930                break;
1931            }
1932            if (target == null) {
1933                target = below;
1934                targetI = i;
1935                // If we were in the middle of a reply chain before this
1936                // task, it doesn't appear like the root of the chain wants
1937                // anything interesting, so drop it.
1938                replyChainEnd = -1;
1939                continue;
1940            }
1941
1942            final int flags = target.info.flags;
1943
1944            final boolean finishOnTaskLaunch =
1945                (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
1946            final boolean allowTaskReparenting =
1947                (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
1948
1949            if (target.task == task) {
1950                // We are inside of the task being reset...  we'll either
1951                // finish this activity, push it out for another task,
1952                // or leave it as-is.  We only do this
1953                // for activities that are not the root of the task (since
1954                // if we finish the root, we may no longer have the task!).
1955                if (taskTopI < 0) {
1956                    taskTopI = targetI;
1957                }
1958                if (below != null && below.task == task) {
1959                    final boolean clearWhenTaskReset =
1960                            (target.intent.getFlags()
1961                                    &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
1962                    if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
1963                        // If this activity is sending a reply to a previous
1964                        // activity, we can't do anything with it now until
1965                        // we reach the start of the reply chain.
1966                        // XXX note that we are assuming the result is always
1967                        // to the previous activity, which is almost always
1968                        // the case but we really shouldn't count on.
1969                        if (replyChainEnd < 0) {
1970                            replyChainEnd = targetI;
1971                        }
1972                    } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
1973                            && target.taskAffinity != null
1974                            && !target.taskAffinity.equals(task.affinity)) {
1975                        // If this activity has an affinity for another
1976                        // task, then we need to move it out of here.  We will
1977                        // move it as far out of the way as possible, to the
1978                        // bottom of the activity stack.  This also keeps it
1979                        // correctly ordered with any activities we previously
1980                        // moved.
1981                        ActivityRecord p = mHistory.get(0);
1982                        if (target.taskAffinity != null
1983                                && target.taskAffinity.equals(p.task.affinity)) {
1984                            // If the activity currently at the bottom has the
1985                            // same task affinity as the one we are moving,
1986                            // then merge it into the same task.
1987                            target.setTask(p.task, p.thumbHolder, false);
1988                            if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
1989                                    + " out to bottom task " + p.task);
1990                        } else {
1991                            mService.mCurTask++;
1992                            if (mService.mCurTask <= 0) {
1993                                mService.mCurTask = 1;
1994                            }
1995                            target.setTask(new TaskRecord(mService.mCurTask, target.info, null),
1996                                    null, false);
1997                            target.task.affinityIntent = target.intent;
1998                            if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
1999                                    + " out to new task " + target.task);
2000                        }
2001                        mService.mWindowManager.setAppGroupId(target.appToken, task.taskId);
2002                        if (replyChainEnd < 0) {
2003                            replyChainEnd = targetI;
2004                        }
2005                        int dstPos = 0;
2006                        ThumbnailHolder curThumbHolder = target.thumbHolder;
2007                        for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
2008                            p = mHistory.get(srcPos);
2009                            if (p.finishing) {
2010                                continue;
2011                            }
2012                            if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
2013                                    + " out to target's task " + target.task);
2014                            p.setTask(target.task, curThumbHolder, false);
2015                            curThumbHolder = p.thumbHolder;
2016                            if (DEBUG_ADD_REMOVE) {
2017                                RuntimeException here = new RuntimeException("here");
2018                                here.fillInStackTrace();
2019                                Slog.i(TAG, "Removing and adding activity " + p + " to stack at "
2020                                        + dstPos, here);
2021                            }
2022                            mHistory.remove(srcPos);
2023                            mHistory.add(dstPos, p);
2024                            mService.mWindowManager.moveAppToken(dstPos, p.appToken);
2025                            mService.mWindowManager.setAppGroupId(p.appToken, p.task.taskId);
2026                            dstPos++;
2027                            if (VALIDATE_TOKENS) {
2028                                validateAppTokensLocked();
2029                            }
2030                            i++;
2031                        }
2032                        if (taskTop == p) {
2033                            taskTop = below;
2034                        }
2035                        if (taskTopI == replyChainEnd) {
2036                            taskTopI = -1;
2037                        }
2038                        replyChainEnd = -1;
2039                    } else if (forceReset || finishOnTaskLaunch
2040                            || clearWhenTaskReset) {
2041                        // If the activity should just be removed -- either
2042                        // because it asks for it, or the task should be
2043                        // cleared -- then finish it and anything that is
2044                        // part of its reply chain.
2045                        if (clearWhenTaskReset) {
2046                            // In this case, we want to finish this activity
2047                            // and everything above it, so be sneaky and pretend
2048                            // like these are all in the reply chain.
2049                            replyChainEnd = targetI+1;
2050                            while (replyChainEnd < mHistory.size() &&
2051                                    (mHistory.get(
2052                                                replyChainEnd)).task == task) {
2053                                replyChainEnd++;
2054                            }
2055                            replyChainEnd--;
2056                        } else if (replyChainEnd < 0) {
2057                            replyChainEnd = targetI;
2058                        }
2059                        ActivityRecord p = null;
2060                        for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
2061                            p = mHistory.get(srcPos);
2062                            if (p.finishing) {
2063                                continue;
2064                            }
2065                            if (finishActivityLocked(p, srcPos,
2066                                    Activity.RESULT_CANCELED, null, "reset")) {
2067                                replyChainEnd--;
2068                                srcPos--;
2069                            }
2070                        }
2071                        if (taskTop == p) {
2072                            taskTop = below;
2073                        }
2074                        if (taskTopI == replyChainEnd) {
2075                            taskTopI = -1;
2076                        }
2077                        replyChainEnd = -1;
2078                    } else {
2079                        // If we were in the middle of a chain, well the
2080                        // activity that started it all doesn't want anything
2081                        // special, so leave it all as-is.
2082                        replyChainEnd = -1;
2083                    }
2084                } else {
2085                    // Reached the bottom of the task -- any reply chain
2086                    // should be left as-is.
2087                    replyChainEnd = -1;
2088                }
2089
2090            } else if (target.resultTo != null && (below == null
2091                    || below.task == target.task)) {
2092                // If this activity is sending a reply to a previous
2093                // activity, we can't do anything with it now until
2094                // we reach the start of the reply chain.
2095                // XXX note that we are assuming the result is always
2096                // to the previous activity, which is almost always
2097                // the case but we really shouldn't count on.
2098                if (replyChainEnd < 0) {
2099                    replyChainEnd = targetI;
2100                }
2101
2102            } else if (taskTopI >= 0 && allowTaskReparenting
2103                    && task.affinity != null
2104                    && task.affinity.equals(target.taskAffinity)) {
2105                // We are inside of another task...  if this activity has
2106                // an affinity for our task, then either remove it if we are
2107                // clearing or move it over to our task.  Note that
2108                // we currently punt on the case where we are resetting a
2109                // task that is not at the top but who has activities above
2110                // with an affinity to it...  this is really not a normal
2111                // case, and we will need to later pull that task to the front
2112                // and usually at that point we will do the reset and pick
2113                // up those remaining activities.  (This only happens if
2114                // someone starts an activity in a new task from an activity
2115                // in a task that is not currently on top.)
2116                if (forceReset || finishOnTaskLaunch) {
2117                    if (replyChainEnd < 0) {
2118                        replyChainEnd = targetI;
2119                    }
2120                    ActivityRecord p = null;
2121                    if (DEBUG_TASKS) Slog.v(TAG, "Finishing task at index "
2122                            + targetI + " to " + replyChainEnd);
2123                    for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
2124                        p = mHistory.get(srcPos);
2125                        if (p.finishing) {
2126                            continue;
2127                        }
2128                        if (finishActivityLocked(p, srcPos,
2129                                Activity.RESULT_CANCELED, null, "reset")) {
2130                            taskTopI--;
2131                            lastReparentPos--;
2132                            replyChainEnd--;
2133                            srcPos--;
2134                        }
2135                    }
2136                    replyChainEnd = -1;
2137                } else {
2138                    if (replyChainEnd < 0) {
2139                        replyChainEnd = targetI;
2140                    }
2141                    if (DEBUG_TASKS) Slog.v(TAG, "Reparenting task at index "
2142                            + targetI + " to " + replyChainEnd);
2143                    for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
2144                        ActivityRecord p = mHistory.get(srcPos);
2145                        if (p.finishing) {
2146                            continue;
2147                        }
2148                        if (lastReparentPos < 0) {
2149                            lastReparentPos = taskTopI;
2150                            taskTop = p;
2151                        } else {
2152                            lastReparentPos--;
2153                        }
2154                        if (DEBUG_ADD_REMOVE) {
2155                            RuntimeException here = new RuntimeException("here");
2156                            here.fillInStackTrace();
2157                            Slog.i(TAG, "Removing and adding activity " + p + " to stack at "
2158                                    + lastReparentPos, here);
2159                        }
2160                        mHistory.remove(srcPos);
2161                        p.setTask(task, null, false);
2162                        mHistory.add(lastReparentPos, p);
2163                        if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
2164                                + " from " + srcPos + " to " + lastReparentPos
2165                                + " in to resetting task " + task);
2166                        mService.mWindowManager.moveAppToken(lastReparentPos, p.appToken);
2167                        mService.mWindowManager.setAppGroupId(p.appToken, p.task.taskId);
2168                        if (VALIDATE_TOKENS) {
2169                            validateAppTokensLocked();
2170                        }
2171                    }
2172                    replyChainEnd = -1;
2173
2174                    // Now we've moved it in to place...  but what if this is
2175                    // a singleTop activity and we have put it on top of another
2176                    // instance of the same activity?  Then we drop the instance
2177                    // below so it remains singleTop.
2178                    if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
2179                        for (int j=lastReparentPos-1; j>=0; j--) {
2180                            ActivityRecord p = mHistory.get(j);
2181                            if (p.finishing) {
2182                                continue;
2183                            }
2184                            if (p.intent.getComponent().equals(target.intent.getComponent())) {
2185                                if (finishActivityLocked(p, j,
2186                                        Activity.RESULT_CANCELED, null, "replace")) {
2187                                    taskTopI--;
2188                                    lastReparentPos--;
2189                                }
2190                            }
2191                        }
2192                    }
2193                }
2194
2195            } else if (below != null && below.task != target.task) {
2196                // We hit the botton of a task; the reply chain can't
2197                // pass through it.
2198                replyChainEnd = -1;
2199            }
2200
2201            target = below;
2202            targetI = i;
2203        }
2204
2205        return taskTop;
2206    }
2207
2208    /**
2209     * Perform clear operation as requested by
2210     * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2211     * stack to the given task, then look for
2212     * an instance of that activity in the stack and, if found, finish all
2213     * activities on top of it and return the instance.
2214     *
2215     * @param newR Description of the new activity being started.
2216     * @return Returns the old activity that should be continued to be used,
2217     * or null if none was found.
2218     */
2219    private final ActivityRecord performClearTaskLocked(int taskId,
2220            ActivityRecord newR, int launchFlags) {
2221        int i = mHistory.size();
2222
2223        // First find the requested task.
2224        while (i > 0) {
2225            i--;
2226            ActivityRecord r = mHistory.get(i);
2227            if (r.task.taskId == taskId) {
2228                i++;
2229                break;
2230            }
2231        }
2232
2233        // Now clear it.
2234        while (i > 0) {
2235            i--;
2236            ActivityRecord r = mHistory.get(i);
2237            if (r.finishing) {
2238                continue;
2239            }
2240            if (r.task.taskId != taskId) {
2241                return null;
2242            }
2243            if (r.realActivity.equals(newR.realActivity)) {
2244                // Here it is!  Now finish everything in front...
2245                ActivityRecord ret = r;
2246                while (i < (mHistory.size()-1)) {
2247                    i++;
2248                    r = mHistory.get(i);
2249                    if (r.task.taskId != taskId) {
2250                        break;
2251                    }
2252                    if (r.finishing) {
2253                        continue;
2254                    }
2255                    if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2256                            null, "clear")) {
2257                        i--;
2258                    }
2259                }
2260
2261                // Finally, if this is a normal launch mode (that is, not
2262                // expecting onNewIntent()), then we will finish the current
2263                // instance of the activity so a new fresh one can be started.
2264                if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
2265                        && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
2266                    if (!ret.finishing) {
2267                        int index = indexOfTokenLocked(ret.appToken);
2268                        if (index >= 0) {
2269                            finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
2270                                    null, "clear");
2271                        }
2272                        return null;
2273                    }
2274                }
2275
2276                return ret;
2277            }
2278        }
2279
2280        return null;
2281    }
2282
2283    /**
2284     * Completely remove all activities associated with an existing
2285     * task starting at a specified index.
2286     */
2287    private final void performClearTaskAtIndexLocked(int taskId, int i) {
2288        while (i < mHistory.size()) {
2289            ActivityRecord r = mHistory.get(i);
2290            if (r.task.taskId != taskId) {
2291                // Whoops hit the end.
2292                return;
2293            }
2294            if (r.finishing) {
2295                i++;
2296                continue;
2297            }
2298            if (!finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2299                    null, "clear")) {
2300                i++;
2301            }
2302        }
2303    }
2304
2305    /**
2306     * Completely remove all activities associated with an existing task.
2307     */
2308    private final void performClearTaskLocked(int taskId) {
2309        int i = mHistory.size();
2310
2311        // First find the requested task.
2312        while (i > 0) {
2313            i--;
2314            ActivityRecord r = mHistory.get(i);
2315            if (r.task.taskId == taskId) {
2316                i++;
2317                break;
2318            }
2319        }
2320
2321        // Now find the start and clear it.
2322        while (i > 0) {
2323            i--;
2324            ActivityRecord r = mHistory.get(i);
2325            if (r.finishing) {
2326                continue;
2327            }
2328            if (r.task.taskId != taskId) {
2329                // We hit the bottom.  Now finish it all...
2330                performClearTaskAtIndexLocked(taskId, i+1);
2331                return;
2332            }
2333        }
2334    }
2335
2336    /**
2337     * Find the activity in the history stack within the given task.  Returns
2338     * the index within the history at which it's found, or < 0 if not found.
2339     */
2340    private final int findActivityInHistoryLocked(ActivityRecord r, int task) {
2341        int i = mHistory.size();
2342        while (i > 0) {
2343            i--;
2344            ActivityRecord candidate = mHistory.get(i);
2345            if (candidate.task.taskId != task) {
2346                break;
2347            }
2348            if (candidate.realActivity.equals(r.realActivity)) {
2349                return i;
2350            }
2351        }
2352
2353        return -1;
2354    }
2355
2356    /**
2357     * Reorder the history stack so that the activity at the given index is
2358     * brought to the front.
2359     */
2360    private final ActivityRecord moveActivityToFrontLocked(int where) {
2361        ActivityRecord newTop = mHistory.remove(where);
2362        int top = mHistory.size();
2363        ActivityRecord oldTop = mHistory.get(top-1);
2364        if (DEBUG_ADD_REMOVE) {
2365            RuntimeException here = new RuntimeException("here");
2366            here.fillInStackTrace();
2367            Slog.i(TAG, "Removing and adding activity " + newTop + " to stack at "
2368                    + top, here);
2369        }
2370        mHistory.add(top, newTop);
2371        oldTop.frontOfTask = false;
2372        newTop.frontOfTask = true;
2373        return newTop;
2374    }
2375
2376    final int startActivityLocked(IApplicationThread caller,
2377            Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
2378            String resultWho, int requestCode,
2379            int callingPid, int callingUid, int startFlags, Bundle options,
2380            boolean componentSpecified, ActivityRecord[] outActivity) {
2381
2382        int err = ActivityManager.START_SUCCESS;
2383
2384        ProcessRecord callerApp = null;
2385        if (caller != null) {
2386            callerApp = mService.getRecordForAppLocked(caller);
2387            if (callerApp != null) {
2388                callingPid = callerApp.pid;
2389                callingUid = callerApp.info.uid;
2390            } else {
2391                Slog.w(TAG, "Unable to find app for caller " + caller
2392                      + " (pid=" + callingPid + ") when starting: "
2393                      + intent.toString());
2394                err = ActivityManager.START_PERMISSION_DENIED;
2395            }
2396        }
2397
2398        if (err == ActivityManager.START_SUCCESS) {
2399            final int userId = aInfo != null ? UserId.getUserId(aInfo.applicationInfo.uid) : 0;
2400            Slog.i(TAG, "START {" + intent.toShortString(true, true, true, false)
2401                    + " u=" + userId + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
2402        }
2403
2404        ActivityRecord sourceRecord = null;
2405        ActivityRecord resultRecord = null;
2406        if (resultTo != null) {
2407            int index = indexOfTokenLocked(resultTo);
2408            if (DEBUG_RESULTS) Slog.v(
2409                TAG, "Will send result to " + resultTo + " (index " + index + ")");
2410            if (index >= 0) {
2411                sourceRecord = mHistory.get(index);
2412                if (requestCode >= 0 && !sourceRecord.finishing) {
2413                    resultRecord = sourceRecord;
2414                }
2415            }
2416        }
2417
2418        int launchFlags = intent.getFlags();
2419
2420        if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
2421                && sourceRecord != null) {
2422            // Transfer the result target from the source activity to the new
2423            // one being started, including any failures.
2424            if (requestCode >= 0) {
2425                ActivityOptions.abort(options);
2426                return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
2427            }
2428            resultRecord = sourceRecord.resultTo;
2429            resultWho = sourceRecord.resultWho;
2430            requestCode = sourceRecord.requestCode;
2431            sourceRecord.resultTo = null;
2432            if (resultRecord != null) {
2433                resultRecord.removeResultsLocked(
2434                    sourceRecord, resultWho, requestCode);
2435            }
2436        }
2437
2438        if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
2439            // We couldn't find a class that can handle the given Intent.
2440            // That's the end of that!
2441            err = ActivityManager.START_INTENT_NOT_RESOLVED;
2442        }
2443
2444        if (err == ActivityManager.START_SUCCESS && aInfo == null) {
2445            // We couldn't find the specific class specified in the Intent.
2446            // Also the end of the line.
2447            err = ActivityManager.START_CLASS_NOT_FOUND;
2448        }
2449
2450        if (err != ActivityManager.START_SUCCESS) {
2451            if (resultRecord != null) {
2452                sendActivityResultLocked(-1,
2453                    resultRecord, resultWho, requestCode,
2454                    Activity.RESULT_CANCELED, null);
2455            }
2456            mDismissKeyguardOnNextActivity = false;
2457            ActivityOptions.abort(options);
2458            return err;
2459        }
2460
2461        final int startAnyPerm = mService.checkPermission(
2462                START_ANY_ACTIVITY, callingPid, callingUid);
2463        final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
2464                callingUid, aInfo.applicationInfo.uid, aInfo.exported);
2465        if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
2466            if (resultRecord != null) {
2467                sendActivityResultLocked(-1,
2468                    resultRecord, resultWho, requestCode,
2469                    Activity.RESULT_CANCELED, null);
2470            }
2471            mDismissKeyguardOnNextActivity = false;
2472            String msg;
2473            if (!aInfo.exported) {
2474                msg = "Permission Denial: starting " + intent.toString()
2475                        + " from " + callerApp + " (pid=" + callingPid
2476                        + ", uid=" + callingUid + ")"
2477                        + " not exported from uid " + aInfo.applicationInfo.uid;
2478            } else {
2479                msg = "Permission Denial: starting " + intent.toString()
2480                        + " from " + callerApp + " (pid=" + callingPid
2481                        + ", uid=" + callingUid + ")"
2482                        + " requires " + aInfo.permission;
2483            }
2484            Slog.w(TAG, msg);
2485            throw new SecurityException(msg);
2486        }
2487
2488        if (mMainStack) {
2489            if (mService.mController != null) {
2490                boolean abort = false;
2491                try {
2492                    // The Intent we give to the watcher has the extra data
2493                    // stripped off, since it can contain private information.
2494                    Intent watchIntent = intent.cloneFilter();
2495                    abort = !mService.mController.activityStarting(watchIntent,
2496                            aInfo.applicationInfo.packageName);
2497                } catch (RemoteException e) {
2498                    mService.mController = null;
2499                }
2500
2501                if (abort) {
2502                    if (resultRecord != null) {
2503                        sendActivityResultLocked(-1,
2504                            resultRecord, resultWho, requestCode,
2505                            Activity.RESULT_CANCELED, null);
2506                    }
2507                    // We pretend to the caller that it was really started, but
2508                    // they will just get a cancel result.
2509                    mDismissKeyguardOnNextActivity = false;
2510                    ActivityOptions.abort(options);
2511                    return ActivityManager.START_SUCCESS;
2512                }
2513            }
2514        }
2515
2516        ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid,
2517                intent, resolvedType, aInfo, mService.mConfiguration,
2518                resultRecord, resultWho, requestCode, componentSpecified);
2519        if (outActivity != null) {
2520            outActivity[0] = r;
2521        }
2522
2523        if (mMainStack) {
2524            if (mResumedActivity == null
2525                    || mResumedActivity.info.applicationInfo.uid != callingUid) {
2526                if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
2527                    PendingActivityLaunch pal = new PendingActivityLaunch();
2528                    pal.r = r;
2529                    pal.sourceRecord = sourceRecord;
2530                    pal.startFlags = startFlags;
2531                    mService.mPendingActivityLaunches.add(pal);
2532                    mDismissKeyguardOnNextActivity = false;
2533                    ActivityOptions.abort(options);
2534                    return ActivityManager.START_SWITCHES_CANCELED;
2535                }
2536            }
2537
2538            if (mService.mDidAppSwitch) {
2539                // This is the second allowed switch since we stopped switches,
2540                // so now just generally allow switches.  Use case: user presses
2541                // home (switches disabled, switch to home, mDidAppSwitch now true);
2542                // user taps a home icon (coming from home so allowed, we hit here
2543                // and now allow anyone to switch again).
2544                mService.mAppSwitchesAllowedTime = 0;
2545            } else {
2546                mService.mDidAppSwitch = true;
2547            }
2548
2549            mService.doPendingActivityLaunchesLocked(false);
2550        }
2551
2552        err = startActivityUncheckedLocked(r, sourceRecord,
2553                startFlags, true, options);
2554        if (mDismissKeyguardOnNextActivity && mPausingActivity == null) {
2555            // Someone asked to have the keyguard dismissed on the next
2556            // activity start, but we are not actually doing an activity
2557            // switch...  just dismiss the keyguard now, because we
2558            // probably want to see whatever is behind it.
2559            mDismissKeyguardOnNextActivity = false;
2560            mService.mWindowManager.dismissKeyguard();
2561        }
2562        return err;
2563    }
2564
2565    final void moveHomeToFrontFromLaunchLocked(int launchFlags) {
2566        if ((launchFlags &
2567                (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
2568                == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
2569            // Caller wants to appear on home activity, so before starting
2570            // their own activity we will bring home to the front.
2571            moveHomeToFrontLocked();
2572        }
2573    }
2574
2575    final int startActivityUncheckedLocked(ActivityRecord r,
2576            ActivityRecord sourceRecord, int startFlags, boolean doResume,
2577            Bundle options) {
2578        final Intent intent = r.intent;
2579        final int callingUid = r.launchedFromUid;
2580        final int userId = r.userId;
2581
2582        int launchFlags = intent.getFlags();
2583
2584        // We'll invoke onUserLeaving before onPause only if the launching
2585        // activity did not explicitly state that this is an automated launch.
2586        mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
2587        if (DEBUG_USER_LEAVING) Slog.v(TAG,
2588                "startActivity() => mUserLeaving=" + mUserLeaving);
2589
2590        // If the caller has asked not to resume at this point, we make note
2591        // of this in the record so that we can skip it when trying to find
2592        // the top running activity.
2593        if (!doResume) {
2594            r.delayedResume = true;
2595        }
2596
2597        ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
2598                != 0 ? r : null;
2599
2600        // If the onlyIfNeeded flag is set, then we can do this if the activity
2601        // being launched is the same as the one making the call...  or, as
2602        // a special case, if we do not know the caller then we count the
2603        // current top activity as the caller.
2604        if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
2605            ActivityRecord checkedCaller = sourceRecord;
2606            if (checkedCaller == null) {
2607                checkedCaller = topRunningNonDelayedActivityLocked(notTop);
2608            }
2609            if (!checkedCaller.realActivity.equals(r.realActivity)) {
2610                // Caller is not the same as launcher, so always needed.
2611                startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
2612            }
2613        }
2614
2615        if (sourceRecord == null) {
2616            // This activity is not being started from another...  in this
2617            // case we -always- start a new task.
2618            if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
2619                Slog.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
2620                      + intent);
2621                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
2622            }
2623        } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
2624            // The original activity who is starting us is running as a single
2625            // instance...  this new activity it is starting must go on its
2626            // own task.
2627            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
2628        } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
2629                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
2630            // The activity being started is a single instance...  it always
2631            // gets launched into its own task.
2632            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
2633        }
2634
2635        if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
2636            // For whatever reason this activity is being launched into a new
2637            // task...  yet the caller has requested a result back.  Well, that
2638            // is pretty messed up, so instead immediately send back a cancel
2639            // and let the new task continue launched as normal without a
2640            // dependency on its originator.
2641            Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
2642            sendActivityResultLocked(-1,
2643                    r.resultTo, r.resultWho, r.requestCode,
2644                Activity.RESULT_CANCELED, null);
2645            r.resultTo = null;
2646        }
2647
2648        boolean addingToTask = false;
2649        boolean movedHome = false;
2650        TaskRecord reuseTask = null;
2651        if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
2652                (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
2653                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
2654                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
2655            // If bring to front is requested, and no result is requested, and
2656            // we can find a task that was started with this same
2657            // component, then instead of launching bring that one to the front.
2658            if (r.resultTo == null) {
2659                // See if there is a task to bring to the front.  If this is
2660                // a SINGLE_INSTANCE activity, there can be one and only one
2661                // instance of it in the history, and it is always in its own
2662                // unique task, so we do a special search.
2663                ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
2664                        ? findTaskLocked(intent, r.info)
2665                        : findActivityLocked(intent, r.info);
2666                if (taskTop != null) {
2667                    if (taskTop.task.intent == null) {
2668                        // This task was started because of movement of
2669                        // the activity based on affinity...  now that we
2670                        // are actually launching it, we can assign the
2671                        // base intent.
2672                        taskTop.task.setIntent(intent, r.info);
2673                    }
2674                    // If the target task is not in the front, then we need
2675                    // to bring it to the front...  except...  well, with
2676                    // SINGLE_TASK_LAUNCH it's not entirely clear.  We'd like
2677                    // to have the same behavior as if a new instance was
2678                    // being started, which means not bringing it to the front
2679                    // if the caller is not itself in the front.
2680                    ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop);
2681                    if (curTop != null && curTop.task != taskTop.task) {
2682                        r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
2683                        boolean callerAtFront = sourceRecord == null
2684                                || curTop.task == sourceRecord.task;
2685                        if (callerAtFront) {
2686                            // We really do want to push this one into the
2687                            // user's face, right now.
2688                            movedHome = true;
2689                            moveHomeToFrontFromLaunchLocked(launchFlags);
2690                            moveTaskToFrontLocked(taskTop.task, r, options);
2691                            options = null;
2692                        }
2693                    }
2694                    // If the caller has requested that the target task be
2695                    // reset, then do so.
2696                    if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2697                        taskTop = resetTaskIfNeededLocked(taskTop, r);
2698                    }
2699                    if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED)  != 0) {
2700                        // We don't need to start a new activity, and
2701                        // the client said not to do anything if that
2702                        // is the case, so this is it!  And for paranoia, make
2703                        // sure we have correctly resumed the top activity.
2704                        if (doResume) {
2705                            resumeTopActivityLocked(null, options);
2706                        } else {
2707                            ActivityOptions.abort(options);
2708                        }
2709                        return ActivityManager.START_RETURN_INTENT_TO_CALLER;
2710                    }
2711                    if ((launchFlags &
2712                            (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
2713                            == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
2714                        // The caller has requested to completely replace any
2715                        // existing task with its new activity.  Well that should
2716                        // not be too hard...
2717                        reuseTask = taskTop.task;
2718                        performClearTaskLocked(taskTop.task.taskId);
2719                        reuseTask.setIntent(r.intent, r.info);
2720                    } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
2721                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
2722                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
2723                        // In this situation we want to remove all activities
2724                        // from the task up to the one being started.  In most
2725                        // cases this means we are resetting the task to its
2726                        // initial state.
2727                        ActivityRecord top = performClearTaskLocked(
2728                                taskTop.task.taskId, r, launchFlags);
2729                        if (top != null) {
2730                            if (top.frontOfTask) {
2731                                // Activity aliases may mean we use different
2732                                // intents for the top activity, so make sure
2733                                // the task now has the identity of the new
2734                                // intent.
2735                                top.task.setIntent(r.intent, r.info);
2736                            }
2737                            logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
2738                            top.deliverNewIntentLocked(callingUid, r.intent);
2739                        } else {
2740                            // A special case: we need to
2741                            // start the activity because it is not currently
2742                            // running, and the caller has asked to clear the
2743                            // current task to have this activity at the top.
2744                            addingToTask = true;
2745                            // Now pretend like this activity is being started
2746                            // by the top of its task, so it is put in the
2747                            // right place.
2748                            sourceRecord = taskTop;
2749                        }
2750                    } else if (r.realActivity.equals(taskTop.task.realActivity)) {
2751                        // In this case the top activity on the task is the
2752                        // same as the one being launched, so we take that
2753                        // as a request to bring the task to the foreground.
2754                        // If the top activity in the task is the root
2755                        // activity, deliver this new intent to it if it
2756                        // desires.
2757                        if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
2758                                && taskTop.realActivity.equals(r.realActivity)) {
2759                            logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
2760                            if (taskTop.frontOfTask) {
2761                                taskTop.task.setIntent(r.intent, r.info);
2762                            }
2763                            taskTop.deliverNewIntentLocked(callingUid, r.intent);
2764                        } else if (!r.intent.filterEquals(taskTop.task.intent)) {
2765                            // In this case we are launching the root activity
2766                            // of the task, but with a different intent.  We
2767                            // should start a new instance on top.
2768                            addingToTask = true;
2769                            sourceRecord = taskTop;
2770                        }
2771                    } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
2772                        // In this case an activity is being launched in to an
2773                        // existing task, without resetting that task.  This
2774                        // is typically the situation of launching an activity
2775                        // from a notification or shortcut.  We want to place
2776                        // the new activity on top of the current task.
2777                        addingToTask = true;
2778                        sourceRecord = taskTop;
2779                    } else if (!taskTop.task.rootWasReset) {
2780                        // In this case we are launching in to an existing task
2781                        // that has not yet been started from its front door.
2782                        // The current task has been brought to the front.
2783                        // Ideally, we'd probably like to place this new task
2784                        // at the bottom of its stack, but that's a little hard
2785                        // to do with the current organization of the code so
2786                        // for now we'll just drop it.
2787                        taskTop.task.setIntent(r.intent, r.info);
2788                    }
2789                    if (!addingToTask && reuseTask == null) {
2790                        // We didn't do anything...  but it was needed (a.k.a., client
2791                        // don't use that intent!)  And for paranoia, make
2792                        // sure we have correctly resumed the top activity.
2793                        if (doResume) {
2794                            resumeTopActivityLocked(null, options);
2795                        } else {
2796                            ActivityOptions.abort(options);
2797                        }
2798                        return ActivityManager.START_TASK_TO_FRONT;
2799                    }
2800                }
2801            }
2802        }
2803
2804        //String uri = r.intent.toURI();
2805        //Intent intent2 = new Intent(uri);
2806        //Slog.i(TAG, "Given intent: " + r.intent);
2807        //Slog.i(TAG, "URI is: " + uri);
2808        //Slog.i(TAG, "To intent: " + intent2);
2809
2810        if (r.packageName != null) {
2811            // If the activity being launched is the same as the one currently
2812            // at the top, then we need to check if it should only be launched
2813            // once.
2814            ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);
2815            if (top != null && r.resultTo == null) {
2816                if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
2817                    if (top.app != null && top.app.thread != null) {
2818                        if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
2819                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
2820                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
2821                            logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
2822                            // For paranoia, make sure we have correctly
2823                            // resumed the top activity.
2824                            if (doResume) {
2825                                resumeTopActivityLocked(null);
2826                            }
2827                            ActivityOptions.abort(options);
2828                            if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
2829                                // We don't need to start a new activity, and
2830                                // the client said not to do anything if that
2831                                // is the case, so this is it!
2832                                return ActivityManager.START_RETURN_INTENT_TO_CALLER;
2833                            }
2834                            top.deliverNewIntentLocked(callingUid, r.intent);
2835                            return ActivityManager.START_DELIVERED_TO_TOP;
2836                        }
2837                    }
2838                }
2839            }
2840
2841        } else {
2842            if (r.resultTo != null) {
2843                sendActivityResultLocked(-1,
2844                        r.resultTo, r.resultWho, r.requestCode,
2845                    Activity.RESULT_CANCELED, null);
2846            }
2847            ActivityOptions.abort(options);
2848            return ActivityManager.START_CLASS_NOT_FOUND;
2849        }
2850
2851        boolean newTask = false;
2852        boolean keepCurTransition = false;
2853
2854        // Should this be considered a new task?
2855        if (r.resultTo == null && !addingToTask
2856                && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
2857            if (reuseTask == null) {
2858                // todo: should do better management of integers.
2859                mService.mCurTask++;
2860                if (mService.mCurTask <= 0) {
2861                    mService.mCurTask = 1;
2862                }
2863                r.setTask(new TaskRecord(mService.mCurTask, r.info, intent), null, true);
2864                if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
2865                        + " in new task " + r.task);
2866            } else {
2867                r.setTask(reuseTask, reuseTask, true);
2868            }
2869            newTask = true;
2870            if (!movedHome) {
2871                moveHomeToFrontFromLaunchLocked(launchFlags);
2872            }
2873
2874        } else if (sourceRecord != null) {
2875            if (!addingToTask &&
2876                    (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
2877                // In this case, we are adding the activity to an existing
2878                // task, but the caller has asked to clear that task if the
2879                // activity is already running.
2880                ActivityRecord top = performClearTaskLocked(
2881                        sourceRecord.task.taskId, r, launchFlags);
2882                keepCurTransition = true;
2883                if (top != null) {
2884                    logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
2885                    top.deliverNewIntentLocked(callingUid, r.intent);
2886                    // For paranoia, make sure we have correctly
2887                    // resumed the top activity.
2888                    if (doResume) {
2889                        resumeTopActivityLocked(null);
2890                    }
2891                    ActivityOptions.abort(options);
2892                    return ActivityManager.START_DELIVERED_TO_TOP;
2893                }
2894            } else if (!addingToTask &&
2895                    (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
2896                // In this case, we are launching an activity in our own task
2897                // that may already be running somewhere in the history, and
2898                // we want to shuffle it to the front of the stack if so.
2899                int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
2900                if (where >= 0) {
2901                    ActivityRecord top = moveActivityToFrontLocked(where);
2902                    logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
2903                    top.updateOptionsLocked(options);
2904                    top.deliverNewIntentLocked(callingUid, r.intent);
2905                    if (doResume) {
2906                        resumeTopActivityLocked(null);
2907                    }
2908                    return ActivityManager.START_DELIVERED_TO_TOP;
2909                }
2910            }
2911            // An existing activity is starting this new activity, so we want
2912            // to keep the new one in the same task as the one that is starting
2913            // it.
2914            r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
2915            if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
2916                    + " in existing task " + r.task);
2917
2918        } else {
2919            // This not being started from an existing activity, and not part
2920            // of a new task...  just put it in the top task, though these days
2921            // this case should never happen.
2922            final int N = mHistory.size();
2923            ActivityRecord prev =
2924                N > 0 ? mHistory.get(N-1) : null;
2925            r.setTask(prev != null
2926                    ? prev.task
2927                    : new TaskRecord(mService.mCurTask, r.info, intent), null, true);
2928            if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
2929                    + " in new guessed " + r.task);
2930        }
2931
2932        mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
2933                intent, r.getUriPermissionsLocked());
2934
2935        if (newTask) {
2936            EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
2937        }
2938        logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
2939        startActivityLocked(r, newTask, doResume, keepCurTransition, options);
2940        return ActivityManager.START_SUCCESS;
2941    }
2942
2943    ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
2944            String profileFile, ParcelFileDescriptor profileFd, int userId) {
2945        // Collect information about the target of the Intent.
2946        ActivityInfo aInfo;
2947        try {
2948            ResolveInfo rInfo =
2949                AppGlobals.getPackageManager().resolveIntent(
2950                        intent, resolvedType,
2951                        PackageManager.MATCH_DEFAULT_ONLY
2952                                    | ActivityManagerService.STOCK_PM_FLAGS, userId);
2953            aInfo = rInfo != null ? rInfo.activityInfo : null;
2954        } catch (RemoteException e) {
2955            aInfo = null;
2956        }
2957
2958        if (aInfo != null) {
2959            // Store the found target back into the intent, because now that
2960            // we have it we never want to do this again.  For example, if the
2961            // user navigates back to this point in the history, we should
2962            // always restart the exact same activity.
2963            intent.setComponent(new ComponentName(
2964                    aInfo.applicationInfo.packageName, aInfo.name));
2965
2966            // Don't debug things in the system process
2967            if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
2968                if (!aInfo.processName.equals("system")) {
2969                    mService.setDebugApp(aInfo.processName, true, false);
2970                }
2971            }
2972
2973            if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
2974                if (!aInfo.processName.equals("system")) {
2975                    mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
2976                }
2977            }
2978
2979            if (profileFile != null) {
2980                if (!aInfo.processName.equals("system")) {
2981                    mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
2982                            profileFile, profileFd,
2983                            (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
2984                }
2985            }
2986        }
2987        return aInfo;
2988    }
2989
2990    final int startActivityMayWait(IApplicationThread caller, int callingUid,
2991            Intent intent, String resolvedType, IBinder resultTo,
2992            String resultWho, int requestCode, int startFlags, String profileFile,
2993            ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
2994            Bundle options, int userId) {
2995        // Refuse possible leaked file descriptors
2996        if (intent != null && intent.hasFileDescriptors()) {
2997            throw new IllegalArgumentException("File descriptors passed in Intent");
2998        }
2999        boolean componentSpecified = intent.getComponent() != null;
3000
3001        // Don't modify the client's object!
3002        intent = new Intent(intent);
3003
3004        // Collect information about the target of the Intent.
3005        ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
3006                profileFile, profileFd, userId);
3007        if (aInfo != null && mService.isSingleton(aInfo.processName, aInfo.applicationInfo)) {
3008            userId = 0;
3009        }
3010        aInfo = mService.getActivityInfoForUser(aInfo, userId);
3011
3012        synchronized (mService) {
3013            int callingPid;
3014            if (callingUid >= 0) {
3015                callingPid = -1;
3016            } else if (caller == null) {
3017                callingPid = Binder.getCallingPid();
3018                callingUid = Binder.getCallingUid();
3019            } else {
3020                callingPid = callingUid = -1;
3021            }
3022
3023            mConfigWillChange = config != null
3024                    && mService.mConfiguration.diff(config) != 0;
3025            if (DEBUG_CONFIGURATION) Slog.v(TAG,
3026                    "Starting activity when config will change = " + mConfigWillChange);
3027
3028            final long origId = Binder.clearCallingIdentity();
3029
3030            if (mMainStack && aInfo != null &&
3031                    (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
3032                // This may be a heavy-weight process!  Check to see if we already
3033                // have another, different heavy-weight process running.
3034                if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
3035                    if (mService.mHeavyWeightProcess != null &&
3036                            (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
3037                            !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
3038                        int realCallingPid = callingPid;
3039                        int realCallingUid = callingUid;
3040                        if (caller != null) {
3041                            ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
3042                            if (callerApp != null) {
3043                                realCallingPid = callerApp.pid;
3044                                realCallingUid = callerApp.info.uid;
3045                            } else {
3046                                Slog.w(TAG, "Unable to find app for caller " + caller
3047                                      + " (pid=" + realCallingPid + ") when starting: "
3048                                      + intent.toString());
3049                                ActivityOptions.abort(options);
3050                                return ActivityManager.START_PERMISSION_DENIED;
3051                            }
3052                        }
3053
3054                        IIntentSender target = mService.getIntentSenderLocked(
3055                                ActivityManager.INTENT_SENDER_ACTIVITY, "android",
3056                                realCallingUid, null, null, 0, new Intent[] { intent },
3057                                new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
3058                                | PendingIntent.FLAG_ONE_SHOT, null);
3059
3060                        Intent newIntent = new Intent();
3061                        if (requestCode >= 0) {
3062                            // Caller is requesting a result.
3063                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
3064                        }
3065                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
3066                                new IntentSender(target));
3067                        if (mService.mHeavyWeightProcess.activities.size() > 0) {
3068                            ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
3069                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
3070                                    hist.packageName);
3071                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
3072                                    hist.task.taskId);
3073                        }
3074                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
3075                                aInfo.packageName);
3076                        newIntent.setFlags(intent.getFlags());
3077                        newIntent.setClassName("android",
3078                                HeavyWeightSwitcherActivity.class.getName());
3079                        intent = newIntent;
3080                        resolvedType = null;
3081                        caller = null;
3082                        callingUid = Binder.getCallingUid();
3083                        callingPid = Binder.getCallingPid();
3084                        componentSpecified = true;
3085                        try {
3086                            ResolveInfo rInfo =
3087                                AppGlobals.getPackageManager().resolveIntent(
3088                                        intent, null,
3089                                        PackageManager.MATCH_DEFAULT_ONLY
3090                                        | ActivityManagerService.STOCK_PM_FLAGS, userId);
3091                            aInfo = rInfo != null ? rInfo.activityInfo : null;
3092                            aInfo = mService.getActivityInfoForUser(aInfo, userId);
3093                        } catch (RemoteException e) {
3094                            aInfo = null;
3095                        }
3096                    }
3097                }
3098            }
3099
3100            int res = startActivityLocked(caller, intent, resolvedType,
3101                    aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
3102                    startFlags, options, componentSpecified, null);
3103
3104            if (mConfigWillChange && mMainStack) {
3105                // If the caller also wants to switch to a new configuration,
3106                // do so now.  This allows a clean switch, as we are waiting
3107                // for the current activity to pause (so we will not destroy
3108                // it), and have not yet started the next activity.
3109                mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3110                        "updateConfiguration()");
3111                mConfigWillChange = false;
3112                if (DEBUG_CONFIGURATION) Slog.v(TAG,
3113                        "Updating to new configuration after starting activity.");
3114                mService.updateConfigurationLocked(config, null, false, false);
3115            }
3116
3117            Binder.restoreCallingIdentity(origId);
3118
3119            if (outResult != null) {
3120                outResult.result = res;
3121                if (res == ActivityManager.START_SUCCESS) {
3122                    mWaitingActivityLaunched.add(outResult);
3123                    do {
3124                        try {
3125                            mService.wait();
3126                        } catch (InterruptedException e) {
3127                        }
3128                    } while (!outResult.timeout && outResult.who == null);
3129                } else if (res == ActivityManager.START_TASK_TO_FRONT) {
3130                    ActivityRecord r = this.topRunningActivityLocked(null);
3131                    if (r.nowVisible) {
3132                        outResult.timeout = false;
3133                        outResult.who = new ComponentName(r.info.packageName, r.info.name);
3134                        outResult.totalTime = 0;
3135                        outResult.thisTime = 0;
3136                    } else {
3137                        outResult.thisTime = SystemClock.uptimeMillis();
3138                        mWaitingActivityVisible.add(outResult);
3139                        do {
3140                            try {
3141                                mService.wait();
3142                            } catch (InterruptedException e) {
3143                            }
3144                        } while (!outResult.timeout && outResult.who == null);
3145                    }
3146                }
3147            }
3148
3149            return res;
3150        }
3151    }
3152
3153    final int startActivities(IApplicationThread caller, int callingUid,
3154            Intent[] intents, String[] resolvedTypes, IBinder resultTo,
3155            Bundle options, int userId) {
3156        if (intents == null) {
3157            throw new NullPointerException("intents is null");
3158        }
3159        if (resolvedTypes == null) {
3160            throw new NullPointerException("resolvedTypes is null");
3161        }
3162        if (intents.length != resolvedTypes.length) {
3163            throw new IllegalArgumentException("intents are length different than resolvedTypes");
3164        }
3165
3166        ActivityRecord[] outActivity = new ActivityRecord[1];
3167
3168        int callingPid;
3169        if (callingUid >= 0) {
3170            callingPid = -1;
3171        } else if (caller == null) {
3172            callingPid = Binder.getCallingPid();
3173            callingUid = Binder.getCallingUid();
3174        } else {
3175            callingPid = callingUid = -1;
3176        }
3177        final long origId = Binder.clearCallingIdentity();
3178        try {
3179            synchronized (mService) {
3180
3181                for (int i=0; i<intents.length; i++) {
3182                    Intent intent = intents[i];
3183                    if (intent == null) {
3184                        continue;
3185                    }
3186
3187                    // Refuse possible leaked file descriptors
3188                    if (intent != null && intent.hasFileDescriptors()) {
3189                        throw new IllegalArgumentException("File descriptors passed in Intent");
3190                    }
3191
3192                    boolean componentSpecified = intent.getComponent() != null;
3193
3194                    // Don't modify the client's object!
3195                    intent = new Intent(intent);
3196
3197                    // Collect information about the target of the Intent.
3198                    ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
3199                            0, null, null, userId);
3200                    // TODO: New, check if this is correct
3201                    aInfo = mService.getActivityInfoForUser(aInfo, userId);
3202
3203                    if (mMainStack && aInfo != null && (aInfo.applicationInfo.flags
3204                            & ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
3205                        throw new IllegalArgumentException(
3206                                "FLAG_CANT_SAVE_STATE not supported here");
3207                    }
3208
3209                    Bundle theseOptions;
3210                    if (options != null && i == intents.length-1) {
3211                        theseOptions = options;
3212                    } else {
3213                        theseOptions = null;
3214                    }
3215                    int res = startActivityLocked(caller, intent, resolvedTypes[i],
3216                            aInfo, resultTo, null, -1, callingPid, callingUid,
3217                            0, theseOptions, componentSpecified, outActivity);
3218                    if (res < 0) {
3219                        return res;
3220                    }
3221
3222                    resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
3223                }
3224            }
3225        } finally {
3226            Binder.restoreCallingIdentity(origId);
3227        }
3228
3229        return ActivityManager.START_SUCCESS;
3230    }
3231
3232    void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
3233            long thisTime, long totalTime) {
3234        for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3235            WaitResult w = mWaitingActivityLaunched.get(i);
3236            w.timeout = timeout;
3237            if (r != null) {
3238                w.who = new ComponentName(r.info.packageName, r.info.name);
3239            }
3240            w.thisTime = thisTime;
3241            w.totalTime = totalTime;
3242        }
3243        mService.notifyAll();
3244    }
3245
3246    void reportActivityVisibleLocked(ActivityRecord r) {
3247        for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3248            WaitResult w = mWaitingActivityVisible.get(i);
3249            w.timeout = false;
3250            if (r != null) {
3251                w.who = new ComponentName(r.info.packageName, r.info.name);
3252            }
3253            w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3254            w.thisTime = w.totalTime;
3255        }
3256        mService.notifyAll();
3257
3258        if (mDismissKeyguardOnNextActivity) {
3259            mDismissKeyguardOnNextActivity = false;
3260            mService.mWindowManager.dismissKeyguard();
3261        }
3262    }
3263
3264    void sendActivityResultLocked(int callingUid, ActivityRecord r,
3265            String resultWho, int requestCode, int resultCode, Intent data) {
3266
3267        if (callingUid > 0) {
3268            mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3269                    data, r.getUriPermissionsLocked());
3270        }
3271
3272        if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
3273                + " : who=" + resultWho + " req=" + requestCode
3274                + " res=" + resultCode + " data=" + data);
3275        if (mResumedActivity == r && r.app != null && r.app.thread != null) {
3276            try {
3277                ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
3278                list.add(new ResultInfo(resultWho, requestCode,
3279                        resultCode, data));
3280                r.app.thread.scheduleSendResult(r.appToken, list);
3281                return;
3282            } catch (Exception e) {
3283                Slog.w(TAG, "Exception thrown sending result to " + r, e);
3284            }
3285        }
3286
3287        r.addResultLocked(null, resultWho, requestCode, resultCode, data);
3288    }
3289
3290    private final void stopActivityLocked(ActivityRecord r) {
3291        if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
3292        if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3293                || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3294            if (!r.finishing) {
3295                if (!mService.mSleeping) {
3296                    if (DEBUG_STATES) {
3297                        Slog.d(TAG, "no-history finish of " + r);
3298                    }
3299                    requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
3300                            "no-history");
3301                } else {
3302                    if (DEBUG_STATES) Slog.d(TAG, "Not finishing noHistory " + r
3303                            + " on stop because we're just sleeping");
3304                }
3305            }
3306        }
3307
3308        if (r.app != null && r.app.thread != null) {
3309            if (mMainStack) {
3310                if (mService.mFocusedActivity == r) {
3311                    mService.setFocusedActivityLocked(topRunningActivityLocked(null));
3312                }
3313            }
3314            r.resumeKeyDispatchingLocked();
3315            try {
3316                r.stopped = false;
3317                if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
3318                        + " (stop requested)");
3319                r.state = ActivityState.STOPPING;
3320                if (DEBUG_VISBILITY) Slog.v(
3321                        TAG, "Stopping visible=" + r.visible + " for " + r);
3322                if (!r.visible) {
3323                    mService.mWindowManager.setAppVisibility(r.appToken, false);
3324                }
3325                r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
3326                if (mService.isSleeping()) {
3327                    r.setSleeping(true);
3328                }
3329                Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG);
3330                msg.obj = r;
3331                mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
3332            } catch (Exception e) {
3333                // Maybe just ignore exceptions here...  if the process
3334                // has crashed, our death notification will clean things
3335                // up.
3336                Slog.w(TAG, "Exception thrown during pause", e);
3337                // Just in case, assume it to be stopped.
3338                r.stopped = true;
3339                if (DEBUG_STATES) Slog.v(TAG, "Stop failed; moving to STOPPED: " + r);
3340                r.state = ActivityState.STOPPED;
3341                if (r.configDestroy) {
3342                    destroyActivityLocked(r, true, false, "stop-except");
3343                }
3344            }
3345        }
3346    }
3347
3348    final ArrayList<ActivityRecord> processStoppingActivitiesLocked(
3349            boolean remove) {
3350        int N = mStoppingActivities.size();
3351        if (N <= 0) return null;
3352
3353        ArrayList<ActivityRecord> stops = null;
3354
3355        final boolean nowVisible = mResumedActivity != null
3356                && mResumedActivity.nowVisible
3357                && !mResumedActivity.waitingVisible;
3358        for (int i=0; i<N; i++) {
3359            ActivityRecord s = mStoppingActivities.get(i);
3360            if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
3361                    + nowVisible + " waitingVisible=" + s.waitingVisible
3362                    + " finishing=" + s.finishing);
3363            if (s.waitingVisible && nowVisible) {
3364                mWaitingVisibleActivities.remove(s);
3365                s.waitingVisible = false;
3366                if (s.finishing) {
3367                    // If this activity is finishing, it is sitting on top of
3368                    // everyone else but we now know it is no longer needed...
3369                    // so get rid of it.  Otherwise, we need to go through the
3370                    // normal flow and hide it once we determine that it is
3371                    // hidden by the activities in front of it.
3372                    if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
3373                    mService.mWindowManager.setAppVisibility(s.appToken, false);
3374                }
3375            }
3376            if ((!s.waitingVisible || mService.isSleeping()) && remove) {
3377                if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
3378                if (stops == null) {
3379                    stops = new ArrayList<ActivityRecord>();
3380                }
3381                stops.add(s);
3382                mStoppingActivities.remove(i);
3383                N--;
3384                i--;
3385            }
3386        }
3387
3388        return stops;
3389    }
3390
3391    final void scheduleIdleLocked() {
3392        Message msg = Message.obtain();
3393        msg.what = IDLE_NOW_MSG;
3394        mHandler.sendMessage(msg);
3395    }
3396
3397    final ActivityRecord activityIdleInternal(IBinder token, boolean fromTimeout,
3398            Configuration config) {
3399        if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
3400
3401        ActivityRecord res = null;
3402
3403        ArrayList<ActivityRecord> stops = null;
3404        ArrayList<ActivityRecord> finishes = null;
3405        ArrayList<ActivityRecord> thumbnails = null;
3406        int NS = 0;
3407        int NF = 0;
3408        int NT = 0;
3409        IApplicationThread sendThumbnail = null;
3410        boolean booting = false;
3411        boolean enableScreen = false;
3412
3413        synchronized (mService) {
3414            ActivityRecord r = ActivityRecord.forToken(token);
3415            if (r != null) {
3416                mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
3417                r.finishLaunchTickingLocked();
3418            }
3419
3420            // Get the activity record.
3421            int index = indexOfActivityLocked(r);
3422            if (index >= 0) {
3423                res = r;
3424
3425                if (fromTimeout) {
3426                    reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
3427                }
3428
3429                // This is a hack to semi-deal with a race condition
3430                // in the client where it can be constructed with a
3431                // newer configuration from when we asked it to launch.
3432                // We'll update with whatever configuration it now says
3433                // it used to launch.
3434                if (config != null) {
3435                    r.configuration = config;
3436                }
3437
3438                // No longer need to keep the device awake.
3439                if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
3440                    mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
3441                    mLaunchingActivity.release();
3442                }
3443
3444                // We are now idle.  If someone is waiting for a thumbnail from
3445                // us, we can now deliver.
3446                r.idle = true;
3447                mService.scheduleAppGcsLocked();
3448                if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
3449                    sendThumbnail = r.app.thread;
3450                    r.thumbnailNeeded = false;
3451                }
3452
3453                // If this activity is fullscreen, set up to hide those under it.
3454
3455                if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
3456                ensureActivitiesVisibleLocked(null, 0);
3457
3458                //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
3459                if (mMainStack) {
3460                    if (!mService.mBooted) {
3461                        mService.mBooted = true;
3462                        enableScreen = true;
3463                    }
3464                }
3465
3466            } else if (fromTimeout) {
3467                reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
3468            }
3469
3470            // Atomically retrieve all of the other things to do.
3471            stops = processStoppingActivitiesLocked(true);
3472            NS = stops != null ? stops.size() : 0;
3473            if ((NF=mFinishingActivities.size()) > 0) {
3474                finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
3475                mFinishingActivities.clear();
3476            }
3477            if ((NT=mService.mCancelledThumbnails.size()) > 0) {
3478                thumbnails = new ArrayList<ActivityRecord>(mService.mCancelledThumbnails);
3479                mService.mCancelledThumbnails.clear();
3480            }
3481
3482            if (mMainStack) {
3483                booting = mService.mBooting;
3484                mService.mBooting = false;
3485            }
3486        }
3487
3488        int i;
3489
3490        // Send thumbnail if requested.
3491        if (sendThumbnail != null) {
3492            try {
3493                sendThumbnail.requestThumbnail(token);
3494            } catch (Exception e) {
3495                Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
3496                mService.sendPendingThumbnail(null, token, null, null, true);
3497            }
3498        }
3499
3500        // Stop any activities that are scheduled to do so but have been
3501        // waiting for the next one to start.
3502        for (i=0; i<NS; i++) {
3503            ActivityRecord r = (ActivityRecord)stops.get(i);
3504            synchronized (mService) {
3505                if (r.finishing) {
3506                    finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
3507                } else {
3508                    stopActivityLocked(r);
3509                }
3510            }
3511        }
3512
3513        // Finish any activities that are scheduled to do so but have been
3514        // waiting for the next one to start.
3515        for (i=0; i<NF; i++) {
3516            ActivityRecord r = (ActivityRecord)finishes.get(i);
3517            synchronized (mService) {
3518                destroyActivityLocked(r, true, false, "finish-idle");
3519            }
3520        }
3521
3522        // Report back to any thumbnail receivers.
3523        for (i=0; i<NT; i++) {
3524            ActivityRecord r = (ActivityRecord)thumbnails.get(i);
3525            mService.sendPendingThumbnail(r, null, null, null, true);
3526        }
3527
3528        if (booting) {
3529            mService.finishBooting();
3530        }
3531
3532        mService.trimApplications();
3533        //dump();
3534        //mWindowManager.dump();
3535
3536        if (enableScreen) {
3537            mService.enableScreenAfterBoot();
3538        }
3539
3540        return res;
3541    }
3542
3543    /**
3544     * @return Returns true if the activity is being finished, false if for
3545     * some reason it is being left as-is.
3546     */
3547    final boolean requestFinishActivityLocked(IBinder token, int resultCode,
3548            Intent resultData, String reason) {
3549        int index = indexOfTokenLocked(token);
3550        if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(
3551                TAG, "Finishing activity @" + index + ": token=" + token
3552                + ", result=" + resultCode + ", data=" + resultData
3553                + ", reason=" + reason);
3554        if (index < 0) {
3555            return false;
3556        }
3557        ActivityRecord r = mHistory.get(index);
3558
3559        finishActivityLocked(r, index, resultCode, resultData, reason);
3560        return true;
3561    }
3562
3563    final void finishSubActivityLocked(IBinder token, String resultWho, int requestCode) {
3564        ActivityRecord self = isInStackLocked(token);
3565        if (self == null) {
3566            return;
3567        }
3568
3569        int i;
3570        for (i=mHistory.size()-1; i>=0; i--) {
3571            ActivityRecord r = (ActivityRecord)mHistory.get(i);
3572            if (r.resultTo == self && r.requestCode == requestCode) {
3573                if ((r.resultWho == null && resultWho == null) ||
3574                    (r.resultWho != null && r.resultWho.equals(resultWho))) {
3575                    finishActivityLocked(r, i,
3576                            Activity.RESULT_CANCELED, null, "request-sub");
3577                }
3578            }
3579        }
3580    }
3581
3582    final boolean finishActivityAffinityLocked(IBinder token) {
3583        int index = indexOfTokenLocked(token);
3584        if (DEBUG_RESULTS) Slog.v(
3585                TAG, "Finishing activity affinity @" + index + ": token=" + token);
3586        if (index < 0) {
3587            return false;
3588        }
3589        ActivityRecord r = mHistory.get(index);
3590
3591        while (index >= 0) {
3592            ActivityRecord cur = mHistory.get(index);
3593            if (cur.task != r.task) {
3594                break;
3595            }
3596            if (cur.taskAffinity == null && r.taskAffinity != null) {
3597                break;
3598            }
3599            if (cur.taskAffinity != null && !cur.taskAffinity.equals(r.taskAffinity)) {
3600                break;
3601            }
3602            finishActivityLocked(cur, index, Activity.RESULT_CANCELED, null, "request-affinity");
3603            index--;
3604        }
3605        return true;
3606    }
3607
3608    final void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
3609        // send the result
3610        ActivityRecord resultTo = r.resultTo;
3611        if (resultTo != null) {
3612            if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
3613                    + " who=" + r.resultWho + " req=" + r.requestCode
3614                    + " res=" + resultCode + " data=" + resultData);
3615            if (r.info.applicationInfo.uid > 0) {
3616                mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
3617                        resultTo.packageName, resultData,
3618                        resultTo.getUriPermissionsLocked());
3619            }
3620            resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
3621                                     resultData);
3622            r.resultTo = null;
3623        }
3624        else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
3625
3626        // Make sure this HistoryRecord is not holding on to other resources,
3627        // because clients have remote IPC references to this object so we
3628        // can't assume that will go away and want to avoid circular IPC refs.
3629        r.results = null;
3630        r.pendingResults = null;
3631        r.newIntents = null;
3632        r.icicle = null;
3633    }
3634
3635    /**
3636     * @return Returns true if this activity has been removed from the history
3637     * list, or false if it is still in the list and will be removed later.
3638     */
3639    final boolean finishActivityLocked(ActivityRecord r, int index,
3640            int resultCode, Intent resultData, String reason) {
3641        return finishActivityLocked(r, index, resultCode, resultData, reason, false);
3642    }
3643
3644    /**
3645     * @return Returns true if this activity has been removed from the history
3646     * list, or false if it is still in the list and will be removed later.
3647     */
3648    final boolean finishActivityLocked(ActivityRecord r, int index,
3649            int resultCode, Intent resultData, String reason, boolean immediate) {
3650        if (r.finishing) {
3651            Slog.w(TAG, "Duplicate finish request for " + r);
3652            return false;
3653        }
3654
3655        r.makeFinishing();
3656        EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
3657                System.identityHashCode(r),
3658                r.task.taskId, r.shortComponentName, reason);
3659        if (index < (mHistory.size()-1)) {
3660            ActivityRecord next = mHistory.get(index+1);
3661            if (next.task == r.task) {
3662                if (r.frontOfTask) {
3663                    // The next activity is now the front of the task.
3664                    next.frontOfTask = true;
3665                }
3666                if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
3667                    // If the caller asked that this activity (and all above it)
3668                    // be cleared when the task is reset, don't lose that information,
3669                    // but propagate it up to the next activity.
3670                    next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
3671                }
3672            }
3673        }
3674
3675        r.pauseKeyDispatchingLocked();
3676        if (mMainStack) {
3677            if (mService.mFocusedActivity == r) {
3678                mService.setFocusedActivityLocked(topRunningActivityLocked(null));
3679            }
3680        }
3681
3682        finishActivityResultsLocked(r, resultCode, resultData);
3683
3684        if (mService.mPendingThumbnails.size() > 0) {
3685            // There are clients waiting to receive thumbnails so, in case
3686            // this is an activity that someone is waiting for, add it
3687            // to the pending list so we can correctly update the clients.
3688            mService.mCancelledThumbnails.add(r);
3689        }
3690
3691        if (immediate) {
3692            return finishCurrentActivityLocked(r, index,
3693                    FINISH_IMMEDIATELY) == null;
3694        } else if (mResumedActivity == r) {
3695            boolean endTask = index <= 0
3696                    || (mHistory.get(index-1)).task != r.task;
3697            if (DEBUG_TRANSITION) Slog.v(TAG,
3698                    "Prepare close transition: finishing " + r);
3699            mService.mWindowManager.prepareAppTransition(endTask
3700                    ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
3701                    : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE, false);
3702
3703            // Tell window manager to prepare for this one to be removed.
3704            mService.mWindowManager.setAppVisibility(r.appToken, false);
3705
3706            if (mPausingActivity == null) {
3707                if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
3708                if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
3709                startPausingLocked(false, false);
3710            }
3711
3712        } else if (r.state != ActivityState.PAUSING) {
3713            // If the activity is PAUSING, we will complete the finish once
3714            // it is done pausing; else we can just directly finish it here.
3715            if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
3716            return finishCurrentActivityLocked(r, index,
3717                    FINISH_AFTER_PAUSE) == null;
3718        } else {
3719            if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
3720        }
3721
3722        return false;
3723    }
3724
3725    private static final int FINISH_IMMEDIATELY = 0;
3726    private static final int FINISH_AFTER_PAUSE = 1;
3727    private static final int FINISH_AFTER_VISIBLE = 2;
3728
3729    private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
3730            int mode) {
3731        final int index = indexOfActivityLocked(r);
3732        if (index < 0) {
3733            return null;
3734        }
3735
3736        return finishCurrentActivityLocked(r, index, mode);
3737    }
3738
3739    private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
3740            int index, int mode) {
3741        // First things first: if this activity is currently visible,
3742        // and the resumed activity is not yet visible, then hold off on
3743        // finishing until the resumed one becomes visible.
3744        if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
3745            if (!mStoppingActivities.contains(r)) {
3746                mStoppingActivities.add(r);
3747                if (mStoppingActivities.size() > 3) {
3748                    // If we already have a few activities waiting to stop,
3749                    // then give up on things going idle and start clearing
3750                    // them out.
3751                    scheduleIdleLocked();
3752                } else {
3753                    checkReadyForSleepLocked();
3754                }
3755            }
3756            if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
3757                    + " (finish requested)");
3758            r.state = ActivityState.STOPPING;
3759            mService.updateOomAdjLocked();
3760            return r;
3761        }
3762
3763        // make sure the record is cleaned out of other places.
3764        mStoppingActivities.remove(r);
3765        mGoingToSleepActivities.remove(r);
3766        mWaitingVisibleActivities.remove(r);
3767        if (mResumedActivity == r) {
3768            mResumedActivity = null;
3769        }
3770        final ActivityState prevState = r.state;
3771        if (DEBUG_STATES) Slog.v(TAG, "Moving to FINISHING: " + r);
3772        r.state = ActivityState.FINISHING;
3773
3774        if (mode == FINISH_IMMEDIATELY
3775                || prevState == ActivityState.STOPPED
3776                || prevState == ActivityState.INITIALIZING) {
3777            // If this activity is already stopped, we can just finish
3778            // it right now.
3779            return destroyActivityLocked(r, true, true, "finish-imm") ? null : r;
3780        } else {
3781            // Need to go through the full pause cycle to get this
3782            // activity into the stopped state and then finish it.
3783            if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
3784            mFinishingActivities.add(r);
3785            resumeTopActivityLocked(null);
3786        }
3787        return r;
3788    }
3789
3790    /**
3791     * Perform the common clean-up of an activity record.  This is called both
3792     * as part of destroyActivityLocked() (when destroying the client-side
3793     * representation) and cleaning things up as a result of its hosting
3794     * processing going away, in which case there is no remaining client-side
3795     * state to destroy so only the cleanup here is needed.
3796     */
3797    final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices,
3798            boolean setState) {
3799        if (mResumedActivity == r) {
3800            mResumedActivity = null;
3801        }
3802        if (mService.mFocusedActivity == r) {
3803            mService.mFocusedActivity = null;
3804        }
3805
3806        r.configDestroy = false;
3807        r.frozenBeforeDestroy = false;
3808
3809        if (setState) {
3810            if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (cleaning up)");
3811            r.state = ActivityState.DESTROYED;
3812        }
3813
3814        // Make sure this record is no longer in the pending finishes list.
3815        // This could happen, for example, if we are trimming activities
3816        // down to the max limit while they are still waiting to finish.
3817        mFinishingActivities.remove(r);
3818        mWaitingVisibleActivities.remove(r);
3819
3820        // Remove any pending results.
3821        if (r.finishing && r.pendingResults != null) {
3822            for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
3823                PendingIntentRecord rec = apr.get();
3824                if (rec != null) {
3825                    mService.cancelIntentSenderLocked(rec, false);
3826                }
3827            }
3828            r.pendingResults = null;
3829        }
3830
3831        if (cleanServices) {
3832            cleanUpActivityServicesLocked(r);
3833        }
3834
3835        if (mService.mPendingThumbnails.size() > 0) {
3836            // There are clients waiting to receive thumbnails so, in case
3837            // this is an activity that someone is waiting for, add it
3838            // to the pending list so we can correctly update the clients.
3839            mService.mCancelledThumbnails.add(r);
3840        }
3841
3842        // Get rid of any pending idle timeouts.
3843        mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
3844        mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
3845        mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
3846        mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
3847        r.finishLaunchTickingLocked();
3848    }
3849
3850    final void removeActivityFromHistoryLocked(ActivityRecord r) {
3851        if (r.state != ActivityState.DESTROYED) {
3852            finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
3853            r.makeFinishing();
3854            if (DEBUG_ADD_REMOVE) {
3855                RuntimeException here = new RuntimeException("here");
3856                here.fillInStackTrace();
3857                Slog.i(TAG, "Removing activity " + r + " from stack");
3858            }
3859            mHistory.remove(r);
3860            r.takeFromHistory();
3861            if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
3862                    + " (removed from history)");
3863            r.state = ActivityState.DESTROYED;
3864            mService.mWindowManager.removeAppToken(r.appToken);
3865            if (VALIDATE_TOKENS) {
3866                validateAppTokensLocked();
3867            }
3868            cleanUpActivityServicesLocked(r);
3869            r.removeUriPermissionsLocked();
3870        }
3871    }
3872
3873    /**
3874     * Perform clean-up of service connections in an activity record.
3875     */
3876    final void cleanUpActivityServicesLocked(ActivityRecord r) {
3877        // Throw away any services that have been bound by this activity.
3878        if (r.connections != null) {
3879            Iterator<ConnectionRecord> it = r.connections.iterator();
3880            while (it.hasNext()) {
3881                ConnectionRecord c = it.next();
3882                mService.removeConnectionLocked(c, null, r);
3883            }
3884            r.connections = null;
3885        }
3886    }
3887
3888    final void scheduleDestroyActivities(ProcessRecord owner, boolean oomAdj, String reason) {
3889        Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG);
3890        msg.obj = new ScheduleDestroyArgs(owner, oomAdj, reason);
3891        mHandler.sendMessage(msg);
3892    }
3893
3894    final void destroyActivitiesLocked(ProcessRecord owner, boolean oomAdj, String reason) {
3895        boolean lastIsOpaque = false;
3896        for (int i=mHistory.size()-1; i>=0; i--) {
3897            ActivityRecord r = mHistory.get(i);
3898            if (r.finishing) {
3899                continue;
3900            }
3901            if (r.fullscreen) {
3902                lastIsOpaque = true;
3903            }
3904            if (owner != null && r.app != owner) {
3905                continue;
3906            }
3907            if (!lastIsOpaque) {
3908                continue;
3909            }
3910            // We can destroy this one if we have its icicle saved and
3911            // it is not in the process of pausing/stopping/finishing.
3912            if (r.app != null && r != mResumedActivity && r != mPausingActivity
3913                    && r.haveState && !r.visible && r.stopped
3914                    && r.state != ActivityState.DESTROYING
3915                    && r.state != ActivityState.DESTROYED) {
3916                if (DEBUG_SWITCH) Slog.v(TAG, "Destroying " + r + " in state " + r.state
3917                        + " resumed=" + mResumedActivity
3918                        + " pausing=" + mPausingActivity);
3919                destroyActivityLocked(r, true, oomAdj, reason);
3920            }
3921        }
3922    }
3923
3924    /**
3925     * Destroy the current CLIENT SIDE instance of an activity.  This may be
3926     * called both when actually finishing an activity, or when performing
3927     * a configuration switch where we destroy the current client-side object
3928     * but then create a new client-side object for this same HistoryRecord.
3929     */
3930    final boolean destroyActivityLocked(ActivityRecord r,
3931            boolean removeFromApp, boolean oomAdj, String reason) {
3932        if (DEBUG_SWITCH) Slog.v(
3933            TAG, "Removing activity from " + reason + ": token=" + r
3934              + ", app=" + (r.app != null ? r.app.processName : "(null)"));
3935        EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
3936                System.identityHashCode(r),
3937                r.task.taskId, r.shortComponentName, reason);
3938
3939        boolean removedFromHistory = false;
3940
3941        cleanUpActivityLocked(r, false, false);
3942
3943        final boolean hadApp = r.app != null;
3944
3945        if (hadApp) {
3946            if (removeFromApp) {
3947                int idx = r.app.activities.indexOf(r);
3948                if (idx >= 0) {
3949                    r.app.activities.remove(idx);
3950                }
3951                if (mService.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
3952                    mService.mHeavyWeightProcess = null;
3953                    mService.mHandler.sendEmptyMessage(
3954                            ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG);
3955                }
3956                if (r.app.activities.size() == 0) {
3957                    // No longer have activities, so update location in
3958                    // LRU list.
3959                    mService.updateLruProcessLocked(r.app, oomAdj, false);
3960                }
3961            }
3962
3963            boolean skipDestroy = false;
3964
3965            try {
3966                if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
3967                r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,
3968                        r.configChangeFlags);
3969            } catch (Exception e) {
3970                // We can just ignore exceptions here...  if the process
3971                // has crashed, our death notification will clean things
3972                // up.
3973                //Slog.w(TAG, "Exception thrown during finish", e);
3974                if (r.finishing) {
3975                    removeActivityFromHistoryLocked(r);
3976                    removedFromHistory = true;
3977                    skipDestroy = true;
3978                }
3979            }
3980
3981            r.app = null;
3982            r.nowVisible = false;
3983
3984            // If the activity is finishing, we need to wait on removing it
3985            // from the list to give it a chance to do its cleanup.  During
3986            // that time it may make calls back with its token so we need to
3987            // be able to find it on the list and so we don't want to remove
3988            // it from the list yet.  Otherwise, we can just immediately put
3989            // it in the destroyed state since we are not removing it from the
3990            // list.
3991            if (r.finishing && !skipDestroy) {
3992                if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYING: " + r
3993                        + " (destroy requested)");
3994                r.state = ActivityState.DESTROYING;
3995                Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
3996                msg.obj = r;
3997                mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
3998            } else {
3999                if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
4000                        + " (destroy skipped)");
4001                r.state = ActivityState.DESTROYED;
4002            }
4003        } else {
4004            // remove this record from the history.
4005            if (r.finishing) {
4006                removeActivityFromHistoryLocked(r);
4007                removedFromHistory = true;
4008            } else {
4009                if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
4010                        + " (no app)");
4011                r.state = ActivityState.DESTROYED;
4012            }
4013        }
4014
4015        r.configChangeFlags = 0;
4016
4017        if (!mLRUActivities.remove(r) && hadApp) {
4018            Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
4019        }
4020
4021        return removedFromHistory;
4022    }
4023
4024    final void activityDestroyed(IBinder token) {
4025        synchronized (mService) {
4026            ActivityRecord r = ActivityRecord.forToken(token);
4027            if (r != null) {
4028                mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
4029            }
4030
4031            int index = indexOfActivityLocked(r);
4032            if (index >= 0) {
4033                if (r.state == ActivityState.DESTROYING) {
4034                    final long origId = Binder.clearCallingIdentity();
4035                    removeActivityFromHistoryLocked(r);
4036                    Binder.restoreCallingIdentity(origId);
4037                }
4038            }
4039        }
4040    }
4041
4042    private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
4043        int i = list.size();
4044        if (localLOGV) Slog.v(
4045            TAG, "Removing app " + app + " from list " + list
4046            + " with " + i + " entries");
4047        while (i > 0) {
4048            i--;
4049            ActivityRecord r = (ActivityRecord)list.get(i);
4050            if (localLOGV) Slog.v(
4051                TAG, "Record #" + i + " " + r + ": app=" + r.app);
4052            if (r.app == app) {
4053                if (localLOGV) Slog.v(TAG, "Removing this entry!");
4054                list.remove(i);
4055            }
4056        }
4057    }
4058
4059    void removeHistoryRecordsForAppLocked(ProcessRecord app) {
4060        removeHistoryRecordsForAppLocked(mLRUActivities, app);
4061        removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4062        removeHistoryRecordsForAppLocked(mGoingToSleepActivities, app);
4063        removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4064        removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4065    }
4066
4067    /**
4068     * Move the current home activity's task (if one exists) to the front
4069     * of the stack.
4070     */
4071    final void moveHomeToFrontLocked() {
4072        TaskRecord homeTask = null;
4073        for (int i=mHistory.size()-1; i>=0; i--) {
4074            ActivityRecord hr = mHistory.get(i);
4075            if (hr.isHomeActivity) {
4076                homeTask = hr.task;
4077                break;
4078            }
4079        }
4080        if (homeTask != null) {
4081            moveTaskToFrontLocked(homeTask, null, null);
4082        }
4083    }
4084
4085    final void updateTransitLocked(int transit, Bundle options) {
4086        if (options != null) {
4087            ActivityRecord r = topRunningActivityLocked(null);
4088            if (r != null && r.state != ActivityState.RESUMED) {
4089                r.updateOptionsLocked(options);
4090            } else {
4091                ActivityOptions.abort(options);
4092            }
4093        }
4094        mService.mWindowManager.prepareAppTransition(transit, false);
4095    }
4096
4097    final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
4098        if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
4099
4100        final int task = tr.taskId;
4101        int top = mHistory.size()-1;
4102
4103        if (top < 0 || (mHistory.get(top)).task.taskId == task) {
4104            // nothing to do!
4105            if (reason != null &&
4106                    (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
4107                ActivityOptions.abort(options);
4108            } else {
4109                updateTransitLocked(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT, options);
4110            }
4111            return;
4112        }
4113
4114        ArrayList<IBinder> moved = new ArrayList<IBinder>();
4115
4116        // Applying the affinities may have removed entries from the history,
4117        // so get the size again.
4118        top = mHistory.size()-1;
4119        int pos = top;
4120
4121        // Shift all activities with this task up to the top
4122        // of the stack, keeping them in the same internal order.
4123        while (pos >= 0) {
4124            ActivityRecord r = mHistory.get(pos);
4125            if (localLOGV) Slog.v(
4126                TAG, "At " + pos + " ckp " + r.task + ": " + r);
4127            if (r.task.taskId == task) {
4128                if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
4129                if (DEBUG_ADD_REMOVE) {
4130                    RuntimeException here = new RuntimeException("here");
4131                    here.fillInStackTrace();
4132                    Slog.i(TAG, "Removing and adding activity " + r + " to stack at " + top, here);
4133                }
4134                mHistory.remove(pos);
4135                mHistory.add(top, r);
4136                moved.add(0, r.appToken);
4137                top--;
4138            }
4139            pos--;
4140        }
4141
4142        if (DEBUG_TRANSITION) Slog.v(TAG,
4143                "Prepare to front transition: task=" + tr);
4144        if (reason != null &&
4145                (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
4146            mService.mWindowManager.prepareAppTransition(
4147                    WindowManagerPolicy.TRANSIT_NONE, false);
4148            ActivityRecord r = topRunningActivityLocked(null);
4149            if (r != null) {
4150                mNoAnimActivities.add(r);
4151            }
4152            ActivityOptions.abort(options);
4153        } else {
4154            updateTransitLocked(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT, options);
4155        }
4156
4157        mService.mWindowManager.moveAppTokensToTop(moved);
4158        if (VALIDATE_TOKENS) {
4159            validateAppTokensLocked();
4160        }
4161
4162        finishTaskMoveLocked(task);
4163        EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
4164    }
4165
4166    private final void finishTaskMoveLocked(int task) {
4167        resumeTopActivityLocked(null);
4168    }
4169
4170    /**
4171     * Worker method for rearranging history stack.  Implements the function of moving all
4172     * activities for a specific task (gathering them if disjoint) into a single group at the
4173     * bottom of the stack.
4174     *
4175     * If a watcher is installed, the action is preflighted and the watcher has an opportunity
4176     * to premeptively cancel the move.
4177     *
4178     * @param task The taskId to collect and move to the bottom.
4179     * @return Returns true if the move completed, false if not.
4180     */
4181    final boolean moveTaskToBackLocked(int task, ActivityRecord reason) {
4182        Slog.i(TAG, "moveTaskToBack: " + task);
4183
4184        // If we have a watcher, preflight the move before committing to it.  First check
4185        // for *other* available tasks, but if none are available, then try again allowing the
4186        // current task to be selected.
4187        if (mMainStack && mService.mController != null) {
4188            ActivityRecord next = topRunningActivityLocked(null, task);
4189            if (next == null) {
4190                next = topRunningActivityLocked(null, 0);
4191            }
4192            if (next != null) {
4193                // ask watcher if this is allowed
4194                boolean moveOK = true;
4195                try {
4196                    moveOK = mService.mController.activityResuming(next.packageName);
4197                } catch (RemoteException e) {
4198                    mService.mController = null;
4199                }
4200                if (!moveOK) {
4201                    return false;
4202                }
4203            }
4204        }
4205
4206        ArrayList<IBinder> moved = new ArrayList<IBinder>();
4207
4208        if (DEBUG_TRANSITION) Slog.v(TAG,
4209                "Prepare to back transition: task=" + task);
4210
4211        final int N = mHistory.size();
4212        int bottom = 0;
4213        int pos = 0;
4214
4215        // Shift all activities with this task down to the bottom
4216        // of the stack, keeping them in the same internal order.
4217        while (pos < N) {
4218            ActivityRecord r = mHistory.get(pos);
4219            if (localLOGV) Slog.v(
4220                TAG, "At " + pos + " ckp " + r.task + ": " + r);
4221            if (r.task.taskId == task) {
4222                if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
4223                if (DEBUG_ADD_REMOVE) {
4224                    RuntimeException here = new RuntimeException("here");
4225                    here.fillInStackTrace();
4226                    Slog.i(TAG, "Removing and adding activity " + r + " to stack at "
4227                            + bottom, here);
4228                }
4229                mHistory.remove(pos);
4230                mHistory.add(bottom, r);
4231                moved.add(r.appToken);
4232                bottom++;
4233            }
4234            pos++;
4235        }
4236
4237        if (reason != null &&
4238                (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
4239            mService.mWindowManager.prepareAppTransition(
4240                    WindowManagerPolicy.TRANSIT_NONE, false);
4241            ActivityRecord r = topRunningActivityLocked(null);
4242            if (r != null) {
4243                mNoAnimActivities.add(r);
4244            }
4245        } else {
4246            mService.mWindowManager.prepareAppTransition(
4247                    WindowManagerPolicy.TRANSIT_TASK_TO_BACK, false);
4248        }
4249        mService.mWindowManager.moveAppTokensToBottom(moved);
4250        if (VALIDATE_TOKENS) {
4251            validateAppTokensLocked();
4252        }
4253
4254        finishTaskMoveLocked(task);
4255        return true;
4256    }
4257
4258    public ActivityManager.TaskThumbnails getTaskThumbnailsLocked(TaskRecord tr) {
4259        TaskAccessInfo info = getTaskAccessInfoLocked(tr.taskId, true);
4260        ActivityRecord resumed = mResumedActivity;
4261        if (resumed != null && resumed.thumbHolder == tr) {
4262            info.mainThumbnail = resumed.stack.screenshotActivities(resumed);
4263        } else {
4264            info.mainThumbnail = tr.lastThumbnail;
4265        }
4266        return info;
4267    }
4268
4269    public ActivityRecord removeTaskActivitiesLocked(int taskId, int subTaskIndex,
4270            boolean taskRequired) {
4271        TaskAccessInfo info = getTaskAccessInfoLocked(taskId, false);
4272        if (info.root == null) {
4273            if (taskRequired) {
4274                Slog.w(TAG, "removeTaskLocked: unknown taskId " + taskId);
4275            }
4276            return null;
4277        }
4278
4279        if (subTaskIndex < 0) {
4280            // Just remove the entire task.
4281            performClearTaskAtIndexLocked(taskId, info.rootIndex);
4282            return info.root;
4283        }
4284
4285        if (subTaskIndex >= info.subtasks.size()) {
4286            if (taskRequired) {
4287                Slog.w(TAG, "removeTaskLocked: unknown subTaskIndex " + subTaskIndex);
4288            }
4289            return null;
4290        }
4291
4292        // Remove all of this task's activies starting at the sub task.
4293        TaskAccessInfo.SubTask subtask = info.subtasks.get(subTaskIndex);
4294        performClearTaskAtIndexLocked(taskId, subtask.index);
4295        return subtask.activity;
4296    }
4297
4298    public TaskAccessInfo getTaskAccessInfoLocked(int taskId, boolean inclThumbs) {
4299        ActivityRecord resumed = mResumedActivity;
4300        final TaskAccessInfo thumbs = new TaskAccessInfo();
4301        // How many different sub-thumbnails?
4302        final int NA = mHistory.size();
4303        int j = 0;
4304        ThumbnailHolder holder = null;
4305        while (j < NA) {
4306            ActivityRecord ar = mHistory.get(j);
4307            if (!ar.finishing && ar.task.taskId == taskId) {
4308                holder = ar.thumbHolder;
4309                break;
4310            }
4311            j++;
4312        }
4313
4314        if (j >= NA) {
4315            return thumbs;
4316        }
4317
4318        thumbs.root = mHistory.get(j);
4319        thumbs.rootIndex = j;
4320
4321        ArrayList<TaskAccessInfo.SubTask> subtasks = new ArrayList<TaskAccessInfo.SubTask>();
4322        thumbs.subtasks = subtasks;
4323        ActivityRecord lastActivity = null;
4324        while (j < NA) {
4325            ActivityRecord ar = mHistory.get(j);
4326            j++;
4327            if (ar.finishing) {
4328                continue;
4329            }
4330            if (ar.task.taskId != taskId) {
4331                break;
4332            }
4333            lastActivity = ar;
4334            if (ar.thumbHolder != holder && holder != null) {
4335                thumbs.numSubThumbbails++;
4336                holder = ar.thumbHolder;
4337                TaskAccessInfo.SubTask sub = new TaskAccessInfo.SubTask();
4338                sub.thumbnail = holder.lastThumbnail;
4339                sub.activity = ar;
4340                sub.index = j-1;
4341                subtasks.add(sub);
4342            }
4343        }
4344        if (lastActivity != null && subtasks.size() > 0) {
4345            if (resumed == lastActivity) {
4346                TaskAccessInfo.SubTask sub = subtasks.get(subtasks.size()-1);
4347                sub.thumbnail = lastActivity.stack.screenshotActivities(lastActivity);
4348            }
4349        }
4350        if (thumbs.numSubThumbbails > 0) {
4351            thumbs.retriever = new IThumbnailRetriever.Stub() {
4352                public Bitmap getThumbnail(int index) {
4353                    if (index < 0 || index >= thumbs.subtasks.size()) {
4354                        return null;
4355                    }
4356                    return thumbs.subtasks.get(index).thumbnail;
4357                }
4358            };
4359        }
4360        return thumbs;
4361    }
4362
4363    private final void logStartActivity(int tag, ActivityRecord r,
4364            TaskRecord task) {
4365        EventLog.writeEvent(tag,
4366                System.identityHashCode(r), task.taskId,
4367                r.shortComponentName, r.intent.getAction(),
4368                r.intent.getType(), r.intent.getDataString(),
4369                r.intent.getFlags());
4370    }
4371
4372    /**
4373     * Make sure the given activity matches the current configuration.  Returns
4374     * false if the activity had to be destroyed.  Returns true if the
4375     * configuration is the same, or the activity will remain running as-is
4376     * for whatever reason.  Ensures the HistoryRecord is updated with the
4377     * correct configuration and all other bookkeeping is handled.
4378     */
4379    final boolean ensureActivityConfigurationLocked(ActivityRecord r,
4380            int globalChanges) {
4381        if (mConfigWillChange) {
4382            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4383                    "Skipping config check (will change): " + r);
4384            return true;
4385        }
4386
4387        if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4388                "Ensuring correct configuration: " + r);
4389
4390        // Short circuit: if the two configurations are the exact same
4391        // object (the common case), then there is nothing to do.
4392        Configuration newConfig = mService.mConfiguration;
4393        if (r.configuration == newConfig && !r.forceNewConfig) {
4394            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4395                    "Configuration unchanged in " + r);
4396            return true;
4397        }
4398
4399        // We don't worry about activities that are finishing.
4400        if (r.finishing) {
4401            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4402                    "Configuration doesn't matter in finishing " + r);
4403            r.stopFreezingScreenLocked(false);
4404            return true;
4405        }
4406
4407        // Okay we now are going to make this activity have the new config.
4408        // But then we need to figure out how it needs to deal with that.
4409        Configuration oldConfig = r.configuration;
4410        r.configuration = newConfig;
4411
4412        // Determine what has changed.  May be nothing, if this is a config
4413        // that has come back from the app after going idle.  In that case
4414        // we just want to leave the official config object now in the
4415        // activity and do nothing else.
4416        final int changes = oldConfig.diff(newConfig);
4417        if (changes == 0 && !r.forceNewConfig) {
4418            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4419                    "Configuration no differences in " + r);
4420            return true;
4421        }
4422
4423        // If the activity isn't currently running, just leave the new
4424        // configuration and it will pick that up next time it starts.
4425        if (r.app == null || r.app.thread == null) {
4426            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4427                    "Configuration doesn't matter not running " + r);
4428            r.stopFreezingScreenLocked(false);
4429            r.forceNewConfig = false;
4430            return true;
4431        }
4432
4433        // Figure out how to handle the changes between the configurations.
4434        if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
4435            Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
4436                    + Integer.toHexString(changes) + ", handles=0x"
4437                    + Integer.toHexString(r.info.getRealConfigChanged())
4438                    + ", newConfig=" + newConfig);
4439        }
4440        if ((changes&(~r.info.getRealConfigChanged())) != 0 || r.forceNewConfig) {
4441            // Aha, the activity isn't handling the change, so DIE DIE DIE.
4442            r.configChangeFlags |= changes;
4443            r.startFreezingScreenLocked(r.app, globalChanges);
4444            r.forceNewConfig = false;
4445            if (r.app == null || r.app.thread == null) {
4446                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4447                        "Config is destroying non-running " + r);
4448                destroyActivityLocked(r, true, false, "config");
4449            } else if (r.state == ActivityState.PAUSING) {
4450                // A little annoying: we are waiting for this activity to
4451                // finish pausing.  Let's not do anything now, but just
4452                // flag that it needs to be restarted when done pausing.
4453                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4454                        "Config is skipping already pausing " + r);
4455                r.configDestroy = true;
4456                return true;
4457            } else if (r.state == ActivityState.RESUMED) {
4458                // Try to optimize this case: the configuration is changing
4459                // and we need to restart the top, resumed activity.
4460                // Instead of doing the normal handshaking, just say
4461                // "restart!".
4462                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4463                        "Config is relaunching resumed " + r);
4464                relaunchActivityLocked(r, r.configChangeFlags, true);
4465                r.configChangeFlags = 0;
4466            } else {
4467                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4468                        "Config is relaunching non-resumed " + r);
4469                relaunchActivityLocked(r, r.configChangeFlags, false);
4470                r.configChangeFlags = 0;
4471            }
4472
4473            // All done...  tell the caller we weren't able to keep this
4474            // activity around.
4475            return false;
4476        }
4477
4478        // Default case: the activity can handle this new configuration, so
4479        // hand it over.  Note that we don't need to give it the new
4480        // configuration, since we always send configuration changes to all
4481        // process when they happen so it can just use whatever configuration
4482        // it last got.
4483        if (r.app != null && r.app.thread != null) {
4484            try {
4485                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
4486                r.app.thread.scheduleActivityConfigurationChanged(r.appToken);
4487            } catch (RemoteException e) {
4488                // If process died, whatever.
4489            }
4490        }
4491        r.stopFreezingScreenLocked(false);
4492
4493        return true;
4494    }
4495
4496    private final boolean relaunchActivityLocked(ActivityRecord r,
4497            int changes, boolean andResume) {
4498        List<ResultInfo> results = null;
4499        List<Intent> newIntents = null;
4500        if (andResume) {
4501            results = r.results;
4502            newIntents = r.newIntents;
4503        }
4504        if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
4505                + " with results=" + results + " newIntents=" + newIntents
4506                + " andResume=" + andResume);
4507        EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
4508                : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
4509                r.task.taskId, r.shortComponentName);
4510
4511        r.startFreezingScreenLocked(r.app, 0);
4512
4513        try {
4514            if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
4515                    (andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ")
4516                    + r);
4517            r.forceNewConfig = false;
4518            r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents,
4519                    changes, !andResume, new Configuration(mService.mConfiguration));
4520            // Note: don't need to call pauseIfSleepingLocked() here, because
4521            // the caller will only pass in 'andResume' if this activity is
4522            // currently resumed, which implies we aren't sleeping.
4523        } catch (RemoteException e) {
4524            if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG, "Relaunch failed", e);
4525        }
4526
4527        if (andResume) {
4528            r.results = null;
4529            r.newIntents = null;
4530            if (mMainStack) {
4531                mService.reportResumedActivityLocked(r);
4532            }
4533            r.state = ActivityState.RESUMED;
4534        } else {
4535            mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4536            r.state = ActivityState.PAUSED;
4537        }
4538
4539        return true;
4540    }
4541
4542    public void dismissKeyguardOnNextActivityLocked() {
4543        mDismissKeyguardOnNextActivity = true;
4544    }
4545}
4546