ActivityStack.java revision f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8
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.UserHandle;
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 = UserHandle.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 = UserHandle.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 ? UserHandle.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                null, 0)) {
3019            userId = 0;
3020        }
3021        aInfo = mService.getActivityInfoForUser(aInfo, userId);
3022
3023        synchronized (mService) {
3024            int callingPid;
3025            if (callingUid >= 0) {
3026                callingPid = -1;
3027            } else if (caller == null) {
3028                callingPid = Binder.getCallingPid();
3029                callingUid = Binder.getCallingUid();
3030            } else {
3031                callingPid = callingUid = -1;
3032            }
3033
3034            mConfigWillChange = config != null
3035                    && mService.mConfiguration.diff(config) != 0;
3036            if (DEBUG_CONFIGURATION) Slog.v(TAG,
3037                    "Starting activity when config will change = " + mConfigWillChange);
3038
3039            final long origId = Binder.clearCallingIdentity();
3040
3041            if (mMainStack && aInfo != null &&
3042                    (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
3043                // This may be a heavy-weight process!  Check to see if we already
3044                // have another, different heavy-weight process running.
3045                if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
3046                    if (mService.mHeavyWeightProcess != null &&
3047                            (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
3048                            !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
3049                        int realCallingPid = callingPid;
3050                        int realCallingUid = callingUid;
3051                        if (caller != null) {
3052                            ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
3053                            if (callerApp != null) {
3054                                realCallingPid = callerApp.pid;
3055                                realCallingUid = callerApp.info.uid;
3056                            } else {
3057                                Slog.w(TAG, "Unable to find app for caller " + caller
3058                                      + " (pid=" + realCallingPid + ") when starting: "
3059                                      + intent.toString());
3060                                ActivityOptions.abort(options);
3061                                return ActivityManager.START_PERMISSION_DENIED;
3062                            }
3063                        }
3064
3065                        IIntentSender target = mService.getIntentSenderLocked(
3066                                ActivityManager.INTENT_SENDER_ACTIVITY, "android",
3067                                realCallingUid, null, null, 0, new Intent[] { intent },
3068                                new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
3069                                | PendingIntent.FLAG_ONE_SHOT, null);
3070
3071                        Intent newIntent = new Intent();
3072                        if (requestCode >= 0) {
3073                            // Caller is requesting a result.
3074                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
3075                        }
3076                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
3077                                new IntentSender(target));
3078                        if (mService.mHeavyWeightProcess.activities.size() > 0) {
3079                            ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
3080                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
3081                                    hist.packageName);
3082                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
3083                                    hist.task.taskId);
3084                        }
3085                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
3086                                aInfo.packageName);
3087                        newIntent.setFlags(intent.getFlags());
3088                        newIntent.setClassName("android",
3089                                HeavyWeightSwitcherActivity.class.getName());
3090                        intent = newIntent;
3091                        resolvedType = null;
3092                        caller = null;
3093                        callingUid = Binder.getCallingUid();
3094                        callingPid = Binder.getCallingPid();
3095                        componentSpecified = true;
3096                        try {
3097                            ResolveInfo rInfo =
3098                                AppGlobals.getPackageManager().resolveIntent(
3099                                        intent, null,
3100                                        PackageManager.MATCH_DEFAULT_ONLY
3101                                        | ActivityManagerService.STOCK_PM_FLAGS, userId);
3102                            aInfo = rInfo != null ? rInfo.activityInfo : null;
3103                            aInfo = mService.getActivityInfoForUser(aInfo, userId);
3104                        } catch (RemoteException e) {
3105                            aInfo = null;
3106                        }
3107                    }
3108                }
3109            }
3110
3111            int res = startActivityLocked(caller, intent, resolvedType,
3112                    aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
3113                    startFlags, options, componentSpecified, null);
3114
3115            if (mConfigWillChange && mMainStack) {
3116                // If the caller also wants to switch to a new configuration,
3117                // do so now.  This allows a clean switch, as we are waiting
3118                // for the current activity to pause (so we will not destroy
3119                // it), and have not yet started the next activity.
3120                mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3121                        "updateConfiguration()");
3122                mConfigWillChange = false;
3123                if (DEBUG_CONFIGURATION) Slog.v(TAG,
3124                        "Updating to new configuration after starting activity.");
3125                mService.updateConfigurationLocked(config, null, false, false);
3126            }
3127
3128            Binder.restoreCallingIdentity(origId);
3129
3130            if (outResult != null) {
3131                outResult.result = res;
3132                if (res == ActivityManager.START_SUCCESS) {
3133                    mWaitingActivityLaunched.add(outResult);
3134                    do {
3135                        try {
3136                            mService.wait();
3137                        } catch (InterruptedException e) {
3138                        }
3139                    } while (!outResult.timeout && outResult.who == null);
3140                } else if (res == ActivityManager.START_TASK_TO_FRONT) {
3141                    ActivityRecord r = this.topRunningActivityLocked(null);
3142                    if (r.nowVisible) {
3143                        outResult.timeout = false;
3144                        outResult.who = new ComponentName(r.info.packageName, r.info.name);
3145                        outResult.totalTime = 0;
3146                        outResult.thisTime = 0;
3147                    } else {
3148                        outResult.thisTime = SystemClock.uptimeMillis();
3149                        mWaitingActivityVisible.add(outResult);
3150                        do {
3151                            try {
3152                                mService.wait();
3153                            } catch (InterruptedException e) {
3154                            }
3155                        } while (!outResult.timeout && outResult.who == null);
3156                    }
3157                }
3158            }
3159
3160            return res;
3161        }
3162    }
3163
3164    final int startActivities(IApplicationThread caller, int callingUid,
3165            Intent[] intents, String[] resolvedTypes, IBinder resultTo,
3166            Bundle options, int userId) {
3167        if (intents == null) {
3168            throw new NullPointerException("intents is null");
3169        }
3170        if (resolvedTypes == null) {
3171            throw new NullPointerException("resolvedTypes is null");
3172        }
3173        if (intents.length != resolvedTypes.length) {
3174            throw new IllegalArgumentException("intents are length different than resolvedTypes");
3175        }
3176
3177        ActivityRecord[] outActivity = new ActivityRecord[1];
3178
3179        int callingPid;
3180        if (callingUid >= 0) {
3181            callingPid = -1;
3182        } else if (caller == null) {
3183            callingPid = Binder.getCallingPid();
3184            callingUid = Binder.getCallingUid();
3185        } else {
3186            callingPid = callingUid = -1;
3187        }
3188        final long origId = Binder.clearCallingIdentity();
3189        try {
3190            synchronized (mService) {
3191
3192                for (int i=0; i<intents.length; i++) {
3193                    Intent intent = intents[i];
3194                    if (intent == null) {
3195                        continue;
3196                    }
3197
3198                    // Refuse possible leaked file descriptors
3199                    if (intent != null && intent.hasFileDescriptors()) {
3200                        throw new IllegalArgumentException("File descriptors passed in Intent");
3201                    }
3202
3203                    boolean componentSpecified = intent.getComponent() != null;
3204
3205                    // Don't modify the client's object!
3206                    intent = new Intent(intent);
3207
3208                    // Collect information about the target of the Intent.
3209                    ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
3210                            0, null, null, userId);
3211                    // TODO: New, check if this is correct
3212                    aInfo = mService.getActivityInfoForUser(aInfo, userId);
3213
3214                    if (mMainStack && aInfo != null && (aInfo.applicationInfo.flags
3215                            & ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
3216                        throw new IllegalArgumentException(
3217                                "FLAG_CANT_SAVE_STATE not supported here");
3218                    }
3219
3220                    Bundle theseOptions;
3221                    if (options != null && i == intents.length-1) {
3222                        theseOptions = options;
3223                    } else {
3224                        theseOptions = null;
3225                    }
3226                    int res = startActivityLocked(caller, intent, resolvedTypes[i],
3227                            aInfo, resultTo, null, -1, callingPid, callingUid,
3228                            0, theseOptions, componentSpecified, outActivity);
3229                    if (res < 0) {
3230                        return res;
3231                    }
3232
3233                    resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
3234                }
3235            }
3236        } finally {
3237            Binder.restoreCallingIdentity(origId);
3238        }
3239
3240        return ActivityManager.START_SUCCESS;
3241    }
3242
3243    void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
3244            long thisTime, long totalTime) {
3245        for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3246            WaitResult w = mWaitingActivityLaunched.get(i);
3247            w.timeout = timeout;
3248            if (r != null) {
3249                w.who = new ComponentName(r.info.packageName, r.info.name);
3250            }
3251            w.thisTime = thisTime;
3252            w.totalTime = totalTime;
3253        }
3254        mService.notifyAll();
3255    }
3256
3257    void reportActivityVisibleLocked(ActivityRecord r) {
3258        for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3259            WaitResult w = mWaitingActivityVisible.get(i);
3260            w.timeout = false;
3261            if (r != null) {
3262                w.who = new ComponentName(r.info.packageName, r.info.name);
3263            }
3264            w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3265            w.thisTime = w.totalTime;
3266        }
3267        mService.notifyAll();
3268
3269        if (mDismissKeyguardOnNextActivity) {
3270            mDismissKeyguardOnNextActivity = false;
3271            mService.mWindowManager.dismissKeyguard();
3272        }
3273    }
3274
3275    void sendActivityResultLocked(int callingUid, ActivityRecord r,
3276            String resultWho, int requestCode, int resultCode, Intent data) {
3277
3278        if (callingUid > 0) {
3279            mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3280                    data, r.getUriPermissionsLocked());
3281        }
3282
3283        if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
3284                + " : who=" + resultWho + " req=" + requestCode
3285                + " res=" + resultCode + " data=" + data);
3286        if (mResumedActivity == r && r.app != null && r.app.thread != null) {
3287            try {
3288                ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
3289                list.add(new ResultInfo(resultWho, requestCode,
3290                        resultCode, data));
3291                r.app.thread.scheduleSendResult(r.appToken, list);
3292                return;
3293            } catch (Exception e) {
3294                Slog.w(TAG, "Exception thrown sending result to " + r, e);
3295            }
3296        }
3297
3298        r.addResultLocked(null, resultWho, requestCode, resultCode, data);
3299    }
3300
3301    private final void stopActivityLocked(ActivityRecord r) {
3302        if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
3303        if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3304                || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3305            if (!r.finishing) {
3306                if (!mService.mSleeping) {
3307                    if (DEBUG_STATES) {
3308                        Slog.d(TAG, "no-history finish of " + r);
3309                    }
3310                    requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
3311                            "no-history");
3312                } else {
3313                    if (DEBUG_STATES) Slog.d(TAG, "Not finishing noHistory " + r
3314                            + " on stop because we're just sleeping");
3315                }
3316            }
3317        }
3318
3319        if (r.app != null && r.app.thread != null) {
3320            if (mMainStack) {
3321                if (mService.mFocusedActivity == r) {
3322                    mService.setFocusedActivityLocked(topRunningActivityLocked(null));
3323                }
3324            }
3325            r.resumeKeyDispatchingLocked();
3326            try {
3327                r.stopped = false;
3328                if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
3329                        + " (stop requested)");
3330                r.state = ActivityState.STOPPING;
3331                if (DEBUG_VISBILITY) Slog.v(
3332                        TAG, "Stopping visible=" + r.visible + " for " + r);
3333                if (!r.visible) {
3334                    mService.mWindowManager.setAppVisibility(r.appToken, false);
3335                }
3336                r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
3337                if (mService.isSleeping()) {
3338                    r.setSleeping(true);
3339                }
3340                Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG);
3341                msg.obj = r;
3342                mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
3343            } catch (Exception e) {
3344                // Maybe just ignore exceptions here...  if the process
3345                // has crashed, our death notification will clean things
3346                // up.
3347                Slog.w(TAG, "Exception thrown during pause", e);
3348                // Just in case, assume it to be stopped.
3349                r.stopped = true;
3350                if (DEBUG_STATES) Slog.v(TAG, "Stop failed; moving to STOPPED: " + r);
3351                r.state = ActivityState.STOPPED;
3352                if (r.configDestroy) {
3353                    destroyActivityLocked(r, true, false, "stop-except");
3354                }
3355            }
3356        }
3357    }
3358
3359    final ArrayList<ActivityRecord> processStoppingActivitiesLocked(
3360            boolean remove) {
3361        int N = mStoppingActivities.size();
3362        if (N <= 0) return null;
3363
3364        ArrayList<ActivityRecord> stops = null;
3365
3366        final boolean nowVisible = mResumedActivity != null
3367                && mResumedActivity.nowVisible
3368                && !mResumedActivity.waitingVisible;
3369        for (int i=0; i<N; i++) {
3370            ActivityRecord s = mStoppingActivities.get(i);
3371            if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
3372                    + nowVisible + " waitingVisible=" + s.waitingVisible
3373                    + " finishing=" + s.finishing);
3374            if (s.waitingVisible && nowVisible) {
3375                mWaitingVisibleActivities.remove(s);
3376                s.waitingVisible = false;
3377                if (s.finishing) {
3378                    // If this activity is finishing, it is sitting on top of
3379                    // everyone else but we now know it is no longer needed...
3380                    // so get rid of it.  Otherwise, we need to go through the
3381                    // normal flow and hide it once we determine that it is
3382                    // hidden by the activities in front of it.
3383                    if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
3384                    mService.mWindowManager.setAppVisibility(s.appToken, false);
3385                }
3386            }
3387            if ((!s.waitingVisible || mService.isSleeping()) && remove) {
3388                if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
3389                if (stops == null) {
3390                    stops = new ArrayList<ActivityRecord>();
3391                }
3392                stops.add(s);
3393                mStoppingActivities.remove(i);
3394                N--;
3395                i--;
3396            }
3397        }
3398
3399        return stops;
3400    }
3401
3402    final void scheduleIdleLocked() {
3403        Message msg = Message.obtain();
3404        msg.what = IDLE_NOW_MSG;
3405        mHandler.sendMessage(msg);
3406    }
3407
3408    final ActivityRecord activityIdleInternal(IBinder token, boolean fromTimeout,
3409            Configuration config) {
3410        if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
3411
3412        ActivityRecord res = null;
3413
3414        ArrayList<ActivityRecord> stops = null;
3415        ArrayList<ActivityRecord> finishes = null;
3416        ArrayList<ActivityRecord> thumbnails = null;
3417        int NS = 0;
3418        int NF = 0;
3419        int NT = 0;
3420        IApplicationThread sendThumbnail = null;
3421        boolean booting = false;
3422        boolean enableScreen = false;
3423        boolean activityRemoved = false;
3424
3425        synchronized (mService) {
3426            ActivityRecord r = ActivityRecord.forToken(token);
3427            if (r != null) {
3428                mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
3429                r.finishLaunchTickingLocked();
3430            }
3431
3432            // Get the activity record.
3433            int index = indexOfActivityLocked(r);
3434            if (index >= 0) {
3435                res = r;
3436
3437                if (fromTimeout) {
3438                    reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
3439                }
3440
3441                // This is a hack to semi-deal with a race condition
3442                // in the client where it can be constructed with a
3443                // newer configuration from when we asked it to launch.
3444                // We'll update with whatever configuration it now says
3445                // it used to launch.
3446                if (config != null) {
3447                    r.configuration = config;
3448                }
3449
3450                // No longer need to keep the device awake.
3451                if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
3452                    mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
3453                    mLaunchingActivity.release();
3454                }
3455
3456                // We are now idle.  If someone is waiting for a thumbnail from
3457                // us, we can now deliver.
3458                r.idle = true;
3459                mService.scheduleAppGcsLocked();
3460                if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
3461                    sendThumbnail = r.app.thread;
3462                    r.thumbnailNeeded = false;
3463                }
3464
3465                // If this activity is fullscreen, set up to hide those under it.
3466
3467                if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
3468                ensureActivitiesVisibleLocked(null, 0);
3469
3470                //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
3471                if (mMainStack) {
3472                    if (!mService.mBooted) {
3473                        mService.mBooted = true;
3474                        enableScreen = true;
3475                    }
3476                }
3477
3478            } else if (fromTimeout) {
3479                reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
3480            }
3481
3482            // Atomically retrieve all of the other things to do.
3483            stops = processStoppingActivitiesLocked(true);
3484            NS = stops != null ? stops.size() : 0;
3485            if ((NF=mFinishingActivities.size()) > 0) {
3486                finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
3487                mFinishingActivities.clear();
3488            }
3489            if ((NT=mService.mCancelledThumbnails.size()) > 0) {
3490                thumbnails = new ArrayList<ActivityRecord>(mService.mCancelledThumbnails);
3491                mService.mCancelledThumbnails.clear();
3492            }
3493
3494            if (mMainStack) {
3495                booting = mService.mBooting;
3496                mService.mBooting = false;
3497            }
3498        }
3499
3500        int i;
3501
3502        // Send thumbnail if requested.
3503        if (sendThumbnail != null) {
3504            try {
3505                sendThumbnail.requestThumbnail(token);
3506            } catch (Exception e) {
3507                Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
3508                mService.sendPendingThumbnail(null, token, null, null, true);
3509            }
3510        }
3511
3512        // Stop any activities that are scheduled to do so but have been
3513        // waiting for the next one to start.
3514        for (i=0; i<NS; i++) {
3515            ActivityRecord r = (ActivityRecord)stops.get(i);
3516            synchronized (mService) {
3517                if (r.finishing) {
3518                    finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
3519                } else {
3520                    stopActivityLocked(r);
3521                }
3522            }
3523        }
3524
3525        // Finish any activities that are scheduled to do so but have been
3526        // waiting for the next one to start.
3527        for (i=0; i<NF; i++) {
3528            ActivityRecord r = (ActivityRecord)finishes.get(i);
3529            synchronized (mService) {
3530                activityRemoved = destroyActivityLocked(r, true, false, "finish-idle");
3531            }
3532        }
3533
3534        // Report back to any thumbnail receivers.
3535        for (i=0; i<NT; i++) {
3536            ActivityRecord r = (ActivityRecord)thumbnails.get(i);
3537            mService.sendPendingThumbnail(r, null, null, null, true);
3538        }
3539
3540        if (booting) {
3541            mService.finishBooting();
3542        }
3543
3544        mService.trimApplications();
3545        //dump();
3546        //mWindowManager.dump();
3547
3548        if (enableScreen) {
3549            mService.enableScreenAfterBoot();
3550        }
3551
3552        if (activityRemoved) {
3553            resumeTopActivityLocked(null);
3554        }
3555
3556        return res;
3557    }
3558
3559    /**
3560     * @return Returns true if the activity is being finished, false if for
3561     * some reason it is being left as-is.
3562     */
3563    final boolean requestFinishActivityLocked(IBinder token, int resultCode,
3564            Intent resultData, String reason) {
3565        int index = indexOfTokenLocked(token);
3566        if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(
3567                TAG, "Finishing activity @" + index + ": token=" + token
3568                + ", result=" + resultCode + ", data=" + resultData
3569                + ", reason=" + reason);
3570        if (index < 0) {
3571            return false;
3572        }
3573        ActivityRecord r = mHistory.get(index);
3574
3575        finishActivityLocked(r, index, resultCode, resultData, reason);
3576        return true;
3577    }
3578
3579    final void finishSubActivityLocked(IBinder token, String resultWho, int requestCode) {
3580        ActivityRecord self = isInStackLocked(token);
3581        if (self == null) {
3582            return;
3583        }
3584
3585        int i;
3586        for (i=mHistory.size()-1; i>=0; i--) {
3587            ActivityRecord r = (ActivityRecord)mHistory.get(i);
3588            if (r.resultTo == self && r.requestCode == requestCode) {
3589                if ((r.resultWho == null && resultWho == null) ||
3590                    (r.resultWho != null && r.resultWho.equals(resultWho))) {
3591                    finishActivityLocked(r, i,
3592                            Activity.RESULT_CANCELED, null, "request-sub");
3593                }
3594            }
3595        }
3596    }
3597
3598    final boolean finishActivityAffinityLocked(IBinder token) {
3599        int index = indexOfTokenLocked(token);
3600        if (DEBUG_RESULTS) Slog.v(
3601                TAG, "Finishing activity affinity @" + index + ": token=" + token);
3602        if (index < 0) {
3603            return false;
3604        }
3605        ActivityRecord r = mHistory.get(index);
3606
3607        while (index >= 0) {
3608            ActivityRecord cur = mHistory.get(index);
3609            if (cur.task != r.task) {
3610                break;
3611            }
3612            if (cur.taskAffinity == null && r.taskAffinity != null) {
3613                break;
3614            }
3615            if (cur.taskAffinity != null && !cur.taskAffinity.equals(r.taskAffinity)) {
3616                break;
3617            }
3618            finishActivityLocked(cur, index, Activity.RESULT_CANCELED, null, "request-affinity");
3619            index--;
3620        }
3621        return true;
3622    }
3623
3624    final void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
3625        // send the result
3626        ActivityRecord resultTo = r.resultTo;
3627        if (resultTo != null) {
3628            if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
3629                    + " who=" + r.resultWho + " req=" + r.requestCode
3630                    + " res=" + resultCode + " data=" + resultData);
3631            if (r.info.applicationInfo.uid > 0) {
3632                mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
3633                        resultTo.packageName, resultData,
3634                        resultTo.getUriPermissionsLocked());
3635            }
3636            resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
3637                                     resultData);
3638            r.resultTo = null;
3639        }
3640        else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
3641
3642        // Make sure this HistoryRecord is not holding on to other resources,
3643        // because clients have remote IPC references to this object so we
3644        // can't assume that will go away and want to avoid circular IPC refs.
3645        r.results = null;
3646        r.pendingResults = null;
3647        r.newIntents = null;
3648        r.icicle = null;
3649    }
3650
3651    /**
3652     * @return Returns true if this activity has been removed from the history
3653     * list, or false if it is still in the list and will be removed later.
3654     */
3655    final boolean finishActivityLocked(ActivityRecord r, int index,
3656            int resultCode, Intent resultData, String reason) {
3657        return finishActivityLocked(r, index, resultCode, resultData, reason, false);
3658    }
3659
3660    /**
3661     * @return Returns true if this activity has been removed from the history
3662     * list, or false if it is still in the list and will be removed later.
3663     */
3664    final boolean finishActivityLocked(ActivityRecord r, int index,
3665            int resultCode, Intent resultData, String reason, boolean immediate) {
3666        if (r.finishing) {
3667            Slog.w(TAG, "Duplicate finish request for " + r);
3668            return false;
3669        }
3670
3671        r.makeFinishing();
3672        EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
3673                System.identityHashCode(r),
3674                r.task.taskId, r.shortComponentName, reason);
3675        if (index < (mHistory.size()-1)) {
3676            ActivityRecord next = mHistory.get(index+1);
3677            if (next.task == r.task) {
3678                if (r.frontOfTask) {
3679                    // The next activity is now the front of the task.
3680                    next.frontOfTask = true;
3681                }
3682                if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
3683                    // If the caller asked that this activity (and all above it)
3684                    // be cleared when the task is reset, don't lose that information,
3685                    // but propagate it up to the next activity.
3686                    next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
3687                }
3688            }
3689        }
3690
3691        r.pauseKeyDispatchingLocked();
3692        if (mMainStack) {
3693            if (mService.mFocusedActivity == r) {
3694                mService.setFocusedActivityLocked(topRunningActivityLocked(null));
3695            }
3696        }
3697
3698        finishActivityResultsLocked(r, resultCode, resultData);
3699
3700        if (mService.mPendingThumbnails.size() > 0) {
3701            // There are clients waiting to receive thumbnails so, in case
3702            // this is an activity that someone is waiting for, add it
3703            // to the pending list so we can correctly update the clients.
3704            mService.mCancelledThumbnails.add(r);
3705        }
3706
3707        if (immediate) {
3708            return finishCurrentActivityLocked(r, index,
3709                    FINISH_IMMEDIATELY) == null;
3710        } else if (mResumedActivity == r) {
3711            boolean endTask = index <= 0
3712                    || (mHistory.get(index-1)).task != r.task;
3713            if (DEBUG_TRANSITION) Slog.v(TAG,
3714                    "Prepare close transition: finishing " + r);
3715            mService.mWindowManager.prepareAppTransition(endTask
3716                    ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
3717                    : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE, false);
3718
3719            // Tell window manager to prepare for this one to be removed.
3720            mService.mWindowManager.setAppVisibility(r.appToken, false);
3721
3722            if (mPausingActivity == null) {
3723                if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
3724                if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
3725                startPausingLocked(false, false);
3726            }
3727
3728        } else if (r.state != ActivityState.PAUSING) {
3729            // If the activity is PAUSING, we will complete the finish once
3730            // it is done pausing; else we can just directly finish it here.
3731            if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
3732            return finishCurrentActivityLocked(r, index,
3733                    FINISH_AFTER_PAUSE) == null;
3734        } else {
3735            if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
3736        }
3737
3738        return false;
3739    }
3740
3741    private static final int FINISH_IMMEDIATELY = 0;
3742    private static final int FINISH_AFTER_PAUSE = 1;
3743    private static final int FINISH_AFTER_VISIBLE = 2;
3744
3745    private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
3746            int mode) {
3747        final int index = indexOfActivityLocked(r);
3748        if (index < 0) {
3749            return null;
3750        }
3751
3752        return finishCurrentActivityLocked(r, index, mode);
3753    }
3754
3755    private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
3756            int index, int mode) {
3757        // First things first: if this activity is currently visible,
3758        // and the resumed activity is not yet visible, then hold off on
3759        // finishing until the resumed one becomes visible.
3760        if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
3761            if (!mStoppingActivities.contains(r)) {
3762                mStoppingActivities.add(r);
3763                if (mStoppingActivities.size() > 3) {
3764                    // If we already have a few activities waiting to stop,
3765                    // then give up on things going idle and start clearing
3766                    // them out.
3767                    scheduleIdleLocked();
3768                } else {
3769                    checkReadyForSleepLocked();
3770                }
3771            }
3772            if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
3773                    + " (finish requested)");
3774            r.state = ActivityState.STOPPING;
3775            mService.updateOomAdjLocked();
3776            return r;
3777        }
3778
3779        // make sure the record is cleaned out of other places.
3780        mStoppingActivities.remove(r);
3781        mGoingToSleepActivities.remove(r);
3782        mWaitingVisibleActivities.remove(r);
3783        if (mResumedActivity == r) {
3784            mResumedActivity = null;
3785        }
3786        final ActivityState prevState = r.state;
3787        if (DEBUG_STATES) Slog.v(TAG, "Moving to FINISHING: " + r);
3788        r.state = ActivityState.FINISHING;
3789
3790        if (mode == FINISH_IMMEDIATELY
3791                || prevState == ActivityState.STOPPED
3792                || prevState == ActivityState.INITIALIZING) {
3793            // If this activity is already stopped, we can just finish
3794            // it right now.
3795            boolean activityRemoved = destroyActivityLocked(r, true, true, "finish-imm");
3796            if (activityRemoved) {
3797                resumeTopActivityLocked(null);
3798            }
3799            return activityRemoved ? null : r;
3800        } else {
3801            // Need to go through the full pause cycle to get this
3802            // activity into the stopped state and then finish it.
3803            if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
3804            mFinishingActivities.add(r);
3805            resumeTopActivityLocked(null);
3806        }
3807        return r;
3808    }
3809
3810    /**
3811     * Perform the common clean-up of an activity record.  This is called both
3812     * as part of destroyActivityLocked() (when destroying the client-side
3813     * representation) and cleaning things up as a result of its hosting
3814     * processing going away, in which case there is no remaining client-side
3815     * state to destroy so only the cleanup here is needed.
3816     */
3817    final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices,
3818            boolean setState) {
3819        if (mResumedActivity == r) {
3820            mResumedActivity = null;
3821        }
3822        if (mService.mFocusedActivity == r) {
3823            mService.mFocusedActivity = null;
3824        }
3825
3826        r.configDestroy = false;
3827        r.frozenBeforeDestroy = false;
3828
3829        if (setState) {
3830            if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (cleaning up)");
3831            r.state = ActivityState.DESTROYED;
3832        }
3833
3834        // Make sure this record is no longer in the pending finishes list.
3835        // This could happen, for example, if we are trimming activities
3836        // down to the max limit while they are still waiting to finish.
3837        mFinishingActivities.remove(r);
3838        mWaitingVisibleActivities.remove(r);
3839
3840        // Remove any pending results.
3841        if (r.finishing && r.pendingResults != null) {
3842            for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
3843                PendingIntentRecord rec = apr.get();
3844                if (rec != null) {
3845                    mService.cancelIntentSenderLocked(rec, false);
3846                }
3847            }
3848            r.pendingResults = null;
3849        }
3850
3851        if (cleanServices) {
3852            cleanUpActivityServicesLocked(r);
3853        }
3854
3855        if (mService.mPendingThumbnails.size() > 0) {
3856            // There are clients waiting to receive thumbnails so, in case
3857            // this is an activity that someone is waiting for, add it
3858            // to the pending list so we can correctly update the clients.
3859            mService.mCancelledThumbnails.add(r);
3860        }
3861
3862        // Get rid of any pending idle timeouts.
3863        removeTimeoutsForActivityLocked(r);
3864    }
3865
3866    private void removeTimeoutsForActivityLocked(ActivityRecord r) {
3867        mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
3868        mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
3869        mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
3870        mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
3871        r.finishLaunchTickingLocked();
3872    }
3873
3874    final void removeActivityFromHistoryLocked(ActivityRecord r) {
3875        if (r.state != ActivityState.DESTROYED) {
3876            finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
3877            r.makeFinishing();
3878            if (DEBUG_ADD_REMOVE) {
3879                RuntimeException here = new RuntimeException("here");
3880                here.fillInStackTrace();
3881                Slog.i(TAG, "Removing activity " + r + " from stack");
3882            }
3883            mHistory.remove(r);
3884            r.takeFromHistory();
3885            if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
3886                    + " (removed from history)");
3887            r.state = ActivityState.DESTROYED;
3888            mService.mWindowManager.removeAppToken(r.appToken);
3889            if (VALIDATE_TOKENS) {
3890                validateAppTokensLocked();
3891            }
3892            cleanUpActivityServicesLocked(r);
3893            r.removeUriPermissionsLocked();
3894        }
3895    }
3896
3897    /**
3898     * Perform clean-up of service connections in an activity record.
3899     */
3900    final void cleanUpActivityServicesLocked(ActivityRecord r) {
3901        // Throw away any services that have been bound by this activity.
3902        if (r.connections != null) {
3903            Iterator<ConnectionRecord> it = r.connections.iterator();
3904            while (it.hasNext()) {
3905                ConnectionRecord c = it.next();
3906                mService.mServices.removeConnectionLocked(c, null, r);
3907            }
3908            r.connections = null;
3909        }
3910    }
3911
3912    final void scheduleDestroyActivities(ProcessRecord owner, boolean oomAdj, String reason) {
3913        Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG);
3914        msg.obj = new ScheduleDestroyArgs(owner, oomAdj, reason);
3915        mHandler.sendMessage(msg);
3916    }
3917
3918    final void destroyActivitiesLocked(ProcessRecord owner, boolean oomAdj, String reason) {
3919        boolean lastIsOpaque = false;
3920        boolean activityRemoved = false;
3921        for (int i=mHistory.size()-1; i>=0; i--) {
3922            ActivityRecord r = mHistory.get(i);
3923            if (r.finishing) {
3924                continue;
3925            }
3926            if (r.fullscreen) {
3927                lastIsOpaque = true;
3928            }
3929            if (owner != null && r.app != owner) {
3930                continue;
3931            }
3932            if (!lastIsOpaque) {
3933                continue;
3934            }
3935            // We can destroy this one if we have its icicle saved and
3936            // it is not in the process of pausing/stopping/finishing.
3937            if (r.app != null && r != mResumedActivity && r != mPausingActivity
3938                    && r.haveState && !r.visible && r.stopped
3939                    && r.state != ActivityState.DESTROYING
3940                    && r.state != ActivityState.DESTROYED) {
3941                if (DEBUG_SWITCH) Slog.v(TAG, "Destroying " + r + " in state " + r.state
3942                        + " resumed=" + mResumedActivity
3943                        + " pausing=" + mPausingActivity);
3944                if (destroyActivityLocked(r, true, oomAdj, reason)) {
3945                    activityRemoved = true;
3946                }
3947            }
3948        }
3949        if (activityRemoved) {
3950            resumeTopActivityLocked(null);
3951        }
3952    }
3953
3954    /**
3955     * Destroy the current CLIENT SIDE instance of an activity.  This may be
3956     * called both when actually finishing an activity, or when performing
3957     * a configuration switch where we destroy the current client-side object
3958     * but then create a new client-side object for this same HistoryRecord.
3959     */
3960    final boolean destroyActivityLocked(ActivityRecord r,
3961            boolean removeFromApp, boolean oomAdj, String reason) {
3962        if (DEBUG_SWITCH) Slog.v(
3963            TAG, "Removing activity from " + reason + ": token=" + r
3964              + ", app=" + (r.app != null ? r.app.processName : "(null)"));
3965        EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
3966                System.identityHashCode(r),
3967                r.task.taskId, r.shortComponentName, reason);
3968
3969        boolean removedFromHistory = false;
3970
3971        cleanUpActivityLocked(r, false, false);
3972
3973        final boolean hadApp = r.app != null;
3974
3975        if (hadApp) {
3976            if (removeFromApp) {
3977                int idx = r.app.activities.indexOf(r);
3978                if (idx >= 0) {
3979                    r.app.activities.remove(idx);
3980                }
3981                if (mService.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
3982                    mService.mHeavyWeightProcess = null;
3983                    mService.mHandler.sendEmptyMessage(
3984                            ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG);
3985                }
3986                if (r.app.activities.size() == 0) {
3987                    // No longer have activities, so update location in
3988                    // LRU list.
3989                    mService.updateLruProcessLocked(r.app, oomAdj, false);
3990                }
3991            }
3992
3993            boolean skipDestroy = false;
3994
3995            try {
3996                if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
3997                r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,
3998                        r.configChangeFlags);
3999            } catch (Exception e) {
4000                // We can just ignore exceptions here...  if the process
4001                // has crashed, our death notification will clean things
4002                // up.
4003                //Slog.w(TAG, "Exception thrown during finish", e);
4004                if (r.finishing) {
4005                    removeActivityFromHistoryLocked(r);
4006                    removedFromHistory = true;
4007                    skipDestroy = true;
4008                }
4009            }
4010
4011            r.app = null;
4012            r.nowVisible = false;
4013
4014            // If the activity is finishing, we need to wait on removing it
4015            // from the list to give it a chance to do its cleanup.  During
4016            // that time it may make calls back with its token so we need to
4017            // be able to find it on the list and so we don't want to remove
4018            // it from the list yet.  Otherwise, we can just immediately put
4019            // it in the destroyed state since we are not removing it from the
4020            // list.
4021            if (r.finishing && !skipDestroy) {
4022                if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYING: " + r
4023                        + " (destroy requested)");
4024                r.state = ActivityState.DESTROYING;
4025                Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4026                msg.obj = r;
4027                mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4028            } else {
4029                if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
4030                        + " (destroy skipped)");
4031                r.state = ActivityState.DESTROYED;
4032            }
4033        } else {
4034            // remove this record from the history.
4035            if (r.finishing) {
4036                removeActivityFromHistoryLocked(r);
4037                removedFromHistory = true;
4038            } else {
4039                if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
4040                        + " (no app)");
4041                r.state = ActivityState.DESTROYED;
4042            }
4043        }
4044
4045        r.configChangeFlags = 0;
4046
4047        if (!mLRUActivities.remove(r) && hadApp) {
4048            Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
4049        }
4050
4051        return removedFromHistory;
4052    }
4053
4054    final void activityDestroyed(IBinder token) {
4055        synchronized (mService) {
4056            final long origId = Binder.clearCallingIdentity();
4057            try {
4058                ActivityRecord r = ActivityRecord.forToken(token);
4059                if (r != null) {
4060                    mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
4061                }
4062
4063                int index = indexOfActivityLocked(r);
4064                if (index >= 0) {
4065                    if (r.state == ActivityState.DESTROYING) {
4066                        cleanUpActivityLocked(r, true, false);
4067                        removeActivityFromHistoryLocked(r);
4068                    }
4069                }
4070                resumeTopActivityLocked(null);
4071            } finally {
4072                Binder.restoreCallingIdentity(origId);
4073            }
4074        }
4075    }
4076
4077    private void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
4078        int i = list.size();
4079        if (localLOGV) Slog.v(
4080            TAG, "Removing app " + app + " from list " + list
4081            + " with " + i + " entries");
4082        while (i > 0) {
4083            i--;
4084            ActivityRecord r = (ActivityRecord)list.get(i);
4085            if (localLOGV) Slog.v(
4086                TAG, "Record #" + i + " " + r + ": app=" + r.app);
4087            if (r.app == app) {
4088                if (localLOGV) Slog.v(TAG, "Removing this entry!");
4089                list.remove(i);
4090                removeTimeoutsForActivityLocked(r);
4091            }
4092        }
4093    }
4094
4095    void removeHistoryRecordsForAppLocked(ProcessRecord app) {
4096        removeHistoryRecordsForAppLocked(mLRUActivities, app);
4097        removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4098        removeHistoryRecordsForAppLocked(mGoingToSleepActivities, app);
4099        removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4100        removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4101    }
4102
4103    /**
4104     * Move the current home activity's task (if one exists) to the front
4105     * of the stack.
4106     */
4107    final void moveHomeToFrontLocked() {
4108        TaskRecord homeTask = null;
4109        for (int i=mHistory.size()-1; i>=0; i--) {
4110            ActivityRecord hr = mHistory.get(i);
4111            if (hr.isHomeActivity) {
4112                homeTask = hr.task;
4113                break;
4114            }
4115        }
4116        if (homeTask != null) {
4117            moveTaskToFrontLocked(homeTask, null, null);
4118        }
4119    }
4120
4121    final void updateTransitLocked(int transit, Bundle options) {
4122        if (options != null) {
4123            ActivityRecord r = topRunningActivityLocked(null);
4124            if (r != null && r.state != ActivityState.RESUMED) {
4125                r.updateOptionsLocked(options);
4126            } else {
4127                ActivityOptions.abort(options);
4128            }
4129        }
4130        mService.mWindowManager.prepareAppTransition(transit, false);
4131    }
4132
4133    final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
4134        if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
4135
4136        final int task = tr.taskId;
4137        int top = mHistory.size()-1;
4138
4139        if (top < 0 || (mHistory.get(top)).task.taskId == task) {
4140            // nothing to do!
4141            if (reason != null &&
4142                    (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
4143                ActivityOptions.abort(options);
4144            } else {
4145                updateTransitLocked(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT, options);
4146            }
4147            return;
4148        }
4149
4150        ArrayList<IBinder> moved = new ArrayList<IBinder>();
4151
4152        // Applying the affinities may have removed entries from the history,
4153        // so get the size again.
4154        top = mHistory.size()-1;
4155        int pos = top;
4156
4157        // Shift all activities with this task up to the top
4158        // of the stack, keeping them in the same internal order.
4159        while (pos >= 0) {
4160            ActivityRecord r = mHistory.get(pos);
4161            if (localLOGV) Slog.v(
4162                TAG, "At " + pos + " ckp " + r.task + ": " + r);
4163            if (r.task.taskId == task) {
4164                if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
4165                if (DEBUG_ADD_REMOVE) {
4166                    RuntimeException here = new RuntimeException("here");
4167                    here.fillInStackTrace();
4168                    Slog.i(TAG, "Removing and adding activity " + r + " to stack at " + top, here);
4169                }
4170                mHistory.remove(pos);
4171                mHistory.add(top, r);
4172                moved.add(0, r.appToken);
4173                top--;
4174            }
4175            pos--;
4176        }
4177
4178        if (DEBUG_TRANSITION) Slog.v(TAG,
4179                "Prepare to front transition: task=" + tr);
4180        if (reason != null &&
4181                (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
4182            mService.mWindowManager.prepareAppTransition(
4183                    WindowManagerPolicy.TRANSIT_NONE, false);
4184            ActivityRecord r = topRunningActivityLocked(null);
4185            if (r != null) {
4186                mNoAnimActivities.add(r);
4187            }
4188            ActivityOptions.abort(options);
4189        } else {
4190            updateTransitLocked(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT, options);
4191        }
4192
4193        mService.mWindowManager.moveAppTokensToTop(moved);
4194        if (VALIDATE_TOKENS) {
4195            validateAppTokensLocked();
4196        }
4197
4198        finishTaskMoveLocked(task);
4199        EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
4200    }
4201
4202    private final void finishTaskMoveLocked(int task) {
4203        resumeTopActivityLocked(null);
4204    }
4205
4206    /**
4207     * Worker method for rearranging history stack.  Implements the function of moving all
4208     * activities for a specific task (gathering them if disjoint) into a single group at the
4209     * bottom of the stack.
4210     *
4211     * If a watcher is installed, the action is preflighted and the watcher has an opportunity
4212     * to premeptively cancel the move.
4213     *
4214     * @param task The taskId to collect and move to the bottom.
4215     * @return Returns true if the move completed, false if not.
4216     */
4217    final boolean moveTaskToBackLocked(int task, ActivityRecord reason) {
4218        Slog.i(TAG, "moveTaskToBack: " + task);
4219
4220        // If we have a watcher, preflight the move before committing to it.  First check
4221        // for *other* available tasks, but if none are available, then try again allowing the
4222        // current task to be selected.
4223        if (mMainStack && mService.mController != null) {
4224            ActivityRecord next = topRunningActivityLocked(null, task);
4225            if (next == null) {
4226                next = topRunningActivityLocked(null, 0);
4227            }
4228            if (next != null) {
4229                // ask watcher if this is allowed
4230                boolean moveOK = true;
4231                try {
4232                    moveOK = mService.mController.activityResuming(next.packageName);
4233                } catch (RemoteException e) {
4234                    mService.mController = null;
4235                }
4236                if (!moveOK) {
4237                    return false;
4238                }
4239            }
4240        }
4241
4242        ArrayList<IBinder> moved = new ArrayList<IBinder>();
4243
4244        if (DEBUG_TRANSITION) Slog.v(TAG,
4245                "Prepare to back transition: task=" + task);
4246
4247        final int N = mHistory.size();
4248        int bottom = 0;
4249        int pos = 0;
4250
4251        // Shift all activities with this task down to the bottom
4252        // of the stack, keeping them in the same internal order.
4253        while (pos < N) {
4254            ActivityRecord r = mHistory.get(pos);
4255            if (localLOGV) Slog.v(
4256                TAG, "At " + pos + " ckp " + r.task + ": " + r);
4257            if (r.task.taskId == task) {
4258                if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
4259                if (DEBUG_ADD_REMOVE) {
4260                    RuntimeException here = new RuntimeException("here");
4261                    here.fillInStackTrace();
4262                    Slog.i(TAG, "Removing and adding activity " + r + " to stack at "
4263                            + bottom, here);
4264                }
4265                mHistory.remove(pos);
4266                mHistory.add(bottom, r);
4267                moved.add(r.appToken);
4268                bottom++;
4269            }
4270            pos++;
4271        }
4272
4273        if (reason != null &&
4274                (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
4275            mService.mWindowManager.prepareAppTransition(
4276                    WindowManagerPolicy.TRANSIT_NONE, false);
4277            ActivityRecord r = topRunningActivityLocked(null);
4278            if (r != null) {
4279                mNoAnimActivities.add(r);
4280            }
4281        } else {
4282            mService.mWindowManager.prepareAppTransition(
4283                    WindowManagerPolicy.TRANSIT_TASK_TO_BACK, false);
4284        }
4285        mService.mWindowManager.moveAppTokensToBottom(moved);
4286        if (VALIDATE_TOKENS) {
4287            validateAppTokensLocked();
4288        }
4289
4290        finishTaskMoveLocked(task);
4291        return true;
4292    }
4293
4294    public ActivityManager.TaskThumbnails getTaskThumbnailsLocked(TaskRecord tr) {
4295        TaskAccessInfo info = getTaskAccessInfoLocked(tr.taskId, true);
4296        ActivityRecord resumed = mResumedActivity;
4297        if (resumed != null && resumed.thumbHolder == tr) {
4298            info.mainThumbnail = resumed.stack.screenshotActivities(resumed);
4299        } else {
4300            info.mainThumbnail = tr.lastThumbnail;
4301        }
4302        return info;
4303    }
4304
4305    public ActivityRecord removeTaskActivitiesLocked(int taskId, int subTaskIndex,
4306            boolean taskRequired) {
4307        TaskAccessInfo info = getTaskAccessInfoLocked(taskId, false);
4308        if (info.root == null) {
4309            if (taskRequired) {
4310                Slog.w(TAG, "removeTaskLocked: unknown taskId " + taskId);
4311            }
4312            return null;
4313        }
4314
4315        if (subTaskIndex < 0) {
4316            // Just remove the entire task.
4317            performClearTaskAtIndexLocked(taskId, info.rootIndex);
4318            return info.root;
4319        }
4320
4321        if (subTaskIndex >= info.subtasks.size()) {
4322            if (taskRequired) {
4323                Slog.w(TAG, "removeTaskLocked: unknown subTaskIndex " + subTaskIndex);
4324            }
4325            return null;
4326        }
4327
4328        // Remove all of this task's activies starting at the sub task.
4329        TaskAccessInfo.SubTask subtask = info.subtasks.get(subTaskIndex);
4330        performClearTaskAtIndexLocked(taskId, subtask.index);
4331        return subtask.activity;
4332    }
4333
4334    public TaskAccessInfo getTaskAccessInfoLocked(int taskId, boolean inclThumbs) {
4335        ActivityRecord resumed = mResumedActivity;
4336        final TaskAccessInfo thumbs = new TaskAccessInfo();
4337        // How many different sub-thumbnails?
4338        final int NA = mHistory.size();
4339        int j = 0;
4340        ThumbnailHolder holder = null;
4341        while (j < NA) {
4342            ActivityRecord ar = mHistory.get(j);
4343            if (!ar.finishing && ar.task.taskId == taskId) {
4344                holder = ar.thumbHolder;
4345                break;
4346            }
4347            j++;
4348        }
4349
4350        if (j >= NA) {
4351            return thumbs;
4352        }
4353
4354        thumbs.root = mHistory.get(j);
4355        thumbs.rootIndex = j;
4356
4357        ArrayList<TaskAccessInfo.SubTask> subtasks = new ArrayList<TaskAccessInfo.SubTask>();
4358        thumbs.subtasks = subtasks;
4359        ActivityRecord lastActivity = null;
4360        while (j < NA) {
4361            ActivityRecord ar = mHistory.get(j);
4362            j++;
4363            if (ar.finishing) {
4364                continue;
4365            }
4366            if (ar.task.taskId != taskId) {
4367                break;
4368            }
4369            lastActivity = ar;
4370            if (ar.thumbHolder != holder && holder != null) {
4371                thumbs.numSubThumbbails++;
4372                holder = ar.thumbHolder;
4373                TaskAccessInfo.SubTask sub = new TaskAccessInfo.SubTask();
4374                sub.thumbnail = holder.lastThumbnail;
4375                sub.activity = ar;
4376                sub.index = j-1;
4377                subtasks.add(sub);
4378            }
4379        }
4380        if (lastActivity != null && subtasks.size() > 0) {
4381            if (resumed == lastActivity) {
4382                TaskAccessInfo.SubTask sub = subtasks.get(subtasks.size()-1);
4383                sub.thumbnail = lastActivity.stack.screenshotActivities(lastActivity);
4384            }
4385        }
4386        if (thumbs.numSubThumbbails > 0) {
4387            thumbs.retriever = new IThumbnailRetriever.Stub() {
4388                public Bitmap getThumbnail(int index) {
4389                    if (index < 0 || index >= thumbs.subtasks.size()) {
4390                        return null;
4391                    }
4392                    return thumbs.subtasks.get(index).thumbnail;
4393                }
4394            };
4395        }
4396        return thumbs;
4397    }
4398
4399    private final void logStartActivity(int tag, ActivityRecord r,
4400            TaskRecord task) {
4401        EventLog.writeEvent(tag,
4402                System.identityHashCode(r), task.taskId,
4403                r.shortComponentName, r.intent.getAction(),
4404                r.intent.getType(), r.intent.getDataString(),
4405                r.intent.getFlags());
4406    }
4407
4408    /**
4409     * Make sure the given activity matches the current configuration.  Returns
4410     * false if the activity had to be destroyed.  Returns true if the
4411     * configuration is the same, or the activity will remain running as-is
4412     * for whatever reason.  Ensures the HistoryRecord is updated with the
4413     * correct configuration and all other bookkeeping is handled.
4414     */
4415    final boolean ensureActivityConfigurationLocked(ActivityRecord r,
4416            int globalChanges) {
4417        if (mConfigWillChange) {
4418            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4419                    "Skipping config check (will change): " + r);
4420            return true;
4421        }
4422
4423        if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4424                "Ensuring correct configuration: " + r);
4425
4426        // Short circuit: if the two configurations are the exact same
4427        // object (the common case), then there is nothing to do.
4428        Configuration newConfig = mService.mConfiguration;
4429        if (r.configuration == newConfig && !r.forceNewConfig) {
4430            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4431                    "Configuration unchanged in " + r);
4432            return true;
4433        }
4434
4435        // We don't worry about activities that are finishing.
4436        if (r.finishing) {
4437            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4438                    "Configuration doesn't matter in finishing " + r);
4439            r.stopFreezingScreenLocked(false);
4440            return true;
4441        }
4442
4443        // Okay we now are going to make this activity have the new config.
4444        // But then we need to figure out how it needs to deal with that.
4445        Configuration oldConfig = r.configuration;
4446        r.configuration = newConfig;
4447
4448        // Determine what has changed.  May be nothing, if this is a config
4449        // that has come back from the app after going idle.  In that case
4450        // we just want to leave the official config object now in the
4451        // activity and do nothing else.
4452        final int changes = oldConfig.diff(newConfig);
4453        if (changes == 0 && !r.forceNewConfig) {
4454            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4455                    "Configuration no differences in " + r);
4456            return true;
4457        }
4458
4459        // If the activity isn't currently running, just leave the new
4460        // configuration and it will pick that up next time it starts.
4461        if (r.app == null || r.app.thread == null) {
4462            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4463                    "Configuration doesn't matter not running " + r);
4464            r.stopFreezingScreenLocked(false);
4465            r.forceNewConfig = false;
4466            return true;
4467        }
4468
4469        // Figure out how to handle the changes between the configurations.
4470        if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
4471            Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
4472                    + Integer.toHexString(changes) + ", handles=0x"
4473                    + Integer.toHexString(r.info.getRealConfigChanged())
4474                    + ", newConfig=" + newConfig);
4475        }
4476        if ((changes&(~r.info.getRealConfigChanged())) != 0 || r.forceNewConfig) {
4477            // Aha, the activity isn't handling the change, so DIE DIE DIE.
4478            r.configChangeFlags |= changes;
4479            r.startFreezingScreenLocked(r.app, globalChanges);
4480            r.forceNewConfig = false;
4481            if (r.app == null || r.app.thread == null) {
4482                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4483                        "Config is destroying non-running " + r);
4484                destroyActivityLocked(r, true, false, "config");
4485            } else if (r.state == ActivityState.PAUSING) {
4486                // A little annoying: we are waiting for this activity to
4487                // finish pausing.  Let's not do anything now, but just
4488                // flag that it needs to be restarted when done pausing.
4489                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4490                        "Config is skipping already pausing " + r);
4491                r.configDestroy = true;
4492                return true;
4493            } else if (r.state == ActivityState.RESUMED) {
4494                // Try to optimize this case: the configuration is changing
4495                // and we need to restart the top, resumed activity.
4496                // Instead of doing the normal handshaking, just say
4497                // "restart!".
4498                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4499                        "Config is relaunching resumed " + r);
4500                relaunchActivityLocked(r, r.configChangeFlags, true);
4501                r.configChangeFlags = 0;
4502            } else {
4503                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4504                        "Config is relaunching non-resumed " + r);
4505                relaunchActivityLocked(r, r.configChangeFlags, false);
4506                r.configChangeFlags = 0;
4507            }
4508
4509            // All done...  tell the caller we weren't able to keep this
4510            // activity around.
4511            return false;
4512        }
4513
4514        // Default case: the activity can handle this new configuration, so
4515        // hand it over.  Note that we don't need to give it the new
4516        // configuration, since we always send configuration changes to all
4517        // process when they happen so it can just use whatever configuration
4518        // it last got.
4519        if (r.app != null && r.app.thread != null) {
4520            try {
4521                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
4522                r.app.thread.scheduleActivityConfigurationChanged(r.appToken);
4523            } catch (RemoteException e) {
4524                // If process died, whatever.
4525            }
4526        }
4527        r.stopFreezingScreenLocked(false);
4528
4529        return true;
4530    }
4531
4532    private final boolean relaunchActivityLocked(ActivityRecord r,
4533            int changes, boolean andResume) {
4534        List<ResultInfo> results = null;
4535        List<Intent> newIntents = null;
4536        if (andResume) {
4537            results = r.results;
4538            newIntents = r.newIntents;
4539        }
4540        if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
4541                + " with results=" + results + " newIntents=" + newIntents
4542                + " andResume=" + andResume);
4543        EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
4544                : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
4545                r.task.taskId, r.shortComponentName);
4546
4547        r.startFreezingScreenLocked(r.app, 0);
4548
4549        try {
4550            if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
4551                    (andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ")
4552                    + r);
4553            r.forceNewConfig = false;
4554            r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents,
4555                    changes, !andResume, new Configuration(mService.mConfiguration));
4556            // Note: don't need to call pauseIfSleepingLocked() here, because
4557            // the caller will only pass in 'andResume' if this activity is
4558            // currently resumed, which implies we aren't sleeping.
4559        } catch (RemoteException e) {
4560            if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG, "Relaunch failed", e);
4561        }
4562
4563        if (andResume) {
4564            r.results = null;
4565            r.newIntents = null;
4566            if (mMainStack) {
4567                mService.reportResumedActivityLocked(r);
4568            }
4569            r.state = ActivityState.RESUMED;
4570        } else {
4571            mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4572            r.state = ActivityState.PAUSED;
4573        }
4574
4575        return true;
4576    }
4577
4578    public void dismissKeyguardOnNextActivityLocked() {
4579        mDismissKeyguardOnNextActivity = true;
4580    }
4581}
4582