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