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