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