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