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