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