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