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