1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.am;
18 
19 import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
20 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
21 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
22 import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
23 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
24 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
25 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
26 import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
27 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
28 import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
29 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
30 import static android.view.Display.DEFAULT_DISPLAY;
31 import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
32 
33 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
34 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
35 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_APP;
36 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CLEANUP;
37 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONTAINERS;
38 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PAUSE;
39 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RELEASE;
40 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
41 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
42 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
43 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES;
44 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
45 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
46 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TRANSITION;
47 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
48 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY;
49 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_ADD_REMOVE;
50 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_APP;
51 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CLEANUP;
52 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONTAINERS;
53 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PAUSE;
54 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RELEASE;
55 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
56 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SAVED_STATE;
57 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK;
58 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES;
59 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH;
60 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS;
61 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TRANSITION;
62 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
63 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
64 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
65 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
66 import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
67 import static com.android.server.am.ActivityRecord.ASSISTANT_ACTIVITY_TYPE;
68 import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
69 import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
70 import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
71 import static com.android.server.am.ActivityStackSupervisor.FindTaskResult;
72 import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
73 import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
74 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
75 import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
76 import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_CLOSE;
77 import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
78 import static com.android.server.wm.AppTransition.TRANSIT_NONE;
79 import static com.android.server.wm.AppTransition.TRANSIT_TASK_CLOSE;
80 import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN;
81 import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN_BEHIND;
82 import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_BACK;
83 import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_FRONT;
84 import static java.lang.Integer.MAX_VALUE;
85 
86 import android.app.Activity;
87 import android.app.ActivityManager;
88 import android.app.ActivityManager.RunningTaskInfo;
89 import android.app.ActivityManager.StackId;
90 import android.app.ActivityOptions;
91 import android.app.AppGlobals;
92 import android.app.IActivityController;
93 import android.app.ResultInfo;
94 import android.content.ComponentName;
95 import android.content.Intent;
96 import android.content.pm.ActivityInfo;
97 import android.content.pm.ApplicationInfo;
98 import android.content.res.Configuration;
99 import android.graphics.Point;
100 import android.graphics.Rect;
101 import android.net.Uri;
102 import android.os.Binder;
103 import android.os.Bundle;
104 import android.os.Debug;
105 import android.os.Handler;
106 import android.os.IBinder;
107 import android.os.Looper;
108 import android.os.Message;
109 import android.os.RemoteException;
110 import android.os.SystemClock;
111 import android.os.Trace;
112 import android.os.UserHandle;
113 import android.service.voice.IVoiceInteractionSession;
114 import android.util.ArraySet;
115 import android.util.EventLog;
116 import android.util.IntArray;
117 import android.util.Log;
118 import android.util.Slog;
119 import android.util.SparseArray;
120 import android.view.Display;
121 
122 import com.android.internal.annotations.VisibleForTesting;
123 import com.android.internal.app.IVoiceInteractor;
124 import com.android.internal.os.BatteryStatsImpl;
125 import com.android.server.Watchdog;
126 import com.android.server.am.ActivityManagerService.ItemMatcher;
127 import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
128 import com.android.server.wm.StackWindowController;
129 import com.android.server.wm.StackWindowListener;
130 import com.android.server.wm.WindowManagerService;
131 
132 import java.io.FileDescriptor;
133 import java.io.PrintWriter;
134 import java.lang.ref.WeakReference;
135 import java.util.ArrayList;
136 import java.util.Iterator;
137 import java.util.List;
138 import java.util.Objects;
139 import java.util.Set;
140 
141 /**
142  * State and management of a single stack of activities.
143  */
144 class ActivityStack<T extends StackWindowController> extends ConfigurationContainer
145         implements StackWindowListener {
146 
147     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_AM;
148     private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
149     private static final String TAG_APP = TAG + POSTFIX_APP;
150     private static final String TAG_CLEANUP = TAG + POSTFIX_CLEANUP;
151     private static final String TAG_CONTAINERS = TAG + POSTFIX_CONTAINERS;
152     private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE;
153     private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
154     private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
155     private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE;
156     private static final String TAG_STACK = TAG + POSTFIX_STACK;
157     private static final String TAG_STATES = TAG + POSTFIX_STATES;
158     private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
159     private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
160     private static final String TAG_TRANSITION = TAG + POSTFIX_TRANSITION;
161     private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
162     private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
163 
164     // Ticks during which we check progress while waiting for an app to launch.
165     static final int LAUNCH_TICK = 500;
166 
167     // How long we wait until giving up on the last activity to pause.  This
168     // is short because it directly impacts the responsiveness of starting the
169     // next activity.
170     private static final int PAUSE_TIMEOUT = 500;
171 
172     // How long we wait for the activity to tell us it has stopped before
173     // giving up.  This is a good amount of time because we really need this
174     // from the application in order to get its saved state.
175     private static final int STOP_TIMEOUT = 10 * 1000;
176 
177     // How long we wait until giving up on an activity telling us it has
178     // finished destroying itself.
179     private static final int DESTROY_TIMEOUT = 10 * 1000;
180 
181     // How long until we reset a task when the user returns to it.  Currently
182     // disabled.
183     private static final long ACTIVITY_INACTIVE_RESET_TIME = 0;
184 
185     // Set to false to disable the preview that is shown while a new activity
186     // is being started.
187     private static final boolean SHOW_APP_STARTING_PREVIEW = true;
188 
189     // How long to wait for all background Activities to redraw following a call to
190     // convertToTranslucent().
191     private static final long TRANSLUCENT_CONVERSION_TIMEOUT = 2000;
192 
193     // How many activities have to be scheduled to stop to force a stop pass.
194     private static final int MAX_STOPPING_TO_FORCE = 3;
195 
196     @Override
getChildCount()197     protected int getChildCount() {
198         return mTaskHistory.size();
199     }
200 
201     @Override
getChildAt(int index)202     protected ConfigurationContainer getChildAt(int index) {
203         return mTaskHistory.get(index);
204     }
205 
206     @Override
getParent()207     protected ConfigurationContainer getParent() {
208         return mActivityContainer.mActivityDisplay;
209     }
210 
211     @Override
onParentChanged()212     void onParentChanged() {
213         super.onParentChanged();
214         mStackSupervisor.updateUIDsPresentOnDisplay();
215     }
216 
217     enum ActivityState {
218         INITIALIZING,
219         RESUMED,
220         PAUSING,
221         PAUSED,
222         STOPPING,
223         STOPPED,
224         FINISHING,
225         DESTROYING,
226         DESTROYED
227     }
228 
229     // Stack is not considered visible.
230     static final int STACK_INVISIBLE = 0;
231     // Stack is considered visible
232     static final int STACK_VISIBLE = 1;
233     // Stack is considered visible, but only becuase it has activity that is visible behind other
234     // activities and there is a specific combination of stacks.
235     static final int STACK_VISIBLE_ACTIVITY_BEHIND = 2;
236 
237     @VisibleForTesting
238     /* The various modes for the method {@link #removeTask}. */
239     // Task is being completely removed from all stacks in the system.
240     protected static final int REMOVE_TASK_MODE_DESTROYING = 0;
241     // Task is being removed from this stack so we can add it to another stack. In the case we are
242     // moving we don't want to perform some operations on the task like removing it from window
243     // manager or recents.
244     static final int REMOVE_TASK_MODE_MOVING = 1;
245     // Similar to {@link #REMOVE_TASK_MODE_MOVING} and the task will be added to the top of its new
246     // stack and the new stack will be on top of all stacks.
247     static final int REMOVE_TASK_MODE_MOVING_TO_TOP = 2;
248 
249     // The height/width divide used when fitting a task within a bounds with method
250     // {@link #fitWithinBounds}.
251     // We always want the task to to be visible in the bounds without affecting its size when
252     // fitting. To make sure this is the case, we don't adjust the task left or top side pass
253     // the input bounds right or bottom side minus the width or height divided by this value.
254     private static final int FIT_WITHIN_BOUNDS_DIVIDER = 3;
255 
256     final ActivityManagerService mService;
257     private final WindowManagerService mWindowManager;
258     T mWindowContainerController;
259     private final RecentTasks mRecentTasks;
260 
261     /**
262      * The back history of all previous (and possibly still
263      * running) activities.  It contains #TaskRecord objects.
264      */
265     private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
266 
267     /**
268      * List of running activities, sorted by recent usage.
269      * The first entry in the list is the least recently used.
270      * It contains HistoryRecord objects.
271      */
272     final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>();
273 
274     /**
275      * Animations that for the current transition have requested not to
276      * be considered for the transition animation.
277      */
278     final ArrayList<ActivityRecord> mNoAnimActivities = new ArrayList<>();
279 
280     /**
281      * When we are in the process of pausing an activity, before starting the
282      * next one, this variable holds the activity that is currently being paused.
283      */
284     ActivityRecord mPausingActivity = null;
285 
286     /**
287      * This is the last activity that we put into the paused state.  This is
288      * used to determine if we need to do an activity transition while sleeping,
289      * when we normally hold the top activity paused.
290      */
291     ActivityRecord mLastPausedActivity = null;
292 
293     /**
294      * Activities that specify No History must be removed once the user navigates away from them.
295      * If the device goes to sleep with such an activity in the paused state then we save it here
296      * and finish it later if another activity replaces it on wakeup.
297      */
298     ActivityRecord mLastNoHistoryActivity = null;
299 
300     /**
301      * Current activity that is resumed, or null if there is none.
302      */
303     ActivityRecord mResumedActivity = null;
304 
305     // The topmost Activity passed to convertToTranslucent(). When non-null it means we are
306     // waiting for all Activities in mUndrawnActivitiesBelowTopTranslucent to be removed as they
307     // are drawn. When the last member of mUndrawnActivitiesBelowTopTranslucent is removed the
308     // Activity in mTranslucentActivityWaiting is notified via
309     // Activity.onTranslucentConversionComplete(false). If a timeout occurs prior to the last
310     // background activity being drawn then the same call will be made with a true value.
311     ActivityRecord mTranslucentActivityWaiting = null;
312     ArrayList<ActivityRecord> mUndrawnActivitiesBelowTopTranslucent = new ArrayList<>();
313 
314     /**
315      * Set when we know we are going to be calling updateConfiguration()
316      * soon, so want to skip intermediate config checks.
317      */
318     boolean mConfigWillChange;
319 
320     /**
321      * When set, will force the stack to report as invisible.
322      */
323     boolean mForceHidden = false;
324 
325     // Whether or not this stack covers the entire screen; by default stacks are fullscreen
326     boolean mFullscreen = true;
327     // Current bounds of the stack or null if fullscreen.
328     Rect mBounds = null;
329 
330     private boolean mUpdateBoundsDeferred;
331     private boolean mUpdateBoundsDeferredCalled;
332     private final Rect mDeferredBounds = new Rect();
333     private final Rect mDeferredTaskBounds = new Rect();
334     private final Rect mDeferredTaskInsetBounds = new Rect();
335 
336     long mLaunchStartTime = 0;
337     long mFullyDrawnStartTime = 0;
338 
339     int mCurrentUser;
340 
341     final int mStackId;
342     final ActivityContainer mActivityContainer;
343     /** The other stacks, in order, on the attached display. Updated at attach/detach time. */
344     ArrayList<ActivityStack> mStacks;
345     /** The attached Display's unique identifier, or -1 if detached */
346     int mDisplayId;
347 
348     /** Temp variables used during override configuration update. */
349     private final SparseArray<Configuration> mTmpConfigs = new SparseArray<>();
350     private final SparseArray<Rect> mTmpBounds = new SparseArray<>();
351     private final SparseArray<Rect> mTmpInsetBounds = new SparseArray<>();
352     private final Rect mTmpRect2 = new Rect();
353 
354     /** Run all ActivityStacks through this */
355     protected final ActivityStackSupervisor mStackSupervisor;
356 
357     private final LaunchingTaskPositioner mTaskPositioner;
358 
359     private boolean mTopActivityOccludesKeyguard;
360     private ActivityRecord mTopDismissingKeyguardActivity;
361 
362     static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
363     static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
364     static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
365     static final int STOP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 4;
366     static final int DESTROY_ACTIVITIES_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 5;
367     static final int TRANSLUCENT_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6;
368     static final int RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG =
369             ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 7;
370 
371     private static class ScheduleDestroyArgs {
372         final ProcessRecord mOwner;
373         final String mReason;
ScheduleDestroyArgs(ProcessRecord owner, String reason)374         ScheduleDestroyArgs(ProcessRecord owner, String reason) {
375             mOwner = owner;
376             mReason = reason;
377         }
378     }
379 
380     final Handler mHandler;
381 
382     private class ActivityStackHandler extends Handler {
383 
ActivityStackHandler(Looper looper)384         ActivityStackHandler(Looper looper) {
385             super(looper);
386         }
387 
388         @Override
handleMessage(Message msg)389         public void handleMessage(Message msg) {
390             switch (msg.what) {
391                 case PAUSE_TIMEOUT_MSG: {
392                     ActivityRecord r = (ActivityRecord)msg.obj;
393                     // We don't at this point know if the activity is fullscreen,
394                     // so we need to be conservative and assume it isn't.
395                     Slog.w(TAG, "Activity pause timeout for " + r);
396                     synchronized (mService) {
397                         if (r.app != null) {
398                             mService.logAppTooSlow(r.app, r.pauseTime, "pausing " + r);
399                         }
400                         activityPausedLocked(r.appToken, true);
401                     }
402                 } break;
403                 case LAUNCH_TICK_MSG: {
404                     ActivityRecord r = (ActivityRecord)msg.obj;
405                     synchronized (mService) {
406                         if (r.continueLaunchTickingLocked()) {
407                             mService.logAppTooSlow(r.app, r.launchTickTime, "launching " + r);
408                         }
409                     }
410                 } break;
411                 case DESTROY_TIMEOUT_MSG: {
412                     ActivityRecord r = (ActivityRecord)msg.obj;
413                     // We don't at this point know if the activity is fullscreen,
414                     // so we need to be conservative and assume it isn't.
415                     Slog.w(TAG, "Activity destroy timeout for " + r);
416                     synchronized (mService) {
417                         activityDestroyedLocked(r != null ? r.appToken : null, "destroyTimeout");
418                     }
419                 } break;
420                 case STOP_TIMEOUT_MSG: {
421                     ActivityRecord r = (ActivityRecord)msg.obj;
422                     // We don't at this point know if the activity is fullscreen,
423                     // so we need to be conservative and assume it isn't.
424                     Slog.w(TAG, "Activity stop timeout for " + r);
425                     synchronized (mService) {
426                         if (r.isInHistory()) {
427                             r.activityStoppedLocked(null /* icicle */,
428                                     null /* persistentState */, null /* description */);
429                         }
430                     }
431                 } break;
432                 case DESTROY_ACTIVITIES_MSG: {
433                     ScheduleDestroyArgs args = (ScheduleDestroyArgs)msg.obj;
434                     synchronized (mService) {
435                         destroyActivitiesLocked(args.mOwner, args.mReason);
436                     }
437                 } break;
438                 case TRANSLUCENT_TIMEOUT_MSG: {
439                     synchronized (mService) {
440                         notifyActivityDrawnLocked(null);
441                     }
442                 } break;
443                 case RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG: {
444                     synchronized (mService) {
445                         final ActivityRecord r = getVisibleBehindActivity();
446                         Slog.e(TAG, "Timeout waiting for cancelVisibleBehind player=" + r);
447                         if (r != null) {
448                             mService.killAppAtUsersRequest(r.app, null);
449                         }
450                     }
451                 } break;
452             }
453         }
454     }
455 
numActivities()456     int numActivities() {
457         int count = 0;
458         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
459             count += mTaskHistory.get(taskNdx).mActivities.size();
460         }
461         return count;
462     }
463 
ActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer, RecentTasks recentTasks, boolean onTop)464     ActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer,
465             RecentTasks recentTasks, boolean onTop) {
466         mActivityContainer = activityContainer;
467         mStackSupervisor = activityContainer.getOuter();
468         mService = mStackSupervisor.mService;
469         mHandler = new ActivityStackHandler(mService.mHandler.getLooper());
470         mWindowManager = mService.mWindowManager;
471         mStackId = activityContainer.mStackId;
472         mCurrentUser = mService.mUserController.getCurrentUserIdLocked();
473         mRecentTasks = recentTasks;
474         mTaskPositioner = mStackId == FREEFORM_WORKSPACE_STACK_ID
475                 ? new LaunchingTaskPositioner() : null;
476         final ActivityStackSupervisor.ActivityDisplay display = mActivityContainer.mActivityDisplay;
477         mTmpRect2.setEmpty();
478         mWindowContainerController = createStackWindowController(display.mDisplayId, onTop,
479                 mTmpRect2);
480         activityContainer.mStack = this;
481         mStackSupervisor.mActivityContainers.put(mStackId, activityContainer);
482         postAddToDisplay(display, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop);
483     }
484 
createStackWindowController(int displayId, boolean onTop, Rect outBounds)485     T createStackWindowController(int displayId, boolean onTop, Rect outBounds) {
486         return (T) new StackWindowController(mStackId, this, displayId, onTop, outBounds);
487     }
488 
getWindowContainerController()489     T getWindowContainerController() {
490         return mWindowContainerController;
491     }
492 
493     /** Adds the stack to specified display and calls WindowManager to do the same. */
reparent(ActivityStackSupervisor.ActivityDisplay activityDisplay, boolean onTop)494     void reparent(ActivityStackSupervisor.ActivityDisplay activityDisplay, boolean onTop) {
495         removeFromDisplay();
496         mTmpRect2.setEmpty();
497         postAddToDisplay(activityDisplay, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop);
498         adjustFocusToNextFocusableStackLocked("reparent", true /* allowFocusSelf */);
499         mStackSupervisor.resumeFocusedStackTopActivityLocked();
500         // Update visibility of activities before notifying WM. This way it won't try to resize
501         // windows that are no longer visible.
502         mStackSupervisor.ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
503                 !PRESERVE_WINDOWS);
504         mWindowContainerController.reparent(activityDisplay.mDisplayId, mTmpRect2, onTop);
505     }
506 
507     /**
508      * Updates internal state after adding to new display.
509      * @param activityDisplay New display to which this stack was attached.
510      * @param bounds Updated bounds.
511      */
postAddToDisplay(ActivityStackSupervisor.ActivityDisplay activityDisplay, Rect bounds, boolean onTop)512     private void postAddToDisplay(ActivityStackSupervisor.ActivityDisplay activityDisplay,
513             Rect bounds, boolean onTop) {
514         mDisplayId = activityDisplay.mDisplayId;
515         mStacks = activityDisplay.mStacks;
516         mBounds = bounds != null ? new Rect(bounds) : null;
517         mFullscreen = mBounds == null;
518         if (mTaskPositioner != null) {
519             mTaskPositioner.setDisplay(activityDisplay.mDisplay);
520             mTaskPositioner.configure(mBounds);
521         }
522         onParentChanged();
523 
524         activityDisplay.attachStack(this, findStackInsertIndex(onTop));
525         if (mStackId == DOCKED_STACK_ID) {
526             // If we created a docked stack we want to resize it so it resizes all other stacks
527             // in the system.
528             mStackSupervisor.resizeDockedStackLocked(
529                     mBounds, null, null, null, null, PRESERVE_WINDOWS);
530         }
531     }
532 
533     /**
534      * Updates the inner state of the stack to remove it from its current parent, so it can be
535      * either destroyed completely or re-parented.
536      */
removeFromDisplay()537     private void removeFromDisplay() {
538         mDisplayId = Display.INVALID_DISPLAY;
539         mStacks = null;
540         if (mTaskPositioner != null) {
541             mTaskPositioner.reset();
542         }
543         if (mStackId == DOCKED_STACK_ID) {
544             // If we removed a docked stack we want to resize it so it resizes all other stacks
545             // in the system to fullscreen.
546             mStackSupervisor.resizeDockedStackLocked(
547                     null, null, null, null, null, PRESERVE_WINDOWS);
548         }
549     }
550 
551     /** Removes the stack completely. Also calls WindowManager to do the same on its side. */
remove()552     void remove() {
553         removeFromDisplay();
554         mStackSupervisor.deleteActivityContainerRecord(mStackId);
555         mWindowContainerController.removeContainer();
556         mWindowContainerController = null;
557         onParentChanged();
558     }
559 
getDisplaySize(Point out)560     void getDisplaySize(Point out) {
561         mActivityContainer.mActivityDisplay.mDisplay.getSize(out);
562     }
563 
564     /**
565      * @see ActivityStack.getStackDockedModeBounds(Rect, Rect, Rect, boolean)
566      */
getStackDockedModeBounds(Rect currentTempTaskBounds, Rect outStackBounds, Rect outTempTaskBounds, boolean ignoreVisibility)567     void getStackDockedModeBounds(Rect currentTempTaskBounds, Rect outStackBounds,
568             Rect outTempTaskBounds, boolean ignoreVisibility) {
569         mWindowContainerController.getStackDockedModeBounds(currentTempTaskBounds,
570                 outStackBounds, outTempTaskBounds, ignoreVisibility);
571     }
572 
prepareFreezingTaskBounds()573     void prepareFreezingTaskBounds() {
574         mWindowContainerController.prepareFreezingTaskBounds();
575     }
576 
getWindowContainerBounds(Rect outBounds)577     void getWindowContainerBounds(Rect outBounds) {
578         if (mWindowContainerController != null) {
579             mWindowContainerController.getBounds(outBounds);
580             return;
581         }
582         outBounds.setEmpty();
583     }
584 
getBoundsForNewConfiguration(Rect outBounds)585     void getBoundsForNewConfiguration(Rect outBounds) {
586         mWindowContainerController.getBoundsForNewConfiguration(outBounds);
587     }
588 
positionChildWindowContainerAtTop(TaskRecord child)589     void positionChildWindowContainerAtTop(TaskRecord child) {
590         mWindowContainerController.positionChildAtTop(child.getWindowContainerController(),
591                 true /* includingParents */);
592     }
593 
594     /**
595      * Returns whether to defer the scheduling of the multi-window mode.
596      */
deferScheduleMultiWindowModeChanged()597     boolean deferScheduleMultiWindowModeChanged() {
598         return false;
599     }
600 
601     /**
602      * Defers updating the bounds of the stack. If the stack was resized/repositioned while
603      * deferring, the bounds will update in {@link #continueUpdateBounds()}.
604      */
deferUpdateBounds()605     void deferUpdateBounds() {
606         if (!mUpdateBoundsDeferred) {
607             mUpdateBoundsDeferred = true;
608             mUpdateBoundsDeferredCalled = false;
609         }
610     }
611 
612     /**
613      * Continues updating bounds after updates have been deferred. If there was a resize attempt
614      * between {@link #deferUpdateBounds()} and {@link #continueUpdateBounds()}, the stack will
615      * be resized to that bounds.
616      */
continueUpdateBounds()617     void continueUpdateBounds() {
618         final boolean wasDeferred = mUpdateBoundsDeferred;
619         mUpdateBoundsDeferred = false;
620         if (wasDeferred && mUpdateBoundsDeferredCalled) {
621             resize(mDeferredBounds.isEmpty() ? null : mDeferredBounds,
622                     mDeferredTaskBounds.isEmpty() ? null : mDeferredTaskBounds,
623                     mDeferredTaskInsetBounds.isEmpty() ? null : mDeferredTaskInsetBounds);
624         }
625     }
626 
updateBoundsAllowed(Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds)627     boolean updateBoundsAllowed(Rect bounds, Rect tempTaskBounds,
628             Rect tempTaskInsetBounds) {
629         if (!mUpdateBoundsDeferred) {
630             return true;
631         }
632         if (bounds != null) {
633             mDeferredBounds.set(bounds);
634         } else {
635             mDeferredBounds.setEmpty();
636         }
637         if (tempTaskBounds != null) {
638             mDeferredTaskBounds.set(tempTaskBounds);
639         } else {
640             mDeferredTaskBounds.setEmpty();
641         }
642         if (tempTaskInsetBounds != null) {
643             mDeferredTaskInsetBounds.set(tempTaskInsetBounds);
644         } else {
645             mDeferredTaskInsetBounds.setEmpty();
646         }
647         mUpdateBoundsDeferredCalled = true;
648         return false;
649     }
650 
setBounds(Rect bounds)651     void setBounds(Rect bounds) {
652         mBounds = mFullscreen ? null : new Rect(bounds);
653         if (mTaskPositioner != null) {
654             mTaskPositioner.configure(bounds);
655         }
656     }
657 
topRunningActivityLocked()658     ActivityRecord topRunningActivityLocked() {
659         return topRunningActivityLocked(false /* focusableOnly */);
660     }
661 
topRunningActivityLocked(boolean focusableOnly)662     private ActivityRecord topRunningActivityLocked(boolean focusableOnly) {
663         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
664             ActivityRecord r = mTaskHistory.get(taskNdx).topRunningActivityLocked();
665             if (r != null && (!focusableOnly || r.isFocusable())) {
666                 return r;
667             }
668         }
669         return null;
670     }
671 
topRunningNonOverlayTaskActivity()672     ActivityRecord topRunningNonOverlayTaskActivity() {
673         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
674             final TaskRecord task = mTaskHistory.get(taskNdx);
675             final ArrayList<ActivityRecord> activities = task.mActivities;
676             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
677                 final ActivityRecord r = activities.get(activityNdx);
678                 if (!r.finishing && !r.mTaskOverlay) {
679                     return r;
680                 }
681             }
682         }
683         return null;
684     }
685 
topRunningNonDelayedActivityLocked(ActivityRecord notTop)686     ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
687         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
688             final TaskRecord task = mTaskHistory.get(taskNdx);
689             final ArrayList<ActivityRecord> activities = task.mActivities;
690             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
691                 ActivityRecord r = activities.get(activityNdx);
692                 if (!r.finishing && !r.delayedResume && r != notTop && r.okToShowLocked()) {
693                     return r;
694                 }
695             }
696         }
697         return null;
698     }
699 
700     /**
701      * This is a simplified version of topRunningActivityLocked that provides a number of
702      * optional skip-over modes.  It is intended for use with the ActivityController hook only.
703      *
704      * @param token If non-null, any history records matching this token will be skipped.
705      * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
706      *
707      * @return Returns the HistoryRecord of the next activity on the stack.
708      */
topRunningActivityLocked(IBinder token, int taskId)709     final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) {
710         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
711             TaskRecord task = mTaskHistory.get(taskNdx);
712             if (task.taskId == taskId) {
713                 continue;
714             }
715             ArrayList<ActivityRecord> activities = task.mActivities;
716             for (int i = activities.size() - 1; i >= 0; --i) {
717                 final ActivityRecord r = activities.get(i);
718                 // Note: the taskId check depends on real taskId fields being non-zero
719                 if (!r.finishing && (token != r.appToken) && r.okToShowLocked()) {
720                     return r;
721                 }
722             }
723         }
724         return null;
725     }
726 
topActivity()727     final ActivityRecord topActivity() {
728         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
729             ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
730             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
731                 final ActivityRecord r = activities.get(activityNdx);
732                 if (!r.finishing) {
733                     return r;
734                 }
735             }
736         }
737         return null;
738     }
739 
topTask()740     final TaskRecord topTask() {
741         final int size = mTaskHistory.size();
742         if (size > 0) {
743             return mTaskHistory.get(size - 1);
744         }
745         return null;
746     }
747 
taskForIdLocked(int id)748     TaskRecord taskForIdLocked(int id) {
749         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
750             final TaskRecord task = mTaskHistory.get(taskNdx);
751             if (task.taskId == id) {
752                 return task;
753             }
754         }
755         return null;
756     }
757 
isInStackLocked(IBinder token)758     ActivityRecord isInStackLocked(IBinder token) {
759         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
760         return isInStackLocked(r);
761     }
762 
isInStackLocked(ActivityRecord r)763     ActivityRecord isInStackLocked(ActivityRecord r) {
764         if (r == null) {
765             return null;
766         }
767         final TaskRecord task = r.getTask();
768         final ActivityStack stack = r.getStack();
769         if (stack != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
770             if (stack != this) Slog.w(TAG,
771                     "Illegal state! task does not point to stack it is in.");
772             return r;
773         }
774         return null;
775     }
776 
isInStackLocked(TaskRecord task)777     boolean isInStackLocked(TaskRecord task) {
778         return mTaskHistory.contains(task);
779     }
780 
781     /** Checks if there are tasks with specific UID in the stack. */
isUidPresent(int uid)782     boolean isUidPresent(int uid) {
783         for (TaskRecord task : mTaskHistory) {
784             for (ActivityRecord r : task.mActivities) {
785                 if (r.getUid() == uid) {
786                     return true;
787                 }
788             }
789         }
790         return false;
791     }
792 
793     /** Get all UIDs that are present in the stack. */
getPresentUIDs(IntArray presentUIDs)794     void getPresentUIDs(IntArray presentUIDs) {
795         for (TaskRecord task : mTaskHistory) {
796             for (ActivityRecord r : task.mActivities) {
797                 presentUIDs.add(r.getUid());
798             }
799         }
800     }
801 
removeActivitiesFromLRUListLocked(TaskRecord task)802     final void removeActivitiesFromLRUListLocked(TaskRecord task) {
803         for (ActivityRecord r : task.mActivities) {
804             mLRUActivities.remove(r);
805         }
806     }
807 
updateLRUListLocked(ActivityRecord r)808     final boolean updateLRUListLocked(ActivityRecord r) {
809         final boolean hadit = mLRUActivities.remove(r);
810         mLRUActivities.add(r);
811         return hadit;
812     }
813 
isHomeStack()814     final boolean isHomeStack() {
815         return mStackId == HOME_STACK_ID;
816     }
817 
isRecentsStack()818     final boolean isRecentsStack() {
819         return mStackId == RECENTS_STACK_ID;
820     }
821 
isHomeOrRecentsStack()822     final boolean isHomeOrRecentsStack() {
823         return StackId.isHomeOrRecentsStack(mStackId);
824     }
825 
isDockedStack()826     final boolean isDockedStack() {
827         return mStackId == DOCKED_STACK_ID;
828     }
829 
isPinnedStack()830     final boolean isPinnedStack() {
831         return mStackId == PINNED_STACK_ID;
832     }
833 
isAssistantStack()834     final boolean isAssistantStack() {
835         return mStackId == ASSISTANT_STACK_ID;
836     }
837 
isOnHomeDisplay()838     final boolean isOnHomeDisplay() {
839         return isAttached() &&
840                 mActivityContainer.mActivityDisplay.mDisplayId == DEFAULT_DISPLAY;
841     }
842 
moveToFront(String reason)843     void moveToFront(String reason) {
844         moveToFront(reason, null);
845     }
846 
847     /**
848      * @param reason The reason for moving the stack to the front.
849      * @param task If non-null, the task will be moved to the top of the stack.
850      * */
moveToFront(String reason, TaskRecord task)851     void moveToFront(String reason, TaskRecord task) {
852         if (!isAttached()) {
853             return;
854         }
855 
856         mStacks.remove(this);
857         mStacks.add(findStackInsertIndex(ON_TOP), this);
858         mStackSupervisor.setFocusStackUnchecked(reason, this);
859         if (task != null) {
860             insertTaskAtTop(task, null);
861             return;
862         }
863 
864         task = topTask();
865         if (task != null) {
866             mWindowContainerController.positionChildAtTop(task.getWindowContainerController(),
867                     true /* includingParents */);
868         }
869     }
870 
871     /**
872      * @param task If non-null, the task will be moved to the back of the stack.
873      * */
moveToBack(TaskRecord task)874     private void moveToBack(TaskRecord task) {
875         if (!isAttached()) {
876             return;
877         }
878 
879         mStacks.remove(this);
880         mStacks.add(0, this);
881 
882         if (task != null) {
883             mTaskHistory.remove(task);
884             mTaskHistory.add(0, task);
885             updateTaskMovement(task, false);
886             mWindowContainerController.positionChildAtBottom(task.getWindowContainerController());
887         }
888     }
889 
890     /**
891      * @return the index to insert a new stack into, taking the always-on-top stacks into account.
892      */
findStackInsertIndex(boolean onTop)893     private int findStackInsertIndex(boolean onTop) {
894         if (onTop) {
895             int addIndex = mStacks.size();
896             if (addIndex > 0) {
897                 final ActivityStack topStack = mStacks.get(addIndex - 1);
898                 if (StackId.isAlwaysOnTop(topStack.mStackId) && topStack != this) {
899                     // If the top stack is always on top, we move this stack just below it.
900                     addIndex--;
901                 }
902             }
903             return addIndex;
904         } else {
905             return 0;
906         }
907     }
908 
isFocusable()909     boolean isFocusable() {
910         if (StackId.canReceiveKeys(mStackId)) {
911             return true;
912         }
913         // The stack isn't focusable. See if its top activity is focusable to force focus on the
914         // stack.
915         final ActivityRecord r = topRunningActivityLocked();
916         return r != null && r.isFocusable();
917     }
918 
isAttached()919     final boolean isAttached() {
920         return mStacks != null;
921     }
922 
923     /**
924      * Returns the top activity in any existing task matching the given Intent in the input result.
925      * Returns null if no such task is found.
926      */
findTaskLocked(ActivityRecord target, FindTaskResult result)927     void findTaskLocked(ActivityRecord target, FindTaskResult result) {
928         Intent intent = target.intent;
929         ActivityInfo info = target.info;
930         ComponentName cls = intent.getComponent();
931         if (info.targetActivity != null) {
932             cls = new ComponentName(info.packageName, info.targetActivity);
933         }
934         final int userId = UserHandle.getUserId(info.applicationInfo.uid);
935         boolean isDocument = intent != null & intent.isDocument();
936         // If documentData is non-null then it must match the existing task data.
937         Uri documentData = isDocument ? intent.getData() : null;
938 
939         if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + target + " in " + this);
940         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
941             final TaskRecord task = mTaskHistory.get(taskNdx);
942             if (task.voiceSession != null) {
943                 // We never match voice sessions; those always run independently.
944                 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": voice session");
945                 continue;
946             }
947             if (task.userId != userId) {
948                 // Looking for a different task.
949                 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": different user");
950                 continue;
951             }
952             final ActivityRecord r = task.getTopActivity();
953             if (r == null || r.finishing || r.userId != userId ||
954                     r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
955                 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r);
956                 continue;
957             }
958             if (r.mActivityType != target.mActivityType) {
959                 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch activity type");
960                 continue;
961             }
962 
963             final Intent taskIntent = task.intent;
964             final Intent affinityIntent = task.affinityIntent;
965             final boolean taskIsDocument;
966             final Uri taskDocumentData;
967             if (taskIntent != null && taskIntent.isDocument()) {
968                 taskIsDocument = true;
969                 taskDocumentData = taskIntent.getData();
970             } else if (affinityIntent != null && affinityIntent.isDocument()) {
971                 taskIsDocument = true;
972                 taskDocumentData = affinityIntent.getData();
973             } else {
974                 taskIsDocument = false;
975                 taskDocumentData = null;
976             }
977 
978             if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls="
979                     + taskIntent.getComponent().flattenToShortString()
980                     + "/aff=" + r.getTask().rootAffinity + " to new cls="
981                     + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
982             // TODO Refactor to remove duplications. Check if logic can be simplified.
983             if (taskIntent != null && taskIntent.getComponent() != null &&
984                     taskIntent.getComponent().compareTo(cls) == 0 &&
985                     Objects.equals(documentData, taskDocumentData)) {
986                 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
987                 //dump();
988                 if (DEBUG_TASKS) Slog.d(TAG_TASKS,
989                         "For Intent " + intent + " bringing to top: " + r.intent);
990                 result.r = r;
991                 result.matchedByRootAffinity = false;
992                 break;
993             } else if (affinityIntent != null && affinityIntent.getComponent() != null &&
994                     affinityIntent.getComponent().compareTo(cls) == 0 &&
995                     Objects.equals(documentData, taskDocumentData)) {
996                 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
997                 //dump();
998                 if (DEBUG_TASKS) Slog.d(TAG_TASKS,
999                         "For Intent " + intent + " bringing to top: " + r.intent);
1000                 result.r = r;
1001                 result.matchedByRootAffinity = false;
1002                 break;
1003             } else if (!isDocument && !taskIsDocument
1004                     && result.r == null && task.rootAffinity != null) {
1005                 if (task.rootAffinity.equals(target.taskAffinity)) {
1006                     if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching affinity candidate!");
1007                     // It is possible for multiple tasks to have the same root affinity especially
1008                     // if they are in separate stacks. We save off this candidate, but keep looking
1009                     // to see if there is a better candidate.
1010                     result.r = r;
1011                     result.matchedByRootAffinity = true;
1012                 }
1013             } else if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Not a match: " + task);
1014         }
1015     }
1016 
1017     /**
1018      * Returns the first activity (starting from the top of the stack) that
1019      * is the same as the given activity.  Returns null if no such activity
1020      * is found.
1021      */
findActivityLocked(Intent intent, ActivityInfo info, boolean compareIntentFilters)1022     ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
1023                                       boolean compareIntentFilters) {
1024         ComponentName cls = intent.getComponent();
1025         if (info.targetActivity != null) {
1026             cls = new ComponentName(info.packageName, info.targetActivity);
1027         }
1028         final int userId = UserHandle.getUserId(info.applicationInfo.uid);
1029 
1030         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1031             final TaskRecord task = mTaskHistory.get(taskNdx);
1032             final ArrayList<ActivityRecord> activities = task.mActivities;
1033 
1034             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1035                 ActivityRecord r = activities.get(activityNdx);
1036                 if (!r.okToShowLocked()) {
1037                     continue;
1038                 }
1039                 if (!r.finishing && r.userId == userId) {
1040                     if (compareIntentFilters) {
1041                         if (r.intent.filterEquals(intent)) {
1042                             return r;
1043                         }
1044                     } else {
1045                         if (r.intent.getComponent().equals(cls)) {
1046                             return r;
1047                         }
1048                     }
1049                 }
1050             }
1051         }
1052 
1053         return null;
1054     }
1055 
1056     /*
1057      * Move the activities around in the stack to bring a user to the foreground.
1058      */
switchUserLocked(int userId)1059     final void switchUserLocked(int userId) {
1060         if (mCurrentUser == userId) {
1061             return;
1062         }
1063         mCurrentUser = userId;
1064 
1065         // Move userId's tasks to the top.
1066         int index = mTaskHistory.size();
1067         for (int i = 0; i < index; ) {
1068             final TaskRecord task = mTaskHistory.get(i);
1069 
1070             if (task.okToShowLocked()) {
1071                 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "switchUserLocked: stack=" + getStackId() +
1072                         " moving " + task + " to top");
1073                 mTaskHistory.remove(i);
1074                 mTaskHistory.add(task);
1075                 --index;
1076                 // Use same value for i.
1077             } else {
1078                 ++i;
1079             }
1080         }
1081     }
1082 
minimalResumeActivityLocked(ActivityRecord r)1083     void minimalResumeActivityLocked(ActivityRecord r) {
1084         if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + r + " (starting new instance)"
1085                 + " callers=" + Debug.getCallers(5));
1086         setResumedActivityLocked(r, "minimalResumeActivityLocked");
1087         r.completeResumeLocked();
1088         setLaunchTime(r);
1089         if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE,
1090                 "Launch completed; removing icicle of " + r.icicle);
1091     }
1092 
addRecentActivityLocked(ActivityRecord r)1093     void addRecentActivityLocked(ActivityRecord r) {
1094         if (r != null) {
1095             final TaskRecord task = r.getTask();
1096             mRecentTasks.addLocked(task);
1097             task.touchActiveTime();
1098         }
1099     }
1100 
startLaunchTraces(String packageName)1101     private void startLaunchTraces(String packageName) {
1102         if (mFullyDrawnStartTime != 0)  {
1103             Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
1104         }
1105         Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching: " + packageName, 0);
1106         Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
1107     }
1108 
stopFullyDrawnTraceIfNeeded()1109     private void stopFullyDrawnTraceIfNeeded() {
1110         if (mFullyDrawnStartTime != 0 && mLaunchStartTime == 0) {
1111             Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
1112             mFullyDrawnStartTime = 0;
1113         }
1114     }
1115 
setLaunchTime(ActivityRecord r)1116     void setLaunchTime(ActivityRecord r) {
1117         if (r.displayStartTime == 0) {
1118             r.fullyDrawnStartTime = r.displayStartTime = SystemClock.uptimeMillis();
1119             if (mLaunchStartTime == 0) {
1120                 startLaunchTraces(r.packageName);
1121                 mLaunchStartTime = mFullyDrawnStartTime = r.displayStartTime;
1122             }
1123         } else if (mLaunchStartTime == 0) {
1124             startLaunchTraces(r.packageName);
1125             mLaunchStartTime = mFullyDrawnStartTime = SystemClock.uptimeMillis();
1126         }
1127     }
1128 
clearLaunchTime(ActivityRecord r)1129     private void clearLaunchTime(ActivityRecord r) {
1130         // Make sure that there is no activity waiting for this to launch.
1131         if (mStackSupervisor.mWaitingActivityLaunched.isEmpty()) {
1132             r.displayStartTime = r.fullyDrawnStartTime = 0;
1133         } else {
1134             mStackSupervisor.removeTimeoutsForActivityLocked(r);
1135             mStackSupervisor.scheduleIdleTimeoutLocked(r);
1136         }
1137     }
1138 
awakeFromSleepingLocked()1139     void awakeFromSleepingLocked() {
1140         // Ensure activities are no longer sleeping.
1141         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1142             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
1143             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1144                 activities.get(activityNdx).setSleeping(false);
1145             }
1146         }
1147         if (mPausingActivity != null) {
1148             Slog.d(TAG, "awakeFromSleepingLocked: previously pausing activity didn't pause");
1149             activityPausedLocked(mPausingActivity.appToken, true);
1150         }
1151     }
1152 
updateActivityApplicationInfoLocked(ApplicationInfo aInfo)1153     void updateActivityApplicationInfoLocked(ApplicationInfo aInfo) {
1154         final String packageName = aInfo.packageName;
1155         final int userId = UserHandle.getUserId(aInfo.uid);
1156 
1157         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1158             final List<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
1159             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1160                 final ActivityRecord ar = activities.get(activityNdx);
1161 
1162                 if ((userId == ar.userId) && packageName.equals(ar.packageName)) {
1163                     ar.info.applicationInfo = aInfo;
1164                 }
1165             }
1166         }
1167     }
1168 
1169     /**
1170      * @return true if something must be done before going to sleep.
1171      */
checkReadyForSleepLocked()1172     boolean checkReadyForSleepLocked() {
1173         if (mResumedActivity != null) {
1174             // Still have something resumed; can't sleep until it is paused.
1175             if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep needs to pause " + mResumedActivity);
1176             if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1177                     "Sleep => pause with userLeaving=false");
1178 
1179             // If we are in the middle of resuming the top activity in
1180             // {@link #resumeTopActivityUncheckedLocked}, mResumedActivity will be set but not
1181             // resumed yet. We must not proceed pausing the activity here. This method will be
1182             // called again if necessary as part of
1183             // {@link ActivityStackSupervisor#checkReadyForSleepLocked}.
1184             if (mStackSupervisor.inResumeTopActivity) {
1185                 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "In the middle of resuming top activity "
1186                         + mResumedActivity);
1187                 return true;
1188             }
1189 
1190             startPausingLocked(false, true, null, false);
1191             return true;
1192         }
1193         if (mPausingActivity != null) {
1194             // Still waiting for something to pause; can't sleep yet.
1195             if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still waiting to pause " + mPausingActivity);
1196             return true;
1197         }
1198 
1199         if (hasVisibleBehindActivity()) {
1200             // Stop visible behind activity before going to sleep.
1201             final ActivityRecord r = getVisibleBehindActivity();
1202             mStackSupervisor.mStoppingActivities.add(r);
1203             if (DEBUG_STATES) Slog.v(TAG_STATES, "Sleep still waiting to stop visible behind " + r);
1204             return true;
1205         }
1206 
1207         return false;
1208     }
1209 
goToSleep()1210     void goToSleep() {
1211         ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
1212 
1213         // Make sure any paused or stopped but visible activities are now sleeping.
1214         // This ensures that the activity's onStop() is called.
1215         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1216             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
1217             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1218                 final ActivityRecord r = activities.get(activityNdx);
1219                 if (r.state == STOPPING || r.state == STOPPED
1220                         || r.state == ActivityState.PAUSED || r.state == ActivityState.PAUSING) {
1221                     r.setSleeping(true);
1222                 }
1223             }
1224         }
1225     }
1226 
1227     /**
1228      * Schedule a pause timeout in case the app doesn't respond. We don't give it much time because
1229      * this directly impacts the responsiveness seen by the user.
1230      */
schedulePauseTimeout(ActivityRecord r)1231     private void schedulePauseTimeout(ActivityRecord r) {
1232         final Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
1233         msg.obj = r;
1234         r.pauseTime = SystemClock.uptimeMillis();
1235         mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
1236         if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete...");
1237     }
1238 
1239     /**
1240      * Start pausing the currently resumed activity.  It is an error to call this if there
1241      * is already an activity being paused or there is no resumed activity.
1242      *
1243      * @param userLeaving True if this should result in an onUserLeaving to the current activity.
1244      * @param uiSleeping True if this is happening with the user interface going to sleep (the
1245      * screen turning off).
1246      * @param resuming The activity we are currently trying to resume or null if this is not being
1247      *                 called as part of resuming the top activity, so we shouldn't try to instigate
1248      *                 a resume here if not null.
1249      * @param pauseImmediately True if the caller does not want to wait for the activity callback to
1250      *                         complete pausing.
1251      * @return Returns true if an activity now is in the PAUSING state, and we are waiting for
1252      * it to tell us when it is done.
1253      */
startPausingLocked(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming, boolean pauseImmediately)1254     final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
1255             ActivityRecord resuming, boolean pauseImmediately) {
1256         if (mPausingActivity != null) {
1257             Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
1258                     + " state=" + mPausingActivity.state);
1259             if (!mService.isSleepingLocked()) {
1260                 // Avoid recursion among check for sleep and complete pause during sleeping.
1261                 // Because activity will be paused immediately after resume, just let pause
1262                 // be completed by the order of activity paused from clients.
1263                 completePauseLocked(false, resuming);
1264             }
1265         }
1266         ActivityRecord prev = mResumedActivity;
1267 
1268         if (prev == null) {
1269             if (resuming == null) {
1270                 Slog.wtf(TAG, "Trying to pause when nothing is resumed");
1271                 mStackSupervisor.resumeFocusedStackTopActivityLocked();
1272             }
1273             return false;
1274         }
1275 
1276         if (mActivityContainer.mParentActivity == null) {
1277             // Top level stack, not a child. Look for child stacks.
1278             mStackSupervisor.pauseChildStacks(prev, userLeaving, uiSleeping, resuming,
1279                     pauseImmediately);
1280         }
1281 
1282         if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev);
1283         else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev);
1284         mResumedActivity = null;
1285         mPausingActivity = prev;
1286         mLastPausedActivity = prev;
1287         mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
1288                 || (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
1289         prev.state = ActivityState.PAUSING;
1290         prev.getTask().touchActiveTime();
1291         clearLaunchTime(prev);
1292         final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
1293         if (mService.mHasRecents
1294                 && (next == null || next.noDisplay || next.getTask() != prev.getTask()
1295                 || uiSleeping)) {
1296             prev.mUpdateTaskThumbnailWhenHidden = true;
1297         }
1298         stopFullyDrawnTraceIfNeeded();
1299 
1300         mService.updateCpuStats();
1301 
1302         if (prev.app != null && prev.app.thread != null) {
1303             if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
1304             try {
1305                 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
1306                         prev.userId, System.identityHashCode(prev),
1307                         prev.shortComponentName);
1308                 mService.updateUsageStats(prev, false);
1309                 prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
1310                         userLeaving, prev.configChangeFlags, pauseImmediately);
1311             } catch (Exception e) {
1312                 // Ignore exception, if process died other code will cleanup.
1313                 Slog.w(TAG, "Exception thrown during pause", e);
1314                 mPausingActivity = null;
1315                 mLastPausedActivity = null;
1316                 mLastNoHistoryActivity = null;
1317             }
1318         } else {
1319             mPausingActivity = null;
1320             mLastPausedActivity = null;
1321             mLastNoHistoryActivity = null;
1322         }
1323 
1324         // If we are not going to sleep, we want to ensure the device is
1325         // awake until the next activity is started.
1326         if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) {
1327             mStackSupervisor.acquireLaunchWakelock();
1328         }
1329 
1330         if (mPausingActivity != null) {
1331             // Have the window manager pause its key dispatching until the new
1332             // activity has started.  If we're pausing the activity just because
1333             // the screen is being turned off and the UI is sleeping, don't interrupt
1334             // key dispatch; the same activity will pick it up again on wakeup.
1335             if (!uiSleeping) {
1336                 prev.pauseKeyDispatchingLocked();
1337             } else if (DEBUG_PAUSE) {
1338                  Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off");
1339             }
1340 
1341             if (pauseImmediately) {
1342                 // If the caller said they don't want to wait for the pause, then complete
1343                 // the pause now.
1344                 completePauseLocked(false, resuming);
1345                 return false;
1346 
1347             } else {
1348                 schedulePauseTimeout(prev);
1349                 return true;
1350             }
1351 
1352         } else {
1353             // This activity failed to schedule the
1354             // pause, so just treat it as being paused now.
1355             if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next.");
1356             if (resuming == null) {
1357                 mStackSupervisor.resumeFocusedStackTopActivityLocked();
1358             }
1359             return false;
1360         }
1361     }
1362 
activityPausedLocked(IBinder token, boolean timeout)1363     final void activityPausedLocked(IBinder token, boolean timeout) {
1364         if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,
1365             "Activity paused: token=" + token + ", timeout=" + timeout);
1366 
1367         final ActivityRecord r = isInStackLocked(token);
1368         if (r != null) {
1369             mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
1370             if (mPausingActivity == r) {
1371                 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r
1372                         + (timeout ? " (due to timeout)" : " (pause complete)"));
1373                 mService.mWindowManager.deferSurfaceLayout();
1374                 try {
1375                     completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
1376                 } finally {
1377                     mService.mWindowManager.continueSurfaceLayout();
1378                 }
1379                 return;
1380             } else {
1381                 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
1382                         r.userId, System.identityHashCode(r), r.shortComponentName,
1383                         mPausingActivity != null
1384                             ? mPausingActivity.shortComponentName : "(none)");
1385                 if (r.state == ActivityState.PAUSING) {
1386                     r.state = ActivityState.PAUSED;
1387                     if (r.finishing) {
1388                         if (DEBUG_PAUSE) Slog.v(TAG,
1389                                 "Executing finish of failed to pause activity: " + r);
1390                         finishCurrentActivityLocked(r, FINISH_AFTER_VISIBLE, false);
1391                     }
1392                 }
1393             }
1394         }
1395         mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
1396     }
1397 
completePauseLocked(boolean resumeNext, ActivityRecord resuming)1398     private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
1399         ActivityRecord prev = mPausingActivity;
1400         if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);
1401 
1402         if (prev != null) {
1403             final boolean wasStopping = prev.state == STOPPING;
1404             prev.state = ActivityState.PAUSED;
1405             if (prev.finishing) {
1406                 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);
1407                 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false);
1408             } else if (prev.app != null) {
1409                 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev
1410                         + " wasStopping=" + wasStopping + " visible=" + prev.visible);
1411                 if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(prev)) {
1412                     if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG_PAUSE,
1413                             "Complete pause, no longer waiting: " + prev);
1414                 }
1415                 if (prev.deferRelaunchUntilPaused) {
1416                     // Complete the deferred relaunch that was waiting for pause to complete.
1417                     if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev);
1418                     prev.relaunchActivityLocked(false /* andResume */,
1419                             prev.preserveWindowOnDeferredRelaunch);
1420                 } else if (wasStopping) {
1421                     // We are also stopping, the stop request must have gone soon after the pause.
1422                     // We can't clobber it, because the stop confirmation will not be handled.
1423                     // We don't need to schedule another stop, we only need to let it happen.
1424                     prev.state = STOPPING;
1425                 } else if ((!prev.visible && !hasVisibleBehindActivity())
1426                         || mService.isSleepingOrShuttingDownLocked()) {
1427                     // Clear out any deferred client hide we might currently have.
1428                     prev.setDeferHidingClient(false);
1429                     // If we were visible then resumeTopActivities will release resources before
1430                     // stopping.
1431                     addToStopping(prev, true /* scheduleIdle */, false /* idleDelayed */);
1432                 }
1433             } else {
1434                 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + prev);
1435                 prev = null;
1436             }
1437             // It is possible the activity was freezing the screen before it was paused.
1438             // In that case go ahead and remove the freeze this activity has on the screen
1439             // since it is no longer visible.
1440             if (prev != null) {
1441                 prev.stopFreezingScreenLocked(true /*force*/);
1442             }
1443             mPausingActivity = null;
1444         }
1445 
1446         if (resumeNext) {
1447             final ActivityStack topStack = mStackSupervisor.getFocusedStack();
1448             if (!mService.isSleepingOrShuttingDownLocked()) {
1449                 mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
1450             } else {
1451                 mStackSupervisor.checkReadyForSleepLocked();
1452                 ActivityRecord top = topStack.topRunningActivityLocked();
1453                 if (top == null || (prev != null && top != prev)) {
1454                     // If there are no more activities available to run, do resume anyway to start
1455                     // something. Also if the top activity on the stack is not the just paused
1456                     // activity, we need to go ahead and resume it to ensure we complete an
1457                     // in-flight app switch.
1458                     mStackSupervisor.resumeFocusedStackTopActivityLocked();
1459                 }
1460             }
1461         }
1462 
1463         if (prev != null) {
1464             prev.resumeKeyDispatchingLocked();
1465 
1466             if (prev.app != null && prev.cpuTimeAtResume > 0
1467                     && mService.mBatteryStatsService.isOnBattery()) {
1468                 long diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid)
1469                         - prev.cpuTimeAtResume;
1470                 if (diff > 0) {
1471                     BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics();
1472                     synchronized (bsi) {
1473                         BatteryStatsImpl.Uid.Proc ps =
1474                                 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
1475                                         prev.info.packageName);
1476                         if (ps != null) {
1477                             ps.addForegroundTimeLocked(diff);
1478                         }
1479                     }
1480                 }
1481             }
1482             prev.cpuTimeAtResume = 0; // reset it
1483         }
1484 
1485         // Notify when the task stack has changed, but only if visibilities changed (not just
1486         // focus). Also if there is an active pinned stack - we always want to notify it about
1487         // task stack changes, because its positioning may depend on it.
1488         if (mStackSupervisor.mAppVisibilitiesChangedSinceLastPause
1489                 || mService.mStackSupervisor.getStack(PINNED_STACK_ID) != null) {
1490             mService.mTaskChangeNotificationController.notifyTaskStackChanged();
1491             mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
1492         }
1493 
1494         mStackSupervisor.ensureActivitiesVisibleLocked(resuming, 0, !PRESERVE_WINDOWS);
1495     }
1496 
addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed)1497     void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed) {
1498         if (!mStackSupervisor.mStoppingActivities.contains(r)) {
1499             mStackSupervisor.mStoppingActivities.add(r);
1500         }
1501 
1502         // If we already have a few activities waiting to stop, then give up
1503         // on things going idle and start clearing them out. Or if r is the
1504         // last of activity of the last task the stack will be empty and must
1505         // be cleared immediately.
1506         boolean forceIdle = mStackSupervisor.mStoppingActivities.size() > MAX_STOPPING_TO_FORCE
1507                 || (r.frontOfTask && mTaskHistory.size() <= 1);
1508         if (scheduleIdle || forceIdle) {
1509             if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Scheduling idle now: forceIdle="
1510                     + forceIdle + "immediate=" + !idleDelayed);
1511             if (!idleDelayed) {
1512                 mStackSupervisor.scheduleIdleLocked();
1513             } else {
1514                 mStackSupervisor.scheduleIdleTimeoutLocked(r);
1515             }
1516         } else {
1517             mStackSupervisor.checkReadyForSleepLocked();
1518         }
1519     }
1520 
1521     // Find the first visible activity above the passed activity and if it is translucent return it
1522     // otherwise return null;
findNextTranslucentActivity(ActivityRecord r)1523     ActivityRecord findNextTranslucentActivity(ActivityRecord r) {
1524         TaskRecord task = r.getTask();
1525         if (task == null) {
1526             return null;
1527         }
1528 
1529         final ActivityStack stack = task.getStack();
1530         if (stack == null) {
1531             return null;
1532         }
1533 
1534         int stackNdx = mStacks.indexOf(stack);
1535 
1536         ArrayList<TaskRecord> tasks = stack.mTaskHistory;
1537         int taskNdx = tasks.indexOf(task);
1538 
1539         ArrayList<ActivityRecord> activities = task.mActivities;
1540         int activityNdx = activities.indexOf(r) + 1;
1541 
1542         final int numStacks = mStacks.size();
1543         while (stackNdx < numStacks) {
1544             final ActivityStack historyStack = mStacks.get(stackNdx);
1545             tasks = historyStack.mTaskHistory;
1546             final int numTasks = tasks.size();
1547             while (taskNdx < numTasks) {
1548                 final TaskRecord currentTask = tasks.get(taskNdx);
1549                 activities = currentTask.mActivities;
1550                 final int numActivities = activities.size();
1551                 while (activityNdx < numActivities) {
1552                     final ActivityRecord activity = activities.get(activityNdx);
1553                     if (!activity.finishing) {
1554                         return historyStack.mFullscreen
1555                                 && currentTask.mFullscreen && activity.fullscreen ? null : activity;
1556                     }
1557                     ++activityNdx;
1558                 }
1559                 activityNdx = 0;
1560                 ++taskNdx;
1561             }
1562             taskNdx = 0;
1563             ++stackNdx;
1564         }
1565 
1566         return null;
1567     }
1568 
1569     /** Returns true if the stack contains a fullscreen task. */
hasFullscreenTask()1570     private boolean hasFullscreenTask() {
1571         for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
1572             final TaskRecord task = mTaskHistory.get(i);
1573             if (task.mFullscreen) {
1574                 return true;
1575             }
1576         }
1577         return false;
1578     }
1579 
1580     /**
1581      * Returns true if the stack is translucent and can have other contents visible behind it if
1582      * needed. A stack is considered translucent if it don't contain a visible or
1583      * starting (about to be visible) activity that is fullscreen (opaque).
1584      * @param starting The currently starting activity or null if there is none.
1585      * @param stackBehindId The id of the stack directly behind this one.
1586      */
isStackTranslucent(ActivityRecord starting, int stackBehindId)1587     private boolean isStackTranslucent(ActivityRecord starting, int stackBehindId) {
1588         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1589             final TaskRecord task = mTaskHistory.get(taskNdx);
1590             final ArrayList<ActivityRecord> activities = task.mActivities;
1591             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1592                 final ActivityRecord r = activities.get(activityNdx);
1593 
1594                 if (r.finishing) {
1595                     // We don't factor in finishing activities when determining translucency since
1596                     // they will be gone soon.
1597                     continue;
1598                 }
1599 
1600                 if (!r.visible && r != starting) {
1601                     // Also ignore invisible activities that are not the currently starting
1602                     // activity (about to be visible).
1603                     continue;
1604                 }
1605 
1606                 if (r.fullscreen) {
1607                     // Stack isn't translucent if it has at least one fullscreen activity
1608                     // that is visible.
1609                     return false;
1610                 }
1611 
1612                 if (!isHomeOrRecentsStack() && r.frontOfTask && task.isOverHomeStack()
1613                         && !StackId.isHomeOrRecentsStack(stackBehindId) && !isAssistantStack()) {
1614                     // Stack isn't translucent if it's top activity should have the home stack
1615                     // behind it and the stack currently behind it isn't the home or recents stack
1616                     // or the assistant stack.
1617                     return false;
1618                 }
1619             }
1620         }
1621         return true;
1622     }
1623 
1624     /** Returns true if the stack is currently considered visible. */
isVisible()1625     boolean isVisible() {
1626         return mWindowContainerController != null && mWindowContainerController.isVisible()
1627                 && !mForceHidden;
1628     }
1629 
1630     /**
1631      * Returns what the stack visibility should be: {@link #STACK_INVISIBLE}, {@link #STACK_VISIBLE}
1632      * or {@link #STACK_VISIBLE_ACTIVITY_BEHIND}.
1633      *
1634      * @param starting The currently starting activity or null if there is none.
1635      */
shouldBeVisible(ActivityRecord starting)1636     int shouldBeVisible(ActivityRecord starting) {
1637         if (!isAttached() || mForceHidden) {
1638             return STACK_INVISIBLE;
1639         }
1640 
1641         if (mStackSupervisor.isFrontStackOnDisplay(this) || mStackSupervisor.isFocusedStack(this)) {
1642             return STACK_VISIBLE;
1643         }
1644 
1645         final int stackIndex = mStacks.indexOf(this);
1646 
1647         if (stackIndex == mStacks.size() - 1) {
1648             Slog.wtf(TAG,
1649                     "Stack=" + this + " isn't front stack but is at the top of the stack list");
1650             return STACK_INVISIBLE;
1651         }
1652 
1653         // Check position and visibility of this stack relative to the front stack on its display.
1654         final ActivityStack topStack = getTopStackOnDisplay();
1655         final int topStackId = topStack.mStackId;
1656 
1657         if (StackId.isBackdropToTranslucentActivity(mStackId)
1658                 && hasVisibleBehindActivity() && StackId.isHomeOrRecentsStack(topStackId)
1659                 && (topStack.topActivity() == null || !topStack.topActivity().fullscreen)) {
1660             // The fullscreen or assistant stack should be visible if it has a visible behind
1661             // activity behind the home or recents stack that is translucent.
1662             return STACK_VISIBLE_ACTIVITY_BEHIND;
1663         }
1664 
1665         if (mStackId == DOCKED_STACK_ID) {
1666             // If the assistant stack is focused and translucent, then the docked stack is always
1667             // visible
1668             if (topStack.isAssistantStack()) {
1669                 return (topStack.isStackTranslucent(starting, DOCKED_STACK_ID)) ? STACK_VISIBLE
1670                         : STACK_INVISIBLE;
1671             }
1672             return STACK_VISIBLE;
1673         }
1674 
1675         // Set home stack to invisible when it is below but not immediately below the docked stack
1676         // A case would be if recents stack exists but has no tasks and is below the docked stack
1677         // and home stack is below recents
1678         if (mStackId == HOME_STACK_ID) {
1679             int dockedStackIndex = mStacks.indexOf(mStackSupervisor.getStack(DOCKED_STACK_ID));
1680             if (dockedStackIndex > stackIndex && stackIndex != dockedStackIndex - 1) {
1681                 return STACK_INVISIBLE;
1682             }
1683         }
1684 
1685         // Find the first stack behind front stack that actually got something visible.
1686         int stackBehindTopIndex = mStacks.indexOf(topStack) - 1;
1687         while (stackBehindTopIndex >= 0 &&
1688                 mStacks.get(stackBehindTopIndex).topRunningActivityLocked() == null) {
1689             stackBehindTopIndex--;
1690         }
1691         final int stackBehindTopId = (stackBehindTopIndex >= 0)
1692                 ? mStacks.get(stackBehindTopIndex).mStackId : INVALID_STACK_ID;
1693         if ((topStackId == DOCKED_STACK_ID || topStackId == PINNED_STACK_ID)
1694                 && (stackIndex == stackBehindTopIndex
1695                 || (stackBehindTopId == DOCKED_STACK_ID
1696                 && stackIndex == stackBehindTopIndex - 1))) {
1697             // Stacks directly behind the docked or pinned stack are always visible.
1698             // Also this stack is visible if behind docked stack and the docked stack is behind the
1699             // top-most pinned stack
1700             return STACK_VISIBLE;
1701         }
1702 
1703         if (StackId.isBackdropToTranslucentActivity(topStackId)
1704                 && topStack.isStackTranslucent(starting, stackBehindTopId)) {
1705             // Stacks behind the fullscreen or assistant stack with a translucent activity are
1706             // always visible so they can act as a backdrop to the translucent activity.
1707             // For example, dialog activities
1708             if (stackIndex == stackBehindTopIndex) {
1709                 return STACK_VISIBLE;
1710             }
1711             if (stackBehindTopIndex >= 0) {
1712                 if ((stackBehindTopId == DOCKED_STACK_ID
1713                         || stackBehindTopId == PINNED_STACK_ID)
1714                         && stackIndex == (stackBehindTopIndex - 1)) {
1715                     // The stack behind the docked or pinned stack is also visible so we can have a
1716                     // complete backdrop to the translucent activity when the docked stack is up.
1717                     return STACK_VISIBLE;
1718                 }
1719             }
1720         }
1721 
1722         if (StackId.isStaticStack(mStackId)) {
1723             // Visibility of any static stack should have been determined by the conditions above.
1724             return STACK_INVISIBLE;
1725         }
1726 
1727         for (int i = stackIndex + 1; i < mStacks.size(); i++) {
1728             final ActivityStack stack = mStacks.get(i);
1729 
1730             if (!stack.mFullscreen && !stack.hasFullscreenTask()) {
1731                 continue;
1732             }
1733 
1734             if (!StackId.isDynamicStacksVisibleBehindAllowed(stack.mStackId)) {
1735                 // These stacks can't have any dynamic stacks visible behind them.
1736                 return STACK_INVISIBLE;
1737             }
1738 
1739             if (!stack.isStackTranslucent(starting, INVALID_STACK_ID)) {
1740                 return STACK_INVISIBLE;
1741             }
1742         }
1743 
1744         return STACK_VISIBLE;
1745     }
1746 
rankTaskLayers(int baseLayer)1747     final int rankTaskLayers(int baseLayer) {
1748         int layer = 0;
1749         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1750             final TaskRecord task = mTaskHistory.get(taskNdx);
1751             ActivityRecord r = task.topRunningActivityLocked();
1752             if (r == null || r.finishing || !r.visible) {
1753                 task.mLayerRank = -1;
1754             } else {
1755                 task.mLayerRank = baseLayer + layer++;
1756             }
1757         }
1758         return layer;
1759     }
1760 
1761     /**
1762      * Make sure that all activities that need to be visible (that is, they
1763      * currently can be seen by the user) actually are.
1764      */
ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges, boolean preserveWindows)1765     final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
1766             boolean preserveWindows) {
1767         mTopActivityOccludesKeyguard = false;
1768         mTopDismissingKeyguardActivity = null;
1769         mStackSupervisor.mKeyguardController.beginActivityVisibilityUpdate();
1770         try {
1771             ActivityRecord top = topRunningActivityLocked();
1772             if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + top
1773                     + " configChanges=0x" + Integer.toHexString(configChanges));
1774             if (top != null) {
1775                 checkTranslucentActivityWaiting(top);
1776             }
1777 
1778             // If the top activity is not fullscreen, then we need to
1779             // make sure any activities under it are now visible.
1780             boolean aboveTop = top != null;
1781             final int stackVisibility = shouldBeVisible(starting);
1782             final boolean stackInvisible = stackVisibility != STACK_VISIBLE;
1783             final boolean stackVisibleBehind = stackVisibility == STACK_VISIBLE_ACTIVITY_BEHIND;
1784             boolean behindFullscreenActivity = stackInvisible;
1785             boolean resumeNextActivity = mStackSupervisor.isFocusedStack(this)
1786                     && (isInStackLocked(starting) == null);
1787             boolean behindTranslucentActivity = false;
1788             final ActivityRecord visibleBehind = getVisibleBehindActivity();
1789             for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1790                 final TaskRecord task = mTaskHistory.get(taskNdx);
1791                 final ArrayList<ActivityRecord> activities = task.mActivities;
1792                 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1793                     final ActivityRecord r = activities.get(activityNdx);
1794                     if (r.finishing) {
1795                         // Normally the screenshot will be taken in makeInvisible(). When an activity
1796                         // is finishing, we no longer change its visibility, but we still need to take
1797                         // the screenshots if startPausingLocked decided it should be taken.
1798                         if (r.mUpdateTaskThumbnailWhenHidden) {
1799                             r.updateThumbnailLocked(r.screenshotActivityLocked(),
1800                                     null /* description */);
1801                             r.mUpdateTaskThumbnailWhenHidden = false;
1802                         }
1803                         continue;
1804                     }
1805                     final boolean isTop = r == top;
1806                     if (aboveTop && !isTop) {
1807                         continue;
1808                     }
1809                     aboveTop = false;
1810 
1811                     // Check whether activity should be visible without Keyguard influence
1812                     final boolean visibleIgnoringKeyguard = r.shouldBeVisibleIgnoringKeyguard(
1813                             behindTranslucentActivity, stackVisibleBehind, visibleBehind,
1814                             behindFullscreenActivity);
1815                     r.visibleIgnoringKeyguard = visibleIgnoringKeyguard;
1816 
1817                     // Now check whether it's really visible depending on Keyguard state.
1818                     final boolean reallyVisible = checkKeyguardVisibility(r,
1819                             visibleIgnoringKeyguard, isTop);
1820                     if (visibleIgnoringKeyguard) {
1821                         behindFullscreenActivity = updateBehindFullscreen(stackInvisible,
1822                                 behindFullscreenActivity, task, r);
1823                         if (behindFullscreenActivity && !r.fullscreen) {
1824                             behindTranslucentActivity = true;
1825                         }
1826                     }
1827                     if (reallyVisible) {
1828                         if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make visible? " + r
1829                                 + " finishing=" + r.finishing + " state=" + r.state);
1830                         // First: if this is not the current activity being started, make
1831                         // sure it matches the current configuration.
1832                         if (r != starting) {
1833                             r.ensureActivityConfigurationLocked(0 /* globalChanges */, preserveWindows);
1834                         }
1835 
1836                         if (r.app == null || r.app.thread == null) {
1837                             if (makeVisibleAndRestartIfNeeded(starting, configChanges, isTop,
1838                                     resumeNextActivity, r)) {
1839                                 if (activityNdx >= activities.size()) {
1840                                     // Record may be removed if its process needs to restart.
1841                                     activityNdx = activities.size() - 1;
1842                                 } else {
1843                                     resumeNextActivity = false;
1844                                 }
1845                             }
1846                         } else if (r.visible) {
1847                             // If this activity is already visible, then there is nothing to do here.
1848                             if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
1849                                     "Skipping: already visible at " + r);
1850 
1851                             if (r.handleAlreadyVisible()) {
1852                                 resumeNextActivity = false;
1853                             }
1854                         } else {
1855                             r.makeVisibleIfNeeded(starting);
1856                         }
1857                         // Aggregate current change flags.
1858                         configChanges |= r.configChangeFlags;
1859                     } else {
1860                         if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make invisible? " + r
1861                                 + " finishing=" + r.finishing + " state=" + r.state + " stackInvisible="
1862                                 + stackInvisible + " behindFullscreenActivity="
1863                                 + behindFullscreenActivity + " mLaunchTaskBehind="
1864                                 + r.mLaunchTaskBehind);
1865                         makeInvisible(r, visibleBehind);
1866                     }
1867                 }
1868                 if (mStackId == FREEFORM_WORKSPACE_STACK_ID) {
1869                     // The visibility of tasks and the activities they contain in freeform stack are
1870                     // determined individually unlike other stacks where the visibility or fullscreen
1871                     // status of an activity in a previous task affects other.
1872                     behindFullscreenActivity = stackVisibility == STACK_INVISIBLE;
1873                 } else if (mStackId == HOME_STACK_ID) {
1874                     if (task.isHomeTask()) {
1875                         if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + task
1876                                 + " stackInvisible=" + stackInvisible
1877                                 + " behindFullscreenActivity=" + behindFullscreenActivity);
1878                         // No other task in the home stack should be visible behind the home activity.
1879                         // Home activities is usually a translucent activity with the wallpaper behind
1880                         // them. However, when they don't have the wallpaper behind them, we want to
1881                         // show activities in the next application stack behind them vs. another
1882                         // task in the home stack like recents.
1883                         behindFullscreenActivity = true;
1884                     } else if (task.isRecentsTask()
1885                             && task.getTaskToReturnTo() == APPLICATION_ACTIVITY_TYPE) {
1886                         if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
1887                                 "Recents task returning to app: at " + task
1888                                         + " stackInvisible=" + stackInvisible
1889                                         + " behindFullscreenActivity=" + behindFullscreenActivity);
1890                         // We don't want any other tasks in the home stack visible if the recents
1891                         // activity is going to be returning to an application activity type.
1892                         // We do this to preserve the visible order the user used to get into the
1893                         // recents activity. The recents activity is normally translucent and if it
1894                         // doesn't have the wallpaper behind it the next activity in the home stack
1895                         // shouldn't be visible when the home stack is brought to the front to display
1896                         // the recents activity from an app.
1897                         behindFullscreenActivity = true;
1898                     }
1899 
1900                 }
1901             }
1902 
1903             if (mTranslucentActivityWaiting != null &&
1904                     mUndrawnActivitiesBelowTopTranslucent.isEmpty()) {
1905                 // Nothing is getting drawn or everything was already visible, don't wait for timeout.
1906                 notifyActivityDrawnLocked(null);
1907             }
1908         } finally {
1909             mStackSupervisor.mKeyguardController.endActivityVisibilityUpdate();
1910         }
1911     }
1912 
addStartingWindowsForVisibleActivities(boolean taskSwitch)1913     void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
1914         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1915             mTaskHistory.get(taskNdx).addStartingWindowsForVisibleActivities(taskSwitch);
1916         }
1917     }
1918 
1919     /**
1920      * @return true if the top visible activity wants to occlude the Keyguard, false otherwise
1921      */
topActivityOccludesKeyguard()1922     boolean topActivityOccludesKeyguard() {
1923         return mTopActivityOccludesKeyguard;
1924     }
1925 
1926     /**
1927      * @return the top most visible activity that wants to dismiss Keyguard
1928      */
getTopDismissingKeyguardActivity()1929     ActivityRecord getTopDismissingKeyguardActivity() {
1930         return mTopDismissingKeyguardActivity;
1931     }
1932 
1933     /**
1934      * Checks whether {@param r} should be visible depending on Keyguard state and updates
1935      * {@link #mTopActivityOccludesKeyguard} and {@link #mTopDismissingKeyguardActivity} if
1936      * necessary.
1937      *
1938      * @return true if {@param r} is visible taken Keyguard state into account, false otherwise
1939      */
checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible, boolean isTop)1940     boolean checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible,
1941             boolean isTop) {
1942         final boolean isInPinnedStack = r.getStack().getStackId() == PINNED_STACK_ID;
1943         final boolean keyguardShowing = mStackSupervisor.mKeyguardController.isKeyguardShowing();
1944         final boolean keyguardLocked = mStackSupervisor.mKeyguardController.isKeyguardLocked();
1945         final boolean showWhenLocked = r.hasShowWhenLockedWindows() && !isInPinnedStack;
1946         final boolean dismissKeyguard = r.hasDismissKeyguardWindows();
1947         if (shouldBeVisible) {
1948             if (dismissKeyguard && mTopDismissingKeyguardActivity == null) {
1949                 mTopDismissingKeyguardActivity = r;
1950             }
1951 
1952             // Only the top activity may control occluded, as we can't occlude the Keyguard if the
1953             // top app doesn't want to occlude it.
1954             if (isTop) {
1955                 mTopActivityOccludesKeyguard |= showWhenLocked;
1956             }
1957 
1958             final boolean canShowWithKeyguard = canShowWithInsecureKeyguard()
1959                     && mStackSupervisor.mKeyguardController.canDismissKeyguard();
1960             if (canShowWithKeyguard) {
1961                 return true;
1962             }
1963         }
1964         if (keyguardShowing) {
1965 
1966             // If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard
1967             // right away.
1968             return shouldBeVisible && mStackSupervisor.mKeyguardController
1969                     .canShowActivityWhileKeyguardShowing(r, dismissKeyguard);
1970         } else if (keyguardLocked) {
1971             return shouldBeVisible && mStackSupervisor.mKeyguardController.canShowWhileOccluded(
1972                     dismissKeyguard, showWhenLocked);
1973         } else {
1974             return shouldBeVisible;
1975         }
1976     }
1977 
1978     /**
1979      * Check if the display to which this stack is attached has
1980      * {@link Display#FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD} applied.
1981      */
canShowWithInsecureKeyguard()1982     private boolean canShowWithInsecureKeyguard() {
1983         final ActivityStackSupervisor.ActivityDisplay activityDisplay
1984                 = mActivityContainer.mActivityDisplay;
1985         if (activityDisplay == null) {
1986             throw new IllegalStateException("Stack is not attached to any display, stackId="
1987                     + mStackId);
1988         }
1989 
1990         final int flags = activityDisplay.mDisplay.getFlags();
1991         return (flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0;
1992     }
1993 
checkTranslucentActivityWaiting(ActivityRecord top)1994     private void checkTranslucentActivityWaiting(ActivityRecord top) {
1995         if (mTranslucentActivityWaiting != top) {
1996             mUndrawnActivitiesBelowTopTranslucent.clear();
1997             if (mTranslucentActivityWaiting != null) {
1998                 // Call the callback with a timeout indication.
1999                 notifyActivityDrawnLocked(null);
2000                 mTranslucentActivityWaiting = null;
2001             }
2002             mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG);
2003         }
2004     }
2005 
makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges, boolean isTop, boolean andResume, ActivityRecord r)2006     private boolean makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges,
2007             boolean isTop, boolean andResume, ActivityRecord r) {
2008         // We need to make sure the app is running if it's the top, or it is just made visible from
2009         // invisible. If the app is already visible, it must have died while it was visible. In this
2010         // case, we'll show the dead window but will not restart the app. Otherwise we could end up
2011         // thrashing.
2012         if (isTop || !r.visible) {
2013             // This activity needs to be visible, but isn't even running...
2014             // get it started and resume if no other stack in this stack is resumed.
2015             if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Start and freeze screen for " + r);
2016             if (r != starting) {
2017                 r.startFreezingScreenLocked(r.app, configChanges);
2018             }
2019             if (!r.visible || r.mLaunchTaskBehind) {
2020                 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Starting and making visible: " + r);
2021                 r.setVisible(true);
2022             }
2023             if (r != starting) {
2024                 mStackSupervisor.startSpecificActivityLocked(r, andResume, false);
2025                 return true;
2026             }
2027         }
2028         return false;
2029     }
2030 
makeInvisible(ActivityRecord r, ActivityRecord visibleBehind)2031     private void makeInvisible(ActivityRecord r, ActivityRecord visibleBehind) {
2032         if (!r.visible) {
2033             if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Already invisible: " + r);
2034             return;
2035         }
2036         // Now for any activities that aren't visible to the user, make sure they no longer are
2037         // keeping the screen frozen.
2038         if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Making invisible: " + r + " " + r.state);
2039         try {
2040             final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState(
2041                     "makeInvisible", true /* noThrow */, true /* beforeStopping */);
2042             // Defer telling the client it is hidden if it can enter Pip and isn't current stopped
2043             // or stopping. This gives it a chance to enter Pip in onPause().
2044             final boolean deferHidingClient = canEnterPictureInPicture
2045                     && r.state != STOPPING && r.state != STOPPED;
2046             r.setDeferHidingClient(deferHidingClient);
2047             r.setVisible(false);
2048 
2049             switch (r.state) {
2050                 case STOPPING:
2051                 case STOPPED:
2052                     if (r.app != null && r.app.thread != null) {
2053                         if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
2054                                 "Scheduling invisibility: " + r);
2055                         r.app.thread.scheduleWindowVisibility(r.appToken, false);
2056                     }
2057 
2058                     // Reset the flag indicating that an app can enter picture-in-picture once the
2059                     // activity is hidden
2060                     r.supportsPictureInPictureWhilePausing = false;
2061                     break;
2062 
2063                 case INITIALIZING:
2064                 case RESUMED:
2065                 case PAUSING:
2066                 case PAUSED:
2067                     // This case created for transitioning activities from
2068                     // translucent to opaque {@link Activity#convertToOpaque}.
2069                     if (visibleBehind == r) {
2070                         releaseBackgroundResources(r);
2071                     } else {
2072                         addToStopping(r, true /* scheduleIdle */,
2073                                 canEnterPictureInPicture /* idleDelayed */);
2074                     }
2075                     break;
2076 
2077                 default:
2078                     break;
2079             }
2080         } catch (Exception e) {
2081             // Just skip on any failure; we'll make it visible when it next restarts.
2082             Slog.w(TAG, "Exception thrown making hidden: " + r.intent.getComponent(), e);
2083         }
2084     }
2085 
updateBehindFullscreen(boolean stackInvisible, boolean behindFullscreenActivity, TaskRecord task, ActivityRecord r)2086     private boolean updateBehindFullscreen(boolean stackInvisible, boolean behindFullscreenActivity,
2087             TaskRecord task, ActivityRecord r) {
2088         if (r.fullscreen) {
2089             if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r
2090                         + " stackInvisible=" + stackInvisible
2091                         + " behindFullscreenActivity=" + behindFullscreenActivity);
2092             // At this point, nothing else needs to be shown in this task.
2093             behindFullscreenActivity = true;
2094         } else if (!isHomeOrRecentsStack() && r.frontOfTask && task.isOverHomeStack()) {
2095             if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Showing home: at " + r
2096                     + " stackInvisible=" + stackInvisible
2097                     + " behindFullscreenActivity=" + behindFullscreenActivity);
2098             behindFullscreenActivity = true;
2099         }
2100         return behindFullscreenActivity;
2101     }
2102 
convertActivityToTranslucent(ActivityRecord r)2103     void convertActivityToTranslucent(ActivityRecord r) {
2104         mTranslucentActivityWaiting = r;
2105         mUndrawnActivitiesBelowTopTranslucent.clear();
2106         mHandler.sendEmptyMessageDelayed(TRANSLUCENT_TIMEOUT_MSG, TRANSLUCENT_CONVERSION_TIMEOUT);
2107     }
2108 
clearOtherAppTimeTrackers(AppTimeTracker except)2109     void clearOtherAppTimeTrackers(AppTimeTracker except) {
2110         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
2111             final TaskRecord task = mTaskHistory.get(taskNdx);
2112             final ArrayList<ActivityRecord> activities = task.mActivities;
2113             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
2114                 final ActivityRecord r = activities.get(activityNdx);
2115                 if ( r.appTimeTracker != except) {
2116                     r.appTimeTracker = null;
2117                 }
2118             }
2119         }
2120     }
2121 
2122     /**
2123      * Called as activities below the top translucent activity are redrawn. When the last one is
2124      * redrawn notify the top activity by calling
2125      * {@link Activity#onTranslucentConversionComplete}.
2126      *
2127      * @param r The most recent background activity to be drawn. Or, if r is null then a timeout
2128      * occurred and the activity will be notified immediately.
2129      */
notifyActivityDrawnLocked(ActivityRecord r)2130     void notifyActivityDrawnLocked(ActivityRecord r) {
2131         mActivityContainer.setDrawn();
2132         if ((r == null)
2133                 || (mUndrawnActivitiesBelowTopTranslucent.remove(r) &&
2134                         mUndrawnActivitiesBelowTopTranslucent.isEmpty())) {
2135             // The last undrawn activity below the top has just been drawn. If there is an
2136             // opaque activity at the top, notify it that it can become translucent safely now.
2137             final ActivityRecord waitingActivity = mTranslucentActivityWaiting;
2138             mTranslucentActivityWaiting = null;
2139             mUndrawnActivitiesBelowTopTranslucent.clear();
2140             mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG);
2141 
2142             if (waitingActivity != null) {
2143                 mWindowManager.setWindowOpaque(waitingActivity.appToken, false);
2144                 if (waitingActivity.app != null && waitingActivity.app.thread != null) {
2145                     try {
2146                         waitingActivity.app.thread.scheduleTranslucentConversionComplete(
2147                                 waitingActivity.appToken, r != null);
2148                     } catch (RemoteException e) {
2149                     }
2150                 }
2151             }
2152         }
2153     }
2154 
2155     /** If any activities below the top running one are in the INITIALIZING state and they have a
2156      * starting window displayed then remove that starting window. It is possible that the activity
2157      * in this state will never resumed in which case that starting window will be orphaned. */
cancelInitializingActivities()2158     void cancelInitializingActivities() {
2159         final ActivityRecord topActivity = topRunningActivityLocked();
2160         boolean aboveTop = true;
2161         // We don't want to clear starting window for activities that aren't behind fullscreen
2162         // activities as we need to display their starting window until they are done initializing.
2163         boolean behindFullscreenActivity = false;
2164 
2165         if (shouldBeVisible(null) == STACK_INVISIBLE) {
2166             // The stack is not visible, so no activity in it should be displaying a starting
2167             // window. Mark all activities below top and behind fullscreen.
2168             aboveTop = false;
2169             behindFullscreenActivity = true;
2170         }
2171 
2172         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
2173             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
2174             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
2175                 final ActivityRecord r = activities.get(activityNdx);
2176                 if (aboveTop) {
2177                     if (r == topActivity) {
2178                         aboveTop = false;
2179                     }
2180                     behindFullscreenActivity |= r.fullscreen;
2181                     continue;
2182                 }
2183 
2184                 r.removeOrphanedStartingWindow(behindFullscreenActivity);
2185                 behindFullscreenActivity |= r.fullscreen;
2186             }
2187         }
2188     }
2189 
2190     /**
2191      * Ensure that the top activity in the stack is resumed.
2192      *
2193      * @param prev The previously resumed activity, for when in the process
2194      * of pausing; can be null to call from elsewhere.
2195      * @param options Activity options.
2196      *
2197      * @return Returns true if something is being resumed, or false if
2198      * nothing happened.
2199      *
2200      * NOTE: It is not safe to call this method directly as it can cause an activity in a
2201      *       non-focused stack to be resumed.
2202      *       Use {@link ActivityStackSupervisor#resumeFocusedStackTopActivityLocked} to resume the
2203      *       right activity for the current system state.
2204      */
resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options)2205     boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
2206         if (mStackSupervisor.inResumeTopActivity) {
2207             // Don't even start recursing.
2208             return false;
2209         }
2210 
2211         boolean result = false;
2212         try {
2213             // Protect against recursion.
2214             mStackSupervisor.inResumeTopActivity = true;
2215             result = resumeTopActivityInnerLocked(prev, options);
2216         } finally {
2217             mStackSupervisor.inResumeTopActivity = false;
2218         }
2219         // When resuming the top activity, it may be necessary to pause the top activity (for
2220         // example, returning to the lock screen. We suppress the normal pause logic in
2221         // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the end.
2222         // We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here to ensure
2223         // any necessary pause logic occurs.
2224         mStackSupervisor.checkReadyForSleepLocked();
2225 
2226         return result;
2227     }
2228 
setResumedActivityLocked(ActivityRecord r, String reason)2229     void setResumedActivityLocked(ActivityRecord r, String reason) {
2230         // TODO: move mResumedActivity to stack supervisor,
2231         // there should only be 1 global copy of resumed activity.
2232         mResumedActivity = r;
2233         r.state = ActivityState.RESUMED;
2234         mService.setResumedActivityUncheckLocked(r, reason);
2235         final TaskRecord task = r.getTask();
2236         task.touchActiveTime();
2237         mRecentTasks.addLocked(task);
2238     }
2239 
resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options)2240     private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
2241         if (!mService.mBooting && !mService.mBooted) {
2242             // Not ready yet!
2243             return false;
2244         }
2245 
2246         // Find the next top-most activity to resume in this stack that is not finishing and is
2247         // focusable. If it is not focusable, we will fall into the case below to resume the
2248         // top activity in the next focusable task.
2249         final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
2250 
2251         final boolean hasRunningActivity = next != null;
2252 
2253         final ActivityRecord parent = mActivityContainer.mParentActivity;
2254         final boolean isParentNotResumed = parent != null && parent.state != ActivityState.RESUMED;
2255         if (hasRunningActivity
2256                 && (isParentNotResumed || !mActivityContainer.isAttachedLocked())) {
2257             // Do not resume this stack if its parent is not resumed.
2258             // TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st.
2259             return false;
2260         }
2261 
2262         mStackSupervisor.cancelInitializingActivities();
2263 
2264         // Remember how we'll process this pause/resume situation, and ensure
2265         // that the state is reset however we wind up proceeding.
2266         final boolean userLeaving = mStackSupervisor.mUserLeaving;
2267         mStackSupervisor.mUserLeaving = false;
2268 
2269         if (!hasRunningActivity) {
2270             // There are no activities left in the stack, let's look somewhere else.
2271             return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities");
2272         }
2273 
2274         next.delayedResume = false;
2275 
2276         // If the top activity is the resumed one, nothing to do.
2277         if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
2278                     mStackSupervisor.allResumedActivitiesComplete()) {
2279             // Make sure we have executed any pending transitions, since there
2280             // should be nothing left to do at this point.
2281             executeAppTransition(options);
2282             if (DEBUG_STATES) Slog.d(TAG_STATES,
2283                     "resumeTopActivityLocked: Top activity resumed " + next);
2284             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2285             return false;
2286         }
2287 
2288         final TaskRecord nextTask = next.getTask();
2289         final TaskRecord prevTask = prev != null ? prev.getTask() : null;
2290         if (prevTask != null && prevTask.getStack() == this &&
2291                 prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
2292             if (DEBUG_STACK)  mStackSupervisor.validateTopActivitiesLocked();
2293             if (prevTask == nextTask) {
2294                 prevTask.setFrontOfTask();
2295             } else if (prevTask != topTask()) {
2296                 // This task is going away but it was supposed to return to the home stack.
2297                 // Now the task above it has to return to the home task instead.
2298                 final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
2299                 mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE);
2300             } else if (!isOnHomeDisplay()) {
2301                 return false;
2302             } else if (!isHomeStack()){
2303                 if (DEBUG_STATES) Slog.d(TAG_STATES,
2304                         "resumeTopActivityLocked: Launching home next");
2305                 return isOnHomeDisplay() &&
2306                         mStackSupervisor.resumeHomeStackTask(prev, "prevFinished");
2307             }
2308         }
2309 
2310         // If we are sleeping, and there is no resumed activity, and the top
2311         // activity is paused, well that is the state we want.
2312         if (mService.isSleepingOrShuttingDownLocked()
2313                 && mLastPausedActivity == next
2314                 && mStackSupervisor.allPausedActivitiesComplete()) {
2315             // Make sure we have executed any pending transitions, since there
2316             // should be nothing left to do at this point.
2317             executeAppTransition(options);
2318             if (DEBUG_STATES) Slog.d(TAG_STATES,
2319                     "resumeTopActivityLocked: Going to sleep and all paused");
2320             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2321             return false;
2322         }
2323 
2324         // Make sure that the user who owns this activity is started.  If not,
2325         // we will just leave it as is because someone should be bringing
2326         // another user's activities to the top of the stack.
2327         if (!mService.mUserController.hasStartedUserState(next.userId)) {
2328             Slog.w(TAG, "Skipping resume of top activity " + next
2329                     + ": user " + next.userId + " is stopped");
2330             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2331             return false;
2332         }
2333 
2334         // The activity may be waiting for stop, but that is no longer
2335         // appropriate for it.
2336         mStackSupervisor.mStoppingActivities.remove(next);
2337         mStackSupervisor.mGoingToSleepActivities.remove(next);
2338         next.sleeping = false;
2339         mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(next);
2340 
2341         if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
2342 
2343         // If we are currently pausing an activity, then don't do anything until that is done.
2344         if (!mStackSupervisor.allPausedActivitiesComplete()) {
2345             if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
2346                     "resumeTopActivityLocked: Skip resume: some activity pausing.");
2347             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2348             return false;
2349         }
2350 
2351         mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
2352 
2353         boolean lastResumedCanPip = false;
2354         final ActivityStack lastFocusedStack = mStackSupervisor.getLastStack();
2355         if (lastFocusedStack != null && lastFocusedStack != this) {
2356             // So, why aren't we using prev here??? See the param comment on the method. prev doesn't
2357             // represent the last resumed activity. However, the last focus stack does if it isn't null.
2358             final ActivityRecord lastResumed = lastFocusedStack.mResumedActivity;
2359             lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState(
2360                     "resumeTopActivity", true /* noThrow */, userLeaving /* beforeStopping */);
2361         }
2362         // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity
2363         // to be paused, while at the same time resuming the new resume activity only if the
2364         // previous activity can't go into Pip since we want to give Pip activities a chance to
2365         // enter Pip before resuming the next activity.
2366         final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0
2367                 && !lastResumedCanPip;
2368 
2369         boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
2370         if (mResumedActivity != null) {
2371             if (DEBUG_STATES) Slog.d(TAG_STATES,
2372                     "resumeTopActivityLocked: Pausing " + mResumedActivity);
2373             pausing |= startPausingLocked(userLeaving, false, next, false);
2374         }
2375         if (pausing && !resumeWhilePausing) {
2376             if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
2377                     "resumeTopActivityLocked: Skip resume: need to start pausing");
2378             // At this point we want to put the upcoming activity's process
2379             // at the top of the LRU list, since we know we will be needing it
2380             // very soon and it would be a waste to let it get killed if it
2381             // happens to be sitting towards the end.
2382             if (next.app != null && next.app.thread != null) {
2383                 mService.updateLruProcessLocked(next.app, true, null);
2384             }
2385             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2386             return true;
2387         } else if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
2388                 mStackSupervisor.allResumedActivitiesComplete()) {
2389             // It is possible for the activity to be resumed when we paused back stacks above if the
2390             // next activity doesn't have to wait for pause to complete.
2391             // So, nothing else to-do except:
2392             // Make sure we have executed any pending transitions, since there
2393             // should be nothing left to do at this point.
2394             executeAppTransition(options);
2395             if (DEBUG_STATES) Slog.d(TAG_STATES,
2396                     "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next);
2397             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2398             return true;
2399         }
2400 
2401         // If the most recent activity was noHistory but was only stopped rather
2402         // than stopped+finished because the device went to sleep, we need to make
2403         // sure to finish it as we're making a new activity topmost.
2404         if (mService.isSleepingLocked() && mLastNoHistoryActivity != null &&
2405                 !mLastNoHistoryActivity.finishing) {
2406             if (DEBUG_STATES) Slog.d(TAG_STATES,
2407                     "no-history finish of " + mLastNoHistoryActivity + " on new resume");
2408             requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
2409                     null, "resume-no-history", false);
2410             mLastNoHistoryActivity = null;
2411         }
2412 
2413         if (prev != null && prev != next) {
2414             if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
2415                     && next != null && !next.nowVisible) {
2416                 mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(prev);
2417                 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
2418                         "Resuming top, waiting visible to hide: " + prev);
2419             } else {
2420                 // The next activity is already visible, so hide the previous
2421                 // activity's windows right now so we can show the new one ASAP.
2422                 // We only do this if the previous is finishing, which should mean
2423                 // it is on top of the one being resumed so hiding it quickly
2424                 // is good.  Otherwise, we want to do the normal route of allowing
2425                 // the resumed activity to be shown so we can decide if the
2426                 // previous should actually be hidden depending on whether the
2427                 // new one is found to be full-screen or not.
2428                 if (prev.finishing) {
2429                     prev.setVisibility(false);
2430                     if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
2431                             "Not waiting for visible to hide: " + prev + ", waitingVisible="
2432                             + mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
2433                             + ", nowVisible=" + next.nowVisible);
2434                 } else {
2435                     if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
2436                             "Previous already visible but still waiting to hide: " + prev
2437                             + ", waitingVisible="
2438                             + mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
2439                             + ", nowVisible=" + next.nowVisible);
2440                 }
2441             }
2442         }
2443 
2444         // Launching this app's activity, make sure the app is no longer
2445         // considered stopped.
2446         try {
2447             AppGlobals.getPackageManager().setPackageStoppedState(
2448                     next.packageName, false, next.userId); /* TODO: Verify if correct userid */
2449         } catch (RemoteException e1) {
2450         } catch (IllegalArgumentException e) {
2451             Slog.w(TAG, "Failed trying to unstop package "
2452                     + next.packageName + ": " + e);
2453         }
2454 
2455         // We are starting up the next activity, so tell the window manager
2456         // that the previous one will be hidden soon.  This way it can know
2457         // to ignore it when computing the desired screen orientation.
2458         boolean anim = true;
2459         if (prev != null) {
2460             if (prev.finishing) {
2461                 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
2462                         "Prepare close transition: prev=" + prev);
2463                 if (mNoAnimActivities.contains(prev)) {
2464                     anim = false;
2465                     mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
2466                 } else {
2467                     mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
2468                             ? TRANSIT_ACTIVITY_CLOSE
2469                             : TRANSIT_TASK_CLOSE, false);
2470                 }
2471                 prev.setVisibility(false);
2472             } else {
2473                 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
2474                         "Prepare open transition: prev=" + prev);
2475                 if (mNoAnimActivities.contains(next)) {
2476                     anim = false;
2477                     mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
2478                 } else {
2479                     mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
2480                             ? TRANSIT_ACTIVITY_OPEN
2481                             : next.mLaunchTaskBehind
2482                                     ? TRANSIT_TASK_OPEN_BEHIND
2483                                     : TRANSIT_TASK_OPEN, false);
2484                 }
2485             }
2486         } else {
2487             if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
2488             if (mNoAnimActivities.contains(next)) {
2489                 anim = false;
2490                 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
2491             } else {
2492                 mWindowManager.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false);
2493             }
2494         }
2495 
2496         Bundle resumeAnimOptions = null;
2497         if (anim) {
2498             ActivityOptions opts = next.getOptionsForTargetActivityLocked();
2499             if (opts != null) {
2500                 resumeAnimOptions = opts.toBundle();
2501             }
2502             next.applyOptionsLocked();
2503         } else {
2504             next.clearOptionsLocked();
2505         }
2506 
2507         ActivityStack lastStack = mStackSupervisor.getLastStack();
2508         if (next.app != null && next.app.thread != null) {
2509             if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next
2510                     + " stopped=" + next.stopped + " visible=" + next.visible);
2511 
2512             // If the previous activity is translucent, force a visibility update of
2513             // the next activity, so that it's added to WM's opening app list, and
2514             // transition animation can be set up properly.
2515             // For example, pressing Home button with a translucent activity in focus.
2516             // Launcher is already visible in this case. If we don't add it to opening
2517             // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a
2518             // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.
2519             final boolean lastActivityTranslucent = lastStack != null
2520                     && (!lastStack.mFullscreen
2521                     || (lastStack.mLastPausedActivity != null
2522                     && !lastStack.mLastPausedActivity.fullscreen));
2523 
2524             // This activity is now becoming visible.
2525             if (!next.visible || next.stopped || lastActivityTranslucent) {
2526                 next.setVisibility(true);
2527             }
2528 
2529             // schedule launch ticks to collect information about slow apps.
2530             next.startLaunchTickingLocked();
2531 
2532             ActivityRecord lastResumedActivity =
2533                     lastStack == null ? null :lastStack.mResumedActivity;
2534             ActivityState lastState = next.state;
2535 
2536             mService.updateCpuStats();
2537 
2538             if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next + " (in existing)");
2539 
2540             setResumedActivityLocked(next, "resumeTopActivityInnerLocked");
2541 
2542             mService.updateLruProcessLocked(next.app, true, null);
2543             updateLRUListLocked(next);
2544             mService.updateOomAdjLocked();
2545 
2546             // Have the window manager re-evaluate the orientation of
2547             // the screen based on the new activity order.
2548             boolean notUpdated = true;
2549             if (mStackSupervisor.isFocusedStack(this)) {
2550                 final Configuration config = mWindowManager.updateOrientationFromAppTokens(
2551                         mStackSupervisor.getDisplayOverrideConfiguration(mDisplayId),
2552                         next.mayFreezeScreenLocked(next.app) ? next.appToken : null, mDisplayId);
2553                 if (config != null) {
2554                     next.frozenBeforeDestroy = true;
2555                 }
2556                 notUpdated = !mService.updateDisplayOverrideConfigurationLocked(config, next,
2557                         false /* deferResume */, mDisplayId);
2558             }
2559 
2560             if (notUpdated) {
2561                 // The configuration update wasn't able to keep the existing
2562                 // instance of the activity, and instead started a new one.
2563                 // We should be all done, but let's just make sure our activity
2564                 // is still at the top and schedule another run if something
2565                 // weird happened.
2566                 ActivityRecord nextNext = topRunningActivityLocked();
2567                 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES,
2568                         "Activity config changed during resume: " + next
2569                         + ", new next: " + nextNext);
2570                 if (nextNext != next) {
2571                     // Do over!
2572                     mStackSupervisor.scheduleResumeTopActivities();
2573                 }
2574                 if (!next.visible || next.stopped) {
2575                     next.setVisibility(true);
2576                 }
2577                 next.completeResumeLocked();
2578                 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2579                 return true;
2580             }
2581 
2582             try {
2583                 // Deliver all pending results.
2584                 ArrayList<ResultInfo> a = next.results;
2585                 if (a != null) {
2586                     final int N = a.size();
2587                     if (!next.finishing && N > 0) {
2588                         if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
2589                                 "Delivering results to " + next + ": " + a);
2590                         next.app.thread.scheduleSendResult(next.appToken, a);
2591                     }
2592                 }
2593 
2594                 if (next.newIntents != null) {
2595                     next.app.thread.scheduleNewIntent(
2596                             next.newIntents, next.appToken, false /* andPause */);
2597                 }
2598 
2599                 // Well the app will no longer be stopped.
2600                 // Clear app token stopped state in window manager if needed.
2601                 next.notifyAppResumed(next.stopped);
2602 
2603                 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
2604                         System.identityHashCode(next), next.getTask().taskId,
2605                         next.shortComponentName);
2606 
2607                 next.sleeping = false;
2608                 mService.showUnsupportedZoomDialogIfNeededLocked(next);
2609                 mService.showAskCompatModeDialogLocked(next);
2610                 next.app.pendingUiClean = true;
2611                 next.app.forceProcessStateUpTo(mService.mTopProcessState);
2612                 next.clearOptionsLocked();
2613                 next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
2614                         mService.isNextTransitionForward(), resumeAnimOptions);
2615 
2616                 if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed " + next);
2617             } catch (Exception e) {
2618                 // Whoops, need to restart this activity!
2619                 if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to "
2620                         + lastState + ": " + next);
2621                 next.state = lastState;
2622                 if (lastStack != null) {
2623                     lastStack.mResumedActivity = lastResumedActivity;
2624                 }
2625                 Slog.i(TAG, "Restarting because process died: " + next);
2626                 if (!next.hasBeenLaunched) {
2627                     next.hasBeenLaunched = true;
2628                 } else  if (SHOW_APP_STARTING_PREVIEW && lastStack != null &&
2629                         mStackSupervisor.isFrontStackOnDisplay(lastStack)) {
2630                     next.showStartingWindow(null /* prev */, false /* newTask */,
2631                             false /* taskSwitch */);
2632                 }
2633                 mStackSupervisor.startSpecificActivityLocked(next, true, false);
2634                 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2635                 return true;
2636             }
2637 
2638             // From this point on, if something goes wrong there is no way
2639             // to recover the activity.
2640             try {
2641                 next.completeResumeLocked();
2642             } catch (Exception e) {
2643                 // If any exception gets thrown, toss away this
2644                 // activity and try the next one.
2645                 Slog.w(TAG, "Exception thrown during resume of " + next, e);
2646                 requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
2647                         "resume-exception", true);
2648                 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2649                 return true;
2650             }
2651         } else {
2652             // Whoops, need to restart this activity!
2653             if (!next.hasBeenLaunched) {
2654                 next.hasBeenLaunched = true;
2655             } else {
2656                 if (SHOW_APP_STARTING_PREVIEW) {
2657                     next.showStartingWindow(null /* prev */, false /* newTask */,
2658                             false /* taskSwich */);
2659                 }
2660                 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
2661             }
2662             if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
2663             mStackSupervisor.startSpecificActivityLocked(next, true, true);
2664         }
2665 
2666         if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2667         return true;
2668     }
2669 
resumeTopActivityInNextFocusableStack(ActivityRecord prev, ActivityOptions options, String reason)2670     private boolean resumeTopActivityInNextFocusableStack(ActivityRecord prev,
2671             ActivityOptions options, String reason) {
2672         if ((!mFullscreen || !isOnHomeDisplay()) && adjustFocusToNextFocusableStackLocked(reason)) {
2673             // Try to move focus to the next visible stack with a running activity if this
2674             // stack is not covering the entire screen or is on a secondary display (with no home
2675             // stack).
2676             return mStackSupervisor.resumeFocusedStackTopActivityLocked(
2677                     mStackSupervisor.getFocusedStack(), prev, null);
2678         }
2679 
2680         // Let's just start up the Launcher...
2681         ActivityOptions.abort(options);
2682         if (DEBUG_STATES) Slog.d(TAG_STATES,
2683                 "resumeTopActivityInNextFocusableStack: " + reason + ", go home");
2684         if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2685         // Only resume home if on home display
2686         return isOnHomeDisplay() &&
2687                 mStackSupervisor.resumeHomeStackTask(prev, reason);
2688     }
2689 
getNextTask(TaskRecord targetTask)2690     private TaskRecord getNextTask(TaskRecord targetTask) {
2691         final int index = mTaskHistory.indexOf(targetTask);
2692         if (index >= 0) {
2693             final int numTasks = mTaskHistory.size();
2694             for (int i = index + 1; i < numTasks; ++i) {
2695                 TaskRecord task = mTaskHistory.get(i);
2696                 if (task.userId == targetTask.userId) {
2697                     return task;
2698                 }
2699             }
2700         }
2701         return null;
2702     }
2703 
2704     /** Returns the position the input task should be placed in this stack. */
getAdjustedPositionForTask(TaskRecord task, int suggestedPosition, ActivityRecord starting)2705     int getAdjustedPositionForTask(TaskRecord task, int suggestedPosition,
2706             ActivityRecord starting) {
2707 
2708         int maxPosition = mTaskHistory.size();
2709         if ((starting != null && starting.okToShowLocked())
2710                 || (starting == null && task.okToShowLocked())) {
2711             // If the task or starting activity can be shown, then whatever position is okay.
2712             return Math.min(suggestedPosition, maxPosition);
2713         }
2714 
2715         // The task can't be shown, put non-current user tasks below current user tasks.
2716         while (maxPosition > 0) {
2717             final TaskRecord tmpTask = mTaskHistory.get(maxPosition - 1);
2718             if (!mStackSupervisor.isCurrentProfileLocked(tmpTask.userId)
2719                     || tmpTask.topRunningActivityLocked() == null) {
2720                 break;
2721             }
2722             maxPosition--;
2723         }
2724 
2725         return  Math.min(suggestedPosition, maxPosition);
2726     }
2727 
2728     /**
2729      * Used from {@link ActivityStack#positionTask(TaskRecord, int)}.
2730      * @see ActivityManagerService#positionTaskInStack(int, int, int).
2731      */
insertTaskAtPosition(TaskRecord task, int position)2732     private void insertTaskAtPosition(TaskRecord task, int position) {
2733         if (position >= mTaskHistory.size()) {
2734             insertTaskAtTop(task, null);
2735             return;
2736         }
2737         position = getAdjustedPositionForTask(task, position, null /* starting */);
2738         mTaskHistory.remove(task);
2739         mTaskHistory.add(position, task);
2740         mWindowContainerController.positionChildAt(task.getWindowContainerController(), position,
2741                 task.mBounds, task.getOverrideConfiguration());
2742         updateTaskMovement(task, true);
2743     }
2744 
insertTaskAtTop(TaskRecord task, ActivityRecord starting)2745     private void insertTaskAtTop(TaskRecord task, ActivityRecord starting) {
2746         updateTaskReturnToForTopInsertion(task);
2747         // TODO: Better place to put all the code below...may be addTask...
2748         mTaskHistory.remove(task);
2749         // Now put task at top.
2750         final int position = getAdjustedPositionForTask(task, mTaskHistory.size(), starting);
2751         mTaskHistory.add(position, task);
2752         updateTaskMovement(task, true);
2753         mWindowContainerController.positionChildAtTop(task.getWindowContainerController(),
2754                 true /* includingParents */);
2755     }
2756 
2757     /**
2758      * Updates the {@param task}'s return type before it is moved to the top.
2759      */
updateTaskReturnToForTopInsertion(TaskRecord task)2760     private void updateTaskReturnToForTopInsertion(TaskRecord task) {
2761         boolean isLastTaskOverHome = false;
2762         // If the moving task is over the home or assistant stack, transfer its return type to next
2763         // task so that they return to the same stack
2764         if (task.isOverHomeStack() || task.isOverAssistantStack()) {
2765             final TaskRecord nextTask = getNextTask(task);
2766             if (nextTask != null) {
2767                 nextTask.setTaskToReturnTo(task.getTaskToReturnTo());
2768             } else {
2769                 isLastTaskOverHome = true;
2770             }
2771         }
2772 
2773         // If this is not on the default display, then just set the return type to application
2774         if (!isOnHomeDisplay()) {
2775             task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
2776             return;
2777         }
2778 
2779         final ActivityStack lastStack = mStackSupervisor.getLastStack();
2780 
2781         // If there is no last task, do not set task to return to
2782         if (lastStack == null) {
2783             return;
2784         }
2785 
2786         // If the task was launched from the assistant stack, set the return type to assistant
2787         if (lastStack.isAssistantStack()) {
2788             task.setTaskToReturnTo(ASSISTANT_ACTIVITY_TYPE);
2789             return;
2790         }
2791 
2792         // If this is being moved to the top by another activity or being launched from the home
2793         // activity, set mTaskToReturnTo accordingly.
2794         final boolean fromHomeOrRecents = lastStack.isHomeOrRecentsStack();
2795         final TaskRecord topTask = lastStack.topTask();
2796         if (!isHomeOrRecentsStack() && (fromHomeOrRecents || topTask() != task)) {
2797             // If it's a last task over home - we default to keep its return to type not to
2798             // make underlying task focused when this one will be finished.
2799             int returnToType = isLastTaskOverHome
2800                     ? task.getTaskToReturnTo() : APPLICATION_ACTIVITY_TYPE;
2801             if (fromHomeOrRecents && StackId.allowTopTaskToReturnHome(mStackId)) {
2802                 returnToType = topTask == null ? HOME_ACTIVITY_TYPE : topTask.taskType;
2803             }
2804             task.setTaskToReturnTo(returnToType);
2805         }
2806     }
2807 
startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity, boolean newTask, boolean keepCurTransition, ActivityOptions options)2808     final void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
2809             boolean newTask, boolean keepCurTransition, ActivityOptions options) {
2810         TaskRecord rTask = r.getTask();
2811         final int taskId = rTask.taskId;
2812         // mLaunchTaskBehind tasks get placed at the back of the task stack.
2813         if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
2814             // Last activity in task had been removed or ActivityManagerService is reusing task.
2815             // Insert or replace.
2816             // Might not even be in.
2817             insertTaskAtTop(rTask, r);
2818         }
2819         TaskRecord task = null;
2820         if (!newTask) {
2821             // If starting in an existing task, find where that is...
2822             boolean startIt = true;
2823             for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
2824                 task = mTaskHistory.get(taskNdx);
2825                 if (task.getTopActivity() == null) {
2826                     // All activities in task are finishing.
2827                     continue;
2828                 }
2829                 if (task == rTask) {
2830                     // Here it is!  Now, if this is not yet visible to the
2831                     // user, then just add it without starting; it will
2832                     // get started when the user navigates back to it.
2833                     if (!startIt) {
2834                         if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
2835                                 + task, new RuntimeException("here").fillInStackTrace());
2836                         r.createWindowContainer();
2837                         ActivityOptions.abort(options);
2838                         return;
2839                     }
2840                     break;
2841                 } else if (task.numFullscreen > 0) {
2842                     startIt = false;
2843                 }
2844             }
2845         }
2846 
2847         // Place a new activity at top of stack, so it is next to interact with the user.
2848 
2849         // If we are not placing the new activity frontmost, we do not want to deliver the
2850         // onUserLeaving callback to the actual frontmost activity
2851         final TaskRecord activityTask = r.getTask();
2852         if (task == activityTask && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
2853             mStackSupervisor.mUserLeaving = false;
2854             if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
2855                     "startActivity() behind front, mUserLeaving=false");
2856         }
2857 
2858         task = activityTask;
2859 
2860         // Slot the activity into the history stack and proceed
2861         if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
2862                 new RuntimeException("here").fillInStackTrace());
2863         // TODO: Need to investigate if it is okay for the controller to already be created by the
2864         // time we get to this point. I think it is, but need to double check.
2865         // Use test in b/34179495 to trace the call path.
2866         if (r.getWindowContainerController() == null) {
2867             r.createWindowContainer();
2868         }
2869         task.setFrontOfTask();
2870 
2871         if (!isHomeOrRecentsStack() || numActivities() > 0) {
2872             if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
2873                     "Prepare open transition: starting " + r);
2874             if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2875                 mWindowManager.prepareAppTransition(TRANSIT_NONE, keepCurTransition);
2876                 mNoAnimActivities.add(r);
2877             } else {
2878                 int transit = TRANSIT_ACTIVITY_OPEN;
2879                 if (newTask) {
2880                     if (r.mLaunchTaskBehind) {
2881                         transit = TRANSIT_TASK_OPEN_BEHIND;
2882                     } else {
2883                         // If a new task is being launched, then mark the existing top activity as
2884                         // supporting picture-in-picture while pausing
2885                         if (focusedTopActivity != null &&
2886                                 focusedTopActivity.getStack().getStackId() != PINNED_STACK_ID) {
2887                             focusedTopActivity.supportsPictureInPictureWhilePausing = true;
2888                         }
2889                         transit = TRANSIT_TASK_OPEN;
2890                     }
2891                 }
2892                 mWindowManager.prepareAppTransition(transit, keepCurTransition);
2893                 mNoAnimActivities.remove(r);
2894             }
2895             boolean doShow = true;
2896             if (newTask) {
2897                 // Even though this activity is starting fresh, we still need
2898                 // to reset it to make sure we apply affinities to move any
2899                 // existing activities from other tasks in to it.
2900                 // If the caller has requested that the target task be
2901                 // reset, then do so.
2902                 if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2903                     resetTaskIfNeededLocked(r, r);
2904                     doShow = topRunningNonDelayedActivityLocked(null) == r;
2905                 }
2906             } else if (options != null && options.getAnimationType()
2907                     == ActivityOptions.ANIM_SCENE_TRANSITION) {
2908                 doShow = false;
2909             }
2910             if (r.mLaunchTaskBehind) {
2911                 // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
2912                 // tell WindowManager that r is visible even though it is at the back of the stack.
2913                 r.setVisibility(true);
2914                 ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
2915             } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
2916                 // Figure out if we are transitioning from another activity that is
2917                 // "has the same starting icon" as the next one.  This allows the
2918                 // window manager to keep the previous window it had previously
2919                 // created, if it still had one.
2920                 TaskRecord prevTask = r.getTask();
2921                 ActivityRecord prev = prevTask.topRunningActivityWithStartingWindowLocked();
2922                 if (prev != null) {
2923                     // We don't want to reuse the previous starting preview if:
2924                     // (1) The current activity is in a different task.
2925                     if (prev.getTask() != prevTask) {
2926                         prev = null;
2927                     }
2928                     // (2) The current activity is already displayed.
2929                     else if (prev.nowVisible) {
2930                         prev = null;
2931                     }
2932                 }
2933                 r.showStartingWindow(prev, newTask, isTaskSwitch(r, focusedTopActivity));
2934             }
2935         } else {
2936             // If this is the first activity, don't do any fancy animations,
2937             // because there is nothing for it to animate on top of.
2938             ActivityOptions.abort(options);
2939         }
2940     }
2941 
isTaskSwitch(ActivityRecord r, ActivityRecord topFocusedActivity)2942     private boolean isTaskSwitch(ActivityRecord r,
2943             ActivityRecord topFocusedActivity) {
2944         return topFocusedActivity != null && r.getTask() != topFocusedActivity.getTask();
2945     }
2946 
2947     /**
2948      * Perform a reset of the given task, if needed as part of launching it.
2949      * Returns the new HistoryRecord at the top of the task.
2950      */
2951     /**
2952      * Helper method for #resetTaskIfNeededLocked.
2953      * We are inside of the task being reset...  we'll either finish this activity, push it out
2954      * for another task, or leave it as-is.
2955      * @param task The task containing the Activity (taskTop) that might be reset.
2956      * @param forceReset
2957      * @return An ActivityOptions that needs to be processed.
2958      */
resetTargetTaskIfNeededLocked(TaskRecord task, boolean forceReset)2959     private ActivityOptions resetTargetTaskIfNeededLocked(TaskRecord task, boolean forceReset) {
2960         ActivityOptions topOptions = null;
2961 
2962         int replyChainEnd = -1;
2963         boolean canMoveOptions = true;
2964 
2965         // We only do this for activities that are not the root of the task (since if we finish
2966         // the root, we may no longer have the task!).
2967         final ArrayList<ActivityRecord> activities = task.mActivities;
2968         final int numActivities = activities.size();
2969         final int rootActivityNdx = task.findEffectiveRootIndex();
2970         for (int i = numActivities - 1; i > rootActivityNdx; --i ) {
2971             ActivityRecord target = activities.get(i);
2972             if (target.frontOfTask)
2973                 break;
2974 
2975             final int flags = target.info.flags;
2976             final boolean finishOnTaskLaunch =
2977                     (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
2978             final boolean allowTaskReparenting =
2979                     (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
2980             final boolean clearWhenTaskReset =
2981                     (target.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
2982 
2983             if (!finishOnTaskLaunch
2984                     && !clearWhenTaskReset
2985                     && target.resultTo != null) {
2986                 // If this activity is sending a reply to a previous
2987                 // activity, we can't do anything with it now until
2988                 // we reach the start of the reply chain.
2989                 // XXX note that we are assuming the result is always
2990                 // to the previous activity, which is almost always
2991                 // the case but we really shouldn't count on.
2992                 if (replyChainEnd < 0) {
2993                     replyChainEnd = i;
2994                 }
2995             } else if (!finishOnTaskLaunch
2996                     && !clearWhenTaskReset
2997                     && allowTaskReparenting
2998                     && target.taskAffinity != null
2999                     && !target.taskAffinity.equals(task.affinity)) {
3000                 // If this activity has an affinity for another
3001                 // task, then we need to move it out of here.  We will
3002                 // move it as far out of the way as possible, to the
3003                 // bottom of the activity stack.  This also keeps it
3004                 // correctly ordered with any activities we previously
3005                 // moved.
3006                 final TaskRecord targetTask;
3007                 final ActivityRecord bottom =
3008                         !mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ?
3009                                 mTaskHistory.get(0).mActivities.get(0) : null;
3010                 if (bottom != null && target.taskAffinity != null
3011                         && target.taskAffinity.equals(bottom.getTask().affinity)) {
3012                     // If the activity currently at the bottom has the
3013                     // same task affinity as the one we are moving,
3014                     // then merge it into the same task.
3015                     targetTask = bottom.getTask();
3016                     if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target
3017                             + " out to bottom task " + targetTask);
3018                 } else {
3019                     targetTask = createTaskRecord(
3020                             mStackSupervisor.getNextTaskIdForUserLocked(target.userId),
3021                             target.info, null, null, null, false, target.mActivityType);
3022                     targetTask.affinityIntent = target.intent;
3023                     if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target
3024                             + " out to new task " + targetTask);
3025                 }
3026 
3027                 boolean noOptions = canMoveOptions;
3028                 final int start = replyChainEnd < 0 ? i : replyChainEnd;
3029                 for (int srcPos = start; srcPos >= i; --srcPos) {
3030                     final ActivityRecord p = activities.get(srcPos);
3031                     if (p.finishing) {
3032                         continue;
3033                     }
3034 
3035                     canMoveOptions = false;
3036                     if (noOptions && topOptions == null) {
3037                         topOptions = p.takeOptionsLocked();
3038                         if (topOptions != null) {
3039                             noOptions = false;
3040                         }
3041                     }
3042                     if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
3043                             "Removing activity " + p + " from task=" + task + " adding to task="
3044                             + targetTask + " Callers=" + Debug.getCallers(4));
3045                     if (DEBUG_TASKS) Slog.v(TAG_TASKS,
3046                             "Pushing next activity " + p + " out to target's task " + target);
3047                     p.reparent(targetTask, 0 /* position - bottom */, "resetTargetTaskIfNeeded");
3048                 }
3049 
3050                 mWindowContainerController.positionChildAtBottom(
3051                         targetTask.getWindowContainerController());
3052                 replyChainEnd = -1;
3053             } else if (forceReset || finishOnTaskLaunch || clearWhenTaskReset) {
3054                 // If the activity should just be removed -- either
3055                 // because it asks for it, or the task should be
3056                 // cleared -- then finish it and anything that is
3057                 // part of its reply chain.
3058                 int end;
3059                 if (clearWhenTaskReset) {
3060                     // In this case, we want to finish this activity
3061                     // and everything above it, so be sneaky and pretend
3062                     // like these are all in the reply chain.
3063                     end = activities.size() - 1;
3064                 } else if (replyChainEnd < 0) {
3065                     end = i;
3066                 } else {
3067                     end = replyChainEnd;
3068                 }
3069                 boolean noOptions = canMoveOptions;
3070                 for (int srcPos = i; srcPos <= end; srcPos++) {
3071                     ActivityRecord p = activities.get(srcPos);
3072                     if (p.finishing) {
3073                         continue;
3074                     }
3075                     canMoveOptions = false;
3076                     if (noOptions && topOptions == null) {
3077                         topOptions = p.takeOptionsLocked();
3078                         if (topOptions != null) {
3079                             noOptions = false;
3080                         }
3081                     }
3082                     if (DEBUG_TASKS) Slog.w(TAG_TASKS,
3083                             "resetTaskIntendedTask: calling finishActivity on " + p);
3084                     if (finishActivityLocked(
3085                             p, Activity.RESULT_CANCELED, null, "reset-task", false)) {
3086                         end--;
3087                         srcPos--;
3088                     }
3089                 }
3090                 replyChainEnd = -1;
3091             } else {
3092                 // If we were in the middle of a chain, well the
3093                 // activity that started it all doesn't want anything
3094                 // special, so leave it all as-is.
3095                 replyChainEnd = -1;
3096             }
3097         }
3098 
3099         return topOptions;
3100     }
3101 
3102     /**
3103      * Helper method for #resetTaskIfNeededLocked. Processes all of the activities in a given
3104      * TaskRecord looking for an affinity with the task of resetTaskIfNeededLocked.taskTop.
3105      * @param affinityTask The task we are looking for an affinity to.
3106      * @param task Task that resetTaskIfNeededLocked.taskTop belongs to.
3107      * @param topTaskIsHigher True if #task has already been processed by resetTaskIfNeededLocked.
3108      * @param forceReset Flag passed in to resetTaskIfNeededLocked.
3109      */
resetAffinityTaskIfNeededLocked(TaskRecord affinityTask, TaskRecord task, boolean topTaskIsHigher, boolean forceReset, int taskInsertionPoint)3110     private int resetAffinityTaskIfNeededLocked(TaskRecord affinityTask, TaskRecord task,
3111             boolean topTaskIsHigher, boolean forceReset, int taskInsertionPoint) {
3112         int replyChainEnd = -1;
3113         final int taskId = task.taskId;
3114         final String taskAffinity = task.affinity;
3115 
3116         final ArrayList<ActivityRecord> activities = affinityTask.mActivities;
3117         final int numActivities = activities.size();
3118         final int rootActivityNdx = affinityTask.findEffectiveRootIndex();
3119 
3120         // Do not operate on or below the effective root Activity.
3121         for (int i = numActivities - 1; i > rootActivityNdx; --i) {
3122             ActivityRecord target = activities.get(i);
3123             if (target.frontOfTask)
3124                 break;
3125 
3126             final int flags = target.info.flags;
3127             boolean finishOnTaskLaunch = (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
3128             boolean allowTaskReparenting = (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
3129 
3130             if (target.resultTo != null) {
3131                 // If this activity is sending a reply to a previous
3132                 // activity, we can't do anything with it now until
3133                 // we reach the start of the reply chain.
3134                 // XXX note that we are assuming the result is always
3135                 // to the previous activity, which is almost always
3136                 // the case but we really shouldn't count on.
3137                 if (replyChainEnd < 0) {
3138                     replyChainEnd = i;
3139                 }
3140             } else if (topTaskIsHigher
3141                     && allowTaskReparenting
3142                     && taskAffinity != null
3143                     && taskAffinity.equals(target.taskAffinity)) {
3144                 // This activity has an affinity for our task. Either remove it if we are
3145                 // clearing or move it over to our task.  Note that
3146                 // we currently punt on the case where we are resetting a
3147                 // task that is not at the top but who has activities above
3148                 // with an affinity to it...  this is really not a normal
3149                 // case, and we will need to later pull that task to the front
3150                 // and usually at that point we will do the reset and pick
3151                 // up those remaining activities.  (This only happens if
3152                 // someone starts an activity in a new task from an activity
3153                 // in a task that is not currently on top.)
3154                 if (forceReset || finishOnTaskLaunch) {
3155                     final int start = replyChainEnd >= 0 ? replyChainEnd : i;
3156                     if (DEBUG_TASKS) Slog.v(TAG_TASKS,
3157                             "Finishing task at index " + start + " to " + i);
3158                     for (int srcPos = start; srcPos >= i; --srcPos) {
3159                         final ActivityRecord p = activities.get(srcPos);
3160                         if (p.finishing) {
3161                             continue;
3162                         }
3163                         finishActivityLocked(
3164                                 p, Activity.RESULT_CANCELED, null, "move-affinity", false);
3165                     }
3166                 } else {
3167                     if (taskInsertionPoint < 0) {
3168                         taskInsertionPoint = task.mActivities.size();
3169 
3170                     }
3171 
3172                     final int start = replyChainEnd >= 0 ? replyChainEnd : i;
3173                     if (DEBUG_TASKS) Slog.v(TAG_TASKS,
3174                             "Reparenting from task=" + affinityTask + ":" + start + "-" + i
3175                             + " to task=" + task + ":" + taskInsertionPoint);
3176                     for (int srcPos = start; srcPos >= i; --srcPos) {
3177                         final ActivityRecord p = activities.get(srcPos);
3178                         p.reparent(task, taskInsertionPoint, "resetAffinityTaskIfNeededLocked");
3179 
3180                         if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
3181                                 "Removing and adding activity " + p + " to stack at " + task
3182                                 + " callers=" + Debug.getCallers(3));
3183                         if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Pulling activity " + p
3184                                 + " from " + srcPos + " in to resetting task " + task);
3185                     }
3186                     mWindowContainerController.positionChildAtTop(
3187                             task.getWindowContainerController(), true /* includingParents */);
3188 
3189                     // Now we've moved it in to place...  but what if this is
3190                     // a singleTop activity and we have put it on top of another
3191                     // instance of the same activity?  Then we drop the instance
3192                     // below so it remains singleTop.
3193                     if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
3194                         ArrayList<ActivityRecord> taskActivities = task.mActivities;
3195                         int targetNdx = taskActivities.indexOf(target);
3196                         if (targetNdx > 0) {
3197                             ActivityRecord p = taskActivities.get(targetNdx - 1);
3198                             if (p.intent.getComponent().equals(target.intent.getComponent())) {
3199                                 finishActivityLocked(p, Activity.RESULT_CANCELED, null, "replace",
3200                                         false);
3201                             }
3202                         }
3203                     }
3204                 }
3205 
3206                 replyChainEnd = -1;
3207             }
3208         }
3209         return taskInsertionPoint;
3210     }
3211 
resetTaskIfNeededLocked(ActivityRecord taskTop, ActivityRecord newActivity)3212     final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
3213             ActivityRecord newActivity) {
3214         boolean forceReset =
3215                 (newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
3216         if (ACTIVITY_INACTIVE_RESET_TIME > 0
3217                 && taskTop.getTask().getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
3218             if ((newActivity.info.flags & ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
3219                 forceReset = true;
3220             }
3221         }
3222 
3223         final TaskRecord task = taskTop.getTask();
3224 
3225         /** False until we evaluate the TaskRecord associated with taskTop. Switches to true
3226          * for remaining tasks. Used for later tasks to reparent to task. */
3227         boolean taskFound = false;
3228 
3229         /** If ActivityOptions are moved out and need to be aborted or moved to taskTop. */
3230         ActivityOptions topOptions = null;
3231 
3232         // Preserve the location for reparenting in the new task.
3233         int reparentInsertionPoint = -1;
3234 
3235         for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
3236             final TaskRecord targetTask = mTaskHistory.get(i);
3237 
3238             if (targetTask == task) {
3239                 topOptions = resetTargetTaskIfNeededLocked(task, forceReset);
3240                 taskFound = true;
3241             } else {
3242                 reparentInsertionPoint = resetAffinityTaskIfNeededLocked(targetTask, task,
3243                         taskFound, forceReset, reparentInsertionPoint);
3244             }
3245         }
3246 
3247         int taskNdx = mTaskHistory.indexOf(task);
3248         if (taskNdx >= 0) {
3249             do {
3250                 taskTop = mTaskHistory.get(taskNdx--).getTopActivity();
3251             } while (taskTop == null && taskNdx >= 0);
3252         }
3253 
3254         if (topOptions != null) {
3255             // If we got some ActivityOptions from an activity on top that
3256             // was removed from the task, propagate them to the new real top.
3257             if (taskTop != null) {
3258                 taskTop.updateOptionsLocked(topOptions);
3259             } else {
3260                 topOptions.abort();
3261             }
3262         }
3263 
3264         return taskTop;
3265     }
3266 
sendActivityResultLocked(int callingUid, ActivityRecord r, String resultWho, int requestCode, int resultCode, Intent data)3267     void sendActivityResultLocked(int callingUid, ActivityRecord r,
3268             String resultWho, int requestCode, int resultCode, Intent data) {
3269 
3270         if (callingUid > 0) {
3271             mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3272                     data, r.getUriPermissionsLocked(), r.userId);
3273         }
3274 
3275         if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
3276                 + " : who=" + resultWho + " req=" + requestCode
3277                 + " res=" + resultCode + " data=" + data);
3278         if (mResumedActivity == r && r.app != null && r.app.thread != null) {
3279             try {
3280                 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
3281                 list.add(new ResultInfo(resultWho, requestCode,
3282                         resultCode, data));
3283                 r.app.thread.scheduleSendResult(r.appToken, list);
3284                 return;
3285             } catch (Exception e) {
3286                 Slog.w(TAG, "Exception thrown sending result to " + r, e);
3287             }
3288         }
3289 
3290         r.addResultLocked(null, resultWho, requestCode, resultCode, data);
3291     }
3292 
3293     /** Returns true if the task is one of the task finishing on-top of the top running task. */
isATopFinishingTask(TaskRecord task)3294     boolean isATopFinishingTask(TaskRecord task) {
3295         for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
3296             final TaskRecord current = mTaskHistory.get(i);
3297             final ActivityRecord r = current.topRunningActivityLocked();
3298             if (r != null) {
3299                 // We got a top running activity, so there isn't a top finishing task...
3300                 return false;
3301             }
3302             if (current == task) {
3303                 return true;
3304             }
3305         }
3306         return false;
3307     }
3308 
adjustFocusedActivityStackLocked(ActivityRecord r, String reason)3309     private void adjustFocusedActivityStackLocked(ActivityRecord r, String reason) {
3310         if (!mStackSupervisor.isFocusedStack(this) ||
3311                 ((mResumedActivity != r) && (mResumedActivity != null))) {
3312             return;
3313         }
3314 
3315         final ActivityRecord next = topRunningActivityLocked();
3316         final String myReason = reason + " adjustFocus";
3317 
3318         if (next != r) {
3319             if (next != null && StackId.keepFocusInStackIfPossible(mStackId) && isFocusable()) {
3320                 // For freeform, docked, and pinned stacks we always keep the focus within the
3321                 // stack as long as there is a running activity.
3322                 return;
3323             } else {
3324                 // Task is not guaranteed to be non-null. For example, destroying the
3325                 // {@link ActivityRecord} will disassociate the task from the activity.
3326                 final TaskRecord task = r.getTask();
3327 
3328                 if (task == null) {
3329                     throw new IllegalStateException("activity no longer associated with task:" + r);
3330                 }
3331 
3332                 final boolean isAssistantOrOverAssistant = task.getStack().isAssistantStack() ||
3333                         task.isOverAssistantStack();
3334                 if (r.frontOfTask && isATopFinishingTask(task)
3335                         && (task.isOverHomeStack() || isAssistantOrOverAssistant)) {
3336                     // For non-fullscreen or assistant stack, we want to move the focus to the next
3337                     // visible stack to prevent the home screen from moving to the top and obscuring
3338                     // other visible stacks.
3339                     if ((!mFullscreen || isAssistantOrOverAssistant)
3340                             && adjustFocusToNextFocusableStackLocked(myReason)) {
3341                         return;
3342                     }
3343                     // Move the home stack to the top if this stack is fullscreen or there is no
3344                     // other visible stack.
3345                     if (task.isOverHomeStack() &&
3346                             mStackSupervisor.moveHomeStackTaskToTop(myReason)) {
3347                         // Activity focus was already adjusted. Nothing else to do...
3348                         return;
3349                     }
3350                 }
3351             }
3352         }
3353 
3354         mStackSupervisor.moveFocusableActivityStackToFrontLocked(
3355                 mStackSupervisor.topRunningActivityLocked(), myReason);
3356     }
3357 
3358     /** Find next proper focusable stack and make it focused. */
adjustFocusToNextFocusableStackLocked(String reason)3359     private boolean adjustFocusToNextFocusableStackLocked(String reason) {
3360         return adjustFocusToNextFocusableStackLocked(reason, false /* allowFocusSelf */);
3361     }
3362 
3363     /**
3364      * Find next proper focusable stack and make it focused.
3365      * @param allowFocusSelf Is the focus allowed to remain on the same stack.
3366      */
adjustFocusToNextFocusableStackLocked(String reason, boolean allowFocusSelf)3367     private boolean adjustFocusToNextFocusableStackLocked(String reason, boolean allowFocusSelf) {
3368         final ActivityStack stack = mStackSupervisor.getNextFocusableStackLocked(
3369                 allowFocusSelf ? null : this);
3370         final String myReason = reason + " adjustFocusToNextFocusableStack";
3371         if (stack == null) {
3372             return false;
3373         }
3374 
3375         final ActivityRecord top = stack.topRunningActivityLocked();
3376 
3377         if (stack.isHomeOrRecentsStack() && (top == null || !top.visible)) {
3378             // If we will be focusing on the home stack next and its current top activity isn't
3379             // visible, then use the task return to value to determine the home task to display
3380             // next.
3381             return mStackSupervisor.moveHomeStackTaskToTop(reason);
3382         }
3383 
3384         stack.moveToFront(myReason);
3385         return true;
3386     }
3387 
stopActivityLocked(ActivityRecord r)3388     final void stopActivityLocked(ActivityRecord r) {
3389         if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + r);
3390         if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3391                 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3392             if (!r.finishing) {
3393                 if (!mService.isSleepingLocked()) {
3394                     if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + r);
3395                     if (requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
3396                             "stop-no-history", false)) {
3397                         // If {@link requestFinishActivityLocked} returns {@code true},
3398                         // {@link adjustFocusedActivityStackLocked} would have been already called.
3399                         r.resumeKeyDispatchingLocked();
3400                         return;
3401                     }
3402                 } else {
3403                     if (DEBUG_STATES) Slog.d(TAG_STATES, "Not finishing noHistory " + r
3404                             + " on stop because we're just sleeping");
3405                 }
3406             }
3407         }
3408 
3409         if (r.app != null && r.app.thread != null) {
3410             adjustFocusedActivityStackLocked(r, "stopActivity");
3411             r.resumeKeyDispatchingLocked();
3412             try {
3413                 r.stopped = false;
3414                 if (DEBUG_STATES) Slog.v(TAG_STATES,
3415                         "Moving to STOPPING: " + r + " (stop requested)");
3416                 r.state = STOPPING;
3417                 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
3418                         "Stopping visible=" + r.visible + " for " + r);
3419                 if (!r.visible) {
3420                     r.setVisible(false);
3421                 }
3422                 EventLogTags.writeAmStopActivity(
3423                         r.userId, System.identityHashCode(r), r.shortComponentName);
3424                 r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
3425                 if (mService.isSleepingOrShuttingDownLocked()) {
3426                     r.setSleeping(true);
3427                 }
3428                 Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r);
3429                 mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
3430             } catch (Exception e) {
3431                 // Maybe just ignore exceptions here...  if the process
3432                 // has crashed, our death notification will clean things
3433                 // up.
3434                 Slog.w(TAG, "Exception thrown during pause", e);
3435                 // Just in case, assume it to be stopped.
3436                 r.stopped = true;
3437                 if (DEBUG_STATES) Slog.v(TAG_STATES, "Stop failed; moving to STOPPED: " + r);
3438                 r.state = STOPPED;
3439                 if (r.deferRelaunchUntilPaused) {
3440                     destroyActivityLocked(r, true, "stop-except");
3441                 }
3442             }
3443         }
3444     }
3445 
3446     /**
3447      * @return Returns true if the activity is being finished, false if for
3448      * some reason it is being left as-is.
3449      */
requestFinishActivityLocked(IBinder token, int resultCode, Intent resultData, String reason, boolean oomAdj)3450     final boolean requestFinishActivityLocked(IBinder token, int resultCode,
3451             Intent resultData, String reason, boolean oomAdj) {
3452         ActivityRecord r = isInStackLocked(token);
3453         if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(TAG_STATES,
3454                 "Finishing activity token=" + token + " r="
3455                 + ", result=" + resultCode + ", data=" + resultData
3456                 + ", reason=" + reason);
3457         if (r == null) {
3458             return false;
3459         }
3460 
3461         finishActivityLocked(r, resultCode, resultData, reason, oomAdj);
3462         return true;
3463     }
3464 
finishSubActivityLocked(ActivityRecord self, String resultWho, int requestCode)3465     final void finishSubActivityLocked(ActivityRecord self, String resultWho, int requestCode) {
3466         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3467             ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3468             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3469                 ActivityRecord r = activities.get(activityNdx);
3470                 if (r.resultTo == self && r.requestCode == requestCode) {
3471                     if ((r.resultWho == null && resultWho == null) ||
3472                         (r.resultWho != null && r.resultWho.equals(resultWho))) {
3473                         finishActivityLocked(r, Activity.RESULT_CANCELED, null, "request-sub",
3474                                 false);
3475                     }
3476                 }
3477             }
3478         }
3479         mService.updateOomAdjLocked();
3480     }
3481 
finishTopRunningActivityLocked(ProcessRecord app, String reason)3482     final TaskRecord finishTopRunningActivityLocked(ProcessRecord app, String reason) {
3483         ActivityRecord r = topRunningActivityLocked();
3484         TaskRecord finishedTask = null;
3485         if (r == null || r.app != app) {
3486             return null;
3487         }
3488         Slog.w(TAG, "  Force finishing activity "
3489                 + r.intent.getComponent().flattenToShortString());
3490         finishedTask = r.getTask();
3491         int taskNdx = mTaskHistory.indexOf(finishedTask);
3492         final TaskRecord task = finishedTask;
3493         int activityNdx = task.mActivities.indexOf(r);
3494         finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false);
3495         finishedTask = task;
3496         // Also terminate any activities below it that aren't yet
3497         // stopped, to avoid a situation where one will get
3498         // re-start our crashing activity once it gets resumed again.
3499         --activityNdx;
3500         if (activityNdx < 0) {
3501             do {
3502                 --taskNdx;
3503                 if (taskNdx < 0) {
3504                     break;
3505                 }
3506                 activityNdx = mTaskHistory.get(taskNdx).mActivities.size() - 1;
3507             } while (activityNdx < 0);
3508         }
3509         if (activityNdx >= 0) {
3510             r = mTaskHistory.get(taskNdx).mActivities.get(activityNdx);
3511             if (r.state == ActivityState.RESUMED
3512                     || r.state == ActivityState.PAUSING
3513                     || r.state == ActivityState.PAUSED) {
3514                 if (!r.isHomeActivity() || mService.mHomeProcess != r.app) {
3515                     Slog.w(TAG, "  Force finishing activity "
3516                             + r.intent.getComponent().flattenToShortString());
3517                     finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false);
3518                 }
3519             }
3520         }
3521         return finishedTask;
3522     }
3523 
finishVoiceTask(IVoiceInteractionSession session)3524     final void finishVoiceTask(IVoiceInteractionSession session) {
3525         IBinder sessionBinder = session.asBinder();
3526         boolean didOne = false;
3527         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3528             TaskRecord tr = mTaskHistory.get(taskNdx);
3529             if (tr.voiceSession != null && tr.voiceSession.asBinder() == sessionBinder) {
3530                 for (int activityNdx = tr.mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
3531                     ActivityRecord r = tr.mActivities.get(activityNdx);
3532                     if (!r.finishing) {
3533                         finishActivityLocked(r, Activity.RESULT_CANCELED, null, "finish-voice",
3534                                 false);
3535                         didOne = true;
3536                     }
3537                 }
3538             } else {
3539                 // Check if any of the activities are using voice
3540                 for (int activityNdx = tr.mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
3541                     ActivityRecord r = tr.mActivities.get(activityNdx);
3542                     if (r.voiceSession != null
3543                             && r.voiceSession.asBinder() == sessionBinder) {
3544                         // Inform of cancellation
3545                         r.clearVoiceSessionLocked();
3546                         try {
3547                             r.app.thread.scheduleLocalVoiceInteractionStarted((IBinder) r.appToken,
3548                                     null);
3549                         } catch (RemoteException re) {
3550                             // Ok
3551                         }
3552                         mService.finishRunningVoiceLocked();
3553                         break;
3554                     }
3555                 }
3556             }
3557         }
3558 
3559         if (didOne) {
3560             mService.updateOomAdjLocked();
3561         }
3562     }
3563 
finishActivityAffinityLocked(ActivityRecord r)3564     final boolean finishActivityAffinityLocked(ActivityRecord r) {
3565         ArrayList<ActivityRecord> activities = r.getTask().mActivities;
3566         for (int index = activities.indexOf(r); index >= 0; --index) {
3567             ActivityRecord cur = activities.get(index);
3568             if (!Objects.equals(cur.taskAffinity, r.taskAffinity)) {
3569                 break;
3570             }
3571             finishActivityLocked(cur, Activity.RESULT_CANCELED, null, "request-affinity", true);
3572         }
3573         return true;
3574     }
3575 
finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData)3576     private void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
3577         // send the result
3578         ActivityRecord resultTo = r.resultTo;
3579         if (resultTo != null) {
3580             if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Adding result to " + resultTo
3581                     + " who=" + r.resultWho + " req=" + r.requestCode
3582                     + " res=" + resultCode + " data=" + resultData);
3583             if (resultTo.userId != r.userId) {
3584                 if (resultData != null) {
3585                     resultData.prepareToLeaveUser(r.userId);
3586                 }
3587             }
3588             if (r.info.applicationInfo.uid > 0) {
3589                 mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
3590                         resultTo.packageName, resultData,
3591                         resultTo.getUriPermissionsLocked(), resultTo.userId);
3592             }
3593             resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
3594                                      resultData);
3595             r.resultTo = null;
3596         }
3597         else if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "No result destination from " + r);
3598 
3599         // Make sure this HistoryRecord is not holding on to other resources,
3600         // because clients have remote IPC references to this object so we
3601         // can't assume that will go away and want to avoid circular IPC refs.
3602         r.results = null;
3603         r.pendingResults = null;
3604         r.newIntents = null;
3605         r.icicle = null;
3606     }
3607 
3608     /**
3609      * See {@link #finishActivityLocked(ActivityRecord, int, Intent, String, boolean, boolean)}
3610      */
finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData, String reason, boolean oomAdj)3611     final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
3612             String reason, boolean oomAdj) {
3613         return finishActivityLocked(r, resultCode, resultData, reason, oomAdj, !PAUSE_IMMEDIATELY);
3614     }
3615 
3616     /**
3617      * @return Returns true if this activity has been removed from the history
3618      * list, or false if it is still in the list and will be removed later.
3619      */
finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData, String reason, boolean oomAdj, boolean pauseImmediately)3620     final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
3621             String reason, boolean oomAdj, boolean pauseImmediately) {
3622         if (r.finishing) {
3623             Slog.w(TAG, "Duplicate finish request for " + r);
3624             return false;
3625         }
3626 
3627         mWindowManager.deferSurfaceLayout();
3628         try {
3629             r.makeFinishingLocked();
3630             final TaskRecord task = r.getTask();
3631             EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
3632                     r.userId, System.identityHashCode(r),
3633                     task.taskId, r.shortComponentName, reason);
3634             final ArrayList<ActivityRecord> activities = task.mActivities;
3635             final int index = activities.indexOf(r);
3636             if (index < (activities.size() - 1)) {
3637                 task.setFrontOfTask();
3638                 if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
3639                     // If the caller asked that this activity (and all above it)
3640                     // be cleared when the task is reset, don't lose that information,
3641                     // but propagate it up to the next activity.
3642                     ActivityRecord next = activities.get(index+1);
3643                     next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
3644                 }
3645             }
3646 
3647             r.pauseKeyDispatchingLocked();
3648 
3649             adjustFocusedActivityStackLocked(r, "finishActivity");
3650 
3651             finishActivityResultsLocked(r, resultCode, resultData);
3652 
3653             final boolean endTask = index <= 0;
3654             final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
3655             if (mResumedActivity == r) {
3656                 if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
3657                         "Prepare close transition: finishing " + r);
3658                 if (endTask) {
3659                     mService.mTaskChangeNotificationController.notifyTaskRemovalStarted(
3660                             task.taskId);
3661                 }
3662                 mWindowManager.prepareAppTransition(transit, false);
3663 
3664                 // Tell window manager to prepare for this one to be removed.
3665                 r.setVisibility(false);
3666 
3667                 if (mPausingActivity == null) {
3668                     if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + r);
3669                     if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
3670                             "finish() => pause with userLeaving=false");
3671                     startPausingLocked(false, false, null, pauseImmediately);
3672                 }
3673 
3674                 if (endTask) {
3675                     mStackSupervisor.removeLockedTaskLocked(task);
3676                 }
3677             } else if (r.state != ActivityState.PAUSING) {
3678                 // If the activity is PAUSING, we will complete the finish once
3679                 // it is done pausing; else we can just directly finish it here.
3680                 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish not pausing: " + r);
3681                 if (r.visible) {
3682                     prepareActivityHideTransitionAnimation(r, transit);
3683                 }
3684 
3685                 final int finishMode = (r.visible || r.nowVisible) ? FINISH_AFTER_VISIBLE
3686                         : FINISH_AFTER_PAUSE;
3687                 final boolean removedActivity = finishCurrentActivityLocked(r, finishMode, oomAdj)
3688                         == null;
3689 
3690                 // The following code is an optimization. When the last non-task overlay activity
3691                 // is removed from the task, we remove the entire task from the stack. However,
3692                 // since that is done after the scheduled destroy callback from the activity, that
3693                 // call to change the visibility of the task overlay activities would be out of
3694                 // sync with the activitiy visibility being set for this finishing activity above.
3695                 // In this case, we can set the visibility of all the task overlay activities when
3696                 // we detect the last one is finishing to keep them in sync.
3697                 if (task.onlyHasTaskOverlayActivities(true /* excludeFinishing */)) {
3698                     for (ActivityRecord taskOverlay : task.mActivities) {
3699                         if (!taskOverlay.mTaskOverlay) {
3700                             continue;
3701                         }
3702                         prepareActivityHideTransitionAnimation(taskOverlay, transit);
3703                     }
3704                 }
3705                 return removedActivity;
3706             } else {
3707                 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + r);
3708             }
3709 
3710             return false;
3711         } finally {
3712             mWindowManager.continueSurfaceLayout();
3713         }
3714     }
3715 
prepareActivityHideTransitionAnimation(ActivityRecord r, int transit)3716     private void prepareActivityHideTransitionAnimation(ActivityRecord r, int transit) {
3717         mWindowManager.prepareAppTransition(transit, false);
3718         r.setVisibility(false);
3719         mWindowManager.executeAppTransition();
3720         if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(r)) {
3721             mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(r);
3722         }
3723     }
3724 
3725     static final int FINISH_IMMEDIATELY = 0;
3726     static final int FINISH_AFTER_PAUSE = 1;
3727     static final int FINISH_AFTER_VISIBLE = 2;
3728 
finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj)3729     final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj) {
3730         // First things first: if this activity is currently visible,
3731         // and the resumed activity is not yet visible, then hold off on
3732         // finishing until the resumed one becomes visible.
3733 
3734         final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
3735 
3736         if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible)
3737                 && next != null && !next.nowVisible) {
3738             if (!mStackSupervisor.mStoppingActivities.contains(r)) {
3739                 addToStopping(r, false /* scheduleIdle */, false /* idleDelayed */);
3740             }
3741             if (DEBUG_STATES) Slog.v(TAG_STATES,
3742                     "Moving to STOPPING: "+ r + " (finish requested)");
3743             r.state = STOPPING;
3744             if (oomAdj) {
3745                 mService.updateOomAdjLocked();
3746             }
3747             return r;
3748         }
3749 
3750         // make sure the record is cleaned out of other places.
3751         mStackSupervisor.mStoppingActivities.remove(r);
3752         mStackSupervisor.mGoingToSleepActivities.remove(r);
3753         mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(r);
3754         if (mResumedActivity == r) {
3755             mResumedActivity = null;
3756         }
3757         final ActivityState prevState = r.state;
3758         if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + r);
3759         r.state = ActivityState.FINISHING;
3760         final boolean finishingActivityInNonFocusedStack
3761                 = r.getStack() != mStackSupervisor.getFocusedStack()
3762                 && prevState == ActivityState.PAUSED && mode == FINISH_AFTER_VISIBLE;
3763 
3764         if (mode == FINISH_IMMEDIATELY
3765                 || (prevState == ActivityState.PAUSED
3766                     && (mode == FINISH_AFTER_PAUSE || mStackId == PINNED_STACK_ID))
3767                 || finishingActivityInNonFocusedStack
3768                 || prevState == STOPPING
3769                 || prevState == STOPPED
3770                 || prevState == ActivityState.INITIALIZING) {
3771             r.makeFinishingLocked();
3772             boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm");
3773 
3774             if (finishingActivityInNonFocusedStack) {
3775                 // Finishing activity that was in paused state and it was in not currently focused
3776                 // stack, need to make something visible in its place.
3777                 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
3778             }
3779             if (activityRemoved) {
3780                 mStackSupervisor.resumeFocusedStackTopActivityLocked();
3781             }
3782             if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS,
3783                     "destroyActivityLocked: finishCurrentActivityLocked r=" + r +
3784                     " destroy returned removed=" + activityRemoved);
3785             return activityRemoved ? null : r;
3786         }
3787 
3788         // Need to go through the full pause cycle to get this
3789         // activity into the stopped state and then finish it.
3790         if (DEBUG_ALL) Slog.v(TAG, "Enqueueing pending finish: " + r);
3791         mStackSupervisor.mFinishingActivities.add(r);
3792         r.resumeKeyDispatchingLocked();
3793         mStackSupervisor.resumeFocusedStackTopActivityLocked();
3794         return r;
3795     }
3796 
finishAllActivitiesLocked(boolean immediately)3797     void finishAllActivitiesLocked(boolean immediately) {
3798         boolean noActivitiesInStack = true;
3799         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3800             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3801             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3802                 final ActivityRecord r = activities.get(activityNdx);
3803                 noActivitiesInStack = false;
3804                 if (r.finishing && !immediately) {
3805                     continue;
3806                 }
3807                 Slog.d(TAG, "finishAllActivitiesLocked: finishing " + r + " immediately");
3808                 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
3809             }
3810         }
3811         if (noActivitiesInStack) {
3812             mActivityContainer.onTaskListEmptyLocked();
3813         }
3814     }
3815 
shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity)3816     final boolean shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity) {
3817         // Basic case: for simple app-centric recents, we need to recreate
3818         // the task if the affinity has changed.
3819         if (srec == null || srec.getTask().affinity == null ||
3820                 !srec.getTask().affinity.equals(destAffinity)) {
3821             return true;
3822         }
3823         // Document-centric case: an app may be split in to multiple documents;
3824         // they need to re-create their task if this current activity is the root
3825         // of a document, unless simply finishing it will return them to the the
3826         // correct app behind.
3827         final TaskRecord task = srec.getTask();
3828         if (srec.frontOfTask && task != null && task.getBaseIntent() != null
3829                 && task.getBaseIntent().isDocument()) {
3830             // Okay, this activity is at the root of its task.  What to do, what to do...
3831             if (task.getTaskToReturnTo() != ActivityRecord.APPLICATION_ACTIVITY_TYPE) {
3832                 // Finishing won't return to an application, so we need to recreate.
3833                 return true;
3834             }
3835             // We now need to get the task below it to determine what to do.
3836             int taskIdx = mTaskHistory.indexOf(task);
3837             if (taskIdx <= 0) {
3838                 Slog.w(TAG, "shouldUpRecreateTask: task not in history for " + srec);
3839                 return false;
3840             }
3841             if (taskIdx == 0) {
3842                 // At the bottom of the stack, nothing to go back to.
3843                 return true;
3844             }
3845             TaskRecord prevTask = mTaskHistory.get(taskIdx);
3846             if (!task.affinity.equals(prevTask.affinity)) {
3847                 // These are different apps, so need to recreate.
3848                 return true;
3849             }
3850         }
3851         return false;
3852     }
3853 
navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode, Intent resultData)3854     final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode,
3855             Intent resultData) {
3856         final TaskRecord task = srec.getTask();
3857         final ArrayList<ActivityRecord> activities = task.mActivities;
3858         final int start = activities.indexOf(srec);
3859         if (!mTaskHistory.contains(task) || (start < 0)) {
3860             return false;
3861         }
3862         int finishTo = start - 1;
3863         ActivityRecord parent = finishTo < 0 ? null : activities.get(finishTo);
3864         boolean foundParentInTask = false;
3865         final ComponentName dest = destIntent.getComponent();
3866         if (start > 0 && dest != null) {
3867             for (int i = finishTo; i >= 0; i--) {
3868                 ActivityRecord r = activities.get(i);
3869                 if (r.info.packageName.equals(dest.getPackageName()) &&
3870                         r.info.name.equals(dest.getClassName())) {
3871                     finishTo = i;
3872                     parent = r;
3873                     foundParentInTask = true;
3874                     break;
3875                 }
3876             }
3877         }
3878 
3879         IActivityController controller = mService.mController;
3880         if (controller != null) {
3881             ActivityRecord next = topRunningActivityLocked(srec.appToken, 0);
3882             if (next != null) {
3883                 // ask watcher if this is allowed
3884                 boolean resumeOK = true;
3885                 try {
3886                     resumeOK = controller.activityResuming(next.packageName);
3887                 } catch (RemoteException e) {
3888                     mService.mController = null;
3889                     Watchdog.getInstance().setActivityController(null);
3890                 }
3891 
3892                 if (!resumeOK) {
3893                     return false;
3894                 }
3895             }
3896         }
3897         final long origId = Binder.clearCallingIdentity();
3898         for (int i = start; i > finishTo; i--) {
3899             ActivityRecord r = activities.get(i);
3900             requestFinishActivityLocked(r.appToken, resultCode, resultData, "navigate-up", true);
3901             // Only return the supplied result for the first activity finished
3902             resultCode = Activity.RESULT_CANCELED;
3903             resultData = null;
3904         }
3905 
3906         if (parent != null && foundParentInTask) {
3907             final int parentLaunchMode = parent.info.launchMode;
3908             final int destIntentFlags = destIntent.getFlags();
3909             if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE ||
3910                     parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
3911                     parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
3912                     (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3913                 parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent,
3914                         srec.packageName);
3915             } else {
3916                 try {
3917                     ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
3918                             destIntent.getComponent(), 0, srec.userId);
3919                     int res = mService.mActivityStarter.startActivityLocked(srec.app.thread,
3920                             destIntent, null /*ephemeralIntent*/, null, aInfo, null /*rInfo*/, null,
3921                             null, parent.appToken, null, 0, -1, parent.launchedFromUid,
3922                             parent.launchedFromPackage, -1, parent.launchedFromUid, 0, null,
3923                             false, true, null, null, null, "navigateUpTo");
3924                     foundParentInTask = res == ActivityManager.START_SUCCESS;
3925                 } catch (RemoteException e) {
3926                     foundParentInTask = false;
3927                 }
3928                 requestFinishActivityLocked(parent.appToken, resultCode,
3929                         resultData, "navigate-top", true);
3930             }
3931         }
3932         Binder.restoreCallingIdentity(origId);
3933         return foundParentInTask;
3934     }
3935 
3936     /**
3937      * Remove any state associated with the {@link ActivityRecord}. This should be called whenever
3938      * an activity moves away from the stack.
3939      */
onActivityRemovedFromStack(ActivityRecord r)3940     void onActivityRemovedFromStack(ActivityRecord r) {
3941         if (mResumedActivity == r) {
3942             mResumedActivity = null;
3943         }
3944         if (mPausingActivity == r) {
3945             mPausingActivity = null;
3946         }
3947 
3948         removeTimeoutsForActivityLocked(r);
3949     }
3950 
3951     /**
3952      * Perform the common clean-up of an activity record.  This is called both
3953      * as part of destroyActivityLocked() (when destroying the client-side
3954      * representation) and cleaning things up as a result of its hosting
3955      * processing going away, in which case there is no remaining client-side
3956      * state to destroy so only the cleanup here is needed.
3957      *
3958      * Note: Call before #removeActivityFromHistoryLocked.
3959      */
cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState)3960     private void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState) {
3961         onActivityRemovedFromStack(r);
3962 
3963         r.deferRelaunchUntilPaused = false;
3964         r.frozenBeforeDestroy = false;
3965 
3966         if (setState) {
3967             if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + r + " (cleaning up)");
3968             r.state = ActivityState.DESTROYED;
3969             if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + r);
3970             r.app = null;
3971         }
3972 
3973         // Inform supervisor the activity has been removed.
3974         mStackSupervisor.cleanupActivity(r);
3975 
3976 
3977         // Remove any pending results.
3978         if (r.finishing && r.pendingResults != null) {
3979             for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
3980                 PendingIntentRecord rec = apr.get();
3981                 if (rec != null) {
3982                     mService.cancelIntentSenderLocked(rec, false);
3983                 }
3984             }
3985             r.pendingResults = null;
3986         }
3987 
3988         if (cleanServices) {
3989             cleanUpActivityServicesLocked(r);
3990         }
3991 
3992         // Get rid of any pending idle timeouts.
3993         removeTimeoutsForActivityLocked(r);
3994         if (getVisibleBehindActivity() == r) {
3995             mStackSupervisor.requestVisibleBehindLocked(r, false);
3996         }
3997 
3998         // Clean-up activities are no longer relaunching (e.g. app process died). Notify window
3999         // manager so it can update its bookkeeping.
4000         mWindowManager.notifyAppRelaunchesCleared(r.appToken);
4001     }
4002 
removeTimeoutsForActivityLocked(ActivityRecord r)4003     void removeTimeoutsForActivityLocked(ActivityRecord r) {
4004         mStackSupervisor.removeTimeoutsForActivityLocked(r);
4005         mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4006         mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
4007         mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
4008         r.finishLaunchTickingLocked();
4009     }
4010 
removeActivityFromHistoryLocked(ActivityRecord r, String reason)4011     private void removeActivityFromHistoryLocked(ActivityRecord r, String reason) {
4012         mStackSupervisor.removeChildActivityContainers(r);
4013         finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
4014         r.makeFinishingLocked();
4015         if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
4016                 "Removing activity " + r + " from stack callers=" + Debug.getCallers(5));
4017 
4018         r.takeFromHistory();
4019         removeTimeoutsForActivityLocked(r);
4020         if (DEBUG_STATES) Slog.v(TAG_STATES,
4021                 "Moving to DESTROYED: " + r + " (removed from history)");
4022         r.state = ActivityState.DESTROYED;
4023         if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + r);
4024         r.app = null;
4025         r.removeWindowContainer();
4026         final TaskRecord task = r.getTask();
4027         final boolean lastActivity = task != null ? task.removeActivity(r) : false;
4028         // If we are removing the last activity in the task, not including task overlay activities,
4029         // then fall through into the block below to remove the entire task itself
4030         final boolean onlyHasTaskOverlays = task != null
4031                 ? task.onlyHasTaskOverlayActivities(false /* excludingFinishing */) : false;
4032 
4033         if (lastActivity || onlyHasTaskOverlays) {
4034             if (DEBUG_STACK) {
4035                 Slog.i(TAG_STACK,
4036                         "removeActivityFromHistoryLocked: last activity removed from " + this
4037                                 + " onlyHasTaskOverlays=" + onlyHasTaskOverlays);
4038             }
4039 
4040             if (mStackSupervisor.isFocusedStack(this) && task == topTask() &&
4041                     task.isOverHomeStack()) {
4042                 mStackSupervisor.moveHomeStackTaskToTop(reason);
4043             }
4044 
4045             // The following block can be executed multiple times if there is more than one overlay.
4046             // {@link ActivityStackSupervisor#removeTaskByIdLocked} handles this by reverse lookup
4047             // of the task by id and exiting early if not found.
4048             if (onlyHasTaskOverlays) {
4049                 // When destroying a task, tell the supervisor to remove it so that any activity it
4050                 // has can be cleaned up correctly. This is currently the only place where we remove
4051                 // a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays
4052                 // state into removeTask(), we just clear the task here before the other residual
4053                 // work.
4054                 // TODO: If the callers to removeTask() changes such that we have multiple places
4055                 //       where we are destroying the task, move this back into removeTask()
4056                 mStackSupervisor.removeTaskByIdLocked(task.taskId, false /* killProcess */,
4057                         !REMOVE_FROM_RECENTS, PAUSE_IMMEDIATELY);
4058             }
4059 
4060             // We must keep the task around until all activities are destroyed. The following
4061             // statement will only execute once since overlays are also considered activities.
4062             if (lastActivity) {
4063                 removeTask(task, reason, REMOVE_TASK_MODE_DESTROYING);
4064             }
4065         }
4066         cleanUpActivityServicesLocked(r);
4067         r.removeUriPermissionsLocked();
4068     }
4069 
4070     /**
4071      * Perform clean-up of service connections in an activity record.
4072      */
cleanUpActivityServicesLocked(ActivityRecord r)4073     private void cleanUpActivityServicesLocked(ActivityRecord r) {
4074         // Throw away any services that have been bound by this activity.
4075         if (r.connections != null) {
4076             Iterator<ConnectionRecord> it = r.connections.iterator();
4077             while (it.hasNext()) {
4078                 ConnectionRecord c = it.next();
4079                 mService.mServices.removeConnectionLocked(c, null, r);
4080             }
4081             r.connections = null;
4082         }
4083     }
4084 
scheduleDestroyActivities(ProcessRecord owner, String reason)4085     final void scheduleDestroyActivities(ProcessRecord owner, String reason) {
4086         Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG);
4087         msg.obj = new ScheduleDestroyArgs(owner, reason);
4088         mHandler.sendMessage(msg);
4089     }
4090 
destroyActivitiesLocked(ProcessRecord owner, String reason)4091     private void destroyActivitiesLocked(ProcessRecord owner, String reason) {
4092         boolean lastIsOpaque = false;
4093         boolean activityRemoved = false;
4094         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4095             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
4096             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
4097                 final ActivityRecord r = activities.get(activityNdx);
4098                 if (r.finishing) {
4099                     continue;
4100                 }
4101                 if (r.fullscreen) {
4102                     lastIsOpaque = true;
4103                 }
4104                 if (owner != null && r.app != owner) {
4105                     continue;
4106                 }
4107                 if (!lastIsOpaque) {
4108                     continue;
4109                 }
4110                 if (r.isDestroyable()) {
4111                     if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Destroying " + r + " in state " + r.state
4112                             + " resumed=" + mResumedActivity
4113                             + " pausing=" + mPausingActivity + " for reason " + reason);
4114                     if (destroyActivityLocked(r, true, reason)) {
4115                         activityRemoved = true;
4116                     }
4117                 }
4118             }
4119         }
4120         if (activityRemoved) {
4121             mStackSupervisor.resumeFocusedStackTopActivityLocked();
4122         }
4123     }
4124 
safelyDestroyActivityLocked(ActivityRecord r, String reason)4125     final boolean safelyDestroyActivityLocked(ActivityRecord r, String reason) {
4126         if (r.isDestroyable()) {
4127             if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
4128                     "Destroying " + r + " in state " + r.state + " resumed=" + mResumedActivity
4129                     + " pausing=" + mPausingActivity + " for reason " + reason);
4130             return destroyActivityLocked(r, true, reason);
4131         }
4132         return false;
4133     }
4134 
releaseSomeActivitiesLocked(ProcessRecord app, ArraySet<TaskRecord> tasks, String reason)4135     final int releaseSomeActivitiesLocked(ProcessRecord app, ArraySet<TaskRecord> tasks,
4136             String reason) {
4137         // Iterate over tasks starting at the back (oldest) first.
4138         if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Trying to release some activities in " + app);
4139         int maxTasks = tasks.size() / 4;
4140         if (maxTasks < 1) {
4141             maxTasks = 1;
4142         }
4143         int numReleased = 0;
4144         for (int taskNdx = 0; taskNdx < mTaskHistory.size() && maxTasks > 0; taskNdx++) {
4145             final TaskRecord task = mTaskHistory.get(taskNdx);
4146             if (!tasks.contains(task)) {
4147                 continue;
4148             }
4149             if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Looking for activities to release in " + task);
4150             int curNum = 0;
4151             final ArrayList<ActivityRecord> activities = task.mActivities;
4152             for (int actNdx = 0; actNdx < activities.size(); actNdx++) {
4153                 final ActivityRecord activity = activities.get(actNdx);
4154                 if (activity.app == app && activity.isDestroyable()) {
4155                     if (DEBUG_RELEASE) Slog.v(TAG_RELEASE, "Destroying " + activity
4156                             + " in state " + activity.state + " resumed=" + mResumedActivity
4157                             + " pausing=" + mPausingActivity + " for reason " + reason);
4158                     destroyActivityLocked(activity, true, reason);
4159                     if (activities.get(actNdx) != activity) {
4160                         // Was removed from list, back up so we don't miss the next one.
4161                         actNdx--;
4162                     }
4163                     curNum++;
4164                 }
4165             }
4166             if (curNum > 0) {
4167                 numReleased += curNum;
4168                 maxTasks--;
4169                 if (mTaskHistory.get(taskNdx) != task) {
4170                     // The entire task got removed, back up so we don't miss the next one.
4171                     taskNdx--;
4172                 }
4173             }
4174         }
4175         if (DEBUG_RELEASE) Slog.d(TAG_RELEASE,
4176                 "Done releasing: did " + numReleased + " activities");
4177         return numReleased;
4178     }
4179 
4180     /**
4181      * Destroy the current CLIENT SIDE instance of an activity.  This may be
4182      * called both when actually finishing an activity, or when performing
4183      * a configuration switch where we destroy the current client-side object
4184      * but then create a new client-side object for this same HistoryRecord.
4185      */
destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason)4186     final boolean destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason) {
4187         if (DEBUG_SWITCH || DEBUG_CLEANUP) Slog.v(TAG_SWITCH,
4188                 "Removing activity from " + reason + ": token=" + r
4189                         + ", app=" + (r.app != null ? r.app.processName : "(null)"));
4190         EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
4191                 r.userId, System.identityHashCode(r),
4192                 r.getTask().taskId, r.shortComponentName, reason);
4193 
4194         boolean removedFromHistory = false;
4195 
4196         cleanUpActivityLocked(r, false, false);
4197 
4198         final boolean hadApp = r.app != null;
4199 
4200         if (hadApp) {
4201             if (removeFromApp) {
4202                 r.app.activities.remove(r);
4203                 if (mService.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
4204                     mService.mHeavyWeightProcess = null;
4205                     mService.mHandler.sendEmptyMessage(
4206                             ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG);
4207                 }
4208                 if (r.app.activities.isEmpty()) {
4209                     // Update any services we are bound to that might care about whether
4210                     // their client may have activities.
4211                     mService.mServices.updateServiceConnectionActivitiesLocked(r.app);
4212                     // No longer have activities, so update LRU list and oom adj.
4213                     mService.updateLruProcessLocked(r.app, false, null);
4214                     mService.updateOomAdjLocked();
4215                 }
4216             }
4217 
4218             boolean skipDestroy = false;
4219 
4220             try {
4221                 if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + r);
4222                 r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,
4223                         r.configChangeFlags);
4224             } catch (Exception e) {
4225                 // We can just ignore exceptions here...  if the process
4226                 // has crashed, our death notification will clean things
4227                 // up.
4228                 //Slog.w(TAG, "Exception thrown during finish", e);
4229                 if (r.finishing) {
4230                     removeActivityFromHistoryLocked(r, reason + " exceptionInScheduleDestroy");
4231                     removedFromHistory = true;
4232                     skipDestroy = true;
4233                 }
4234             }
4235 
4236             r.nowVisible = false;
4237 
4238             // If the activity is finishing, we need to wait on removing it
4239             // from the list to give it a chance to do its cleanup.  During
4240             // that time it may make calls back with its token so we need to
4241             // be able to find it on the list and so we don't want to remove
4242             // it from the list yet.  Otherwise, we can just immediately put
4243             // it in the destroyed state since we are not removing it from the
4244             // list.
4245             if (r.finishing && !skipDestroy) {
4246                 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYING: " + r
4247                         + " (destroy requested)");
4248                 r.state = ActivityState.DESTROYING;
4249                 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG, r);
4250                 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4251             } else {
4252                 if (DEBUG_STATES) Slog.v(TAG_STATES,
4253                         "Moving to DESTROYED: " + r + " (destroy skipped)");
4254                 r.state = ActivityState.DESTROYED;
4255                 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + r);
4256                 r.app = null;
4257             }
4258         } else {
4259             // remove this record from the history.
4260             if (r.finishing) {
4261                 removeActivityFromHistoryLocked(r, reason + " hadNoApp");
4262                 removedFromHistory = true;
4263             } else {
4264                 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + r + " (no app)");
4265                 r.state = ActivityState.DESTROYED;
4266                 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + r);
4267                 r.app = null;
4268             }
4269         }
4270 
4271         r.configChangeFlags = 0;
4272 
4273         if (!mLRUActivities.remove(r) && hadApp) {
4274             Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
4275         }
4276 
4277         return removedFromHistory;
4278     }
4279 
activityDestroyedLocked(IBinder token, String reason)4280     final void activityDestroyedLocked(IBinder token, String reason) {
4281         final long origId = Binder.clearCallingIdentity();
4282         try {
4283             ActivityRecord r = ActivityRecord.forTokenLocked(token);
4284             if (r != null) {
4285                 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
4286             }
4287             if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS, "activityDestroyedLocked: r=" + r);
4288 
4289             if (isInStackLocked(r) != null) {
4290                 if (r.state == ActivityState.DESTROYING) {
4291                     cleanUpActivityLocked(r, true, false);
4292                     removeActivityFromHistoryLocked(r, reason);
4293                 }
4294             }
4295             mStackSupervisor.resumeFocusedStackTopActivityLocked();
4296         } finally {
4297             Binder.restoreCallingIdentity(origId);
4298         }
4299     }
4300 
releaseBackgroundResources(ActivityRecord r)4301     void releaseBackgroundResources(ActivityRecord r) {
4302         if (hasVisibleBehindActivity() &&
4303                 !mHandler.hasMessages(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG)) {
4304             if (r == topRunningActivityLocked()
4305                     && shouldBeVisible(null) == STACK_VISIBLE) {
4306                 // Don't release the top activity if it has requested to run behind the next
4307                 // activity and the stack is currently visible.
4308                 return;
4309             }
4310             if (DEBUG_STATES) Slog.d(TAG_STATES, "releaseBackgroundResources activtyDisplay=" +
4311                     mActivityContainer.mActivityDisplay + " visibleBehind=" + r + " app=" + r.app +
4312                     " thread=" + r.app.thread);
4313             if (r != null && r.app != null && r.app.thread != null) {
4314                 try {
4315                     r.app.thread.scheduleCancelVisibleBehind(r.appToken);
4316                 } catch (RemoteException e) {
4317                 }
4318                 mHandler.sendEmptyMessageDelayed(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG, 500);
4319             } else {
4320                 Slog.e(TAG, "releaseBackgroundResources: activity " + r + " no longer running");
4321                 backgroundResourcesReleased();
4322             }
4323         }
4324     }
4325 
backgroundResourcesReleased()4326     final void backgroundResourcesReleased() {
4327         mHandler.removeMessages(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG);
4328         final ActivityRecord r = getVisibleBehindActivity();
4329         if (r != null) {
4330             mStackSupervisor.mStoppingActivities.add(r);
4331             setVisibleBehindActivity(null);
4332             mStackSupervisor.scheduleIdleTimeoutLocked(null);
4333         }
4334         mStackSupervisor.resumeFocusedStackTopActivityLocked();
4335     }
4336 
hasVisibleBehindActivity()4337     boolean hasVisibleBehindActivity() {
4338         return isAttached() && mActivityContainer.mActivityDisplay.hasVisibleBehindActivity();
4339     }
4340 
setVisibleBehindActivity(ActivityRecord r)4341     void setVisibleBehindActivity(ActivityRecord r) {
4342         if (isAttached()) {
4343             mActivityContainer.mActivityDisplay.setVisibleBehindActivity(r);
4344         }
4345     }
4346 
getVisibleBehindActivity()4347     ActivityRecord getVisibleBehindActivity() {
4348         return isAttached() ? mActivityContainer.mActivityDisplay.mVisibleBehindActivity : null;
4349     }
4350 
removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list, ProcessRecord app, String listName)4351     private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list,
4352             ProcessRecord app, String listName) {
4353         int i = list.size();
4354         if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
4355             "Removing app " + app + " from list " + listName + " with " + i + " entries");
4356         while (i > 0) {
4357             i--;
4358             ActivityRecord r = list.get(i);
4359             if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Record #" + i + " " + r);
4360             if (r.app == app) {
4361                 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "---> REMOVING this entry!");
4362                 list.remove(i);
4363                 removeTimeoutsForActivityLocked(r);
4364             }
4365         }
4366     }
4367 
removeHistoryRecordsForAppLocked(ProcessRecord app)4368     private boolean removeHistoryRecordsForAppLocked(ProcessRecord app) {
4369         removeHistoryRecordsForAppLocked(mLRUActivities, app, "mLRUActivities");
4370         removeHistoryRecordsForAppLocked(mStackSupervisor.mStoppingActivities, app,
4371                 "mStoppingActivities");
4372         removeHistoryRecordsForAppLocked(mStackSupervisor.mGoingToSleepActivities, app,
4373                 "mGoingToSleepActivities");
4374         removeHistoryRecordsForAppLocked(mStackSupervisor.mActivitiesWaitingForVisibleActivity, app,
4375                 "mActivitiesWaitingForVisibleActivity");
4376         removeHistoryRecordsForAppLocked(mStackSupervisor.mFinishingActivities, app,
4377                 "mFinishingActivities");
4378 
4379         boolean hasVisibleActivities = false;
4380 
4381         // Clean out the history list.
4382         int i = numActivities();
4383         if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
4384                 "Removing app " + app + " from history with " + i + " entries");
4385         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4386             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
4387             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
4388                 final ActivityRecord r = activities.get(activityNdx);
4389                 --i;
4390                 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
4391                         "Record #" + i + " " + r + ": app=" + r.app);
4392                 if (r.app == app) {
4393                     if (r.visible) {
4394                         hasVisibleActivities = true;
4395                     }
4396                     final boolean remove;
4397                     if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
4398                         // Don't currently have state for the activity, or
4399                         // it is finishing -- always remove it.
4400                         remove = true;
4401                     } else if (!r.visible && r.launchCount > 2 &&
4402                             r.lastLaunchTime > (SystemClock.uptimeMillis() - 60000)) {
4403                         // We have launched this activity too many times since it was
4404                         // able to run, so give up and remove it.
4405                         // (Note if the activity is visible, we don't remove the record.
4406                         // We leave the dead window on the screen but the process will
4407                         // not be restarted unless user explicitly tap on it.)
4408                         remove = true;
4409                     } else {
4410                         // The process may be gone, but the activity lives on!
4411                         remove = false;
4412                     }
4413                     if (remove) {
4414                         if (DEBUG_ADD_REMOVE || DEBUG_CLEANUP) Slog.i(TAG_ADD_REMOVE,
4415                                 "Removing activity " + r + " from stack at " + i
4416                                 + ": haveState=" + r.haveState
4417                                 + " stateNotNeeded=" + r.stateNotNeeded
4418                                 + " finishing=" + r.finishing
4419                                 + " state=" + r.state + " callers=" + Debug.getCallers(5));
4420                         if (!r.finishing) {
4421                             Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
4422                             EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
4423                                     r.userId, System.identityHashCode(r),
4424                                     r.getTask().taskId, r.shortComponentName,
4425                                     "proc died without state saved");
4426                             if (r.state == ActivityState.RESUMED) {
4427                                 mService.updateUsageStats(r, false);
4428                             }
4429                         }
4430                     } else {
4431                         // We have the current state for this activity, so
4432                         // it can be restarted later when needed.
4433                         if (DEBUG_ALL) Slog.v(TAG, "Keeping entry, setting app to null");
4434                         if (DEBUG_APP) Slog.v(TAG_APP,
4435                                 "Clearing app during removeHistory for activity " + r);
4436                         r.app = null;
4437                         // Set nowVisible to previous visible state. If the app was visible while
4438                         // it died, we leave the dead window on screen so it's basically visible.
4439                         // This is needed when user later tap on the dead window, we need to stop
4440                         // other apps when user transfers focus to the restarted activity.
4441                         r.nowVisible = r.visible;
4442                         if (!r.haveState) {
4443                             if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE,
4444                                     "App died, clearing saved state of " + r);
4445                             r.icicle = null;
4446                         }
4447                     }
4448                     cleanUpActivityLocked(r, true, true);
4449                     if (remove) {
4450                         removeActivityFromHistoryLocked(r, "appDied");
4451                     }
4452                 }
4453             }
4454         }
4455 
4456         return hasVisibleActivities;
4457     }
4458 
updateTransitLocked(int transit, ActivityOptions options)4459     private void updateTransitLocked(int transit, ActivityOptions options) {
4460         if (options != null) {
4461             ActivityRecord r = topRunningActivityLocked();
4462             if (r != null && r.state != ActivityState.RESUMED) {
4463                 r.updateOptionsLocked(options);
4464             } else {
4465                 ActivityOptions.abort(options);
4466             }
4467         }
4468         mWindowManager.prepareAppTransition(transit, false);
4469     }
4470 
updateTaskMovement(TaskRecord task, boolean toFront)4471     private void updateTaskMovement(TaskRecord task, boolean toFront) {
4472         if (task.isPersistable) {
4473             task.mLastTimeMoved = System.currentTimeMillis();
4474             // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most
4475             // recently will be most negative, tasks sent to the bottom before that will be less
4476             // negative. Similarly for recent tasks moved to the top which will be most positive.
4477             if (!toFront) {
4478                 task.mLastTimeMoved *= -1;
4479             }
4480         }
4481         mStackSupervisor.invalidateTaskLayers();
4482     }
4483 
moveHomeStackTaskToTop()4484     void moveHomeStackTaskToTop() {
4485         final int top = mTaskHistory.size() - 1;
4486         for (int taskNdx = top; taskNdx >= 0; --taskNdx) {
4487             final TaskRecord task = mTaskHistory.get(taskNdx);
4488             if (task.taskType == HOME_ACTIVITY_TYPE) {
4489                 if (DEBUG_TASKS || DEBUG_STACK) Slog.d(TAG_STACK,
4490                         "moveHomeStackTaskToTop: moving " + task);
4491                 mTaskHistory.remove(taskNdx);
4492                 mTaskHistory.add(top, task);
4493                 updateTaskMovement(task, true);
4494                 return;
4495             }
4496         }
4497     }
4498 
moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options, AppTimeTracker timeTracker, String reason)4499     final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options,
4500             AppTimeTracker timeTracker, String reason) {
4501         if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
4502 
4503         final ActivityStack topStack = getTopStackOnDisplay();
4504         final ActivityRecord topActivity = topStack != null ? topStack.topActivity() : null;
4505         final int numTasks = mTaskHistory.size();
4506         final int index = mTaskHistory.indexOf(tr);
4507         if (numTasks == 0 || index < 0)  {
4508             // nothing to do!
4509             if (noAnimation) {
4510                 ActivityOptions.abort(options);
4511             } else {
4512                 updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
4513             }
4514             return;
4515         }
4516 
4517         if (timeTracker != null) {
4518             // The caller wants a time tracker associated with this task.
4519             for (int i = tr.mActivities.size() - 1; i >= 0; i--) {
4520                 tr.mActivities.get(i).appTimeTracker = timeTracker;
4521             }
4522         }
4523 
4524         // Shift all activities with this task up to the top
4525         // of the stack, keeping them in the same internal order.
4526         insertTaskAtTop(tr, null);
4527 
4528         // Don't refocus if invisible to current user
4529         final ActivityRecord top = tr.getTopActivity();
4530         if (top == null || !top.okToShowLocked()) {
4531             addRecentActivityLocked(top);
4532             ActivityOptions.abort(options);
4533             return;
4534         }
4535 
4536         // Set focus to the top running activity of this stack.
4537         final ActivityRecord r = topRunningActivityLocked();
4538         mStackSupervisor.moveFocusableActivityStackToFrontLocked(r, reason);
4539 
4540         if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
4541         if (noAnimation) {
4542             mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
4543             if (r != null) {
4544                 mNoAnimActivities.add(r);
4545             }
4546             ActivityOptions.abort(options);
4547         } else {
4548             updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
4549         }
4550         // If a new task is moved to the front, then mark the existing top activity as supporting
4551         // picture-in-picture while paused
4552         if (topActivity != null && topActivity.getStack().getStackId() != PINNED_STACK_ID) {
4553             topActivity.supportsPictureInPictureWhilePausing = true;
4554         }
4555 
4556         mStackSupervisor.resumeFocusedStackTopActivityLocked();
4557         EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
4558 
4559         mService.mTaskChangeNotificationController.notifyTaskMovedToFront(tr.taskId);
4560     }
4561 
4562     /**
4563      * Worker method for rearranging history stack. Implements the function of moving all
4564      * activities for a specific task (gathering them if disjoint) into a single group at the
4565      * bottom of the stack.
4566      *
4567      * If a watcher is installed, the action is preflighted and the watcher has an opportunity
4568      * to premeptively cancel the move.
4569      *
4570      * @param taskId The taskId to collect and move to the bottom.
4571      * @return Returns true if the move completed, false if not.
4572      */
moveTaskToBackLocked(int taskId)4573     final boolean moveTaskToBackLocked(int taskId) {
4574         final TaskRecord tr = taskForIdLocked(taskId);
4575         if (tr == null) {
4576             Slog.i(TAG, "moveTaskToBack: bad taskId=" + taskId);
4577             return false;
4578         }
4579         Slog.i(TAG, "moveTaskToBack: " + tr);
4580 
4581         // If the task is locked, then show the lock task toast
4582         if (mStackSupervisor.isLockedTask(tr)) {
4583             mStackSupervisor.showLockTaskToast();
4584             return false;
4585         }
4586 
4587         // If we have a watcher, preflight the move before committing to it.  First check
4588         // for *other* available tasks, but if none are available, then try again allowing the
4589         // current task to be selected.
4590         if (mStackSupervisor.isFrontStackOnDisplay(this) && mService.mController != null) {
4591             ActivityRecord next = topRunningActivityLocked(null, taskId);
4592             if (next == null) {
4593                 next = topRunningActivityLocked(null, 0);
4594             }
4595             if (next != null) {
4596                 // ask watcher if this is allowed
4597                 boolean moveOK = true;
4598                 try {
4599                     moveOK = mService.mController.activityResuming(next.packageName);
4600                 } catch (RemoteException e) {
4601                     mService.mController = null;
4602                     Watchdog.getInstance().setActivityController(null);
4603                 }
4604                 if (!moveOK) {
4605                     return false;
4606                 }
4607             }
4608         }
4609 
4610         if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to back transition: task=" + taskId);
4611 
4612         if (mStackId == HOME_STACK_ID && topTask().isHomeTask()) {
4613             // For the case where we are moving the home task back and there is an activity visible
4614             // behind it on the fullscreen or assistant stack, we want to move the focus to the
4615             // visible behind activity to maintain order with what the user is seeing.
4616             ActivityRecord visibleBehind = null;
4617             final ActivityStack fullscreenStack =
4618                     mStackSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID);
4619             final ActivityStack assistantStack =
4620                     mStackSupervisor.getStack(ASSISTANT_STACK_ID);
4621             if (fullscreenStack != null && fullscreenStack.hasVisibleBehindActivity()) {
4622                 visibleBehind = fullscreenStack.getVisibleBehindActivity();
4623             } else if (assistantStack != null && assistantStack.hasVisibleBehindActivity()) {
4624                 visibleBehind = assistantStack.getVisibleBehindActivity();
4625             }
4626             if (visibleBehind != null) {
4627                 mStackSupervisor.moveFocusableActivityStackToFrontLocked(visibleBehind,
4628                         "moveTaskToBack");
4629                 mStackSupervisor.resumeFocusedStackTopActivityLocked();
4630                 return true;
4631             }
4632         }
4633 
4634         boolean prevIsHome = false;
4635 
4636         // If true, we should resume the home activity next if the task we are moving to the
4637         // back is over the home stack. We force to false if the task we are moving to back
4638         // is the home task and we don't want it resumed after moving to the back.
4639         final boolean canGoHome = !tr.isHomeTask() && tr.isOverHomeStack();
4640         if (canGoHome) {
4641             final TaskRecord nextTask = getNextTask(tr);
4642             if (nextTask != null) {
4643                 nextTask.setTaskToReturnTo(tr.getTaskToReturnTo());
4644             } else {
4645                 prevIsHome = true;
4646             }
4647         }
4648 
4649         boolean requiresMove = mTaskHistory.indexOf(tr) != 0;
4650         if (requiresMove) {
4651             mTaskHistory.remove(tr);
4652             mTaskHistory.add(0, tr);
4653             updateTaskMovement(tr, false);
4654 
4655             mWindowManager.prepareAppTransition(TRANSIT_TASK_TO_BACK, false);
4656             mWindowContainerController.positionChildAtBottom(tr.getWindowContainerController());
4657         }
4658 
4659         if (mStackId == PINNED_STACK_ID) {
4660             mStackSupervisor.removeStackLocked(PINNED_STACK_ID);
4661             return true;
4662         }
4663 
4664         // Otherwise, there is an assumption that moving a task to the back moves it behind the
4665         // home activity. We make sure here that some activity in the stack will launch home.
4666         int numTasks = mTaskHistory.size();
4667         for (int taskNdx = numTasks - 1; taskNdx >= 1; --taskNdx) {
4668             final TaskRecord task = mTaskHistory.get(taskNdx);
4669             if (task.isOverHomeStack()) {
4670                 break;
4671             }
4672             if (taskNdx == 1) {
4673                 // Set the last task before tr to go to home.
4674                 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
4675             }
4676         }
4677 
4678         final TaskRecord task = mResumedActivity != null ? mResumedActivity.getTask() : null;
4679         if (prevIsHome || (task == tr && canGoHome) || (numTasks <= 1 && isOnHomeDisplay())) {
4680             if (!mService.mBooting && !mService.mBooted) {
4681                 // Not ready yet!
4682                 return false;
4683             }
4684             tr.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
4685             return mStackSupervisor.resumeHomeStackTask(null, "moveTaskToBack");
4686         }
4687 
4688         mStackSupervisor.resumeFocusedStackTopActivityLocked();
4689         return true;
4690     }
4691 
4692     /**
4693      * Get the topmost stack on the current display. It may be different from focused stack, because
4694      * focus may be on another display.
4695      */
getTopStackOnDisplay()4696     private ActivityStack getTopStackOnDisplay() {
4697         final ArrayList<ActivityStack> stacks = mActivityContainer.mActivityDisplay.mStacks;
4698         return stacks.isEmpty() ? null : stacks.get(stacks.size() - 1);
4699     }
4700 
logStartActivity(int tag, ActivityRecord r, TaskRecord task)4701     static void logStartActivity(int tag, ActivityRecord r, TaskRecord task) {
4702         final Uri data = r.intent.getData();
4703         final String strData = data != null ? data.toSafeString() : null;
4704 
4705         EventLog.writeEvent(tag,
4706                 r.userId, System.identityHashCode(r), task.taskId,
4707                 r.shortComponentName, r.intent.getAction(),
4708                 r.intent.getType(), strData, r.intent.getFlags());
4709     }
4710 
4711     /**
4712      * Ensures all visible activities at or below the input activity have the right configuration.
4713      */
ensureVisibleActivitiesConfigurationLocked(ActivityRecord start, boolean preserveWindow)4714     void ensureVisibleActivitiesConfigurationLocked(ActivityRecord start, boolean preserveWindow) {
4715         if (start == null || !start.visible) {
4716             return;
4717         }
4718 
4719         final TaskRecord startTask = start.getTask();
4720         boolean behindFullscreen = false;
4721         boolean updatedConfig = false;
4722 
4723         for (int taskIndex = mTaskHistory.indexOf(startTask); taskIndex >= 0; --taskIndex) {
4724             final TaskRecord task = mTaskHistory.get(taskIndex);
4725             final ArrayList<ActivityRecord> activities = task.mActivities;
4726             int activityIndex =
4727                     (start.getTask() == task) ? activities.indexOf(start) : activities.size() - 1;
4728             for (; activityIndex >= 0; --activityIndex) {
4729                 final ActivityRecord r = activities.get(activityIndex);
4730                 updatedConfig |= r.ensureActivityConfigurationLocked(0 /* globalChanges */,
4731                         preserveWindow);
4732                 if (r.fullscreen) {
4733                     behindFullscreen = true;
4734                     break;
4735                 }
4736             }
4737             if (behindFullscreen) {
4738                 break;
4739             }
4740         }
4741         if (updatedConfig) {
4742             // Ensure the resumed state of the focus activity if we updated the configuration of
4743             // any activity.
4744             mStackSupervisor.resumeFocusedStackTopActivityLocked();
4745         }
4746     }
4747 
4748     // TODO: Figure-out a way to consolidate with resize() method below.
4749     @Override
requestResize(Rect bounds)4750     public void requestResize(Rect bounds) {
4751         mService.resizeStack(mStackId, bounds, true /* allowResizeInDockedMode */,
4752                 false /* preserveWindows */, false /* animate */, -1 /* animationDuration */);
4753     }
4754 
4755     // TODO: Can only be called from special methods in ActivityStackSupervisor.
4756     // Need to consolidate those calls points into this resize method so anyone can call directly.
resize(Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds)4757     void resize(Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds) {
4758         bounds = TaskRecord.validateBounds(bounds);
4759 
4760         if (!updateBoundsAllowed(bounds, tempTaskBounds, tempTaskInsetBounds)) {
4761             return;
4762         }
4763 
4764         // Update override configurations of all tasks in the stack.
4765         final Rect taskBounds = tempTaskBounds != null ? tempTaskBounds : bounds;
4766         final Rect insetBounds = tempTaskInsetBounds != null ? tempTaskInsetBounds : taskBounds;
4767 
4768         mTmpBounds.clear();
4769         mTmpConfigs.clear();
4770         mTmpInsetBounds.clear();
4771 
4772         for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
4773             final TaskRecord task = mTaskHistory.get(i);
4774             if (task.isResizeable()) {
4775                 if (mStackId == FREEFORM_WORKSPACE_STACK_ID) {
4776                     // For freeform stack we don't adjust the size of the tasks to match that
4777                     // of the stack, but we do try to make sure the tasks are still contained
4778                     // with the bounds of the stack.
4779                     mTmpRect2.set(task.mBounds);
4780                     fitWithinBounds(mTmpRect2, bounds);
4781                     task.updateOverrideConfiguration(mTmpRect2);
4782                 } else {
4783                     task.updateOverrideConfiguration(taskBounds, insetBounds);
4784                 }
4785             }
4786 
4787             mTmpConfigs.put(task.taskId, task.getOverrideConfiguration());
4788             mTmpBounds.put(task.taskId, task.mBounds);
4789             if (tempTaskInsetBounds != null) {
4790                 mTmpInsetBounds.put(task.taskId, tempTaskInsetBounds);
4791             }
4792         }
4793 
4794         mFullscreen = mWindowContainerController.resize(bounds, mTmpConfigs, mTmpBounds,
4795                 mTmpInsetBounds);
4796         setBounds(bounds);
4797     }
4798 
4799 
4800     /**
4801      * Adjust bounds to stay within stack bounds.
4802      *
4803      * Since bounds might be outside of stack bounds, this method tries to move the bounds in a way
4804      * that keep them unchanged, but be contained within the stack bounds.
4805      *
4806      * @param bounds Bounds to be adjusted.
4807      * @param stackBounds Bounds within which the other bounds should remain.
4808      */
fitWithinBounds(Rect bounds, Rect stackBounds)4809     private static void fitWithinBounds(Rect bounds, Rect stackBounds) {
4810         if (stackBounds == null || stackBounds.contains(bounds)) {
4811             return;
4812         }
4813 
4814         if (bounds.left < stackBounds.left || bounds.right > stackBounds.right) {
4815             final int maxRight = stackBounds.right
4816                     - (stackBounds.width() / FIT_WITHIN_BOUNDS_DIVIDER);
4817             int horizontalDiff = stackBounds.left - bounds.left;
4818             if ((horizontalDiff < 0 && bounds.left >= maxRight)
4819                     || (bounds.left + horizontalDiff >= maxRight)) {
4820                 horizontalDiff = maxRight - bounds.left;
4821             }
4822             bounds.left += horizontalDiff;
4823             bounds.right += horizontalDiff;
4824         }
4825 
4826         if (bounds.top < stackBounds.top || bounds.bottom > stackBounds.bottom) {
4827             final int maxBottom = stackBounds.bottom
4828                     - (stackBounds.height() / FIT_WITHIN_BOUNDS_DIVIDER);
4829             int verticalDiff = stackBounds.top - bounds.top;
4830             if ((verticalDiff < 0 && bounds.top >= maxBottom)
4831                     || (bounds.top + verticalDiff >= maxBottom)) {
4832                 verticalDiff = maxBottom - bounds.top;
4833             }
4834             bounds.top += verticalDiff;
4835             bounds.bottom += verticalDiff;
4836         }
4837     }
4838 
willActivityBeVisibleLocked(IBinder token)4839     boolean willActivityBeVisibleLocked(IBinder token) {
4840         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4841             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
4842             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
4843                 final ActivityRecord r = activities.get(activityNdx);
4844                 if (r.appToken == token) {
4845                     return true;
4846                 }
4847                 if (r.fullscreen && !r.finishing) {
4848                     return false;
4849                 }
4850             }
4851         }
4852         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
4853         if (r == null) {
4854             return false;
4855         }
4856         if (r.finishing) Slog.e(TAG, "willActivityBeVisibleLocked: Returning false,"
4857                 + " would have returned true for r=" + r);
4858         return !r.finishing;
4859     }
4860 
closeSystemDialogsLocked()4861     void closeSystemDialogsLocked() {
4862         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4863             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
4864             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
4865                 final ActivityRecord r = activities.get(activityNdx);
4866                 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
4867                     finishActivityLocked(r, Activity.RESULT_CANCELED, null, "close-sys", true);
4868                 }
4869             }
4870         }
4871     }
4872 
finishDisabledPackageActivitiesLocked(String packageName, Set<String> filterByClasses, boolean doit, boolean evenPersistent, int userId)4873     boolean finishDisabledPackageActivitiesLocked(String packageName, Set<String> filterByClasses,
4874             boolean doit, boolean evenPersistent, int userId) {
4875         boolean didSomething = false;
4876         TaskRecord lastTask = null;
4877         ComponentName homeActivity = null;
4878         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4879             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
4880             int numActivities = activities.size();
4881             for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
4882                 ActivityRecord r = activities.get(activityNdx);
4883                 final boolean sameComponent =
4884                         (r.packageName.equals(packageName) && (filterByClasses == null
4885                                 || filterByClasses.contains(r.realActivity.getClassName())))
4886                         || (packageName == null && r.userId == userId);
4887                 if ((userId == UserHandle.USER_ALL || r.userId == userId)
4888                         && (sameComponent || r.getTask() == lastTask)
4889                         && (r.app == null || evenPersistent || !r.app.persistent)) {
4890                     if (!doit) {
4891                         if (r.finishing) {
4892                             // If this activity is just finishing, then it is not
4893                             // interesting as far as something to stop.
4894                             continue;
4895                         }
4896                         return true;
4897                     }
4898                     if (r.isHomeActivity()) {
4899                         if (homeActivity != null && homeActivity.equals(r.realActivity)) {
4900                             Slog.i(TAG, "Skip force-stop again " + r);
4901                             continue;
4902                         } else {
4903                             homeActivity = r.realActivity;
4904                         }
4905                     }
4906                     didSomething = true;
4907                     Slog.i(TAG, "  Force finishing activity " + r);
4908                     if (sameComponent) {
4909                         if (r.app != null) {
4910                             r.app.removed = true;
4911                         }
4912                         r.app = null;
4913                     }
4914                     lastTask = r.getTask();
4915                     if (finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop",
4916                             true)) {
4917                         // r has been deleted from mActivities, accommodate.
4918                         --numActivities;
4919                         --activityNdx;
4920                     }
4921                 }
4922             }
4923         }
4924         return didSomething;
4925     }
4926 
getTasksLocked(List<RunningTaskInfo> list, int callingUid, boolean allowed)4927     void getTasksLocked(List<RunningTaskInfo> list, int callingUid, boolean allowed) {
4928         boolean focusedStack = mStackSupervisor.getFocusedStack() == this;
4929         boolean topTask = true;
4930         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4931             final TaskRecord task = mTaskHistory.get(taskNdx);
4932             if (task.getTopActivity() == null) {
4933                 continue;
4934             }
4935             ActivityRecord r = null;
4936             ActivityRecord top = null;
4937             ActivityRecord tmp;
4938             int numActivities = 0;
4939             int numRunning = 0;
4940             final ArrayList<ActivityRecord> activities = task.mActivities;
4941             if (!allowed && !task.isHomeTask() && task.effectiveUid != callingUid) {
4942                 continue;
4943             }
4944             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
4945                 tmp = activities.get(activityNdx);
4946                 if (tmp.finishing) {
4947                     continue;
4948                 }
4949                 r = tmp;
4950 
4951                 // Initialize state for next task if needed.
4952                 if (top == null || (top.state == ActivityState.INITIALIZING)) {
4953                     top = r;
4954                     numActivities = numRunning = 0;
4955                 }
4956 
4957                 // Add 'r' into the current task.
4958                 numActivities++;
4959                 if (r.app != null && r.app.thread != null) {
4960                     numRunning++;
4961                 }
4962 
4963                 if (DEBUG_ALL) Slog.v(
4964                     TAG, r.intent.getComponent().flattenToShortString()
4965                     + ": task=" + r.getTask());
4966             }
4967 
4968             RunningTaskInfo ci = new RunningTaskInfo();
4969             ci.id = task.taskId;
4970             ci.stackId = mStackId;
4971             ci.baseActivity = r.intent.getComponent();
4972             ci.topActivity = top.intent.getComponent();
4973             ci.lastActiveTime = task.lastActiveTime;
4974             if (focusedStack && topTask) {
4975                 // Give the latest time to ensure foreground task can be sorted
4976                 // at the first, because lastActiveTime of creating task is 0.
4977                 ci.lastActiveTime = System.currentTimeMillis();
4978                 topTask = false;
4979             }
4980 
4981             if (top.getTask() != null) {
4982                 ci.description = top.getTask().lastDescription;
4983             }
4984             ci.numActivities = numActivities;
4985             ci.numRunning = numRunning;
4986             ci.supportsSplitScreenMultiWindow = task.supportsSplitScreen();
4987             ci.resizeMode = task.mResizeMode;
4988             list.add(ci);
4989         }
4990     }
4991 
unhandledBackLocked()4992     void unhandledBackLocked() {
4993         final int top = mTaskHistory.size() - 1;
4994         if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Performing unhandledBack(): top activity at " + top);
4995         if (top >= 0) {
4996             final ArrayList<ActivityRecord> activities = mTaskHistory.get(top).mActivities;
4997             int activityTop = activities.size() - 1;
4998             if (activityTop >= 0) {
4999                 finishActivityLocked(activities.get(activityTop), Activity.RESULT_CANCELED, null,
5000                         "unhandled-back", true);
5001             }
5002         }
5003     }
5004 
5005     /**
5006      * Reset local parameters because an app's activity died.
5007      * @param app The app of the activity that died.
5008      * @return result from removeHistoryRecordsForAppLocked.
5009      */
handleAppDiedLocked(ProcessRecord app)5010     boolean handleAppDiedLocked(ProcessRecord app) {
5011         if (mPausingActivity != null && mPausingActivity.app == app) {
5012             if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG_PAUSE,
5013                     "App died while pausing: " + mPausingActivity);
5014             mPausingActivity = null;
5015         }
5016         if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
5017             mLastPausedActivity = null;
5018             mLastNoHistoryActivity = null;
5019         }
5020 
5021         return removeHistoryRecordsForAppLocked(app);
5022     }
5023 
handleAppCrashLocked(ProcessRecord app)5024     void handleAppCrashLocked(ProcessRecord app) {
5025         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
5026             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
5027             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
5028                 final ActivityRecord r = activities.get(activityNdx);
5029                 if (r.app == app) {
5030                     Slog.w(TAG, "  Force finishing activity "
5031                             + r.intent.getComponent().flattenToShortString());
5032                     // Force the destroy to skip right to removal.
5033                     r.app = null;
5034                     finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
5035                 }
5036             }
5037         }
5038     }
5039 
dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient, String dumpPackage, boolean needSep, String header)5040     boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
5041             boolean dumpClient, String dumpPackage, boolean needSep, String header) {
5042         boolean printed = false;
5043         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
5044             final TaskRecord task = mTaskHistory.get(taskNdx);
5045             printed |= ActivityStackSupervisor.dumpHistoryList(fd, pw,
5046                     mTaskHistory.get(taskNdx).mActivities, "    ", "Hist", true, !dumpAll,
5047                     dumpClient, dumpPackage, needSep, header,
5048                     "    Task id #" + task.taskId + "\n" +
5049                     "    mFullscreen=" + task.mFullscreen + "\n" +
5050                     "    mBounds=" + task.mBounds + "\n" +
5051                     "    mMinWidth=" + task.mMinWidth + "\n" +
5052                     "    mMinHeight=" + task.mMinHeight + "\n" +
5053                     "    mLastNonFullscreenBounds=" + task.mLastNonFullscreenBounds);
5054             if (printed) {
5055                 header = null;
5056             }
5057         }
5058         return printed;
5059     }
5060 
getDumpActivitiesLocked(String name)5061     ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
5062         ArrayList<ActivityRecord> activities = new ArrayList<>();
5063 
5064         if ("all".equals(name)) {
5065             for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
5066                 activities.addAll(mTaskHistory.get(taskNdx).mActivities);
5067             }
5068         } else if ("top".equals(name)) {
5069             final int top = mTaskHistory.size() - 1;
5070             if (top >= 0) {
5071                 final ArrayList<ActivityRecord> list = mTaskHistory.get(top).mActivities;
5072                 int listTop = list.size() - 1;
5073                 if (listTop >= 0) {
5074                     activities.add(list.get(listTop));
5075                 }
5076             }
5077         } else {
5078             ItemMatcher matcher = new ItemMatcher();
5079             matcher.build(name);
5080 
5081             for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
5082                 for (ActivityRecord r1 : mTaskHistory.get(taskNdx).mActivities) {
5083                     if (matcher.match(r1, r1.intent.getComponent())) {
5084                         activities.add(r1);
5085                     }
5086                 }
5087             }
5088         }
5089 
5090         return activities;
5091     }
5092 
restartPackage(String packageName)5093     ActivityRecord restartPackage(String packageName) {
5094         ActivityRecord starting = topRunningActivityLocked();
5095 
5096         // All activities that came from the package must be
5097         // restarted as if there was a config change.
5098         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
5099             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
5100             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
5101                 final ActivityRecord a = activities.get(activityNdx);
5102                 if (a.info.packageName.equals(packageName)) {
5103                     a.forceNewConfig = true;
5104                     if (starting != null && a == starting && a.visible) {
5105                         a.startFreezingScreenLocked(starting.app,
5106                                 CONFIG_SCREEN_LAYOUT);
5107                     }
5108                 }
5109             }
5110         }
5111 
5112         return starting;
5113     }
5114 
5115     /**
5116      * Removes the input task from this stack.
5117      * @param task to remove.
5118      * @param reason for removal.
5119      * @param mode task removal mode. Either {@link #REMOVE_TASK_MODE_DESTROYING},
5120      *             {@link #REMOVE_TASK_MODE_MOVING}, {@link #REMOVE_TASK_MODE_MOVING_TO_TOP}.
5121      */
removeTask(TaskRecord task, String reason, int mode)5122     void removeTask(TaskRecord task, String reason, int mode) {
5123         for (ActivityRecord record : task.mActivities) {
5124             onActivityRemovedFromStack(record);
5125         }
5126 
5127         final int taskNdx = mTaskHistory.indexOf(task);
5128         final int topTaskNdx = mTaskHistory.size() - 1;
5129         if (task.isOverHomeStack() && taskNdx < topTaskNdx) {
5130             final TaskRecord nextTask = mTaskHistory.get(taskNdx + 1);
5131             if (!nextTask.isOverHomeStack() && !nextTask.isOverAssistantStack()) {
5132                 nextTask.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
5133             }
5134         }
5135         mTaskHistory.remove(task);
5136         removeActivitiesFromLRUListLocked(task);
5137         updateTaskMovement(task, true);
5138 
5139         if (mode == REMOVE_TASK_MODE_DESTROYING && task.mActivities.isEmpty()) {
5140             // TODO: VI what about activity?
5141             final boolean isVoiceSession = task.voiceSession != null;
5142             if (isVoiceSession) {
5143                 try {
5144                     task.voiceSession.taskFinished(task.intent, task.taskId);
5145                 } catch (RemoteException e) {
5146                 }
5147             }
5148             if (task.autoRemoveFromRecents() || isVoiceSession) {
5149                 // Task creator asked to remove this when done, or this task was a voice
5150                 // interaction, so it should not remain on the recent tasks list.
5151                 mRecentTasks.remove(task);
5152                 task.removedFromRecents();
5153             }
5154 
5155             task.removeWindowContainer();
5156         }
5157 
5158         if (mTaskHistory.isEmpty()) {
5159             if (DEBUG_STACK) Slog.i(TAG_STACK, "removeTask: removing stack=" + this);
5160             // We only need to adjust focused stack if this stack is in focus and we are not in the
5161             // process of moving the task to the top of the stack that will be focused.
5162             if (isOnHomeDisplay() && mode != REMOVE_TASK_MODE_MOVING_TO_TOP
5163                     && mStackSupervisor.isFocusedStack(this)) {
5164                 String myReason = reason + " leftTaskHistoryEmpty";
5165                 if (mFullscreen || !adjustFocusToNextFocusableStackLocked(myReason)) {
5166                     mStackSupervisor.moveHomeStackToFront(myReason);
5167                 }
5168             }
5169             if (mStacks != null) {
5170                 mStacks.remove(this);
5171                 mStacks.add(0, this);
5172             }
5173             if (!isHomeOrRecentsStack()) {
5174                 mActivityContainer.onTaskListEmptyLocked();
5175             }
5176         }
5177 
5178         task.setStack(null);
5179 
5180         // Notify if a task from the pinned stack is being removed (or moved depending on the mode)
5181         if (mStackId == PINNED_STACK_ID) {
5182             mService.mTaskChangeNotificationController.notifyActivityUnpinned();
5183         }
5184     }
5185 
createTaskRecord(int taskId, ActivityInfo info, Intent intent, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, boolean toTop, int type)5186     TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
5187             IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
5188             boolean toTop, int type) {
5189         TaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession,
5190                 voiceInteractor, type);
5191         // add the task to stack first, mTaskPositioner might need the stack association
5192         addTask(task, toTop, "createTaskRecord");
5193         final boolean isLockscreenShown =
5194                 mService.mStackSupervisor.mKeyguardController.isKeyguardShowing();
5195         if (!layoutTaskInStack(task, info.windowLayout) && mBounds != null && task.isResizeable()
5196                 && !isLockscreenShown) {
5197             task.updateOverrideConfiguration(mBounds);
5198         }
5199         task.createWindowContainer(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
5200         return task;
5201     }
5202 
layoutTaskInStack(TaskRecord task, ActivityInfo.WindowLayout windowLayout)5203     boolean layoutTaskInStack(TaskRecord task, ActivityInfo.WindowLayout windowLayout) {
5204         if (mTaskPositioner == null) {
5205             return false;
5206         }
5207         mTaskPositioner.updateDefaultBounds(task, mTaskHistory, windowLayout);
5208         return true;
5209     }
5210 
getAllTasks()5211     ArrayList<TaskRecord> getAllTasks() {
5212         return new ArrayList<>(mTaskHistory);
5213     }
5214 
addTask(final TaskRecord task, final boolean toTop, String reason)5215     void addTask(final TaskRecord task, final boolean toTop, String reason) {
5216         addTask(task, toTop ? MAX_VALUE : 0, true /* schedulePictureInPictureModeChange */, reason);
5217         if (toTop) {
5218             // TODO: figure-out a way to remove this call.
5219             mWindowContainerController.positionChildAtTop(task.getWindowContainerController(),
5220                     true /* includingParents */);
5221         }
5222     }
5223 
5224     // TODO: This shouldn't allow automatic reparenting. Remove the call to preAddTask and deal
5225     // with the fall-out...
addTask(final TaskRecord task, int position, boolean schedulePictureInPictureModeChange, String reason)5226     void addTask(final TaskRecord task, int position, boolean schedulePictureInPictureModeChange,
5227             String reason) {
5228         // TODO: Is this remove really needed? Need to look into the call path for the other addTask
5229         mTaskHistory.remove(task);
5230         position = getAdjustedPositionForTask(task, position, null /* starting */);
5231         final boolean toTop = position >= mTaskHistory.size();
5232         final ActivityStack prevStack = preAddTask(task, reason, toTop);
5233 
5234         mTaskHistory.add(position, task);
5235         task.setStack(this);
5236 
5237         if (toTop) {
5238             updateTaskReturnToForTopInsertion(task);
5239         }
5240 
5241         updateTaskMovement(task, toTop);
5242 
5243         postAddTask(task, prevStack, schedulePictureInPictureModeChange);
5244     }
5245 
positionChildAt(TaskRecord task, int index)5246     void positionChildAt(TaskRecord task, int index) {
5247 
5248         if (task.getStack() != this) {
5249             throw new IllegalArgumentException("AS.positionChildAt: task=" + task
5250                     + " is not a child of stack=" + this + " current parent=" + task.getStack());
5251         }
5252 
5253         task.updateOverrideConfigurationForStack(this);
5254 
5255         final ActivityRecord topRunningActivity = task.topRunningActivityLocked();
5256         final boolean wasResumed = topRunningActivity == task.getStack().mResumedActivity;
5257         insertTaskAtPosition(task, index);
5258         task.setStack(this);
5259         postAddTask(task, null /* prevStack */, true /* schedulePictureInPictureModeChange */);
5260 
5261         if (wasResumed) {
5262             if (mResumedActivity != null) {
5263                 Log.wtf(TAG, "mResumedActivity was already set when moving mResumedActivity from"
5264                         + " other stack to this stack mResumedActivity=" + mResumedActivity
5265                         + " other mResumedActivity=" + topRunningActivity);
5266             }
5267             mResumedActivity = topRunningActivity;
5268         }
5269 
5270         // The task might have already been running and its visibility needs to be synchronized with
5271         // the visibility of the stack / windows.
5272         ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
5273         mStackSupervisor.resumeFocusedStackTopActivityLocked();
5274     }
5275 
preAddTask(TaskRecord task, String reason, boolean toTop)5276     private ActivityStack preAddTask(TaskRecord task, String reason, boolean toTop) {
5277         final ActivityStack prevStack = task.getStack();
5278         if (prevStack != null && prevStack != this) {
5279             prevStack.removeTask(task, reason,
5280                     toTop ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING);
5281         }
5282         return prevStack;
5283     }
5284 
5285     /**
5286      * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
5287      *            change. Callers may set this to false if they are explicitly scheduling PiP mode
5288      *            changes themselves, like during the PiP animation
5289      */
postAddTask(TaskRecord task, ActivityStack prevStack, boolean schedulePictureInPictureModeChange)5290     private void postAddTask(TaskRecord task, ActivityStack prevStack,
5291             boolean schedulePictureInPictureModeChange) {
5292         if (schedulePictureInPictureModeChange && prevStack != null) {
5293             mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(task, prevStack);
5294         } else if (task.voiceSession != null) {
5295             try {
5296                 task.voiceSession.taskStarted(task.intent, task.taskId);
5297             } catch (RemoteException e) {
5298             }
5299         }
5300     }
5301 
moveToFrontAndResumeStateIfNeeded(ActivityRecord r, boolean moveToFront, boolean setResume, boolean setPause, String reason)5302     void moveToFrontAndResumeStateIfNeeded(ActivityRecord r, boolean moveToFront, boolean setResume,
5303             boolean setPause, String reason) {
5304         if (!moveToFront) {
5305             return;
5306         }
5307 
5308         // If the activity owns the last resumed activity, transfer that together,
5309         // so that we don't resume the same activity again in the new stack.
5310         // Apps may depend on onResume()/onPause() being called in pairs.
5311         if (setResume) {
5312             mResumedActivity = r;
5313             updateLRUListLocked(r);
5314         }
5315         // If the activity was previously pausing, then ensure we transfer that as well
5316         if (setPause) {
5317             mPausingActivity = r;
5318             schedulePauseTimeout(r);
5319         }
5320         // Move the stack in which we are placing the activity to the front. The call will also
5321         // make sure the activity focus is set.
5322         moveToFront(reason);
5323     }
5324 
getStackId()5325     public int getStackId() {
5326         return mStackId;
5327     }
5328 
5329     @Override
toString()5330     public String toString() {
5331         return "ActivityStack{" + Integer.toHexString(System.identityHashCode(this))
5332                 + " stackId=" + mStackId + ", " + mTaskHistory.size() + " tasks}";
5333     }
5334 
onLockTaskPackagesUpdatedLocked()5335     void onLockTaskPackagesUpdatedLocked() {
5336         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
5337             mTaskHistory.get(taskNdx).setLockTaskAuth();
5338         }
5339     }
5340 
executeAppTransition(ActivityOptions options)5341     void executeAppTransition(ActivityOptions options) {
5342         mWindowManager.executeAppTransition();
5343         mNoAnimActivities.clear();
5344         ActivityOptions.abort(options);
5345     }
5346 }
5347