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