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