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