• 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 com.android.server.am.ActivityManagerService.TAG;
20 import static com.android.server.am.ActivityManagerService.localLOGV;
21 import static com.android.server.am.ActivityManagerService.DEBUG_CLEANUP;
22 import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION;
23 import static com.android.server.am.ActivityManagerService.DEBUG_PAUSE;
24 import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
25 import static com.android.server.am.ActivityManagerService.DEBUG_STACK;
26 import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
27 import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
28 import static com.android.server.am.ActivityManagerService.DEBUG_TRANSITION;
29 import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
30 import static com.android.server.am.ActivityManagerService.DEBUG_VISBILITY;
31 import static com.android.server.am.ActivityManagerService.VALIDATE_TOKENS;
32 
33 import static com.android.server.am.ActivityStackSupervisor.DEBUG_ADD_REMOVE;
34 import static com.android.server.am.ActivityStackSupervisor.DEBUG_APP;
35 import static com.android.server.am.ActivityStackSupervisor.DEBUG_SAVED_STATE;
36 import static com.android.server.am.ActivityStackSupervisor.DEBUG_STATES;
37 import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
38 
39 import com.android.internal.os.BatteryStatsImpl;
40 import com.android.internal.util.Objects;
41 import com.android.server.Watchdog;
42 import com.android.server.am.ActivityManagerService.ItemMatcher;
43 import com.android.server.wm.AppTransition;
44 import com.android.server.wm.TaskGroup;
45 import com.android.server.wm.WindowManagerService;
46 
47 import android.app.Activity;
48 import android.app.ActivityManager;
49 import android.app.ActivityOptions;
50 import android.app.AppGlobals;
51 import android.app.IActivityController;
52 import android.app.IThumbnailReceiver;
53 import android.app.ResultInfo;
54 import android.app.ActivityManager.RunningTaskInfo;
55 import android.content.ComponentName;
56 import android.content.Context;
57 import android.content.Intent;
58 import android.content.pm.ActivityInfo;
59 import android.content.pm.PackageManager;
60 import android.content.res.Configuration;
61 import android.content.res.Resources;
62 import android.graphics.Bitmap;
63 import android.net.Uri;
64 import android.os.Binder;
65 import android.os.Bundle;
66 import android.os.Debug;
67 import android.os.Handler;
68 import android.os.IBinder;
69 import android.os.Looper;
70 import android.os.Message;
71 import android.os.RemoteException;
72 import android.os.SystemClock;
73 import android.os.Trace;
74 import android.os.UserHandle;
75 import android.util.EventLog;
76 import android.util.Slog;
77 import android.view.Display;
78 
79 import java.io.FileDescriptor;
80 import java.io.PrintWriter;
81 import java.lang.ref.WeakReference;
82 import java.util.ArrayList;
83 import java.util.Iterator;
84 import java.util.List;
85 
86 /**
87  * State and management of a single stack of activities.
88  */
89 final class ActivityStack {
90 
91     // Ticks during which we check progress while waiting for an app to launch.
92     static final int LAUNCH_TICK = 500;
93 
94     // How long we wait until giving up on the last activity to pause.  This
95     // is short because it directly impacts the responsiveness of starting the
96     // next activity.
97     static final int PAUSE_TIMEOUT = 500;
98 
99     // How long we wait for the activity to tell us it has stopped before
100     // giving up.  This is a good amount of time because we really need this
101     // from the application in order to get its saved state.
102     static final int STOP_TIMEOUT = 10*1000;
103 
104     // How long we wait until giving up on an activity telling us it has
105     // finished destroying itself.
106     static final int DESTROY_TIMEOUT = 10*1000;
107 
108     // How long until we reset a task when the user returns to it.  Currently
109     // disabled.
110     static final long ACTIVITY_INACTIVE_RESET_TIME = 0;
111 
112     // How long between activity launches that we consider safe to not warn
113     // the user about an unexpected activity being launched on top.
114     static final long START_WARN_TIME = 5*1000;
115 
116     // Set to false to disable the preview that is shown while a new activity
117     // is being started.
118     static final boolean SHOW_APP_STARTING_PREVIEW = true;
119 
120     // How long to wait for all background Activities to redraw following a call to
121     // convertToTranslucent().
122     static final long TRANSLUCENT_CONVERSION_TIMEOUT = 2000;
123 
124     static final boolean SCREENSHOT_FORCE_565 = ActivityManager
125             .isLowRamDeviceStatic() ? true : false;
126 
127     enum ActivityState {
128         INITIALIZING,
129         RESUMED,
130         PAUSING,
131         PAUSED,
132         STOPPING,
133         STOPPED,
134         FINISHING,
135         DESTROYING,
136         DESTROYED
137     }
138 
139     final ActivityManagerService mService;
140     final WindowManagerService mWindowManager;
141 
142     final Context mContext;
143 
144     /**
145      * The back history of all previous (and possibly still
146      * running) activities.  It contains #TaskRecord objects.
147      */
148     private ArrayList<TaskRecord> mTaskHistory = new ArrayList<TaskRecord>();
149 
150     /**
151      * Used for validating app tokens with window manager.
152      */
153     final ArrayList<TaskGroup> mValidateAppTokens = new ArrayList<TaskGroup>();
154 
155     /**
156      * List of running activities, sorted by recent usage.
157      * The first entry in the list is the least recently used.
158      * It contains HistoryRecord objects.
159      */
160     final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<ActivityRecord>();
161 
162     /**
163      * Animations that for the current transition have requested not to
164      * be considered for the transition animation.
165      */
166     final ArrayList<ActivityRecord> mNoAnimActivities = new ArrayList<ActivityRecord>();
167 
168     /**
169      * When we are in the process of pausing an activity, before starting the
170      * next one, this variable holds the activity that is currently being paused.
171      */
172     ActivityRecord mPausingActivity = null;
173 
174     /**
175      * This is the last activity that we put into the paused state.  This is
176      * used to determine if we need to do an activity transition while sleeping,
177      * when we normally hold the top activity paused.
178      */
179     ActivityRecord mLastPausedActivity = null;
180 
181     /**
182      * Activities that specify No History must be removed once the user navigates away from them.
183      * If the device goes to sleep with such an activity in the paused state then we save it here
184      * and finish it later if another activity replaces it on wakeup.
185      */
186     ActivityRecord mLastNoHistoryActivity = null;
187 
188     /**
189      * Current activity that is resumed, or null if there is none.
190      */
191     ActivityRecord mResumedActivity = null;
192 
193     /**
194      * This is the last activity that has been started.  It is only used to
195      * identify when multiple activities are started at once so that the user
196      * can be warned they may not be in the activity they think they are.
197      */
198     ActivityRecord mLastStartedActivity = null;
199 
200     // The topmost Activity passed to convertToTranslucent(). When non-null it means we are
201     // waiting for all Activities in mUndrawnActivitiesBelowTopTranslucent to be removed as they
202     // are drawn. When the last member of mUndrawnActivitiesBelowTopTranslucent is removed the
203     // Activity in mTranslucentActivityWaiting is notified via
204     // Activity.onTranslucentConversionComplete(false). If a timeout occurs prior to the last
205     // background activity being drawn then the same call will be made with a true value.
206     ActivityRecord mTranslucentActivityWaiting = null;
207     ArrayList<ActivityRecord> mUndrawnActivitiesBelowTopTranslucent =
208             new ArrayList<ActivityRecord>();
209 
210     /**
211      * Set when we know we are going to be calling updateConfiguration()
212      * soon, so want to skip intermediate config checks.
213      */
214     boolean mConfigWillChange;
215 
216     long mLaunchStartTime = 0;
217     long mFullyDrawnStartTime = 0;
218 
219     /**
220      * Save the most recent screenshot for reuse. This keeps Recents from taking two identical
221      * screenshots, one for the Recents thumbnail and one for the pauseActivity thumbnail.
222      */
223     private ActivityRecord mLastScreenshotActivity = null;
224     private Bitmap mLastScreenshotBitmap = null;
225 
226     int mThumbnailWidth = -1;
227     int mThumbnailHeight = -1;
228 
229     int mCurrentUser;
230 
231     final int mStackId;
232 
233     /** Run all ActivityStacks through this */
234     final ActivityStackSupervisor mStackSupervisor;
235 
236     static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
237     static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
238     static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
239     static final int STOP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 4;
240     static final int DESTROY_ACTIVITIES_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 5;
241     static final int TRANSLUCENT_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6;
242 
243     static class ScheduleDestroyArgs {
244         final ProcessRecord mOwner;
245         final boolean mOomAdj;
246         final String mReason;
ScheduleDestroyArgs(ProcessRecord owner, boolean oomAdj, String reason)247         ScheduleDestroyArgs(ProcessRecord owner, boolean oomAdj, String reason) {
248             mOwner = owner;
249             mOomAdj = oomAdj;
250             mReason = reason;
251         }
252     }
253 
254     final Handler mHandler;
255 
256     final class ActivityStackHandler extends Handler {
257         //public Handler() {
258         //    if (localLOGV) Slog.v(TAG, "Handler started!");
259         //}
ActivityStackHandler(Looper looper)260         ActivityStackHandler(Looper looper) {
261             super(looper);
262         }
263 
264         @Override
handleMessage(Message msg)265         public void handleMessage(Message msg) {
266             switch (msg.what) {
267                 case PAUSE_TIMEOUT_MSG: {
268                     ActivityRecord r = (ActivityRecord)msg.obj;
269                     // We don't at this point know if the activity is fullscreen,
270                     // so we need to be conservative and assume it isn't.
271                     Slog.w(TAG, "Activity pause timeout for " + r);
272                     synchronized (mService) {
273                         if (r.app != null) {
274                             mService.logAppTooSlow(r.app, r.pauseTime, "pausing " + r);
275                         }
276                         activityPausedLocked(r.appToken, true);
277                     }
278                 } break;
279                 case LAUNCH_TICK_MSG: {
280                     ActivityRecord r = (ActivityRecord)msg.obj;
281                     synchronized (mService) {
282                         if (r.continueLaunchTickingLocked()) {
283                             mService.logAppTooSlow(r.app, r.launchTickTime, "launching " + r);
284                         }
285                     }
286                 } break;
287                 case DESTROY_TIMEOUT_MSG: {
288                     ActivityRecord r = (ActivityRecord)msg.obj;
289                     // We don't at this point know if the activity is fullscreen,
290                     // so we need to be conservative and assume it isn't.
291                     Slog.w(TAG, "Activity destroy timeout for " + r);
292                     synchronized (mService) {
293                         activityDestroyedLocked(r != null ? r.appToken : null);
294                     }
295                 } break;
296                 case STOP_TIMEOUT_MSG: {
297                     ActivityRecord r = (ActivityRecord)msg.obj;
298                     // We don't at this point know if the activity is fullscreen,
299                     // so we need to be conservative and assume it isn't.
300                     Slog.w(TAG, "Activity stop timeout for " + r);
301                     synchronized (mService) {
302                         if (r.isInHistory()) {
303                             activityStoppedLocked(r, null, null, null);
304                         }
305                     }
306                 } break;
307                 case DESTROY_ACTIVITIES_MSG: {
308                     ScheduleDestroyArgs args = (ScheduleDestroyArgs)msg.obj;
309                     synchronized (mService) {
310                         destroyActivitiesLocked(args.mOwner, args.mOomAdj, args.mReason);
311                     }
312                 } break;
313                 case TRANSLUCENT_TIMEOUT_MSG: {
314                     synchronized (mService) {
315                         notifyActivityDrawnLocked(null);
316                     }
317                 } break;
318             }
319         }
320     }
321 
numActivities()322     private int numActivities() {
323         int count = 0;
324         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
325             count += mTaskHistory.get(taskNdx).mActivities.size();
326         }
327         return count;
328     }
329 
ActivityStack(ActivityManagerService service, Context context, Looper looper, int stackId)330     ActivityStack(ActivityManagerService service, Context context, Looper looper, int stackId) {
331         mHandler = new ActivityStackHandler(looper);
332         mService = service;
333         mWindowManager = service.mWindowManager;
334         mStackSupervisor = service.mStackSupervisor;
335         mContext = context;
336         mStackId = stackId;
337         mCurrentUser = service.mCurrentUserId;
338     }
339 
okToShow(ActivityRecord r)340     boolean okToShow(ActivityRecord r) {
341         return r.userId == mCurrentUser
342                 || (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0;
343     }
344 
topRunningActivityLocked(ActivityRecord notTop)345     final ActivityRecord topRunningActivityLocked(ActivityRecord notTop) {
346         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
347             ActivityRecord r = mTaskHistory.get(taskNdx).topRunningActivityLocked(notTop);
348             if (r != null) {
349                 return r;
350             }
351         }
352         return null;
353     }
354 
topRunningNonDelayedActivityLocked(ActivityRecord notTop)355     final ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
356         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
357             final TaskRecord task = mTaskHistory.get(taskNdx);
358             final ArrayList<ActivityRecord> activities = task.mActivities;
359             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
360                 ActivityRecord r = activities.get(activityNdx);
361                 if (!r.finishing && !r.delayedResume && r != notTop && okToShow(r)) {
362                     return r;
363                 }
364             }
365         }
366         return null;
367     }
368 
369     /**
370      * This is a simplified version of topRunningActivityLocked that provides a number of
371      * optional skip-over modes.  It is intended for use with the ActivityController hook only.
372      *
373      * @param token If non-null, any history records matching this token will be skipped.
374      * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
375      *
376      * @return Returns the HistoryRecord of the next activity on the stack.
377      */
topRunningActivityLocked(IBinder token, int taskId)378     final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) {
379         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
380             TaskRecord task = mTaskHistory.get(taskNdx);
381             if (task.taskId == taskId) {
382                 continue;
383             }
384             ArrayList<ActivityRecord> activities = task.mActivities;
385             for (int i = activities.size() - 1; i >= 0; --i) {
386                 final ActivityRecord r = activities.get(i);
387                 // Note: the taskId check depends on real taskId fields being non-zero
388                 if (!r.finishing && (token != r.appToken) && okToShow(r)) {
389                     return r;
390                 }
391             }
392         }
393         return null;
394     }
395 
topActivity()396     final ActivityRecord topActivity() {
397         // Iterate to find the first non-empty task stack. Note that this code can
398         // be simplified once we stop storing tasks with empty mActivities lists.
399         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
400             ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
401             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
402                 return activities.get(activityNdx);
403             }
404         }
405         return null;
406     }
407 
topTask()408     final TaskRecord topTask() {
409         final int size = mTaskHistory.size();
410         if (size > 0) {
411             return mTaskHistory.get(size - 1);
412         }
413         return null;
414     }
415 
taskForIdLocked(int id)416     TaskRecord taskForIdLocked(int id) {
417         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
418             final TaskRecord task = mTaskHistory.get(taskNdx);
419             if (task.taskId == id) {
420                 return task;
421             }
422         }
423         return null;
424     }
425 
isInStackLocked(IBinder token)426     ActivityRecord isInStackLocked(IBinder token) {
427         final ActivityRecord r = ActivityRecord.forToken(token);
428         if (r != null) {
429             final TaskRecord task = r.task;
430             if (task.mActivities.contains(r) && mTaskHistory.contains(task)) {
431                 if (task.stack != this) Slog.w(TAG,
432                     "Illegal state! task does not point to stack it is in.");
433                 return r;
434             }
435         }
436         return null;
437     }
438 
containsApp(ProcessRecord app)439     boolean containsApp(ProcessRecord app) {
440         if (app == null) {
441             return false;
442         }
443         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
444             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
445             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
446                 final ActivityRecord r = activities.get(activityNdx);
447                 if (r.finishing) {
448                     continue;
449                 }
450                 if (r.app == app) {
451                     return true;
452                 }
453             }
454         }
455         return false;
456     }
457 
updateLRUListLocked(ActivityRecord r)458     final boolean updateLRUListLocked(ActivityRecord r) {
459         final boolean hadit = mLRUActivities.remove(r);
460         mLRUActivities.add(r);
461         return hadit;
462     }
463 
isHomeStack()464     final boolean isHomeStack() {
465         return mStackId == HOME_STACK_ID;
466     }
467 
468     /**
469      * Returns the top activity in any existing task matching the given
470      * Intent.  Returns null if no such task is found.
471      */
findTaskLocked(ActivityRecord target)472     ActivityRecord findTaskLocked(ActivityRecord target) {
473         Intent intent = target.intent;
474         ActivityInfo info = target.info;
475         ComponentName cls = intent.getComponent();
476         if (info.targetActivity != null) {
477             cls = new ComponentName(info.packageName, info.targetActivity);
478         }
479         final int userId = UserHandle.getUserId(info.applicationInfo.uid);
480 
481         if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + target + " in " + this);
482         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
483             final TaskRecord task = mTaskHistory.get(taskNdx);
484             if (task.userId != userId) {
485                 // Looking for a different task.
486                 if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": different user");
487                 continue;
488             }
489             final ActivityRecord r = task.getTopActivity();
490             if (r == null || r.finishing || r.userId != userId ||
491                     r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
492                 if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": mismatch root " + r);
493                 continue;
494             }
495 
496             if (DEBUG_TASKS) Slog.d(TAG, "Comparing existing cls="
497                     + r.task.intent.getComponent().flattenToShortString()
498                     + "/aff=" + r.task.affinity + " to new cls="
499                     + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
500             if (task.affinity != null) {
501                 if (task.affinity.equals(info.taskAffinity)) {
502                     if (DEBUG_TASKS) Slog.d(TAG, "Found matching affinity!");
503                     return r;
504                 }
505             } else if (task.intent != null && task.intent.getComponent().equals(cls)) {
506                 if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
507                 //dump();
508                 if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
509                         + r.intent);
510                 return r;
511             } else if (task.affinityIntent != null
512                     && task.affinityIntent.getComponent().equals(cls)) {
513                 if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
514                 //dump();
515                 if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
516                         + r.intent);
517                 return r;
518             } else if (DEBUG_TASKS) {
519                 Slog.d(TAG, "Not a match: " + task);
520             }
521         }
522 
523         return null;
524     }
525 
526     /**
527      * Returns the first activity (starting from the top of the stack) that
528      * is the same as the given activity.  Returns null if no such activity
529      * is found.
530      */
findActivityLocked(Intent intent, ActivityInfo info)531     ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
532         ComponentName cls = intent.getComponent();
533         if (info.targetActivity != null) {
534             cls = new ComponentName(info.packageName, info.targetActivity);
535         }
536         final int userId = UserHandle.getUserId(info.applicationInfo.uid);
537 
538         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
539             TaskRecord task = mTaskHistory.get(taskNdx);
540             if (task.userId != mCurrentUser) {
541                 return null;
542             }
543             final ArrayList<ActivityRecord> activities = task.mActivities;
544             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
545                 ActivityRecord r = activities.get(activityNdx);
546                 if (!r.finishing && r.intent.getComponent().equals(cls) && r.userId == userId) {
547                     //Slog.i(TAG, "Found matching class!");
548                     //dump();
549                     //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
550                     return r;
551                 }
552             }
553         }
554 
555         return null;
556     }
557 
558     /*
559      * Move the activities around in the stack to bring a user to the foreground.
560      */
switchUserLocked(int userId)561     final void switchUserLocked(int userId) {
562         if (mCurrentUser == userId) {
563             return;
564         }
565         mCurrentUser = userId;
566 
567         // Move userId's tasks to the top.
568         int index = mTaskHistory.size();
569         for (int i = 0; i < index; ) {
570             TaskRecord task = mTaskHistory.get(i);
571             if (task.userId == userId) {
572                 if (DEBUG_TASKS) Slog.d(TAG, "switchUserLocked: stack=" + getStackId() +
573                         " moving " + task + " to top");
574                 mTaskHistory.remove(i);
575                 mTaskHistory.add(task);
576                 --index;
577                 // Use same value for i.
578             } else {
579                 ++i;
580             }
581         }
582         if (VALIDATE_TOKENS) {
583             validateAppTokensLocked();
584         }
585     }
586 
minimalResumeActivityLocked(ActivityRecord r)587     void minimalResumeActivityLocked(ActivityRecord r) {
588         r.state = ActivityState.RESUMED;
589         if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + r
590                 + " (starting new instance)");
591         r.stopped = false;
592         mResumedActivity = r;
593         r.task.touchActiveTime();
594         mService.addRecentTaskLocked(r.task);
595         completeResumeLocked(r);
596         mStackSupervisor.checkReadyForSleepLocked();
597         setLaunchTime(r);
598         if (DEBUG_SAVED_STATE) Slog.i(TAG, "Launch completed; removing icicle of " + r.icicle);
599     }
600 
startLaunchTraces()601     private void startLaunchTraces() {
602         if (mFullyDrawnStartTime != 0)  {
603             Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
604         }
605         Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching", 0);
606         Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
607     }
608 
stopFullyDrawnTraceIfNeeded()609     private void stopFullyDrawnTraceIfNeeded() {
610         if (mFullyDrawnStartTime != 0 && mLaunchStartTime == 0) {
611             Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
612             mFullyDrawnStartTime = 0;
613         }
614     }
615 
setLaunchTime(ActivityRecord r)616     void setLaunchTime(ActivityRecord r) {
617         if (r.displayStartTime == 0) {
618             r.fullyDrawnStartTime = r.displayStartTime = SystemClock.uptimeMillis();
619             if (mLaunchStartTime == 0) {
620                 startLaunchTraces();
621                 mLaunchStartTime = mFullyDrawnStartTime = r.displayStartTime;
622             }
623         } else if (mLaunchStartTime == 0) {
624             startLaunchTraces();
625             mLaunchStartTime = mFullyDrawnStartTime = SystemClock.uptimeMillis();
626         }
627     }
628 
clearLaunchTime(ActivityRecord r)629     void clearLaunchTime(ActivityRecord r) {
630         // Make sure that there is no activity waiting for this to launch.
631         if (mStackSupervisor.mWaitingActivityLaunched.isEmpty()) {
632             r.displayStartTime = r.fullyDrawnStartTime = 0;
633         } else {
634             mStackSupervisor.removeTimeoutsForActivityLocked(r);
635             mStackSupervisor.scheduleIdleTimeoutLocked(r);
636         }
637     }
638 
awakeFromSleepingLocked()639     void awakeFromSleepingLocked() {
640         // Ensure activities are no longer sleeping.
641         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
642             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
643             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
644                 activities.get(activityNdx).setSleeping(false);
645             }
646         }
647     }
648 
649     /**
650      * @return true if something must be done before going to sleep.
651      */
checkReadyForSleepLocked()652     boolean checkReadyForSleepLocked() {
653         if (mResumedActivity != null) {
654             // Still have something resumed; can't sleep until it is paused.
655             if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause " + mResumedActivity);
656             if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
657             startPausingLocked(false, true);
658             return true;
659         }
660         if (mPausingActivity != null) {
661             // Still waiting for something to pause; can't sleep yet.
662             if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still waiting to pause " + mPausingActivity);
663             return true;
664         }
665 
666         return false;
667     }
668 
goToSleep()669     void goToSleep() {
670         ensureActivitiesVisibleLocked(null, 0);
671 
672         // Make sure any stopped but visible activities are now sleeping.
673         // This ensures that the activity's onStop() is called.
674         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
675             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
676             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
677                 final ActivityRecord r = activities.get(activityNdx);
678                 if (r.state == ActivityState.STOPPING || r.state == ActivityState.STOPPED) {
679                     r.setSleeping(true);
680                 }
681             }
682         }
683     }
684 
screenshotActivities(ActivityRecord who)685     public final Bitmap screenshotActivities(ActivityRecord who) {
686         if (who.noDisplay) {
687             return null;
688         }
689 
690         TaskRecord tr = who.task;
691         if (mService.getMostRecentTask() != tr && tr.intent != null &&
692                 (tr.intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0) {
693             // If this task is being excluded from recents, we don't want to take
694             // the expense of capturing a thumbnail, since we will never show it.
695             return null;
696         }
697 
698         Resources res = mService.mContext.getResources();
699         int w = mThumbnailWidth;
700         int h = mThumbnailHeight;
701         if (w < 0) {
702             mThumbnailWidth = w =
703                 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
704             mThumbnailHeight = h =
705                 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
706         }
707 
708         if (w > 0) {
709             if (who != mLastScreenshotActivity || mLastScreenshotBitmap == null
710                     || mLastScreenshotActivity.state == ActivityState.RESUMED
711                     || mLastScreenshotBitmap.getWidth() != w
712                     || mLastScreenshotBitmap.getHeight() != h) {
713                 mLastScreenshotActivity = who;
714                 mLastScreenshotBitmap = mWindowManager.screenshotApplications(
715                         who.appToken, Display.DEFAULT_DISPLAY, w, h, SCREENSHOT_FORCE_565);
716             }
717             if (mLastScreenshotBitmap != null) {
718                 return mLastScreenshotBitmap.copy(mLastScreenshotBitmap.getConfig(), true);
719             }
720         }
721         return null;
722     }
723 
startPausingLocked(boolean userLeaving, boolean uiSleeping)724     final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
725         if (mPausingActivity != null) {
726             Slog.e(TAG, "Trying to pause when pause is already pending for "
727                   + mPausingActivity, new RuntimeException("here").fillInStackTrace());
728         }
729         ActivityRecord prev = mResumedActivity;
730         if (prev == null) {
731             Slog.e(TAG, "Trying to pause when nothing is resumed",
732                     new RuntimeException("here").fillInStackTrace());
733             mStackSupervisor.resumeTopActivitiesLocked();
734             return;
735         }
736         if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev);
737         else if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
738         mResumedActivity = null;
739         mPausingActivity = prev;
740         mLastPausedActivity = prev;
741         mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
742                 || (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
743         prev.state = ActivityState.PAUSING;
744         prev.task.touchActiveTime();
745         clearLaunchTime(prev);
746         final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
747         if (next == null || next.task != prev.task) {
748             prev.updateThumbnail(screenshotActivities(prev), null);
749         }
750         stopFullyDrawnTraceIfNeeded();
751 
752         mService.updateCpuStats();
753 
754         if (prev.app != null && prev.app.thread != null) {
755             if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
756             try {
757                 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
758                         prev.userId, System.identityHashCode(prev),
759                         prev.shortComponentName);
760                 mService.updateUsageStats(prev, false);
761                 prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
762                         userLeaving, prev.configChangeFlags);
763             } catch (Exception e) {
764                 // Ignore exception, if process died other code will cleanup.
765                 Slog.w(TAG, "Exception thrown during pause", e);
766                 mPausingActivity = null;
767                 mLastPausedActivity = null;
768                 mLastNoHistoryActivity = null;
769             }
770         } else {
771             mPausingActivity = null;
772             mLastPausedActivity = null;
773             mLastNoHistoryActivity = null;
774         }
775 
776         // If we are not going to sleep, we want to ensure the device is
777         // awake until the next activity is started.
778         if (!mService.isSleepingOrShuttingDown()) {
779             mStackSupervisor.acquireLaunchWakelock();
780         }
781 
782         if (mPausingActivity != null) {
783             // Have the window manager pause its key dispatching until the new
784             // activity has started.  If we're pausing the activity just because
785             // the screen is being turned off and the UI is sleeping, don't interrupt
786             // key dispatch; the same activity will pick it up again on wakeup.
787             if (!uiSleeping) {
788                 prev.pauseKeyDispatchingLocked();
789             } else {
790                 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
791             }
792 
793             // Schedule a pause timeout in case the app doesn't respond.
794             // We don't give it much time because this directly impacts the
795             // responsiveness seen by the user.
796             Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
797             msg.obj = prev;
798             prev.pauseTime = SystemClock.uptimeMillis();
799             mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
800             if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
801         } else {
802             // This activity failed to schedule the
803             // pause, so just treat it as being paused now.
804             if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
805             mStackSupervisor.getFocusedStack().resumeTopActivityLocked(null);
806         }
807     }
808 
activityPausedLocked(IBinder token, boolean timeout)809     final void activityPausedLocked(IBinder token, boolean timeout) {
810         if (DEBUG_PAUSE) Slog.v(
811             TAG, "Activity paused: token=" + token + ", timeout=" + timeout);
812 
813         final ActivityRecord r = isInStackLocked(token);
814         if (r != null) {
815             mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
816             if (mPausingActivity == r) {
817                 if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r
818                         + (timeout ? " (due to timeout)" : " (pause complete)"));
819                 r.state = ActivityState.PAUSED;
820                 completePauseLocked();
821             } else {
822                 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
823                         r.userId, System.identityHashCode(r), r.shortComponentName,
824                         mPausingActivity != null
825                             ? mPausingActivity.shortComponentName : "(none)");
826             }
827         }
828     }
829 
activityStoppedLocked(ActivityRecord r, Bundle icicle, Bitmap thumbnail, CharSequence description)830     final void activityStoppedLocked(ActivityRecord r, Bundle icicle, Bitmap thumbnail,
831             CharSequence description) {
832         if (r.state != ActivityState.STOPPING) {
833             Slog.i(TAG, "Activity reported stop, but no longer stopping: " + r);
834             mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
835             return;
836         }
837         if (DEBUG_SAVED_STATE) Slog.i(TAG, "Saving icicle of " + r + ": " + icicle);
838         if (icicle != null) {
839             // If icicle is null, this is happening due to a timeout, so we
840             // haven't really saved the state.
841             r.icicle = icicle;
842             r.haveState = true;
843             r.launchCount = 0;
844             r.updateThumbnail(thumbnail, description);
845         }
846         if (!r.stopped) {
847             if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r + " (stop complete)");
848             mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
849             r.stopped = true;
850             r.state = ActivityState.STOPPED;
851             if (r.finishing) {
852                 r.clearOptionsLocked();
853             } else {
854                 if (r.configDestroy) {
855                     destroyActivityLocked(r, true, false, "stop-config");
856                     mStackSupervisor.resumeTopActivitiesLocked();
857                 } else {
858                     mStackSupervisor.updatePreviousProcessLocked(r);
859                 }
860             }
861         }
862     }
863 
completePauseLocked()864     private void completePauseLocked() {
865         ActivityRecord prev = mPausingActivity;
866         if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
867 
868         if (prev != null) {
869             if (prev.finishing) {
870                 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
871                 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false);
872             } else if (prev.app != null) {
873                 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
874                 if (prev.waitingVisible) {
875                     prev.waitingVisible = false;
876                     mStackSupervisor.mWaitingVisibleActivities.remove(prev);
877                     if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
878                             TAG, "Complete pause, no longer waiting: " + prev);
879                 }
880                 if (prev.configDestroy) {
881                     // The previous is being paused because the configuration
882                     // is changing, which means it is actually stopping...
883                     // To juggle the fact that we are also starting a new
884                     // instance right now, we need to first completely stop
885                     // the current instance before starting the new one.
886                     if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
887                     destroyActivityLocked(prev, true, false, "pause-config");
888                 } else {
889                     mStackSupervisor.mStoppingActivities.add(prev);
890                     if (mStackSupervisor.mStoppingActivities.size() > 3 ||
891                             prev.frontOfTask && mTaskHistory.size() <= 1) {
892                         // If we already have a few activities waiting to stop,
893                         // then give up on things going idle and start clearing
894                         // them out. Or if r is the last of activity of the last task the stack
895                         // will be empty and must be cleared immediately.
896                         if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
897                         mStackSupervisor.scheduleIdleLocked();
898                     } else {
899                         mStackSupervisor.checkReadyForSleepLocked();
900                     }
901                 }
902             } else {
903                 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
904                 prev = null;
905             }
906             mPausingActivity = null;
907         }
908 
909         final ActivityStack topStack = mStackSupervisor.getFocusedStack();
910         if (!mService.isSleepingOrShuttingDown()) {
911             mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);
912         } else {
913             mStackSupervisor.checkReadyForSleepLocked();
914             ActivityRecord top = topStack.topRunningActivityLocked(null);
915             if (top == null || (prev != null && top != prev)) {
916                 // If there are no more activities available to run,
917                 // do resume anyway to start something.  Also if the top
918                 // activity on the stack is not the just paused activity,
919                 // we need to go ahead and resume it to ensure we complete
920                 // an in-flight app switch.
921                 mStackSupervisor.resumeTopActivitiesLocked(topStack, null, null);
922             }
923         }
924 
925         if (prev != null) {
926             prev.resumeKeyDispatchingLocked();
927 
928             if (prev.app != null && prev.cpuTimeAtResume > 0
929                     && mService.mBatteryStatsService.isOnBattery()) {
930                 long diff;
931                 synchronized (mService.mProcessCpuThread) {
932                     diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid)
933                             - prev.cpuTimeAtResume;
934                 }
935                 if (diff > 0) {
936                     BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics();
937                     synchronized (bsi) {
938                         BatteryStatsImpl.Uid.Proc ps =
939                                 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
940                                         prev.info.packageName);
941                         if (ps != null) {
942                             ps.addForegroundTimeLocked(diff);
943                         }
944                     }
945                 }
946             }
947             prev.cpuTimeAtResume = 0; // reset it
948         }
949     }
950 
951     /**
952      * Once we know that we have asked an application to put an activity in
953      * the resumed state (either by launching it or explicitly telling it),
954      * this function updates the rest of our state to match that fact.
955      */
completeResumeLocked(ActivityRecord next)956     private void completeResumeLocked(ActivityRecord next) {
957         next.idle = false;
958         next.results = null;
959         next.newIntents = null;
960         if (next.nowVisible) {
961             // We won't get a call to reportActivityVisibleLocked() so dismiss lockscreen now.
962             mStackSupervisor.dismissKeyguard();
963         }
964 
965         // schedule an idle timeout in case the app doesn't do it for us.
966         mStackSupervisor.scheduleIdleTimeoutLocked(next);
967 
968         mStackSupervisor.reportResumedActivityLocked(next);
969 
970         next.resumeKeyDispatchingLocked();
971         mNoAnimActivities.clear();
972 
973         // Mark the point when the activity is resuming
974         // TODO: To be more accurate, the mark should be before the onCreate,
975         //       not after the onResume. But for subsequent starts, onResume is fine.
976         if (next.app != null) {
977             synchronized (mService.mProcessCpuThread) {
978                 next.cpuTimeAtResume = mService.mProcessCpuTracker.getCpuTimeForPid(next.app.pid);
979             }
980         } else {
981             next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
982         }
983     }
984 
985     /**
986      * Determine if home should be visible below the passed record.
987      * @param record activity we are querying for.
988      * @return true if home is visible below the passed activity, false otherwise.
989      */
isActivityOverHome(ActivityRecord record)990     boolean isActivityOverHome(ActivityRecord record) {
991         // Start at record and go down, look for either home or a visible fullscreen activity.
992         final TaskRecord recordTask = record.task;
993         for (int taskNdx = mTaskHistory.indexOf(recordTask); taskNdx >= 0; --taskNdx) {
994             TaskRecord task = mTaskHistory.get(taskNdx);
995             final ArrayList<ActivityRecord> activities = task.mActivities;
996             final int startNdx =
997                     task == recordTask ? activities.indexOf(record) : activities.size() - 1;
998             for (int activityNdx = startNdx; activityNdx >= 0; --activityNdx) {
999                 final ActivityRecord r = activities.get(activityNdx);
1000                 if (r.isHomeActivity()) {
1001                     return true;
1002                 }
1003                 if (!r.finishing && r.fullscreen) {
1004                     // Passed activity is over a fullscreen activity.
1005                     return false;
1006                 }
1007             }
1008             if (task.mOnTopOfHome) {
1009                 // Got to the bottom of a task on top of home without finding a visible fullscreen
1010                 // activity. Home is visible.
1011                 return true;
1012             }
1013         }
1014         // Got to the bottom of this stack and still don't know. If this is over the home stack
1015         // then record is over home. May not work if we ever get more than two layers.
1016         return mStackSupervisor.isFrontStack(this);
1017     }
1018 
1019     /**
1020      * Version of ensureActivitiesVisible that can easily be called anywhere.
1021      */
ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges)1022     final boolean ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
1023         return ensureActivitiesVisibleLocked(starting, configChanges, false);
1024     }
1025 
ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges, boolean forceHomeShown)1026     final boolean ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
1027             boolean forceHomeShown) {
1028         ActivityRecord r = topRunningActivityLocked(null);
1029         return r != null &&
1030                 ensureActivitiesVisibleLocked(r, starting, null, configChanges, forceHomeShown);
1031     }
1032 
1033     /**
1034      * Make sure that all activities that need to be visible (that is, they
1035      * currently can be seen by the user) actually are.
1036      */
ensureActivitiesVisibleLocked(ActivityRecord top, ActivityRecord starting, String onlyThisProcess, int configChanges, boolean forceHomeShown)1037     final boolean ensureActivitiesVisibleLocked(ActivityRecord top, ActivityRecord starting,
1038             String onlyThisProcess, int configChanges, boolean forceHomeShown) {
1039         if (DEBUG_VISBILITY) Slog.v(
1040                 TAG, "ensureActivitiesVisible behind " + top
1041                 + " configChanges=0x" + Integer.toHexString(configChanges));
1042 
1043         if (mTranslucentActivityWaiting != top) {
1044             mUndrawnActivitiesBelowTopTranslucent.clear();
1045             if (mTranslucentActivityWaiting != null) {
1046                 // Call the callback with a timeout indication.
1047                 notifyActivityDrawnLocked(null);
1048                 mTranslucentActivityWaiting = null;
1049             }
1050             mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG);
1051         }
1052 
1053         // If the top activity is not fullscreen, then we need to
1054         // make sure any activities under it are now visible.
1055         boolean aboveTop = true;
1056         boolean showHomeBehindStack = false;
1057         boolean behindFullscreen = !mStackSupervisor.isFrontStack(this) &&
1058                 !(forceHomeShown && isHomeStack());
1059         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1060             final TaskRecord task = mTaskHistory.get(taskNdx);
1061             final ArrayList<ActivityRecord> activities = task.mActivities;
1062             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1063                 final ActivityRecord r = activities.get(activityNdx);
1064                 if (r.finishing) {
1065                     continue;
1066                 }
1067                 if (aboveTop && r != top) {
1068                     continue;
1069                 }
1070                 aboveTop = false;
1071                 if (!behindFullscreen) {
1072                     if (DEBUG_VISBILITY) Slog.v(
1073                             TAG, "Make visible? " + r + " finishing=" + r.finishing
1074                             + " state=" + r.state);
1075 
1076                     final boolean doThisProcess = onlyThisProcess == null
1077                             || onlyThisProcess.equals(r.processName);
1078 
1079                     // First: if this is not the current activity being started, make
1080                     // sure it matches the current configuration.
1081                     if (r != starting && doThisProcess) {
1082                         ensureActivityConfigurationLocked(r, 0);
1083                     }
1084 
1085                     if (r.app == null || r.app.thread == null) {
1086                         if (onlyThisProcess == null || onlyThisProcess.equals(r.processName)) {
1087                             // This activity needs to be visible, but isn't even
1088                             // running...  get it started, but don't resume it
1089                             // at this point.
1090                             if (DEBUG_VISBILITY) Slog.v(TAG, "Start and freeze screen for " + r);
1091                             if (r != starting) {
1092                                 r.startFreezingScreenLocked(r.app, configChanges);
1093                             }
1094                             if (!r.visible) {
1095                                 if (DEBUG_VISBILITY) Slog.v(
1096                                         TAG, "Starting and making visible: " + r);
1097                                 r.visible = true;
1098                                 mWindowManager.setAppVisibility(r.appToken, true);
1099                             }
1100                             if (r != starting) {
1101                                 mStackSupervisor.startSpecificActivityLocked(r, false, false);
1102                             }
1103                         }
1104 
1105                     } else if (r.visible) {
1106                         // If this activity is already visible, then there is nothing
1107                         // else to do here.
1108                         if (DEBUG_VISBILITY) Slog.v(TAG, "Skipping: already visible at " + r);
1109                         r.stopFreezingScreenLocked(false);
1110 
1111                     } else if (onlyThisProcess == null) {
1112                         // This activity is not currently visible, but is running.
1113                         // Tell it to become visible.
1114                         r.visible = true;
1115                         if (r.state != ActivityState.RESUMED && r != starting) {
1116                             // If this activity is paused, tell it
1117                             // to now show its window.
1118                             if (DEBUG_VISBILITY) Slog.v(
1119                                     TAG, "Making visible and scheduling visibility: " + r);
1120                             try {
1121                                 if (mTranslucentActivityWaiting != null) {
1122                                     mUndrawnActivitiesBelowTopTranslucent.add(r);
1123                                 }
1124                                 mWindowManager.setAppVisibility(r.appToken, true);
1125                                 r.sleeping = false;
1126                                 r.app.pendingUiClean = true;
1127                                 r.app.thread.scheduleWindowVisibility(r.appToken, true);
1128                                 r.stopFreezingScreenLocked(false);
1129                             } catch (Exception e) {
1130                                 // Just skip on any failure; we'll make it
1131                                 // visible when it next restarts.
1132                                 Slog.w(TAG, "Exception thrown making visibile: "
1133                                         + r.intent.getComponent(), e);
1134                             }
1135                         }
1136                     }
1137 
1138                     // Aggregate current change flags.
1139                     configChanges |= r.configChangeFlags;
1140 
1141                     if (r.fullscreen) {
1142                         // At this point, nothing else needs to be shown
1143                         if (DEBUG_VISBILITY) Slog.v(TAG, "Fullscreen: at " + r);
1144                         behindFullscreen = true;
1145                     } else if (isActivityOverHome(r)) {
1146                         if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r);
1147                         showHomeBehindStack = true;
1148                         behindFullscreen = !isHomeStack();
1149                     }
1150                 } else {
1151                     if (DEBUG_VISBILITY) Slog.v(
1152                         TAG, "Make invisible? " + r + " finishing=" + r.finishing
1153                         + " state=" + r.state
1154                         + " behindFullscreen=" + behindFullscreen);
1155                     // Now for any activities that aren't visible to the user, make
1156                     // sure they no longer are keeping the screen frozen.
1157                     if (r.visible) {
1158                         if (DEBUG_VISBILITY) Slog.v(TAG, "Making invisible: " + r);
1159                         r.visible = false;
1160                         try {
1161                             mWindowManager.setAppVisibility(r.appToken, false);
1162                             switch (r.state) {
1163                                 case STOPPING:
1164                                 case STOPPED:
1165                                     if (r.app != null && r.app.thread != null) {
1166                                         if (DEBUG_VISBILITY) Slog.v(
1167                                                 TAG, "Scheduling invisibility: " + r);
1168                                         r.app.thread.scheduleWindowVisibility(r.appToken, false);
1169                                     }
1170                                     break;
1171 
1172                                 case INITIALIZING:
1173                                 case RESUMED:
1174                                 case PAUSING:
1175                                 case PAUSED:
1176                                     // This case created for transitioning activities from
1177                                     // translucent to opaque {@link Activity#convertToOpaque}.
1178                                     if (!mStackSupervisor.mStoppingActivities.contains(r)) {
1179                                         mStackSupervisor.mStoppingActivities.add(r);
1180                                     }
1181                                     mStackSupervisor.scheduleIdleLocked();
1182                                     break;
1183 
1184                                 default:
1185                                     break;
1186                             }
1187                         } catch (Exception e) {
1188                             // Just skip on any failure; we'll make it
1189                             // visible when it next restarts.
1190                             Slog.w(TAG, "Exception thrown making hidden: "
1191                                     + r.intent.getComponent(), e);
1192                         }
1193                     } else {
1194                         if (DEBUG_VISBILITY) Slog.v(TAG, "Already invisible: " + r);
1195                     }
1196                 }
1197             }
1198         }
1199         return showHomeBehindStack;
1200     }
1201 
convertToTranslucent(ActivityRecord r)1202     void convertToTranslucent(ActivityRecord r) {
1203         mTranslucentActivityWaiting = r;
1204         mUndrawnActivitiesBelowTopTranslucent.clear();
1205         mHandler.sendEmptyMessageDelayed(TRANSLUCENT_TIMEOUT_MSG, TRANSLUCENT_CONVERSION_TIMEOUT);
1206     }
1207 
1208     /**
1209      * Called as activities below the top translucent activity are redrawn. When the last one is
1210      * redrawn notify the top activity by calling
1211      * {@link Activity#onTranslucentConversionComplete}.
1212      *
1213      * @param r The most recent background activity to be drawn. Or, if r is null then a timeout
1214      * occurred and the activity will be notified immediately.
1215      */
notifyActivityDrawnLocked(ActivityRecord r)1216     void notifyActivityDrawnLocked(ActivityRecord r) {
1217         if ((r == null)
1218                 || (mUndrawnActivitiesBelowTopTranslucent.remove(r) &&
1219                         mUndrawnActivitiesBelowTopTranslucent.isEmpty())) {
1220             // The last undrawn activity below the top has just been drawn. If there is an
1221             // opaque activity at the top, notify it that it can become translucent safely now.
1222             final ActivityRecord waitingActivity = mTranslucentActivityWaiting;
1223             mTranslucentActivityWaiting = null;
1224             mUndrawnActivitiesBelowTopTranslucent.clear();
1225             mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG);
1226 
1227             if (waitingActivity != null && waitingActivity.app != null &&
1228                     waitingActivity.app.thread != null) {
1229                 try {
1230                     waitingActivity.app.thread.scheduleTranslucentConversionComplete(
1231                             waitingActivity.appToken, r != null);
1232                 } catch (RemoteException e) {
1233                 }
1234             }
1235         }
1236     }
1237 
1238     /**
1239      * Ensure that the top activity in the stack is resumed.
1240      *
1241      * @param prev The previously resumed activity, for when in the process
1242      * of pausing; can be null to call from elsewhere.
1243      *
1244      * @return Returns true if something is being resumed, or false if
1245      * nothing happened.
1246      */
resumeTopActivityLocked(ActivityRecord prev)1247     final boolean resumeTopActivityLocked(ActivityRecord prev) {
1248         return resumeTopActivityLocked(prev, null);
1249     }
1250 
resumeTopActivityLocked(ActivityRecord prev, Bundle options)1251     final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
1252         if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
1253 
1254         // Find the first activity that is not finishing.
1255         ActivityRecord next = topRunningActivityLocked(null);
1256 
1257         // Remember how we'll process this pause/resume situation, and ensure
1258         // that the state is reset however we wind up proceeding.
1259         final boolean userLeaving = mStackSupervisor.mUserLeaving;
1260         mStackSupervisor.mUserLeaving = false;
1261 
1262         if (next == null) {
1263             // There are no more activities!  Let's just start up the
1264             // Launcher...
1265             ActivityOptions.abort(options);
1266             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
1267             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1268             return mStackSupervisor.resumeHomeActivity(prev);
1269         }
1270 
1271         next.delayedResume = false;
1272 
1273         // If the top activity is the resumed one, nothing to do.
1274         if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
1275                     mStackSupervisor.allResumedActivitiesComplete()) {
1276             // Make sure we have executed any pending transitions, since there
1277             // should be nothing left to do at this point.
1278             mWindowManager.executeAppTransition();
1279             mNoAnimActivities.clear();
1280             ActivityOptions.abort(options);
1281             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Top activity resumed " + next);
1282             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1283             return false;
1284         }
1285 
1286         final TaskRecord nextTask = next.task;
1287         final TaskRecord prevTask = prev != null ? prev.task : null;
1288         if (prevTask != null && prevTask.mOnTopOfHome && prev.finishing && prev.frontOfTask) {
1289             if (DEBUG_STACK)  mStackSupervisor.validateTopActivitiesLocked();
1290             if (prevTask == nextTask) {
1291                 prevTask.setFrontOfTask();
1292             } else if (prevTask != topTask()) {
1293                 // This task is going away but it was supposed to return to the home task.
1294                 // Now the task above it has to return to the home task instead.
1295                 final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
1296                 mTaskHistory.get(taskNdx).mOnTopOfHome = true;
1297             } else {
1298                 if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Launching home next");
1299                 return mStackSupervisor.resumeHomeActivity(prev);
1300             }
1301         }
1302 
1303         // If we are sleeping, and there is no resumed activity, and the top
1304         // activity is paused, well that is the state we want.
1305         if (mService.isSleepingOrShuttingDown()
1306                 && mLastPausedActivity == next
1307                 && mStackSupervisor.allPausedActivitiesComplete()) {
1308             // Make sure we have executed any pending transitions, since there
1309             // should be nothing left to do at this point.
1310             mWindowManager.executeAppTransition();
1311             mNoAnimActivities.clear();
1312             ActivityOptions.abort(options);
1313             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Going to sleep and all paused");
1314             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1315             return false;
1316         }
1317 
1318         // Make sure that the user who owns this activity is started.  If not,
1319         // we will just leave it as is because someone should be bringing
1320         // another user's activities to the top of the stack.
1321         if (mService.mStartedUsers.get(next.userId) == null) {
1322             Slog.w(TAG, "Skipping resume of top activity " + next
1323                     + ": user " + next.userId + " is stopped");
1324             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1325             return false;
1326         }
1327 
1328         // The activity may be waiting for stop, but that is no longer
1329         // appropriate for it.
1330         mStackSupervisor.mStoppingActivities.remove(next);
1331         mStackSupervisor.mGoingToSleepActivities.remove(next);
1332         next.sleeping = false;
1333         mStackSupervisor.mWaitingVisibleActivities.remove(next);
1334 
1335         next.updateOptionsLocked(options);
1336 
1337         if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
1338 
1339         // If we are currently pausing an activity, then don't do anything
1340         // until that is done.
1341         if (!mStackSupervisor.allPausedActivitiesComplete()) {
1342             if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG,
1343                     "resumeTopActivityLocked: Skip resume: some activity pausing.");
1344             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1345             return false;
1346         }
1347 
1348         // Okay we are now going to start a switch, to 'next'.  We may first
1349         // have to pause the current activity, but this is an important point
1350         // where we have decided to go to 'next' so keep track of that.
1351         // XXX "App Redirected" dialog is getting too many false positives
1352         // at this point, so turn off for now.
1353         if (false) {
1354             if (mLastStartedActivity != null && !mLastStartedActivity.finishing) {
1355                 long now = SystemClock.uptimeMillis();
1356                 final boolean inTime = mLastStartedActivity.startTime != 0
1357                         && (mLastStartedActivity.startTime + START_WARN_TIME) >= now;
1358                 final int lastUid = mLastStartedActivity.info.applicationInfo.uid;
1359                 final int nextUid = next.info.applicationInfo.uid;
1360                 if (inTime && lastUid != nextUid
1361                         && lastUid != next.launchedFromUid
1362                         && mService.checkPermission(
1363                                 android.Manifest.permission.STOP_APP_SWITCHES,
1364                                 -1, next.launchedFromUid)
1365                         != PackageManager.PERMISSION_GRANTED) {
1366                     mService.showLaunchWarningLocked(mLastStartedActivity, next);
1367                 } else {
1368                     next.startTime = now;
1369                     mLastStartedActivity = next;
1370                 }
1371             } else {
1372                 next.startTime = SystemClock.uptimeMillis();
1373                 mLastStartedActivity = next;
1374             }
1375         }
1376 
1377         // We need to start pausing the current activity so the top one
1378         // can be resumed...
1379         boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving);
1380         if (mResumedActivity != null) {
1381             pausing = true;
1382             startPausingLocked(userLeaving, false);
1383             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);
1384         }
1385         if (pausing) {
1386             if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG,
1387                     "resumeTopActivityLocked: Skip resume: need to start pausing");
1388             // At this point we want to put the upcoming activity's process
1389             // at the top of the LRU list, since we know we will be needing it
1390             // very soon and it would be a waste to let it get killed if it
1391             // happens to be sitting towards the end.
1392             if (next.app != null && next.app.thread != null) {
1393                 // No reason to do full oom adj update here; we'll let that
1394                 // happen whenever it needs to later.
1395                 mService.updateLruProcessLocked(next.app, true, null);
1396             }
1397             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1398             return true;
1399         }
1400 
1401         // If the most recent activity was noHistory but was only stopped rather
1402         // than stopped+finished because the device went to sleep, we need to make
1403         // sure to finish it as we're making a new activity topmost.
1404         if (mService.mSleeping && mLastNoHistoryActivity != null &&
1405                 !mLastNoHistoryActivity.finishing) {
1406             if (DEBUG_STATES) Slog.d(TAG, "no-history finish of " + mLastNoHistoryActivity +
1407                     " on new resume");
1408             requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
1409                     null, "no-history", false);
1410             mLastNoHistoryActivity = null;
1411         }
1412 
1413         if (prev != null && prev != next) {
1414             if (!prev.waitingVisible && next != null && !next.nowVisible) {
1415                 prev.waitingVisible = true;
1416                 mStackSupervisor.mWaitingVisibleActivities.add(prev);
1417                 if (DEBUG_SWITCH) Slog.v(
1418                         TAG, "Resuming top, waiting visible to hide: " + prev);
1419             } else {
1420                 // The next activity is already visible, so hide the previous
1421                 // activity's windows right now so we can show the new one ASAP.
1422                 // We only do this if the previous is finishing, which should mean
1423                 // it is on top of the one being resumed so hiding it quickly
1424                 // is good.  Otherwise, we want to do the normal route of allowing
1425                 // the resumed activity to be shown so we can decide if the
1426                 // previous should actually be hidden depending on whether the
1427                 // new one is found to be full-screen or not.
1428                 if (prev.finishing) {
1429                     mWindowManager.setAppVisibility(prev.appToken, false);
1430                     if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
1431                             + prev + ", waitingVisible="
1432                             + (prev != null ? prev.waitingVisible : null)
1433                             + ", nowVisible=" + next.nowVisible);
1434                 } else {
1435                     if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
1436                         + prev + ", waitingVisible="
1437                         + (prev != null ? prev.waitingVisible : null)
1438                         + ", nowVisible=" + next.nowVisible);
1439                 }
1440             }
1441         }
1442 
1443         // Launching this app's activity, make sure the app is no longer
1444         // considered stopped.
1445         try {
1446             AppGlobals.getPackageManager().setPackageStoppedState(
1447                     next.packageName, false, next.userId); /* TODO: Verify if correct userid */
1448         } catch (RemoteException e1) {
1449         } catch (IllegalArgumentException e) {
1450             Slog.w(TAG, "Failed trying to unstop package "
1451                     + next.packageName + ": " + e);
1452         }
1453 
1454         // We are starting up the next activity, so tell the window manager
1455         // that the previous one will be hidden soon.  This way it can know
1456         // to ignore it when computing the desired screen orientation.
1457         boolean anim = true;
1458         if (prev != null) {
1459             if (prev.finishing) {
1460                 if (DEBUG_TRANSITION) Slog.v(TAG,
1461                         "Prepare close transition: prev=" + prev);
1462                 if (mNoAnimActivities.contains(prev)) {
1463                     anim = false;
1464                     mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
1465                 } else {
1466                     mWindowManager.prepareAppTransition(prev.task == next.task
1467                             ? AppTransition.TRANSIT_ACTIVITY_CLOSE
1468                             : AppTransition.TRANSIT_TASK_CLOSE, false);
1469                 }
1470                 mWindowManager.setAppWillBeHidden(prev.appToken);
1471                 mWindowManager.setAppVisibility(prev.appToken, false);
1472             } else {
1473                 if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: prev=" + prev);
1474                 if (mNoAnimActivities.contains(next)) {
1475                     anim = false;
1476                     mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
1477                 } else {
1478                     mWindowManager.prepareAppTransition(prev.task == next.task
1479                             ? AppTransition.TRANSIT_ACTIVITY_OPEN
1480                             : AppTransition.TRANSIT_TASK_OPEN, false);
1481                 }
1482             }
1483             if (false) {
1484                 mWindowManager.setAppWillBeHidden(prev.appToken);
1485                 mWindowManager.setAppVisibility(prev.appToken, false);
1486             }
1487         } else {
1488             if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: no previous");
1489             if (mNoAnimActivities.contains(next)) {
1490                 anim = false;
1491                 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
1492             } else {
1493                 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_OPEN, false);
1494             }
1495         }
1496         if (anim) {
1497             next.applyOptionsLocked();
1498         } else {
1499             next.clearOptionsLocked();
1500         }
1501 
1502         ActivityStack lastStack = mStackSupervisor.getLastStack();
1503         if (next.app != null && next.app.thread != null) {
1504             if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
1505 
1506             // This activity is now becoming visible.
1507             mWindowManager.setAppVisibility(next.appToken, true);
1508 
1509             // schedule launch ticks to collect information about slow apps.
1510             next.startLaunchTickingLocked();
1511 
1512             ActivityRecord lastResumedActivity =
1513                     lastStack == null ? null :lastStack.mResumedActivity;
1514             ActivityState lastState = next.state;
1515 
1516             mService.updateCpuStats();
1517 
1518             if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + next + " (in existing)");
1519             next.state = ActivityState.RESUMED;
1520             mResumedActivity = next;
1521             next.task.touchActiveTime();
1522             mService.addRecentTaskLocked(next.task);
1523             mService.updateLruProcessLocked(next.app, true, null);
1524             updateLRUListLocked(next);
1525             mService.updateOomAdjLocked();
1526 
1527             // Have the window manager re-evaluate the orientation of
1528             // the screen based on the new activity order.
1529             boolean notUpdated = true;
1530             if (mStackSupervisor.isFrontStack(this)) {
1531                 Configuration config = mWindowManager.updateOrientationFromAppTokens(
1532                         mService.mConfiguration,
1533                         next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
1534                 if (config != null) {
1535                     next.frozenBeforeDestroy = true;
1536                 }
1537                 notUpdated = !mService.updateConfigurationLocked(config, next, false, false);
1538             }
1539 
1540             if (notUpdated) {
1541                 // The configuration update wasn't able to keep the existing
1542                 // instance of the activity, and instead started a new one.
1543                 // We should be all done, but let's just make sure our activity
1544                 // is still at the top and schedule another run if something
1545                 // weird happened.
1546                 ActivityRecord nextNext = topRunningActivityLocked(null);
1547                 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
1548                         "Activity config changed during resume: " + next
1549                         + ", new next: " + nextNext);
1550                 if (nextNext != next) {
1551                     // Do over!
1552                     mStackSupervisor.scheduleResumeTopActivities();
1553                 }
1554                 if (mStackSupervisor.reportResumedActivityLocked(next)) {
1555                     mNoAnimActivities.clear();
1556                     if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1557                     return true;
1558                 }
1559                 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1560                 return false;
1561             }
1562 
1563             try {
1564                 // Deliver all pending results.
1565                 ArrayList<ResultInfo> a = next.results;
1566                 if (a != null) {
1567                     final int N = a.size();
1568                     if (!next.finishing && N > 0) {
1569                         if (DEBUG_RESULTS) Slog.v(
1570                                 TAG, "Delivering results to " + next
1571                                 + ": " + a);
1572                         next.app.thread.scheduleSendResult(next.appToken, a);
1573                     }
1574                 }
1575 
1576                 if (next.newIntents != null) {
1577                     next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
1578                 }
1579 
1580                 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
1581                         next.userId, System.identityHashCode(next),
1582                         next.task.taskId, next.shortComponentName);
1583 
1584                 next.sleeping = false;
1585                 mService.showAskCompatModeDialogLocked(next);
1586                 next.app.pendingUiClean = true;
1587                 next.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
1588                 next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
1589                         mService.isNextTransitionForward());
1590 
1591                 mStackSupervisor.checkReadyForSleepLocked();
1592 
1593                 if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Resumed " + next);
1594             } catch (Exception e) {
1595                 // Whoops, need to restart this activity!
1596                 if (DEBUG_STATES) Slog.v(TAG, "Resume failed; resetting state to "
1597                         + lastState + ": " + next);
1598                 next.state = lastState;
1599                 if (lastStack != null) {
1600                     lastStack.mResumedActivity = lastResumedActivity;
1601                 }
1602                 Slog.i(TAG, "Restarting because process died: " + next);
1603                 if (!next.hasBeenLaunched) {
1604                     next.hasBeenLaunched = true;
1605                 } else  if (SHOW_APP_STARTING_PREVIEW && lastStack != null &&
1606                         mStackSupervisor.isFrontStack(lastStack)) {
1607                     mWindowManager.setAppStartingWindow(
1608                             next.appToken, next.packageName, next.theme,
1609                             mService.compatibilityInfoForPackageLocked(next.info.applicationInfo),
1610                             next.nonLocalizedLabel, next.labelRes, next.icon, next.logo,
1611                             next.windowFlags, null, true);
1612                 }
1613                 mStackSupervisor.startSpecificActivityLocked(next, true, false);
1614                 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1615                 return true;
1616             }
1617 
1618             // From this point on, if something goes wrong there is no way
1619             // to recover the activity.
1620             try {
1621                 next.visible = true;
1622                 completeResumeLocked(next);
1623             } catch (Exception e) {
1624                 // If any exception gets thrown, toss away this
1625                 // activity and try the next one.
1626                 Slog.w(TAG, "Exception thrown during resume of " + next, e);
1627                 requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
1628                         "resume-exception", true);
1629                 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1630                 return true;
1631             }
1632             next.stopped = false;
1633 
1634         } else {
1635             // Whoops, need to restart this activity!
1636             if (!next.hasBeenLaunched) {
1637                 next.hasBeenLaunched = true;
1638             } else {
1639                 if (SHOW_APP_STARTING_PREVIEW) {
1640                     mWindowManager.setAppStartingWindow(
1641                             next.appToken, next.packageName, next.theme,
1642                             mService.compatibilityInfoForPackageLocked(
1643                                     next.info.applicationInfo),
1644                             next.nonLocalizedLabel,
1645                             next.labelRes, next.icon, next.logo, next.windowFlags,
1646                             null, true);
1647                 }
1648                 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
1649             }
1650             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Restarting " + next);
1651             mStackSupervisor.startSpecificActivityLocked(next, true, true);
1652         }
1653 
1654         if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1655         return true;
1656     }
1657 
insertTaskAtTop(TaskRecord task)1658     private void insertTaskAtTop(TaskRecord task) {
1659         // If this is being moved to the top by another activity or being launched from the home
1660         // activity, set mOnTopOfHome accordingly.
1661         ActivityStack lastStack = mStackSupervisor.getLastStack();
1662         final boolean fromHome = lastStack == null ? true : lastStack.isHomeStack();
1663         if (!isHomeStack() && (fromHome || topTask() != task)) {
1664             task.mOnTopOfHome = fromHome;
1665         }
1666 
1667         mTaskHistory.remove(task);
1668         // Now put task at top.
1669         int stackNdx = mTaskHistory.size();
1670         if (task.userId != mCurrentUser) {
1671             // Put non-current user tasks below current user tasks.
1672             while (--stackNdx >= 0) {
1673                 if (mTaskHistory.get(stackNdx).userId != mCurrentUser) {
1674                     break;
1675                 }
1676             }
1677             ++stackNdx;
1678         }
1679         mTaskHistory.add(stackNdx, task);
1680     }
1681 
startActivityLocked(ActivityRecord r, boolean newTask, boolean doResume, boolean keepCurTransition, Bundle options)1682     final void startActivityLocked(ActivityRecord r, boolean newTask,
1683             boolean doResume, boolean keepCurTransition, Bundle options) {
1684         TaskRecord rTask = r.task;
1685         final int taskId = rTask.taskId;
1686         if (taskForIdLocked(taskId) == null || newTask) {
1687             // Last activity in task had been removed or ActivityManagerService is reusing task.
1688             // Insert or replace.
1689             // Might not even be in.
1690             insertTaskAtTop(rTask);
1691             mWindowManager.moveTaskToTop(taskId);
1692         }
1693         TaskRecord task = null;
1694         if (!newTask) {
1695             // If starting in an existing task, find where that is...
1696             boolean startIt = true;
1697             for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1698                 task = mTaskHistory.get(taskNdx);
1699                 if (task == r.task) {
1700                     // Here it is!  Now, if this is not yet visible to the
1701                     // user, then just add it without starting; it will
1702                     // get started when the user navigates back to it.
1703                     if (!startIt) {
1704                         if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
1705                                 + task, new RuntimeException("here").fillInStackTrace());
1706                         task.addActivityToTop(r);
1707                         r.putInHistory();
1708                         mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
1709                                 r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
1710                                 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
1711                                 r.userId, r.info.configChanges);
1712                         if (VALIDATE_TOKENS) {
1713                             validateAppTokensLocked();
1714                         }
1715                         ActivityOptions.abort(options);
1716                         return;
1717                     }
1718                     break;
1719                 } else if (task.numFullscreen > 0) {
1720                     startIt = false;
1721                 }
1722             }
1723         }
1724 
1725         // Place a new activity at top of stack, so it is next to interact
1726         // with the user.
1727 
1728         // If we are not placing the new activity frontmost, we do not want
1729         // to deliver the onUserLeaving callback to the actual frontmost
1730         // activity
1731         if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
1732             mStackSupervisor.mUserLeaving = false;
1733             if (DEBUG_USER_LEAVING) Slog.v(TAG,
1734                     "startActivity() behind front, mUserLeaving=false");
1735         }
1736 
1737         task = r.task;
1738 
1739         // Slot the activity into the history stack and proceed
1740         if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
1741                 new RuntimeException("here").fillInStackTrace());
1742         task.addActivityToTop(r);
1743         task.setFrontOfTask();
1744 
1745         r.putInHistory();
1746         if (!isHomeStack() || numActivities() > 0) {
1747             // We want to show the starting preview window if we are
1748             // switching to a new task, or the next activity's process is
1749             // not currently running.
1750             boolean showStartingIcon = newTask;
1751             ProcessRecord proc = r.app;
1752             if (proc == null) {
1753                 proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
1754             }
1755             if (proc == null || proc.thread == null) {
1756                 showStartingIcon = true;
1757             }
1758             if (DEBUG_TRANSITION) Slog.v(TAG,
1759                     "Prepare open transition: starting " + r);
1760             if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
1761                 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, keepCurTransition);
1762                 mNoAnimActivities.add(r);
1763             } else {
1764                 mWindowManager.prepareAppTransition(newTask
1765                         ? AppTransition.TRANSIT_TASK_OPEN
1766                         : AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
1767                 mNoAnimActivities.remove(r);
1768             }
1769             r.updateOptionsLocked(options);
1770             mWindowManager.addAppToken(task.mActivities.indexOf(r),
1771                     r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
1772                     (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId,
1773                     r.info.configChanges);
1774             boolean doShow = true;
1775             if (newTask) {
1776                 // Even though this activity is starting fresh, we still need
1777                 // to reset it to make sure we apply affinities to move any
1778                 // existing activities from other tasks in to it.
1779                 // If the caller has requested that the target task be
1780                 // reset, then do so.
1781                 if ((r.intent.getFlags()
1782                         &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1783                     resetTaskIfNeededLocked(r, r);
1784                     doShow = topRunningNonDelayedActivityLocked(null) == r;
1785                 }
1786             }
1787             if (SHOW_APP_STARTING_PREVIEW && doShow) {
1788                 // Figure out if we are transitioning from another activity that is
1789                 // "has the same starting icon" as the next one.  This allows the
1790                 // window manager to keep the previous window it had previously
1791                 // created, if it still had one.
1792                 ActivityRecord prev = mResumedActivity;
1793                 if (prev != null) {
1794                     // We don't want to reuse the previous starting preview if:
1795                     // (1) The current activity is in a different task.
1796                     if (prev.task != r.task) {
1797                         prev = null;
1798                     }
1799                     // (2) The current activity is already displayed.
1800                     else if (prev.nowVisible) {
1801                         prev = null;
1802                     }
1803                 }
1804                 mWindowManager.setAppStartingWindow(
1805                         r.appToken, r.packageName, r.theme,
1806                         mService.compatibilityInfoForPackageLocked(
1807                                 r.info.applicationInfo), r.nonLocalizedLabel,
1808                         r.labelRes, r.icon, r.logo, r.windowFlags,
1809                         prev != null ? prev.appToken : null, showStartingIcon);
1810             }
1811         } else {
1812             // If this is the first activity, don't do any fancy animations,
1813             // because there is nothing for it to animate on top of.
1814             mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
1815                     r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
1816                     (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId,
1817                     r.info.configChanges);
1818             ActivityOptions.abort(options);
1819         }
1820         if (VALIDATE_TOKENS) {
1821             validateAppTokensLocked();
1822         }
1823 
1824         if (doResume) {
1825             mStackSupervisor.resumeTopActivitiesLocked();
1826         }
1827     }
1828 
validateAppTokensLocked()1829     final void validateAppTokensLocked() {
1830         mValidateAppTokens.clear();
1831         mValidateAppTokens.ensureCapacity(numActivities());
1832         final int numTasks = mTaskHistory.size();
1833         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
1834             TaskRecord task = mTaskHistory.get(taskNdx);
1835             final ArrayList<ActivityRecord> activities = task.mActivities;
1836             if (activities.isEmpty()) {
1837                 continue;
1838             }
1839             TaskGroup group = new TaskGroup();
1840             group.taskId = task.taskId;
1841             mValidateAppTokens.add(group);
1842             final int numActivities = activities.size();
1843             for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
1844                 final ActivityRecord r = activities.get(activityNdx);
1845                 group.tokens.add(r.appToken);
1846             }
1847         }
1848         mWindowManager.validateAppTokens(mStackId, mValidateAppTokens);
1849     }
1850 
1851     /**
1852      * Perform a reset of the given task, if needed as part of launching it.
1853      * Returns the new HistoryRecord at the top of the task.
1854      */
1855     /**
1856      * Helper method for #resetTaskIfNeededLocked.
1857      * We are inside of the task being reset...  we'll either finish this activity, push it out
1858      * for another task, or leave it as-is.
1859      * @param task The task containing the Activity (taskTop) that might be reset.
1860      * @param forceReset
1861      * @return An ActivityOptions that needs to be processed.
1862      */
resetTargetTaskIfNeededLocked(TaskRecord task, boolean forceReset)1863     final ActivityOptions resetTargetTaskIfNeededLocked(TaskRecord task, boolean forceReset) {
1864         ActivityOptions topOptions = null;
1865 
1866         int replyChainEnd = -1;
1867         boolean canMoveOptions = true;
1868 
1869         // We only do this for activities that are not the root of the task (since if we finish
1870         // the root, we may no longer have the task!).
1871         final ArrayList<ActivityRecord> activities = task.mActivities;
1872         final int numActivities = activities.size();
1873         for (int i = numActivities - 1; i > 0; --i ) {
1874             ActivityRecord target = activities.get(i);
1875 
1876             final int flags = target.info.flags;
1877             final boolean finishOnTaskLaunch =
1878                     (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
1879             final boolean allowTaskReparenting =
1880                     (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
1881             final boolean clearWhenTaskReset =
1882                     (target.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
1883 
1884             if (!finishOnTaskLaunch
1885                     && !clearWhenTaskReset
1886                     && target.resultTo != null) {
1887                 // If this activity is sending a reply to a previous
1888                 // activity, we can't do anything with it now until
1889                 // we reach the start of the reply chain.
1890                 // XXX note that we are assuming the result is always
1891                 // to the previous activity, which is almost always
1892                 // the case but we really shouldn't count on.
1893                 if (replyChainEnd < 0) {
1894                     replyChainEnd = i;
1895                 }
1896             } else if (!finishOnTaskLaunch
1897                     && !clearWhenTaskReset
1898                     && allowTaskReparenting
1899                     && target.taskAffinity != null
1900                     && !target.taskAffinity.equals(task.affinity)) {
1901                 // If this activity has an affinity for another
1902                 // task, then we need to move it out of here.  We will
1903                 // move it as far out of the way as possible, to the
1904                 // bottom of the activity stack.  This also keeps it
1905                 // correctly ordered with any activities we previously
1906                 // moved.
1907                 final ThumbnailHolder newThumbHolder;
1908                 final TaskRecord targetTask;
1909                 final ActivityRecord bottom =
1910                         !mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ?
1911                                 mTaskHistory.get(0).mActivities.get(0) : null;
1912                 if (bottom != null && target.taskAffinity != null
1913                         && target.taskAffinity.equals(bottom.task.affinity)) {
1914                     // If the activity currently at the bottom has the
1915                     // same task affinity as the one we are moving,
1916                     // then merge it into the same task.
1917                     targetTask = bottom.task;
1918                     newThumbHolder = bottom.thumbHolder == null ? targetTask : bottom.thumbHolder;
1919                     if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
1920                             + " out to bottom task " + bottom.task);
1921                 } else {
1922                     targetTask = createTaskRecord(mStackSupervisor.getNextTaskId(), target.info,
1923                             null, false);
1924                     newThumbHolder = targetTask;
1925                     targetTask.affinityIntent = target.intent;
1926                     if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
1927                             + " out to new task " + target.task);
1928                 }
1929 
1930                 if (clearWhenTaskReset) {
1931                     // This is the start of a new sub-task.
1932                     if (target.thumbHolder == null) {
1933                         target.thumbHolder = new ThumbnailHolder();
1934                     }
1935                 } else {
1936                     target.thumbHolder = newThumbHolder;
1937                 }
1938 
1939                 final int targetTaskId = targetTask.taskId;
1940                 mWindowManager.setAppGroupId(target.appToken, targetTaskId);
1941 
1942                 boolean noOptions = canMoveOptions;
1943                 final int start = replyChainEnd < 0 ? i : replyChainEnd;
1944                 for (int srcPos = start; srcPos >= i; --srcPos) {
1945                     final ActivityRecord p = activities.get(srcPos);
1946                     if (p.finishing) {
1947                         continue;
1948                     }
1949 
1950                     ThumbnailHolder curThumbHolder = p.thumbHolder;
1951                     canMoveOptions = false;
1952                     if (noOptions && topOptions == null) {
1953                         topOptions = p.takeOptionsLocked();
1954                         if (topOptions != null) {
1955                             noOptions = false;
1956                         }
1957                     }
1958                     if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing activity " + p + " from task="
1959                             + task + " adding to task=" + targetTask
1960                             + " Callers=" + Debug.getCallers(4));
1961                     if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
1962                             + " out to target's task " + target.task);
1963                     p.setTask(targetTask, curThumbHolder, false);
1964                     targetTask.addActivityAtBottom(p);
1965 
1966                     mWindowManager.setAppGroupId(p.appToken, targetTaskId);
1967                 }
1968 
1969                 mWindowManager.moveTaskToBottom(targetTaskId);
1970                 if (VALIDATE_TOKENS) {
1971                     validateAppTokensLocked();
1972                 }
1973 
1974                 replyChainEnd = -1;
1975             } else if (forceReset || finishOnTaskLaunch || clearWhenTaskReset) {
1976                 // If the activity should just be removed -- either
1977                 // because it asks for it, or the task should be
1978                 // cleared -- then finish it and anything that is
1979                 // part of its reply chain.
1980                 int end;
1981                 if (clearWhenTaskReset) {
1982                     // In this case, we want to finish this activity
1983                     // and everything above it, so be sneaky and pretend
1984                     // like these are all in the reply chain.
1985                     end = numActivities - 1;
1986                 } else if (replyChainEnd < 0) {
1987                     end = i;
1988                 } else {
1989                     end = replyChainEnd;
1990                 }
1991                 boolean noOptions = canMoveOptions;
1992                 for (int srcPos = i; srcPos <= end; srcPos++) {
1993                     ActivityRecord p = activities.get(srcPos);
1994                     if (p.finishing) {
1995                         continue;
1996                     }
1997                     canMoveOptions = false;
1998                     if (noOptions && topOptions == null) {
1999                         topOptions = p.takeOptionsLocked();
2000                         if (topOptions != null) {
2001                             noOptions = false;
2002                         }
2003                     }
2004                     if (DEBUG_TASKS) Slog.w(TAG,
2005                             "resetTaskIntendedTask: calling finishActivity on " + p);
2006                     if (finishActivityLocked(p, Activity.RESULT_CANCELED, null, "reset", false)) {
2007                         end--;
2008                         srcPos--;
2009                     }
2010                 }
2011                 replyChainEnd = -1;
2012             } else {
2013                 // If we were in the middle of a chain, well the
2014                 // activity that started it all doesn't want anything
2015                 // special, so leave it all as-is.
2016                 replyChainEnd = -1;
2017             }
2018         }
2019 
2020         return topOptions;
2021     }
2022 
2023     /**
2024      * Helper method for #resetTaskIfNeededLocked. Processes all of the activities in a given
2025      * TaskRecord looking for an affinity with the task of resetTaskIfNeededLocked.taskTop.
2026      * @param affinityTask The task we are looking for an affinity to.
2027      * @param task Task that resetTaskIfNeededLocked.taskTop belongs to.
2028      * @param topTaskIsHigher True if #task has already been processed by resetTaskIfNeededLocked.
2029      * @param forceReset Flag passed in to resetTaskIfNeededLocked.
2030      */
resetAffinityTaskIfNeededLocked(TaskRecord affinityTask, TaskRecord task, boolean topTaskIsHigher, boolean forceReset, int taskInsertionPoint)2031     private int resetAffinityTaskIfNeededLocked(TaskRecord affinityTask, TaskRecord task,
2032             boolean topTaskIsHigher, boolean forceReset, int taskInsertionPoint) {
2033         int replyChainEnd = -1;
2034         final int taskId = task.taskId;
2035         final String taskAffinity = task.affinity;
2036 
2037         final ArrayList<ActivityRecord> activities = affinityTask.mActivities;
2038         final int numActivities = activities.size();
2039         // Do not operate on the root Activity.
2040         for (int i = numActivities - 1; i > 0; --i) {
2041             ActivityRecord target = activities.get(i);
2042 
2043             final int flags = target.info.flags;
2044             boolean finishOnTaskLaunch = (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
2045             boolean allowTaskReparenting = (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
2046 
2047             if (target.resultTo != null) {
2048                 // If this activity is sending a reply to a previous
2049                 // activity, we can't do anything with it now until
2050                 // we reach the start of the reply chain.
2051                 // XXX note that we are assuming the result is always
2052                 // to the previous activity, which is almost always
2053                 // the case but we really shouldn't count on.
2054                 if (replyChainEnd < 0) {
2055                     replyChainEnd = i;
2056                 }
2057             } else if (topTaskIsHigher
2058                     && allowTaskReparenting
2059                     && taskAffinity != null
2060                     && taskAffinity.equals(target.taskAffinity)) {
2061                 // This activity has an affinity for our task. Either remove it if we are
2062                 // clearing or move it over to our task.  Note that
2063                 // we currently punt on the case where we are resetting a
2064                 // task that is not at the top but who has activities above
2065                 // with an affinity to it...  this is really not a normal
2066                 // case, and we will need to later pull that task to the front
2067                 // and usually at that point we will do the reset and pick
2068                 // up those remaining activities.  (This only happens if
2069                 // someone starts an activity in a new task from an activity
2070                 // in a task that is not currently on top.)
2071                 if (forceReset || finishOnTaskLaunch) {
2072                     final int start = replyChainEnd >= 0 ? replyChainEnd : i;
2073                     if (DEBUG_TASKS) Slog.v(TAG, "Finishing task at index " + start + " to " + i);
2074                     for (int srcPos = start; srcPos >= i; --srcPos) {
2075                         final ActivityRecord p = activities.get(srcPos);
2076                         if (p.finishing) {
2077                             continue;
2078                         }
2079                         finishActivityLocked(p, Activity.RESULT_CANCELED, null, "reset", false);
2080                     }
2081                 } else {
2082                     if (taskInsertionPoint < 0) {
2083                         taskInsertionPoint = task.mActivities.size();
2084 
2085                     }
2086 
2087                     final int start = replyChainEnd >= 0 ? replyChainEnd : i;
2088                     if (DEBUG_TASKS) Slog.v(TAG, "Reparenting from task=" + affinityTask + ":"
2089                             + start + "-" + i + " to task=" + task + ":" + taskInsertionPoint);
2090                     for (int srcPos = start; srcPos >= i; --srcPos) {
2091                         final ActivityRecord p = activities.get(srcPos);
2092                         p.setTask(task, null, false);
2093                         task.addActivityAtIndex(taskInsertionPoint, p);
2094 
2095                         if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing and adding activity " + p
2096                                 + " to stack at " + task,
2097                                 new RuntimeException("here").fillInStackTrace());
2098                         if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p + " from " + srcPos
2099                                 + " in to resetting task " + task);
2100                         mWindowManager.setAppGroupId(p.appToken, taskId);
2101                     }
2102                     mWindowManager.moveTaskToTop(taskId);
2103                     if (VALIDATE_TOKENS) {
2104                         validateAppTokensLocked();
2105                     }
2106 
2107                     // Now we've moved it in to place...  but what if this is
2108                     // a singleTop activity and we have put it on top of another
2109                     // instance of the same activity?  Then we drop the instance
2110                     // below so it remains singleTop.
2111                     if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
2112                         ArrayList<ActivityRecord> taskActivities = task.mActivities;
2113                         int targetNdx = taskActivities.indexOf(target);
2114                         if (targetNdx > 0) {
2115                             ActivityRecord p = taskActivities.get(targetNdx - 1);
2116                             if (p.intent.getComponent().equals(target.intent.getComponent())) {
2117                                 finishActivityLocked(p, Activity.RESULT_CANCELED, null, "replace",
2118                                         false);
2119                             }
2120                         }
2121                     }
2122                 }
2123 
2124                 replyChainEnd = -1;
2125             }
2126         }
2127         return taskInsertionPoint;
2128     }
2129 
resetTaskIfNeededLocked(ActivityRecord taskTop, ActivityRecord newActivity)2130     final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
2131             ActivityRecord newActivity) {
2132         boolean forceReset =
2133                 (newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
2134         if (ACTIVITY_INACTIVE_RESET_TIME > 0
2135                 && taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
2136             if ((newActivity.info.flags & ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
2137                 forceReset = true;
2138             }
2139         }
2140 
2141         final TaskRecord task = taskTop.task;
2142 
2143         /** False until we evaluate the TaskRecord associated with taskTop. Switches to true
2144          * for remaining tasks. Used for later tasks to reparent to task. */
2145         boolean taskFound = false;
2146 
2147         /** If ActivityOptions are moved out and need to be aborted or moved to taskTop. */
2148         ActivityOptions topOptions = null;
2149 
2150         // Preserve the location for reparenting in the new task.
2151         int reparentInsertionPoint = -1;
2152 
2153         for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
2154             final TaskRecord targetTask = mTaskHistory.get(i);
2155 
2156             if (targetTask == task) {
2157                 topOptions = resetTargetTaskIfNeededLocked(task, forceReset);
2158                 taskFound = true;
2159             } else {
2160                 reparentInsertionPoint = resetAffinityTaskIfNeededLocked(targetTask, task,
2161                         taskFound, forceReset, reparentInsertionPoint);
2162             }
2163         }
2164 
2165         int taskNdx = mTaskHistory.indexOf(task);
2166         do {
2167             taskTop = mTaskHistory.get(taskNdx--).getTopActivity();
2168         } while (taskTop == null && taskNdx >= 0);
2169 
2170         if (topOptions != null) {
2171             // If we got some ActivityOptions from an activity on top that
2172             // was removed from the task, propagate them to the new real top.
2173             if (taskTop != null) {
2174                 taskTop.updateOptionsLocked(topOptions);
2175             } else {
2176                 topOptions.abort();
2177             }
2178         }
2179 
2180         return taskTop;
2181     }
2182 
sendActivityResultLocked(int callingUid, ActivityRecord r, String resultWho, int requestCode, int resultCode, Intent data)2183     void sendActivityResultLocked(int callingUid, ActivityRecord r,
2184             String resultWho, int requestCode, int resultCode, Intent data) {
2185 
2186         if (callingUid > 0) {
2187             mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
2188                     data, r.getUriPermissionsLocked());
2189         }
2190 
2191         if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
2192                 + " : who=" + resultWho + " req=" + requestCode
2193                 + " res=" + resultCode + " data=" + data);
2194         if (mResumedActivity == r && r.app != null && r.app.thread != null) {
2195             try {
2196                 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
2197                 list.add(new ResultInfo(resultWho, requestCode,
2198                         resultCode, data));
2199                 r.app.thread.scheduleSendResult(r.appToken, list);
2200                 return;
2201             } catch (Exception e) {
2202                 Slog.w(TAG, "Exception thrown sending result to " + r, e);
2203             }
2204         }
2205 
2206         r.addResultLocked(null, resultWho, requestCode, resultCode, data);
2207     }
2208 
adjustFocusedActivityLocked(ActivityRecord r)2209     private void adjustFocusedActivityLocked(ActivityRecord r) {
2210         if (mStackSupervisor.isFrontStack(this) && mService.mFocusedActivity == r) {
2211             ActivityRecord next = topRunningActivityLocked(null);
2212             if (next != r) {
2213                 final TaskRecord task = r.task;
2214                 if (r.frontOfTask && task == topTask() && task.mOnTopOfHome) {
2215                     mStackSupervisor.moveHomeToTop();
2216                 }
2217             }
2218             mService.setFocusedActivityLocked(mStackSupervisor.topRunningActivityLocked());
2219         }
2220     }
2221 
stopActivityLocked(ActivityRecord r)2222     final void stopActivityLocked(ActivityRecord r) {
2223         if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
2224         if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
2225                 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
2226             if (!r.finishing) {
2227                 if (!mService.mSleeping) {
2228                     if (DEBUG_STATES) {
2229                         Slog.d(TAG, "no-history finish of " + r);
2230                     }
2231                     requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
2232                             "no-history", false);
2233                 } else {
2234                     if (DEBUG_STATES) Slog.d(TAG, "Not finishing noHistory " + r
2235                             + " on stop because we're just sleeping");
2236                 }
2237             }
2238         }
2239 
2240         if (r.app != null && r.app.thread != null) {
2241             adjustFocusedActivityLocked(r);
2242             r.resumeKeyDispatchingLocked();
2243             try {
2244                 r.stopped = false;
2245                 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
2246                         + " (stop requested)");
2247                 r.state = ActivityState.STOPPING;
2248                 if (DEBUG_VISBILITY) Slog.v(
2249                         TAG, "Stopping visible=" + r.visible + " for " + r);
2250                 if (!r.visible) {
2251                     mWindowManager.setAppVisibility(r.appToken, false);
2252                 }
2253                 r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
2254                 if (mService.isSleepingOrShuttingDown()) {
2255                     r.setSleeping(true);
2256                 }
2257                 Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r);
2258                 mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
2259             } catch (Exception e) {
2260                 // Maybe just ignore exceptions here...  if the process
2261                 // has crashed, our death notification will clean things
2262                 // up.
2263                 Slog.w(TAG, "Exception thrown during pause", e);
2264                 // Just in case, assume it to be stopped.
2265                 r.stopped = true;
2266                 if (DEBUG_STATES) Slog.v(TAG, "Stop failed; moving to STOPPED: " + r);
2267                 r.state = ActivityState.STOPPED;
2268                 if (r.configDestroy) {
2269                     destroyActivityLocked(r, true, false, "stop-except");
2270                 }
2271             }
2272         }
2273     }
2274 
2275     /**
2276      * @return Returns true if the activity is being finished, false if for
2277      * some reason it is being left as-is.
2278      */
requestFinishActivityLocked(IBinder token, int resultCode, Intent resultData, String reason, boolean oomAdj)2279     final boolean requestFinishActivityLocked(IBinder token, int resultCode,
2280             Intent resultData, String reason, boolean oomAdj) {
2281         ActivityRecord r = isInStackLocked(token);
2282         if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(
2283                 TAG, "Finishing activity token=" + token + " r="
2284                 + ", result=" + resultCode + ", data=" + resultData
2285                 + ", reason=" + reason);
2286         if (r == null) {
2287             return false;
2288         }
2289 
2290         finishActivityLocked(r, resultCode, resultData, reason, oomAdj);
2291         return true;
2292     }
2293 
finishSubActivityLocked(ActivityRecord self, String resultWho, int requestCode)2294     final void finishSubActivityLocked(ActivityRecord self, String resultWho, int requestCode) {
2295         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
2296             ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
2297             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
2298                 ActivityRecord r = activities.get(activityNdx);
2299                 if (r.resultTo == self && r.requestCode == requestCode) {
2300                     if ((r.resultWho == null && resultWho == null) ||
2301                         (r.resultWho != null && r.resultWho.equals(resultWho))) {
2302                         finishActivityLocked(r, Activity.RESULT_CANCELED, null, "request-sub",
2303                                 false);
2304                     }
2305                 }
2306             }
2307         }
2308         mService.updateOomAdjLocked();
2309     }
2310 
finishTopRunningActivityLocked(ProcessRecord app)2311     final void finishTopRunningActivityLocked(ProcessRecord app) {
2312         ActivityRecord r = topRunningActivityLocked(null);
2313         if (r != null && r.app == app) {
2314             // If the top running activity is from this crashing
2315             // process, then terminate it to avoid getting in a loop.
2316             Slog.w(TAG, "  Force finishing activity "
2317                     + r.intent.getComponent().flattenToShortString());
2318             int taskNdx = mTaskHistory.indexOf(r.task);
2319             int activityNdx = r.task.mActivities.indexOf(r);
2320             finishActivityLocked(r, Activity.RESULT_CANCELED, null, "crashed", false);
2321             // Also terminate any activities below it that aren't yet
2322             // stopped, to avoid a situation where one will get
2323             // re-start our crashing activity once it gets resumed again.
2324             --activityNdx;
2325             if (activityNdx < 0) {
2326                 do {
2327                     --taskNdx;
2328                     if (taskNdx < 0) {
2329                         break;
2330                     }
2331                     activityNdx = mTaskHistory.get(taskNdx).mActivities.size() - 1;
2332                 } while (activityNdx < 0);
2333             }
2334             if (activityNdx >= 0) {
2335                 r = mTaskHistory.get(taskNdx).mActivities.get(activityNdx);
2336                 if (r.state == ActivityState.RESUMED
2337                         || r.state == ActivityState.PAUSING
2338                         || r.state == ActivityState.PAUSED) {
2339                     if (!r.isHomeActivity() || mService.mHomeProcess != r.app) {
2340                         Slog.w(TAG, "  Force finishing activity "
2341                                 + r.intent.getComponent().flattenToShortString());
2342                         finishActivityLocked(r, Activity.RESULT_CANCELED, null, "crashed", false);
2343                     }
2344                 }
2345             }
2346         }
2347     }
2348 
finishActivityAffinityLocked(ActivityRecord r)2349     final boolean finishActivityAffinityLocked(ActivityRecord r) {
2350         ArrayList<ActivityRecord> activities = r.task.mActivities;
2351         for (int index = activities.indexOf(r); index >= 0; --index) {
2352             ActivityRecord cur = activities.get(index);
2353             if (!Objects.equal(cur.taskAffinity, r.taskAffinity)) {
2354                 break;
2355             }
2356             finishActivityLocked(cur, Activity.RESULT_CANCELED, null, "request-affinity", true);
2357         }
2358         return true;
2359     }
2360 
finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData)2361     final void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
2362         // send the result
2363         ActivityRecord resultTo = r.resultTo;
2364         if (resultTo != null) {
2365             if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
2366                     + " who=" + r.resultWho + " req=" + r.requestCode
2367                     + " res=" + resultCode + " data=" + resultData);
2368             if (r.info.applicationInfo.uid > 0) {
2369                 mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
2370                         resultTo.packageName, resultData,
2371                         resultTo.getUriPermissionsLocked());
2372             }
2373             resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
2374                                      resultData);
2375             r.resultTo = null;
2376         }
2377         else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
2378 
2379         // Make sure this HistoryRecord is not holding on to other resources,
2380         // because clients have remote IPC references to this object so we
2381         // can't assume that will go away and want to avoid circular IPC refs.
2382         r.results = null;
2383         r.pendingResults = null;
2384         r.newIntents = null;
2385         r.icicle = null;
2386     }
2387 
2388     /**
2389      * @return Returns true if this activity has been removed from the history
2390      * list, or false if it is still in the list and will be removed later.
2391      */
finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData, String reason, boolean oomAdj)2392     final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
2393             String reason, boolean oomAdj) {
2394         if (r.finishing) {
2395             Slog.w(TAG, "Duplicate finish request for " + r);
2396             return false;
2397         }
2398 
2399         r.makeFinishing();
2400         EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
2401                 r.userId, System.identityHashCode(r),
2402                 r.task.taskId, r.shortComponentName, reason);
2403         final ArrayList<ActivityRecord> activities = r.task.mActivities;
2404         final int index = activities.indexOf(r);
2405         if (index < (activities.size() - 1)) {
2406             r.task.setFrontOfTask();
2407             if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2408                 // If the caller asked that this activity (and all above it)
2409                 // be cleared when the task is reset, don't lose that information,
2410                 // but propagate it up to the next activity.
2411                 ActivityRecord next = activities.get(index+1);
2412                 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
2413             }
2414         }
2415 
2416         r.pauseKeyDispatchingLocked();
2417 
2418         adjustFocusedActivityLocked(r);
2419 
2420         finishActivityResultsLocked(r, resultCode, resultData);
2421 
2422         if (!mService.mPendingThumbnails.isEmpty()) {
2423             // There are clients waiting to receive thumbnails so, in case
2424             // this is an activity that someone is waiting for, add it
2425             // to the pending list so we can correctly update the clients.
2426             mStackSupervisor.mCancelledThumbnails.add(r);
2427         }
2428 
2429         if (mResumedActivity == r) {
2430             boolean endTask = index <= 0;
2431             if (DEBUG_VISBILITY || DEBUG_TRANSITION) Slog.v(TAG,
2432                     "Prepare close transition: finishing " + r);
2433             mWindowManager.prepareAppTransition(endTask
2434                     ? AppTransition.TRANSIT_TASK_CLOSE
2435                     : AppTransition.TRANSIT_ACTIVITY_CLOSE, false);
2436 
2437             // Tell window manager to prepare for this one to be removed.
2438             mWindowManager.setAppVisibility(r.appToken, false);
2439 
2440             if (mPausingActivity == null) {
2441                 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
2442                 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
2443                 startPausingLocked(false, false);
2444             }
2445 
2446         } else if (r.state != ActivityState.PAUSING) {
2447             // If the activity is PAUSING, we will complete the finish once
2448             // it is done pausing; else we can just directly finish it here.
2449             if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
2450             return finishCurrentActivityLocked(r, FINISH_AFTER_PAUSE, oomAdj) == null;
2451         } else {
2452             if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
2453         }
2454 
2455         return false;
2456     }
2457 
2458     static final int FINISH_IMMEDIATELY = 0;
2459     static final int FINISH_AFTER_PAUSE = 1;
2460     static final int FINISH_AFTER_VISIBLE = 2;
2461 
finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj)2462     final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj) {
2463         // First things first: if this activity is currently visible,
2464         // and the resumed activity is not yet visible, then hold off on
2465         // finishing until the resumed one becomes visible.
2466         if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
2467             if (!mStackSupervisor.mStoppingActivities.contains(r)) {
2468                 mStackSupervisor.mStoppingActivities.add(r);
2469                 if (mStackSupervisor.mStoppingActivities.size() > 3
2470                         || r.frontOfTask && mTaskHistory.size() <= 1) {
2471                     // If we already have a few activities waiting to stop,
2472                     // then give up on things going idle and start clearing
2473                     // them out. Or if r is the last of activity of the last task the stack
2474                     // will be empty and must be cleared immediately.
2475                     mStackSupervisor.scheduleIdleLocked();
2476                 } else {
2477                     mStackSupervisor.checkReadyForSleepLocked();
2478                 }
2479             }
2480             if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
2481                     + " (finish requested)");
2482             r.state = ActivityState.STOPPING;
2483             if (oomAdj) {
2484                 mService.updateOomAdjLocked();
2485             }
2486             return r;
2487         }
2488 
2489         // make sure the record is cleaned out of other places.
2490         mStackSupervisor.mStoppingActivities.remove(r);
2491         mStackSupervisor.mGoingToSleepActivities.remove(r);
2492         mStackSupervisor.mWaitingVisibleActivities.remove(r);
2493         if (mResumedActivity == r) {
2494             mResumedActivity = null;
2495         }
2496         final ActivityState prevState = r.state;
2497         if (DEBUG_STATES) Slog.v(TAG, "Moving to FINISHING: " + r);
2498         r.state = ActivityState.FINISHING;
2499 
2500         if (mode == FINISH_IMMEDIATELY
2501                 || prevState == ActivityState.STOPPED
2502                 || prevState == ActivityState.INITIALIZING) {
2503             // If this activity is already stopped, we can just finish
2504             // it right now.
2505             boolean activityRemoved = destroyActivityLocked(r, true,
2506                     oomAdj, "finish-imm");
2507             if (activityRemoved) {
2508                 mStackSupervisor.resumeTopActivitiesLocked();
2509             }
2510             return activityRemoved ? null : r;
2511         }
2512 
2513         // Need to go through the full pause cycle to get this
2514         // activity into the stopped state and then finish it.
2515         if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
2516         mStackSupervisor.mFinishingActivities.add(r);
2517         mStackSupervisor.getFocusedStack().resumeTopActivityLocked(null);
2518         return r;
2519     }
2520 
navigateUpToLocked(IBinder token, Intent destIntent, int resultCode, Intent resultData)2521     final boolean navigateUpToLocked(IBinder token, Intent destIntent, int resultCode,
2522             Intent resultData) {
2523         final ActivityRecord srec = ActivityRecord.forToken(token);
2524         final TaskRecord task = srec.task;
2525         final ArrayList<ActivityRecord> activities = task.mActivities;
2526         final int start = activities.indexOf(srec);
2527         if (!mTaskHistory.contains(task) || (start < 0)) {
2528             return false;
2529         }
2530         int finishTo = start - 1;
2531         ActivityRecord parent = finishTo < 0 ? null : activities.get(finishTo);
2532         boolean foundParentInTask = false;
2533         final ComponentName dest = destIntent.getComponent();
2534         if (start > 0 && dest != null) {
2535             for (int i = finishTo; i >= 0; i--) {
2536                 ActivityRecord r = activities.get(i);
2537                 if (r.info.packageName.equals(dest.getPackageName()) &&
2538                         r.info.name.equals(dest.getClassName())) {
2539                     finishTo = i;
2540                     parent = r;
2541                     foundParentInTask = true;
2542                     break;
2543                 }
2544             }
2545         }
2546 
2547         IActivityController controller = mService.mController;
2548         if (controller != null) {
2549             ActivityRecord next = topRunningActivityLocked(srec.appToken, 0);
2550             if (next != null) {
2551                 // ask watcher if this is allowed
2552                 boolean resumeOK = true;
2553                 try {
2554                     resumeOK = controller.activityResuming(next.packageName);
2555                 } catch (RemoteException e) {
2556                     mService.mController = null;
2557                     Watchdog.getInstance().setActivityController(null);
2558                 }
2559 
2560                 if (!resumeOK) {
2561                     return false;
2562                 }
2563             }
2564         }
2565         final long origId = Binder.clearCallingIdentity();
2566         for (int i = start; i > finishTo; i--) {
2567             ActivityRecord r = activities.get(i);
2568             requestFinishActivityLocked(r.appToken, resultCode, resultData, "navigate-up", true);
2569             // Only return the supplied result for the first activity finished
2570             resultCode = Activity.RESULT_CANCELED;
2571             resultData = null;
2572         }
2573 
2574         if (parent != null && foundParentInTask) {
2575             final int parentLaunchMode = parent.info.launchMode;
2576             final int destIntentFlags = destIntent.getFlags();
2577             if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE ||
2578                     parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
2579                     parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
2580                     (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
2581                 parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent);
2582             } else {
2583                 try {
2584                     ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
2585                             destIntent.getComponent(), 0, srec.userId);
2586                     int res = mStackSupervisor.startActivityLocked(srec.app.thread, destIntent,
2587                             null, aInfo, parent.appToken, null,
2588                             0, -1, parent.launchedFromUid, parent.launchedFromPackage,
2589                             0, null, true, null);
2590                     foundParentInTask = res == ActivityManager.START_SUCCESS;
2591                 } catch (RemoteException e) {
2592                     foundParentInTask = false;
2593                 }
2594                 requestFinishActivityLocked(parent.appToken, resultCode,
2595                         resultData, "navigate-up", true);
2596             }
2597         }
2598         Binder.restoreCallingIdentity(origId);
2599         return foundParentInTask;
2600     }
2601     /**
2602      * Perform the common clean-up of an activity record.  This is called both
2603      * as part of destroyActivityLocked() (when destroying the client-side
2604      * representation) and cleaning things up as a result of its hosting
2605      * processing going away, in which case there is no remaining client-side
2606      * state to destroy so only the cleanup here is needed.
2607      */
cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState)2608     final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices,
2609             boolean setState) {
2610         if (mResumedActivity == r) {
2611             mResumedActivity = null;
2612         }
2613         if (mService.mFocusedActivity == r) {
2614             mService.mFocusedActivity = null;
2615         }
2616 
2617         r.configDestroy = false;
2618         r.frozenBeforeDestroy = false;
2619 
2620         if (setState) {
2621             if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (cleaning up)");
2622             r.state = ActivityState.DESTROYED;
2623             if (DEBUG_APP) Slog.v(TAG, "Clearing app during cleanUp for activity " + r);
2624             r.app = null;
2625         }
2626 
2627         // Make sure this record is no longer in the pending finishes list.
2628         // This could happen, for example, if we are trimming activities
2629         // down to the max limit while they are still waiting to finish.
2630         mStackSupervisor.mFinishingActivities.remove(r);
2631         mStackSupervisor.mWaitingVisibleActivities.remove(r);
2632 
2633         // Remove any pending results.
2634         if (r.finishing && r.pendingResults != null) {
2635             for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
2636                 PendingIntentRecord rec = apr.get();
2637                 if (rec != null) {
2638                     mService.cancelIntentSenderLocked(rec, false);
2639                 }
2640             }
2641             r.pendingResults = null;
2642         }
2643 
2644         if (cleanServices) {
2645             cleanUpActivityServicesLocked(r);
2646         }
2647 
2648         if (!mService.mPendingThumbnails.isEmpty()) {
2649             // There are clients waiting to receive thumbnails so, in case
2650             // this is an activity that someone is waiting for, add it
2651             // to the pending list so we can correctly update the clients.
2652             mStackSupervisor.mCancelledThumbnails.add(r);
2653         }
2654 
2655         // Get rid of any pending idle timeouts.
2656         removeTimeoutsForActivityLocked(r);
2657     }
2658 
removeTimeoutsForActivityLocked(ActivityRecord r)2659     private void removeTimeoutsForActivityLocked(ActivityRecord r) {
2660         mStackSupervisor.removeTimeoutsForActivityLocked(r);
2661         mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
2662         mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
2663         mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
2664         r.finishLaunchTickingLocked();
2665     }
2666 
removeActivityFromHistoryLocked(ActivityRecord r)2667     final void removeActivityFromHistoryLocked(ActivityRecord r) {
2668         finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
2669         r.makeFinishing();
2670         if (DEBUG_ADD_REMOVE) {
2671             RuntimeException here = new RuntimeException("here");
2672             here.fillInStackTrace();
2673             Slog.i(TAG, "Removing activity " + r + " from stack");
2674         }
2675         final TaskRecord task = r.task;
2676         if (task != null && task.removeActivity(r)) {
2677             if (DEBUG_STACK) Slog.i(TAG,
2678                     "removeActivityFromHistoryLocked: last activity removed from " + this);
2679             if (mStackSupervisor.isFrontStack(this) && task == topTask() && task.mOnTopOfHome) {
2680                 mStackSupervisor.moveHomeToTop();
2681             }
2682             mStackSupervisor.removeTask(task);
2683         }
2684         r.takeFromHistory();
2685         removeTimeoutsForActivityLocked(r);
2686         if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (removed from history)");
2687         r.state = ActivityState.DESTROYED;
2688         if (DEBUG_APP) Slog.v(TAG, "Clearing app during remove for activity " + r);
2689         r.app = null;
2690         mWindowManager.removeAppToken(r.appToken);
2691         if (VALIDATE_TOKENS) {
2692             validateAppTokensLocked();
2693         }
2694         cleanUpActivityServicesLocked(r);
2695         r.removeUriPermissionsLocked();
2696     }
2697 
2698     /**
2699      * Perform clean-up of service connections in an activity record.
2700      */
cleanUpActivityServicesLocked(ActivityRecord r)2701     final void cleanUpActivityServicesLocked(ActivityRecord r) {
2702         // Throw away any services that have been bound by this activity.
2703         if (r.connections != null) {
2704             Iterator<ConnectionRecord> it = r.connections.iterator();
2705             while (it.hasNext()) {
2706                 ConnectionRecord c = it.next();
2707                 mService.mServices.removeConnectionLocked(c, null, r);
2708             }
2709             r.connections = null;
2710         }
2711     }
2712 
scheduleDestroyActivities(ProcessRecord owner, boolean oomAdj, String reason)2713     final void scheduleDestroyActivities(ProcessRecord owner, boolean oomAdj, String reason) {
2714         Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG);
2715         msg.obj = new ScheduleDestroyArgs(owner, oomAdj, reason);
2716         mHandler.sendMessage(msg);
2717     }
2718 
destroyActivitiesLocked(ProcessRecord owner, boolean oomAdj, String reason)2719     final void destroyActivitiesLocked(ProcessRecord owner, boolean oomAdj, String reason) {
2720         boolean lastIsOpaque = false;
2721         boolean activityRemoved = false;
2722         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
2723             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
2724             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
2725                 final ActivityRecord r = activities.get(activityNdx);
2726                 if (r.finishing) {
2727                     continue;
2728                 }
2729                 if (r.fullscreen) {
2730                     lastIsOpaque = true;
2731                 }
2732                 if (owner != null && r.app != owner) {
2733                     continue;
2734                 }
2735                 if (!lastIsOpaque) {
2736                     continue;
2737                 }
2738                 // We can destroy this one if we have its icicle saved and
2739                 // it is not in the process of pausing/stopping/finishing.
2740                 if (r.app != null && r != mResumedActivity && r != mPausingActivity
2741                         && r.haveState && !r.visible && r.stopped
2742                         && r.state != ActivityState.DESTROYING
2743                         && r.state != ActivityState.DESTROYED) {
2744                     if (DEBUG_SWITCH) Slog.v(TAG, "Destroying " + r + " in state " + r.state
2745                             + " resumed=" + mResumedActivity
2746                             + " pausing=" + mPausingActivity);
2747                     if (destroyActivityLocked(r, true, oomAdj, reason)) {
2748                         activityRemoved = true;
2749                     }
2750                 }
2751             }
2752         }
2753         if (activityRemoved) {
2754             mStackSupervisor.resumeTopActivitiesLocked();
2755 
2756         }
2757     }
2758 
2759     /**
2760      * Destroy the current CLIENT SIDE instance of an activity.  This may be
2761      * called both when actually finishing an activity, or when performing
2762      * a configuration switch where we destroy the current client-side object
2763      * but then create a new client-side object for this same HistoryRecord.
2764      */
destroyActivityLocked(ActivityRecord r, boolean removeFromApp, boolean oomAdj, String reason)2765     final boolean destroyActivityLocked(ActivityRecord r,
2766             boolean removeFromApp, boolean oomAdj, String reason) {
2767         if (DEBUG_SWITCH || DEBUG_CLEANUP) Slog.v(
2768             TAG, "Removing activity from " + reason + ": token=" + r
2769               + ", app=" + (r.app != null ? r.app.processName : "(null)"));
2770         EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
2771                 r.userId, System.identityHashCode(r),
2772                 r.task.taskId, r.shortComponentName, reason);
2773 
2774         boolean removedFromHistory = false;
2775 
2776         cleanUpActivityLocked(r, false, false);
2777 
2778         final boolean hadApp = r.app != null;
2779 
2780         if (hadApp) {
2781             if (removeFromApp) {
2782                 r.app.activities.remove(r);
2783                 if (mService.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
2784                     mService.mHeavyWeightProcess = null;
2785                     mService.mHandler.sendEmptyMessage(
2786                             ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG);
2787                 }
2788                 if (r.app.activities.isEmpty()) {
2789                     // No longer have activities, so update LRU list and oom adj.
2790                     mService.updateLruProcessLocked(r.app, false, null);
2791                     mService.updateOomAdjLocked();
2792                 }
2793             }
2794 
2795             boolean skipDestroy = false;
2796 
2797             try {
2798                 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
2799                 r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,
2800                         r.configChangeFlags);
2801             } catch (Exception e) {
2802                 // We can just ignore exceptions here...  if the process
2803                 // has crashed, our death notification will clean things
2804                 // up.
2805                 //Slog.w(TAG, "Exception thrown during finish", e);
2806                 if (r.finishing) {
2807                     removeActivityFromHistoryLocked(r);
2808                     removedFromHistory = true;
2809                     skipDestroy = true;
2810                 }
2811             }
2812 
2813             r.nowVisible = false;
2814 
2815             // If the activity is finishing, we need to wait on removing it
2816             // from the list to give it a chance to do its cleanup.  During
2817             // that time it may make calls back with its token so we need to
2818             // be able to find it on the list and so we don't want to remove
2819             // it from the list yet.  Otherwise, we can just immediately put
2820             // it in the destroyed state since we are not removing it from the
2821             // list.
2822             if (r.finishing && !skipDestroy) {
2823                 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYING: " + r
2824                         + " (destroy requested)");
2825                 r.state = ActivityState.DESTROYING;
2826                 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG, r);
2827                 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
2828             } else {
2829                 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (destroy skipped)");
2830                 r.state = ActivityState.DESTROYED;
2831                 if (DEBUG_APP) Slog.v(TAG, "Clearing app during destroy for activity " + r);
2832                 r.app = null;
2833             }
2834         } else {
2835             // remove this record from the history.
2836             if (r.finishing) {
2837                 removeActivityFromHistoryLocked(r);
2838                 removedFromHistory = true;
2839             } else {
2840                 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (no app)");
2841                 r.state = ActivityState.DESTROYED;
2842                 if (DEBUG_APP) Slog.v(TAG, "Clearing app during destroy for activity " + r);
2843                 r.app = null;
2844             }
2845         }
2846 
2847         r.configChangeFlags = 0;
2848 
2849         if (!mLRUActivities.remove(r) && hadApp) {
2850             Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
2851         }
2852 
2853         return removedFromHistory;
2854     }
2855 
activityDestroyedLocked(IBinder token)2856     final void activityDestroyedLocked(IBinder token) {
2857         final long origId = Binder.clearCallingIdentity();
2858         try {
2859             ActivityRecord r = ActivityRecord.forToken(token);
2860             if (r != null) {
2861                 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
2862             }
2863 
2864             if (isInStackLocked(token) != null) {
2865                 if (r.state == ActivityState.DESTROYING) {
2866                     cleanUpActivityLocked(r, true, false);
2867                     removeActivityFromHistoryLocked(r);
2868                 }
2869             }
2870             mStackSupervisor.resumeTopActivitiesLocked();
2871         } finally {
2872             Binder.restoreCallingIdentity(origId);
2873         }
2874     }
2875 
removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list, ProcessRecord app, String listName)2876     private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list,
2877             ProcessRecord app, String listName) {
2878         int i = list.size();
2879         if (DEBUG_CLEANUP) Slog.v(
2880             TAG, "Removing app " + app + " from list " + listName
2881             + " with " + i + " entries");
2882         while (i > 0) {
2883             i--;
2884             ActivityRecord r = list.get(i);
2885             if (DEBUG_CLEANUP) Slog.v(TAG, "Record #" + i + " " + r);
2886             if (r.app == app) {
2887                 if (DEBUG_CLEANUP) Slog.v(TAG, "---> REMOVING this entry!");
2888                 list.remove(i);
2889                 removeTimeoutsForActivityLocked(r);
2890             }
2891         }
2892     }
2893 
removeHistoryRecordsForAppLocked(ProcessRecord app)2894     boolean removeHistoryRecordsForAppLocked(ProcessRecord app) {
2895         removeHistoryRecordsForAppLocked(mLRUActivities, app, "mLRUActivities");
2896         removeHistoryRecordsForAppLocked(mStackSupervisor.mStoppingActivities, app,
2897                 "mStoppingActivities");
2898         removeHistoryRecordsForAppLocked(mStackSupervisor.mGoingToSleepActivities, app,
2899                 "mGoingToSleepActivities");
2900         removeHistoryRecordsForAppLocked(mStackSupervisor.mWaitingVisibleActivities, app,
2901                 "mWaitingVisibleActivities");
2902         removeHistoryRecordsForAppLocked(mStackSupervisor.mFinishingActivities, app,
2903                 "mFinishingActivities");
2904 
2905         boolean hasVisibleActivities = false;
2906 
2907         // Clean out the history list.
2908         int i = numActivities();
2909         if (DEBUG_CLEANUP) Slog.v(
2910             TAG, "Removing app " + app + " from history with " + i + " entries");
2911         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
2912             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
2913             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
2914                 final ActivityRecord r = activities.get(activityNdx);
2915                 --i;
2916                 if (DEBUG_CLEANUP) Slog.v(
2917                     TAG, "Record #" + i + " " + r + ": app=" + r.app);
2918                 if (r.app == app) {
2919                     boolean remove;
2920                     if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
2921                         // Don't currently have state for the activity, or
2922                         // it is finishing -- always remove it.
2923                         remove = true;
2924                     } else if (r.launchCount > 2 &&
2925                             r.lastLaunchTime > (SystemClock.uptimeMillis()-60000)) {
2926                         // We have launched this activity too many times since it was
2927                         // able to run, so give up and remove it.
2928                         remove = true;
2929                     } else {
2930                         // The process may be gone, but the activity lives on!
2931                         remove = false;
2932                     }
2933                     if (remove) {
2934                         if (DEBUG_ADD_REMOVE || DEBUG_CLEANUP) {
2935                             RuntimeException here = new RuntimeException("here");
2936                             here.fillInStackTrace();
2937                             Slog.i(TAG, "Removing activity " + r + " from stack at " + i
2938                                     + ": haveState=" + r.haveState
2939                                     + " stateNotNeeded=" + r.stateNotNeeded
2940                                     + " finishing=" + r.finishing
2941                                     + " state=" + r.state, here);
2942                         }
2943                         if (!r.finishing) {
2944                             Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
2945                             EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
2946                                     r.userId, System.identityHashCode(r),
2947                                     r.task.taskId, r.shortComponentName,
2948                                     "proc died without state saved");
2949                             if (r.state == ActivityState.RESUMED) {
2950                                 mService.updateUsageStats(r, false);
2951                             }
2952                         }
2953                         removeActivityFromHistoryLocked(r);
2954 
2955                     } else {
2956                         // We have the current state for this activity, so
2957                         // it can be restarted later when needed.
2958                         if (localLOGV) Slog.v(
2959                             TAG, "Keeping entry, setting app to null");
2960                         if (r.visible) {
2961                             hasVisibleActivities = true;
2962                         }
2963                         if (DEBUG_APP) Slog.v(TAG, "Clearing app during removeHistory for activity "
2964                                 + r);
2965                         r.app = null;
2966                         r.nowVisible = false;
2967                         if (!r.haveState) {
2968                             if (DEBUG_SAVED_STATE) Slog.i(TAG,
2969                                     "App died, clearing saved state of " + r);
2970                             r.icicle = null;
2971                         }
2972                     }
2973 
2974                     cleanUpActivityLocked(r, true, true);
2975                 }
2976             }
2977         }
2978 
2979         return hasVisibleActivities;
2980     }
2981 
updateTransitLocked(int transit, Bundle options)2982     final void updateTransitLocked(int transit, Bundle options) {
2983         if (options != null) {
2984             ActivityRecord r = topRunningActivityLocked(null);
2985             if (r != null && r.state != ActivityState.RESUMED) {
2986                 r.updateOptionsLocked(options);
2987             } else {
2988                 ActivityOptions.abort(options);
2989             }
2990         }
2991         mWindowManager.prepareAppTransition(transit, false);
2992     }
2993 
moveHomeTaskToTop()2994     void moveHomeTaskToTop() {
2995         final int top = mTaskHistory.size() - 1;
2996         for (int taskNdx = top; taskNdx >= 0; --taskNdx) {
2997             final TaskRecord task = mTaskHistory.get(taskNdx);
2998             if (task.isHomeTask()) {
2999                 if (DEBUG_TASKS || DEBUG_STACK) Slog.d(TAG, "moveHomeTaskToTop: moving " + task);
3000                 mTaskHistory.remove(taskNdx);
3001                 mTaskHistory.add(top, task);
3002                 mWindowManager.moveTaskToTop(task.taskId);
3003                 return;
3004             }
3005         }
3006     }
3007 
findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options)3008     final boolean findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
3009         final TaskRecord task = taskForIdLocked(taskId);
3010         if (task != null) {
3011             if ((flags & ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
3012                 mStackSupervisor.mUserLeaving = true;
3013             }
3014             if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
3015                 // Caller wants the home activity moved with it.  To accomplish this,
3016                 // we'll just indicate that this task returns to the home task.
3017                 task.mOnTopOfHome = true;
3018             }
3019             moveTaskToFrontLocked(task, null, options);
3020             return true;
3021         }
3022         return false;
3023     }
3024 
moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options)3025     final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
3026         if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
3027 
3028         final int numTasks = mTaskHistory.size();
3029         final int index = mTaskHistory.indexOf(tr);
3030         if (numTasks == 0 || index < 0)  {
3031             // nothing to do!
3032             if (reason != null &&
3033                     (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
3034                 ActivityOptions.abort(options);
3035             } else {
3036                 updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
3037             }
3038             return;
3039         }
3040 
3041         mStackSupervisor.moveHomeStack(isHomeStack());
3042 
3043         // Shift all activities with this task up to the top
3044         // of the stack, keeping them in the same internal order.
3045         insertTaskAtTop(tr);
3046 
3047         if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare to front transition: task=" + tr);
3048         if (reason != null &&
3049                 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
3050             mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
3051             ActivityRecord r = topRunningActivityLocked(null);
3052             if (r != null) {
3053                 mNoAnimActivities.add(r);
3054             }
3055             ActivityOptions.abort(options);
3056         } else {
3057             updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
3058         }
3059 
3060         mWindowManager.moveTaskToTop(tr.taskId);
3061 
3062         mStackSupervisor.resumeTopActivitiesLocked();
3063         EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
3064 
3065         if (VALIDATE_TOKENS) {
3066             validateAppTokensLocked();
3067         }
3068     }
3069 
3070     /**
3071      * Worker method for rearranging history stack. Implements the function of moving all
3072      * activities for a specific task (gathering them if disjoint) into a single group at the
3073      * bottom of the stack.
3074      *
3075      * If a watcher is installed, the action is preflighted and the watcher has an opportunity
3076      * to premeptively cancel the move.
3077      *
3078      * @param taskId The taskId to collect and move to the bottom.
3079      * @return Returns true if the move completed, false if not.
3080      */
moveTaskToBackLocked(int taskId, ActivityRecord reason)3081     final boolean moveTaskToBackLocked(int taskId, ActivityRecord reason) {
3082         Slog.i(TAG, "moveTaskToBack: " + taskId);
3083 
3084         // If we have a watcher, preflight the move before committing to it.  First check
3085         // for *other* available tasks, but if none are available, then try again allowing the
3086         // current task to be selected.
3087         if (mStackSupervisor.isFrontStack(this) && mService.mController != null) {
3088             ActivityRecord next = topRunningActivityLocked(null, taskId);
3089             if (next == null) {
3090                 next = topRunningActivityLocked(null, 0);
3091             }
3092             if (next != null) {
3093                 // ask watcher if this is allowed
3094                 boolean moveOK = true;
3095                 try {
3096                     moveOK = mService.mController.activityResuming(next.packageName);
3097                 } catch (RemoteException e) {
3098                     mService.mController = null;
3099                     Watchdog.getInstance().setActivityController(null);
3100                 }
3101                 if (!moveOK) {
3102                     return false;
3103                 }
3104             }
3105         }
3106 
3107         if (DEBUG_TRANSITION) Slog.v(TAG,
3108                 "Prepare to back transition: task=" + taskId);
3109 
3110         final TaskRecord tr = taskForIdLocked(taskId);
3111         if (tr == null) {
3112             return false;
3113         }
3114 
3115         mTaskHistory.remove(tr);
3116         mTaskHistory.add(0, tr);
3117 
3118         // There is an assumption that moving a task to the back moves it behind the home activity.
3119         // We make sure here that some activity in the stack will launch home.
3120         ActivityRecord lastActivity = null;
3121         int numTasks = mTaskHistory.size();
3122         for (int taskNdx = numTasks - 1; taskNdx >= 1; --taskNdx) {
3123             final TaskRecord task = mTaskHistory.get(taskNdx);
3124             if (task.mOnTopOfHome) {
3125                 break;
3126             }
3127             if (taskNdx == 1) {
3128                 // Set the last task before tr to go to home.
3129                 task.mOnTopOfHome = true;
3130             }
3131         }
3132 
3133         if (reason != null &&
3134                 (reason.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
3135             mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
3136             ActivityRecord r = topRunningActivityLocked(null);
3137             if (r != null) {
3138                 mNoAnimActivities.add(r);
3139             }
3140         } else {
3141             mWindowManager.prepareAppTransition(AppTransition.TRANSIT_TASK_TO_BACK, false);
3142         }
3143         mWindowManager.moveTaskToBottom(taskId);
3144 
3145         if (VALIDATE_TOKENS) {
3146             validateAppTokensLocked();
3147         }
3148 
3149         final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null;
3150         if (task == tr && task.mOnTopOfHome || numTasks <= 1) {
3151             if (task != null) {
3152                 task.mOnTopOfHome = false;
3153             }
3154             return mStackSupervisor.resumeHomeActivity(null);
3155         }
3156 
3157         mStackSupervisor.resumeTopActivitiesLocked();
3158         return true;
3159     }
3160 
logStartActivity(int tag, ActivityRecord r, TaskRecord task)3161     static final void logStartActivity(int tag, ActivityRecord r,
3162             TaskRecord task) {
3163         final Uri data = r.intent.getData();
3164         final String strData = data != null ? data.toSafeString() : null;
3165 
3166         EventLog.writeEvent(tag,
3167                 r.userId, System.identityHashCode(r), task.taskId,
3168                 r.shortComponentName, r.intent.getAction(),
3169                 r.intent.getType(), strData, r.intent.getFlags());
3170     }
3171 
3172     /**
3173      * Make sure the given activity matches the current configuration.  Returns
3174      * false if the activity had to be destroyed.  Returns true if the
3175      * configuration is the same, or the activity will remain running as-is
3176      * for whatever reason.  Ensures the HistoryRecord is updated with the
3177      * correct configuration and all other bookkeeping is handled.
3178      */
ensureActivityConfigurationLocked(ActivityRecord r, int globalChanges)3179     final boolean ensureActivityConfigurationLocked(ActivityRecord r,
3180             int globalChanges) {
3181         if (mConfigWillChange) {
3182             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3183                     "Skipping config check (will change): " + r);
3184             return true;
3185         }
3186 
3187         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3188                 "Ensuring correct configuration: " + r);
3189 
3190         // Short circuit: if the two configurations are the exact same
3191         // object (the common case), then there is nothing to do.
3192         Configuration newConfig = mService.mConfiguration;
3193         if (r.configuration == newConfig && !r.forceNewConfig) {
3194             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3195                     "Configuration unchanged in " + r);
3196             return true;
3197         }
3198 
3199         // We don't worry about activities that are finishing.
3200         if (r.finishing) {
3201             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3202                     "Configuration doesn't matter in finishing " + r);
3203             r.stopFreezingScreenLocked(false);
3204             return true;
3205         }
3206 
3207         // Okay we now are going to make this activity have the new config.
3208         // But then we need to figure out how it needs to deal with that.
3209         Configuration oldConfig = r.configuration;
3210         r.configuration = newConfig;
3211 
3212         // Determine what has changed.  May be nothing, if this is a config
3213         // that has come back from the app after going idle.  In that case
3214         // we just want to leave the official config object now in the
3215         // activity and do nothing else.
3216         final int changes = oldConfig.diff(newConfig);
3217         if (changes == 0 && !r.forceNewConfig) {
3218             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3219                     "Configuration no differences in " + r);
3220             return true;
3221         }
3222 
3223         // If the activity isn't currently running, just leave the new
3224         // configuration and it will pick that up next time it starts.
3225         if (r.app == null || r.app.thread == null) {
3226             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3227                     "Configuration doesn't matter not running " + r);
3228             r.stopFreezingScreenLocked(false);
3229             r.forceNewConfig = false;
3230             return true;
3231         }
3232 
3233         // Figure out how to handle the changes between the configurations.
3234         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
3235             Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
3236                     + Integer.toHexString(changes) + ", handles=0x"
3237                     + Integer.toHexString(r.info.getRealConfigChanged())
3238                     + ", newConfig=" + newConfig);
3239         }
3240         if ((changes&(~r.info.getRealConfigChanged())) != 0 || r.forceNewConfig) {
3241             // Aha, the activity isn't handling the change, so DIE DIE DIE.
3242             r.configChangeFlags |= changes;
3243             r.startFreezingScreenLocked(r.app, globalChanges);
3244             r.forceNewConfig = false;
3245             if (r.app == null || r.app.thread == null) {
3246                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3247                         "Config is destroying non-running " + r);
3248                 destroyActivityLocked(r, true, false, "config");
3249             } else if (r.state == ActivityState.PAUSING) {
3250                 // A little annoying: we are waiting for this activity to
3251                 // finish pausing.  Let's not do anything now, but just
3252                 // flag that it needs to be restarted when done pausing.
3253                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3254                         "Config is skipping already pausing " + r);
3255                 r.configDestroy = true;
3256                 return true;
3257             } else if (r.state == ActivityState.RESUMED) {
3258                 // Try to optimize this case: the configuration is changing
3259                 // and we need to restart the top, resumed activity.
3260                 // Instead of doing the normal handshaking, just say
3261                 // "restart!".
3262                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3263                         "Config is relaunching resumed " + r);
3264                 relaunchActivityLocked(r, r.configChangeFlags, true);
3265                 r.configChangeFlags = 0;
3266             } else {
3267                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3268                         "Config is relaunching non-resumed " + r);
3269                 relaunchActivityLocked(r, r.configChangeFlags, false);
3270                 r.configChangeFlags = 0;
3271             }
3272 
3273             // All done...  tell the caller we weren't able to keep this
3274             // activity around.
3275             return false;
3276         }
3277 
3278         // Default case: the activity can handle this new configuration, so
3279         // hand it over.  Note that we don't need to give it the new
3280         // configuration, since we always send configuration changes to all
3281         // process when they happen so it can just use whatever configuration
3282         // it last got.
3283         if (r.app != null && r.app.thread != null) {
3284             try {
3285                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
3286                 r.app.thread.scheduleActivityConfigurationChanged(r.appToken);
3287             } catch (RemoteException e) {
3288                 // If process died, whatever.
3289             }
3290         }
3291         r.stopFreezingScreenLocked(false);
3292 
3293         return true;
3294     }
3295 
relaunchActivityLocked(ActivityRecord r, int changes, boolean andResume)3296     private boolean relaunchActivityLocked(ActivityRecord r,
3297             int changes, boolean andResume) {
3298         List<ResultInfo> results = null;
3299         List<Intent> newIntents = null;
3300         if (andResume) {
3301             results = r.results;
3302             newIntents = r.newIntents;
3303         }
3304         if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
3305                 + " with results=" + results + " newIntents=" + newIntents
3306                 + " andResume=" + andResume);
3307         EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
3308                 : EventLogTags.AM_RELAUNCH_ACTIVITY, r.userId, System.identityHashCode(r),
3309                 r.task.taskId, r.shortComponentName);
3310 
3311         r.startFreezingScreenLocked(r.app, 0);
3312 
3313         try {
3314             if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
3315                     (andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ")
3316                     + r);
3317             r.forceNewConfig = false;
3318             r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents,
3319                     changes, !andResume, new Configuration(mService.mConfiguration));
3320             // Note: don't need to call pauseIfSleepingLocked() here, because
3321             // the caller will only pass in 'andResume' if this activity is
3322             // currently resumed, which implies we aren't sleeping.
3323         } catch (RemoteException e) {
3324             if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG, "Relaunch failed", e);
3325         }
3326 
3327         if (andResume) {
3328             r.results = null;
3329             r.newIntents = null;
3330             r.state = ActivityState.RESUMED;
3331         } else {
3332             mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
3333             r.state = ActivityState.PAUSED;
3334         }
3335 
3336         return true;
3337     }
3338 
willActivityBeVisibleLocked(IBinder token)3339     boolean willActivityBeVisibleLocked(IBinder token) {
3340         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3341             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3342             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3343                 final ActivityRecord r = activities.get(activityNdx);
3344                 if (r.appToken == token) {
3345                         return true;
3346                 }
3347                 if (r.fullscreen && !r.finishing) {
3348                     return false;
3349                 }
3350             }
3351         }
3352         return true;
3353     }
3354 
closeSystemDialogsLocked()3355     void closeSystemDialogsLocked() {
3356         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3357             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3358             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3359                 final ActivityRecord r = activities.get(activityNdx);
3360                 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
3361                     finishActivityLocked(r, Activity.RESULT_CANCELED, null, "close-sys", true);
3362                 }
3363             }
3364         }
3365     }
3366 
forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId)3367     boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
3368         boolean didSomething = false;
3369         TaskRecord lastTask = null;
3370         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3371             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3372             int numActivities = activities.size();
3373             for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
3374                 ActivityRecord r = activities.get(activityNdx);
3375                 final boolean samePackage = r.packageName.equals(name)
3376                         || (name == null && r.userId == userId);
3377                 if ((userId == UserHandle.USER_ALL || r.userId == userId)
3378                         && (samePackage || r.task == lastTask)
3379                         && (r.app == null || evenPersistent || !r.app.persistent)) {
3380                     if (!doit) {
3381                         if (r.finishing) {
3382                             // If this activity is just finishing, then it is not
3383                             // interesting as far as something to stop.
3384                             continue;
3385                         }
3386                         return true;
3387                     }
3388                     didSomething = true;
3389                     Slog.i(TAG, "  Force finishing activity " + r);
3390                     if (samePackage) {
3391                         if (r.app != null) {
3392                             r.app.removed = true;
3393                         }
3394                         r.app = null;
3395                     }
3396                     lastTask = r.task;
3397                     if (finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop",
3398                             true)) {
3399                         // r has been deleted from mActivities, accommodate.
3400                         --numActivities;
3401                         --activityNdx;
3402                     }
3403                 }
3404             }
3405         }
3406         return didSomething;
3407     }
3408 
getTasksLocked(IThumbnailReceiver receiver, PendingThumbnailsRecord pending, List<RunningTaskInfo> list)3409     ActivityRecord getTasksLocked(IThumbnailReceiver receiver,
3410             PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
3411         ActivityRecord topRecord = null;
3412         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3413             final TaskRecord task = mTaskHistory.get(taskNdx);
3414             ActivityRecord r = null;
3415             ActivityRecord top = null;
3416             int numActivities = 0;
3417             int numRunning = 0;
3418             final ArrayList<ActivityRecord> activities = task.mActivities;
3419             if (activities.isEmpty()) {
3420                 continue;
3421             }
3422             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3423                 r = activities.get(activityNdx);
3424 
3425                 // Initialize state for next task if needed.
3426                 if (top == null || (top.state == ActivityState.INITIALIZING)) {
3427                     top = r;
3428                     numActivities = numRunning = 0;
3429                 }
3430 
3431                 // Add 'r' into the current task.
3432                 numActivities++;
3433                 if (r.app != null && r.app.thread != null) {
3434                     numRunning++;
3435                 }
3436 
3437                 if (localLOGV) Slog.v(
3438                     TAG, r.intent.getComponent().flattenToShortString()
3439                     + ": task=" + r.task);
3440             }
3441 
3442             RunningTaskInfo ci = new RunningTaskInfo();
3443             ci.id = task.taskId;
3444             ci.baseActivity = r.intent.getComponent();
3445             ci.topActivity = top.intent.getComponent();
3446             ci.lastActiveTime = task.lastActiveTime;
3447 
3448             if (top.thumbHolder != null) {
3449                 ci.description = top.thumbHolder.lastDescription;
3450             }
3451             ci.numActivities = numActivities;
3452             ci.numRunning = numRunning;
3453             //System.out.println(
3454             //    "#" + maxNum + ": " + " descr=" + ci.description);
3455             if (receiver != null) {
3456                 if (localLOGV) Slog.v(
3457                     TAG, "State=" + top.state + "Idle=" + top.idle
3458                     + " app=" + top.app
3459                     + " thr=" + (top.app != null ? top.app.thread : null));
3460                 if (top.state == ActivityState.RESUMED || top.state == ActivityState.PAUSING) {
3461                     if (top.idle && top.app != null && top.app.thread != null) {
3462                         topRecord = top;
3463                     } else {
3464                         top.thumbnailNeeded = true;
3465                     }
3466                 }
3467                 pending.pendingRecords.add(top);
3468             }
3469             list.add(ci);
3470         }
3471         return topRecord;
3472     }
3473 
unhandledBackLocked()3474     public void unhandledBackLocked() {
3475         final int top = mTaskHistory.size() - 1;
3476         if (DEBUG_SWITCH) Slog.d(
3477             TAG, "Performing unhandledBack(): top activity at " + top);
3478         if (top >= 0) {
3479             final ArrayList<ActivityRecord> activities = mTaskHistory.get(top).mActivities;
3480             int activityTop = activities.size() - 1;
3481             if (activityTop > 0) {
3482                 finishActivityLocked(activities.get(activityTop), Activity.RESULT_CANCELED, null,
3483                         "unhandled-back", true);
3484             }
3485         }
3486     }
3487 
3488     /**
3489      * Reset local parameters because an app's activity died.
3490      * @param app The app of the activity that died.
3491      * @return result from removeHistoryRecordsForAppLocked.
3492      */
handleAppDiedLocked(ProcessRecord app)3493     boolean handleAppDiedLocked(ProcessRecord app) {
3494         if (mPausingActivity != null && mPausingActivity.app == app) {
3495             if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG,
3496                     "App died while pausing: " + mPausingActivity);
3497             mPausingActivity = null;
3498         }
3499         if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
3500             mLastPausedActivity = null;
3501             mLastNoHistoryActivity = null;
3502         }
3503 
3504         return removeHistoryRecordsForAppLocked(app);
3505     }
3506 
handleAppCrashLocked(ProcessRecord app)3507     void handleAppCrashLocked(ProcessRecord app) {
3508         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3509             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3510             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3511                 final ActivityRecord r = activities.get(activityNdx);
3512                 if (r.app == app) {
3513                     Slog.w(TAG, "  Force finishing activity "
3514                             + r.intent.getComponent().flattenToShortString());
3515                     finishActivityLocked(r, Activity.RESULT_CANCELED, null, "crashed", false);
3516                 }
3517             }
3518         }
3519     }
3520 
dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient, String dumpPackage, boolean needSep, String header)3521     boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
3522             boolean dumpClient, String dumpPackage, boolean needSep, String header) {
3523         boolean printed = false;
3524         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3525             final TaskRecord task = mTaskHistory.get(taskNdx);
3526             printed |= ActivityStackSupervisor.dumpHistoryList(fd, pw,
3527                     mTaskHistory.get(taskNdx).mActivities, "    ", "Hist", true, !dumpAll,
3528                     dumpClient, dumpPackage, needSep, header,
3529                     "    Task id #" + task.taskId);
3530             if (printed) {
3531                 header = null;
3532             }
3533         }
3534         return printed;
3535     }
3536 
getDumpActivitiesLocked(String name)3537     ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
3538         ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
3539 
3540         if ("all".equals(name)) {
3541             for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3542                 activities.addAll(mTaskHistory.get(taskNdx).mActivities);
3543             }
3544         } else if ("top".equals(name)) {
3545             final int top = mTaskHistory.size() - 1;
3546             if (top >= 0) {
3547                 final ArrayList<ActivityRecord> list = mTaskHistory.get(top).mActivities;
3548                 int listTop = list.size() - 1;
3549                 if (listTop >= 0) {
3550                     activities.add(list.get(listTop));
3551                 }
3552             }
3553         } else {
3554             ItemMatcher matcher = new ItemMatcher();
3555             matcher.build(name);
3556 
3557             for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3558                 for (ActivityRecord r1 : mTaskHistory.get(taskNdx).mActivities) {
3559                     if (matcher.match(r1, r1.intent.getComponent())) {
3560                         activities.add(r1);
3561                     }
3562                 }
3563             }
3564         }
3565 
3566         return activities;
3567     }
3568 
restartPackage(String packageName)3569     ActivityRecord restartPackage(String packageName) {
3570         ActivityRecord starting = topRunningActivityLocked(null);
3571 
3572         // All activities that came from the package must be
3573         // restarted as if there was a config change.
3574         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3575             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3576             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3577                 final ActivityRecord a = activities.get(activityNdx);
3578                 if (a.info.packageName.equals(packageName)) {
3579                     a.forceNewConfig = true;
3580                     if (starting != null && a == starting && a.visible) {
3581                         a.startFreezingScreenLocked(starting.app,
3582                                 ActivityInfo.CONFIG_SCREEN_LAYOUT);
3583                     }
3584                 }
3585             }
3586         }
3587 
3588         return starting;
3589     }
3590 
removeTask(TaskRecord task)3591     boolean removeTask(TaskRecord task) {
3592         final int taskNdx = mTaskHistory.indexOf(task);
3593         final int topTaskNdx = mTaskHistory.size() - 1;
3594         if (task.mOnTopOfHome && taskNdx < topTaskNdx) {
3595             mTaskHistory.get(taskNdx + 1).mOnTopOfHome = true;
3596         }
3597         mTaskHistory.remove(task);
3598         return mTaskHistory.isEmpty();
3599     }
3600 
createTaskRecord(int taskId, ActivityInfo info, Intent intent, boolean toTop)3601     TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent, boolean toTop) {
3602         TaskRecord task = new TaskRecord(taskId, info, intent);
3603         addTask(task, toTop);
3604         return task;
3605     }
3606 
getAllTasks()3607     ArrayList<TaskRecord> getAllTasks() {
3608         return new ArrayList<TaskRecord>(mTaskHistory);
3609     }
3610 
addTask(final TaskRecord task, final boolean toTop)3611     void addTask(final TaskRecord task, final boolean toTop) {
3612         task.stack = this;
3613         if (toTop) {
3614             insertTaskAtTop(task);
3615         } else {
3616             mTaskHistory.add(0, task);
3617         }
3618     }
3619 
getStackId()3620     public int getStackId() {
3621         return mStackId;
3622     }
3623 
3624     @Override
toString()3625     public String toString() {
3626         return "ActivityStack{" + Integer.toHexString(System.identityHashCode(this))
3627                 + " stackId=" + mStackId + ", " + mTaskHistory.size() + " tasks}";
3628     }
3629 }
3630