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