OSDN Git Service

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