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