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