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