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