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