• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.ActivityTaskManager.INVALID_TASK_ID;
20 import static android.app.KeyguardManager.ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER;
21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
23 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
24 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
25 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
26 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
27 import static android.content.res.Configuration.EMPTY;
28 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
29 import static android.view.Display.DEFAULT_DISPLAY;
30 import static android.view.Display.INVALID_DISPLAY;
31 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
32 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
33 import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
34 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_OCCLUDING;
35 import static android.view.WindowManager.TRANSIT_NONE;
36 import static android.view.WindowManager.TRANSIT_PIP;
37 import static android.view.WindowManager.TRANSIT_SLEEP;
38 import static android.view.WindowManager.TRANSIT_WAKE;
39 import static android.window.DesktopExperienceFlags.ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT;
40 
41 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_FOCUS_LIGHT;
42 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_KEEP_SCREEN_ON;
43 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_ORIENTATION;
44 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_SLEEP_TOKEN;
45 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_STATES;
46 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_TASKS;
47 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_WALLPAPER;
48 import static com.android.internal.protolog.WmProtoLogGroups.WM_SHOW_SURFACE_ALLOC;
49 import static com.android.server.policy.PhoneWindowManager.SYSTEM_DIALOG_REASON_ASSIST;
50 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
51 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
52 import static com.android.server.wm.ActivityRecord.State.FINISHING;
53 import static com.android.server.wm.ActivityRecord.State.PAUSED;
54 import static com.android.server.wm.ActivityRecord.State.RESUMED;
55 import static com.android.server.wm.ActivityRecord.State.STOPPED;
56 import static com.android.server.wm.ActivityRecord.State.STOPPING;
57 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
58 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ROOT_TASK;
59 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
60 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
61 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
62 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
63 import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
64 import static com.android.server.wm.ActivityTaskManagerService.TAG_SWITCH;
65 import static com.android.server.wm.ActivityTaskManagerService.isPip2ExperimentEnabled;
66 import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME;
67 import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
68 import static com.android.server.wm.ActivityTaskSupervisor.dumpHistoryList;
69 import static com.android.server.wm.ActivityTaskSupervisor.printThisActivity;
70 import static com.android.server.wm.RootWindowContainerProto.IS_HOME_RECENTS_COMPONENT;
71 import static com.android.server.wm.RootWindowContainerProto.KEYGUARD_CONTROLLER;
72 import static com.android.server.wm.RootWindowContainerProto.WINDOW_CONTAINER;
73 import static com.android.server.wm.Task.REPARENT_LEAVE_ROOT_TASK_IN_PLACE;
74 import static com.android.server.wm.Task.REPARENT_MOVE_ROOT_TASK_TO_FRONT;
75 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
76 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
77 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
78 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
79 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
80 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
81 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
82 
83 import static java.lang.Integer.MAX_VALUE;
84 
85 import android.annotation.IntDef;
86 import android.annotation.NonNull;
87 import android.annotation.Nullable;
88 import android.annotation.UserIdInt;
89 import android.app.ActivityManager;
90 import android.app.ActivityOptions;
91 import android.app.ActivityTaskManager.RootTaskInfo;
92 import android.app.AppGlobals;
93 import android.app.WindowConfiguration;
94 import android.content.ComponentName;
95 import android.content.Context;
96 import android.content.Intent;
97 import android.content.pm.ActivityInfo;
98 import android.content.pm.ApplicationInfo;
99 import android.content.pm.ResolveInfo;
100 import android.content.pm.UserProperties;
101 import android.content.res.Configuration;
102 import android.graphics.Rect;
103 import android.graphics.Region;
104 import android.hardware.display.DisplayManager;
105 import android.hardware.display.DisplayManagerInternal;
106 import android.hardware.display.DisplayManagerInternal.DisplayBrightnessOverrideRequest;
107 import android.hardware.power.Mode;
108 import android.net.Uri;
109 import android.os.Binder;
110 import android.os.Debug;
111 import android.os.FactoryTest;
112 import android.os.Handler;
113 import android.os.IBinder;
114 import android.os.Looper;
115 import android.os.Message;
116 import android.os.PowerManager;
117 import android.os.RemoteException;
118 import android.os.SystemClock;
119 import android.os.Trace;
120 import android.os.UserHandle;
121 import android.os.storage.StorageManager;
122 import android.provider.Settings;
123 import android.service.voice.IVoiceInteractionSession;
124 import android.util.ArrayMap;
125 import android.util.ArraySet;
126 import android.util.IntArray;
127 import android.util.Pair;
128 import android.util.Slog;
129 import android.util.SparseArray;
130 import android.util.SparseIntArray;
131 import android.util.TimeUtils;
132 import android.util.proto.ProtoOutputStream;
133 import android.view.Display;
134 import android.view.DisplayInfo;
135 import android.view.SurfaceControl;
136 import android.view.WindowManager;
137 import android.window.DesktopModeFlags;
138 import android.window.TaskFragmentAnimationParams;
139 import android.window.WindowContainerToken;
140 
141 import com.android.internal.annotations.VisibleForTesting;
142 import com.android.internal.app.ResolverActivity;
143 import com.android.internal.protolog.ProtoLog;
144 import com.android.internal.util.function.pooled.PooledLambda;
145 import com.android.internal.util.function.pooled.PooledPredicate;
146 import com.android.server.LocalServices;
147 import com.android.server.am.ActivityManagerService;
148 import com.android.server.am.AppTimeTracker;
149 import com.android.server.am.UserState;
150 import com.android.server.pm.UserManagerInternal;
151 import com.android.server.policy.PermissionPolicyInternal;
152 import com.android.server.policy.WindowManagerPolicy;
153 import com.android.server.utils.Slogf;
154 import com.android.server.wm.utils.RegionUtils;
155 import com.android.window.flags.Flags;
156 
157 import java.io.FileDescriptor;
158 import java.io.PrintWriter;
159 import java.lang.annotation.Retention;
160 import java.lang.annotation.RetentionPolicy;
161 import java.util.ArrayList;
162 import java.util.Collections;
163 import java.util.List;
164 import java.util.Objects;
165 import java.util.Set;
166 import java.util.function.Consumer;
167 import java.util.function.Predicate;
168 
169 /** Root {@link WindowContainer} for the device. */
170 class RootWindowContainer extends WindowContainer<DisplayContent>
171         implements DisplayManager.DisplayListener {
172     private static final String TAG = TAG_WITH_CLASS_NAME ? "RootWindowContainer" : TAG_WM;
173 
174     private static final int SET_SCREEN_BRIGHTNESS_OVERRIDE = 1;
175     private static final int SET_USER_ACTIVITY_TIMEOUT = 2;
176     private static final int MSG_SEND_SLEEP_TRANSITION = 3;
177     private static final int PINNED_TASK_ABORT_TIMEOUT = 1000;
178 
179     static final String TAG_TASKS = TAG + POSTFIX_TASKS;
180     static final String TAG_STATES = TAG + POSTFIX_STATES;
181     private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
182 
183     private static final long SLEEP_TRANSITION_WAIT_MILLIS = 1000L;
184 
185     private Object mLastWindowFreezeSource = null;
186     // Per-display WindowManager overrides that are passed on.
187     private final SparseArray<DisplayBrightnessOverrideRequest> mDisplayBrightnessOverrides =
188             new SparseArray<>();
189     private long mUserActivityTimeout = -1;
190     private boolean mUpdateRotation = false;
191     // Only set while traversing the default display based on its content.
192     // Affects the behavior of mirroring on secondary displays.
193     private boolean mObscureApplicationContentOnSecondaryDisplays = false;
194 
195     private boolean mSustainedPerformanceModeEnabled = false;
196     private boolean mSustainedPerformanceModeCurrent = false;
197 
198     private final Handler mHandler;
199 
200     private String mCloseSystemDialogsReason;
201 
202     // The ID of the display which is responsible for receiving display-unspecified key and pointer
203     // events.
204     private int mTopFocusedDisplayId = INVALID_DISPLAY;
205 
206     // Map from the PID to the top most app which has a focused window of the process.
207     final ArrayMap<Integer, ActivityRecord> mTopFocusedAppByProcess = new ArrayMap<>();
208 
209     // The tag for the token to put root tasks on the displays to sleep.
210     private static final String DISPLAY_OFF_SLEEP_TOKEN_TAG = "Display-off";
211 
212     /** The token acquirer to put root tasks on the displays to sleep */
213     final ActivityTaskManagerService.SleepTokenAcquirer mDisplayOffTokenAcquirer;
214 
215     /**
216      * The modes which affect which tasks are returned when calling
217      * {@link RootWindowContainer#anyTaskForId(int)}.
218      */
219     @Retention(RetentionPolicy.SOURCE)
220     @IntDef({
221             MATCH_ATTACHED_TASK_ONLY,
222             MATCH_ATTACHED_TASK_OR_RECENT_TASKS,
223             MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE
224     })
225     public @interface AnyTaskForIdMatchTaskMode {
226     }
227 
228     // Match only tasks that are attached to the hierarchy
229     static final int MATCH_ATTACHED_TASK_ONLY = 0;
230     // Match either attached tasks, or in the recent tasks if the tasks are detached
231     static final int MATCH_ATTACHED_TASK_OR_RECENT_TASKS = 1;
232     // Match either attached tasks, or in the recent tasks, restoring it to the provided task id
233     static final int MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE = 2;
234 
235     ActivityTaskManagerService mService;
236     ActivityTaskSupervisor mTaskSupervisor;
237     WindowManagerService mWindowManager;
238     DisplayManager mDisplayManager;
239     private DisplayManagerInternal mDisplayManagerInternal;
240     @NonNull
241     private final DeviceStateController mDeviceStateController;
242     @NonNull
243     private final DisplayRotationCoordinator mDisplayRotationCoordinator;
244 
245     /** Reference to default display so we can quickly look it up. */
246     private DisplayContent mDefaultDisplay;
247     private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>();
248     private final SparseArray<SurfaceControl.Transaction> mDisplayTransactions =
249             new SparseArray<>();
250 
251     /** The current user */
252     int mCurrentUser;
253     /** Root task id of the front root task when user switched, indexed by userId. */
254     SparseIntArray mUserRootTaskInFront = new SparseIntArray(2);
255     SparseArray<IntArray> mUserVisibleRootTasks = new SparseArray<>();
256 
257     /**
258      * A list of tokens that cause the top activity to be put to sleep.
259      * They are used by components that may hide and block interaction with underlying
260      * activities.
261      */
262     final SparseArray<SleepToken> mSleepTokens = new SparseArray<>();
263 
264     // Whether tasks have moved and we need to rank the tasks before next OOM scoring
265     private boolean mTaskLayersChanged = true;
266     private int mTmpTaskLayerRank;
267     private final RankTaskLayersRunnable mRankTaskLayersRunnable = new RankTaskLayersRunnable();
268     private Region mTmpOccludingRegion;
269     private Region mTmpTaskRegion;
270 
271     private String mDestroyAllActivitiesReason;
272     private final Runnable mDestroyAllActivitiesRunnable = new Runnable() {
273         @Override
274         public void run() {
275             synchronized (mService.mGlobalLock) {
276                 try {
277                     mTaskSupervisor.beginDeferResume();
278                     forAllActivities(r -> {
279                         if (r.finishing || !r.isDestroyable()) return;
280                         if (DEBUG_SWITCH) {
281                             Slog.v(TAG_SWITCH, "Destroying " + r + " in state " + r.getState()
282                                     + " resumed=" + r.getTask().getTopResumedActivity()
283                                     + " pausing=" + r.getTask().getTopPausingActivity()
284                                     + " for reason " + mDestroyAllActivitiesReason);
285                         }
286                         r.destroyImmediately(mDestroyAllActivitiesReason);
287                     });
288                 } finally {
289                     mTaskSupervisor.endDeferResume();
290                     resumeFocusedTasksTopActivities();
291                 }
292             }
293         }
294 
295     };
296 
297     // TODO: b/335866033 Remove the abort PiP on timeout once PiP2 flag is on.
298     @Nullable private Runnable mMaybeAbortPipEnterRunnable = null;
299 
300     private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
301 
302     static class FindTaskResult implements Predicate<Task> {
303         ActivityRecord mIdealRecord;
304         ActivityRecord mCandidateRecord;
305 
306         private int mActivityType;
307         private String mTaskAffinity;
308         private Intent mIntent;
309         private ActivityInfo mInfo;
310         private ComponentName cls;
311         private int userId;
312         private boolean isDocument;
313         private Uri documentData;
314 
315         // determines whether to include bubbled tasks. defaults to true to preserve previous
316         // behavior.
317         private boolean mIncludeLaunchedFromBubble = true;
318 
init(int activityType, String taskAffinity, Intent intent, ActivityInfo info, boolean includeLaunchedFromBubble)319         void init(int activityType, String taskAffinity, Intent intent, ActivityInfo info,
320                 boolean includeLaunchedFromBubble) {
321             mActivityType = activityType;
322             mTaskAffinity = taskAffinity;
323             mIntent = intent;
324             mInfo = info;
325             mIdealRecord = null;
326             mCandidateRecord = null;
327             mIncludeLaunchedFromBubble = includeLaunchedFromBubble;
328         }
329 
330         /**
331          * Returns the top activity in any existing task matching the given Intent in the input
332          * result. Returns null if no such task is found.
333          */
process(WindowContainer parent)334         void process(WindowContainer parent) {
335             cls = mIntent.getComponent();
336             if (mInfo.targetActivity != null) {
337                 cls = new ComponentName(mInfo.packageName, mInfo.targetActivity);
338             }
339             userId = UserHandle.getUserId(mInfo.applicationInfo.uid);
340             isDocument = mIntent != null & mIntent.isDocument();
341             // If documentData is non-null then it must match the existing task data.
342             documentData = isDocument ? mIntent.getData() : null;
343 
344             ProtoLog.d(WM_DEBUG_TASKS, "Looking for task of %s in %s", mInfo,
345                     parent);
346             parent.forAllLeafTasks(this);
347         }
348 
349         @Override
test(Task task)350         public boolean test(Task task) {
351             if (!ConfigurationContainer.isCompatibleActivityType(mActivityType,
352                     task.getActivityType())) {
353                 ProtoLog.d(WM_DEBUG_TASKS, "Skipping task: (mismatch activity/task) %s", task);
354                 return false;
355             }
356 
357             if (task.voiceSession != null) {
358                 // We never match voice sessions; those always run independently.
359                 ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: voice session", task);
360                 return false;
361             }
362             if (task.mUserId != userId) {
363                 // Looking for a different task.
364                 ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: different user", task);
365                 return false;
366             }
367 
368             // Overlays should not be considered as the task's logical top activity.
369             final ActivityRecord r = task.getTopNonFinishingActivity(
370                     false /* includeOverlays */, mIncludeLaunchedFromBubble);
371 
372             if (r == null || r.finishing || r.mUserId != userId
373                     || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
374                 ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: mismatch root %s", task, r);
375                 return false;
376             }
377             if (!ConfigurationContainer.isCompatibleActivityType(r.getActivityType(),
378                     mActivityType)) {
379                 ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: mismatch activity type", task);
380                 return false;
381             }
382 
383             final Intent taskIntent = task.intent;
384             final Intent affinityIntent = task.affinityIntent;
385             final boolean taskIsDocument;
386             final Uri taskDocumentData;
387             if (taskIntent != null && taskIntent.isDocument()) {
388                 taskIsDocument = true;
389                 taskDocumentData = taskIntent.getData();
390             } else if (affinityIntent != null && affinityIntent.isDocument()) {
391                 taskIsDocument = true;
392                 taskDocumentData = affinityIntent.getData();
393             } else {
394                 taskIsDocument = false;
395                 taskDocumentData = null;
396             }
397 
398             ProtoLog.d(WM_DEBUG_TASKS, "Comparing existing cls=%s /aff=%s to new cls=%s /aff=%s",
399                     (task.realActivity != null ? task.realActivity.flattenToShortString() : ""),
400                     task.rootAffinity, mIntent.getComponent().flattenToShortString(),
401                     mTaskAffinity);
402             // TODO Refactor to remove duplications. Check if logic can be simplified.
403             if (task.realActivity != null && task.realActivity.compareTo(cls) == 0
404                     && Objects.equals(documentData, taskDocumentData)) {
405                 ProtoLog.d(WM_DEBUG_TASKS, "Found matching class!");
406                 //dump();
407                 ProtoLog.d(WM_DEBUG_TASKS, "For Intent %s bringing to top: %s", mIntent, r.intent);
408                 mIdealRecord = r;
409                 return true;
410             } else if (affinityIntent != null && affinityIntent.getComponent() != null
411                     && affinityIntent.getComponent().compareTo(cls) == 0 &&
412                     Objects.equals(documentData, taskDocumentData)) {
413                 ProtoLog.d(WM_DEBUG_TASKS, "Found matching class!");
414                 ProtoLog.d(WM_DEBUG_TASKS, "For Intent %s bringing to top: %s", mIntent, r.intent);
415                 mIdealRecord = r;
416                 return true;
417             } else if (!isDocument && !taskIsDocument
418                     && mIdealRecord == null && mCandidateRecord == null
419                     && task.rootAffinity != null) {
420                 if (task.rootAffinity.equals(mTaskAffinity)
421                         && task.isSameRequiredDisplayCategory(mInfo)) {
422                     ProtoLog.d(WM_DEBUG_TASKS, "Found matching affinity candidate!");
423                     // It is possible for multiple tasks to have the same root affinity especially
424                     // if they are in separate root tasks. We save off this candidate, but keep
425                     // looking to see if there is a better candidate.
426                     mCandidateRecord = r;
427                 }
428             } else {
429                 ProtoLog.d(WM_DEBUG_TASKS, "Not a match: %s", task);
430             }
431 
432             return false;
433         }
434     }
435 
436     private final Consumer<WindowState> mCloseSystemDialogsConsumer = w -> {
437         if (w.mHasSurface) {
438             try {
439                 w.mClient.closeSystemDialogs(mCloseSystemDialogsReason);
440             } catch (RemoteException e) {
441             }
442         }
443     };
444 
RootWindowContainer(WindowManagerService service)445     RootWindowContainer(WindowManagerService service) {
446         super(service);
447         mHandler = new MyHandler(service.mH.getLooper());
448         mService = service.mAtmService;
449         mTaskSupervisor = mService.mTaskSupervisor;
450         mTaskSupervisor.mRootWindowContainer = this;
451         mDisplayOffTokenAcquirer = mService.new SleepTokenAcquirer(DISPLAY_OFF_SLEEP_TOKEN_TAG);
452         mDeviceStateController = new DeviceStateController(service.mContext, service.mGlobalLock);
453         mDisplayRotationCoordinator = new DisplayRotationCoordinator();
454     }
455 
456     /**
457      * Updates the children's focused window and the top focused display if needed.
458      */
updateFocusedWindowLocked(int mode, boolean updateInputWindows)459     boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
460         mTopFocusedAppByProcess.clear();
461         boolean changed = false;
462         int topFocusedDisplayId = INVALID_DISPLAY;
463         // Go through the children in z-order starting at the top-most
464         for (int i = mChildren.size() - 1; i >= 0; --i) {
465             final DisplayContent dc = mChildren.get(i);
466             changed |= dc.updateFocusedWindowLocked(mode, updateInputWindows, topFocusedDisplayId);
467             final WindowState newFocus = dc.mCurrentFocus;
468             if (newFocus != null) {
469                 final int pidOfNewFocus = newFocus.mSession.mPid;
470                 if (mTopFocusedAppByProcess.get(pidOfNewFocus) == null) {
471                     mTopFocusedAppByProcess.put(pidOfNewFocus, newFocus.mActivityRecord);
472                 }
473                 if (topFocusedDisplayId == INVALID_DISPLAY) {
474                     topFocusedDisplayId = dc.getDisplayId();
475                 }
476             } else if (topFocusedDisplayId == INVALID_DISPLAY && dc.mFocusedApp != null) {
477                 // The top-most display that has a focused app should still be the top focused
478                 // display even when the app window is not ready yet (process not attached or
479                 // window not added yet).
480                 topFocusedDisplayId = dc.getDisplayId();
481             }
482         }
483         if (topFocusedDisplayId == INVALID_DISPLAY) {
484             topFocusedDisplayId = DEFAULT_DISPLAY;
485         }
486         if (mTopFocusedDisplayId != topFocusedDisplayId) {
487             mTopFocusedDisplayId = topFocusedDisplayId;
488             mWmService.mInputManager.setFocusedDisplay(topFocusedDisplayId);
489             mWmService.mPolicy.setTopFocusedDisplay(topFocusedDisplayId);
490             mWmService.mAccessibilityController.setFocusedDisplay(topFocusedDisplayId);
491             ProtoLog.d(WM_DEBUG_FOCUS_LIGHT, "New topFocusedDisplayId=%d", topFocusedDisplayId);
492         }
493         return changed;
494     }
495 
getTopFocusedDisplayContent()496     DisplayContent getTopFocusedDisplayContent() {
497         final DisplayContent dc = getDisplayContent(mTopFocusedDisplayId);
498         return dc != null ? dc : getDisplayContent(DEFAULT_DISPLAY);
499     }
500 
501     @Override
isOnTop()502     boolean isOnTop() {
503         // Considered always on top
504         return true;
505     }
506 
507     @Override
onChildPositionChanged(WindowContainer child)508     void onChildPositionChanged(WindowContainer child) {
509         mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
510                 !mWmService.mPerDisplayFocusEnabled /* updateInputWindows */);
511         mTaskSupervisor.updateTopResumedActivityIfNeeded("onChildPositionChanged");
512     }
513 
514     @Override
isAttached()515     boolean isAttached() {
516         return true;
517     }
518 
519     /**
520      * Called when DisplayWindowSettings values may change.
521      */
onSettingsRetrieved()522     void onSettingsRetrieved() {
523         final int numDisplays = mChildren.size();
524         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
525             final DisplayContent displayContent = mChildren.get(displayNdx);
526             final boolean changed = mWmService.mDisplayWindowSettings.updateSettingsForDisplay(
527                     displayContent);
528             if (!changed) {
529                 continue;
530             }
531 
532             displayContent.reconfigureDisplayLocked();
533 
534             // We need to update global configuration as well if config of default display has
535             // changed. Do it inline because ATMS#retrieveSettings() will soon update the
536             // configuration inline, which will overwrite the new windowing mode.
537             if (displayContent.isDefaultDisplay) {
538                 final Configuration newConfig = mWmService.computeNewConfiguration(
539                         displayContent.getDisplayId());
540                 mWmService.mAtmService.updateConfigurationLocked(newConfig, null /* starting */,
541                         false /* initLocale */);
542             }
543         }
544     }
545 
isLayoutNeeded()546     boolean isLayoutNeeded() {
547         final int numDisplays = mChildren.size();
548         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
549             final DisplayContent displayContent = mChildren.get(displayNdx);
550             if (displayContent.isLayoutNeeded()) {
551                 return true;
552             }
553         }
554         return false;
555     }
556 
getWindowsByName(ArrayList<WindowState> output, String name)557     void getWindowsByName(ArrayList<WindowState> output, String name) {
558         int objectId = 0;
559         // See if this is an object ID.
560         try {
561             objectId = Integer.parseInt(name, 16);
562             name = null;
563         } catch (RuntimeException e) {
564         }
565 
566         getWindowsByName(output, name, objectId);
567     }
568 
getWindowsByName(ArrayList<WindowState> output, String name, int objectId)569     private void getWindowsByName(ArrayList<WindowState> output, String name, int objectId) {
570         forAllWindows((w) -> {
571             if (name != null) {
572                 if (w.mAttrs.getTitle().toString().contains(name)) {
573                     output.add(w);
574                 }
575             } else if (System.identityHashCode(w) == objectId) {
576                 output.add(w);
577             }
578         }, true /* traverseTopToBottom */);
579     }
580 
581     /** Returns the window token for the input binder if it exist in the system. */
getWindowToken(IBinder binder)582     WindowToken getWindowToken(IBinder binder) {
583         for (int i = mChildren.size() - 1; i >= 0; --i) {
584             final DisplayContent dc = mChildren.get(i);
585             final WindowToken wtoken = dc.getWindowToken(binder);
586             if (wtoken != null) {
587                 return wtoken;
588             }
589         }
590         return null;
591     }
592 
593     /** Returns the display object the input window token is currently mapped on. */
getWindowTokenDisplay(WindowToken token)594     DisplayContent getWindowTokenDisplay(WindowToken token) {
595         if (token == null) {
596             return null;
597         }
598 
599         for (int i = mChildren.size() - 1; i >= 0; --i) {
600             final DisplayContent dc = mChildren.get(i);
601             final WindowToken current = dc.getWindowToken(token.token);
602             if (current == token) {
603                 return dc;
604             }
605         }
606 
607         return null;
608     }
609 
610     @Override
dispatchConfigurationToChild(DisplayContent child, Configuration config)611     void dispatchConfigurationToChild(DisplayContent child, Configuration config) {
612         if (child.isDefaultDisplay) {
613             // The global configuration is also the override configuration of default display.
614             child.performDisplayOverrideConfigUpdate(config);
615         } else {
616             child.onConfigurationChanged(config);
617         }
618     }
619 
refreshSecureSurfaceState()620     void refreshSecureSurfaceState() {
621         forAllWindows(w -> {
622             w.setSecureLocked(w.isSecureLocked());
623         }, true /* traverseTopToBottom */);
624     }
625 
updateHiddenWhileSuspendedState(final ArraySet<String> packages, final boolean suspended)626     void updateHiddenWhileSuspendedState(final ArraySet<String> packages, final boolean suspended) {
627         forAllWindows((w) -> {
628             if (packages.contains(w.getOwningPackage())) {
629                 w.setHiddenWhileSuspended(suspended);
630             }
631         }, false);
632     }
633 
updateAppOpsState()634     void updateAppOpsState() {
635         forAllWindows((w) -> {
636             w.updateAppOpsState();
637         }, false /* traverseTopToBottom */);
638     }
639 
canShowStrictModeViolation(int pid)640     boolean canShowStrictModeViolation(int pid) {
641         final WindowState win = getWindow((w) -> w.mSession.mPid == pid && w.isVisible());
642         return win != null;
643     }
644 
closeSystemDialogs(String reason)645     void closeSystemDialogs(String reason) {
646         mCloseSystemDialogsReason = reason;
647         forAllWindows(mCloseSystemDialogsConsumer, false /* traverseTopToBottom */);
648     }
649 
hasPendingLayoutChanges(WindowAnimator animator)650     boolean hasPendingLayoutChanges(WindowAnimator animator) {
651         boolean hasChanges = false;
652 
653         final int count = mChildren.size();
654         for (int i = 0; i < count; ++i) {
655             final int pendingChanges = mChildren.get(i).pendingLayoutChanges;
656             if (pendingChanges != 0) {
657                 hasChanges = true;
658             }
659         }
660 
661         return hasChanges;
662     }
663 
reclaimSomeSurfaceMemory(WindowStateAnimator winAnimator, String operation, boolean secure)664     boolean reclaimSomeSurfaceMemory(WindowStateAnimator winAnimator, String operation,
665             boolean secure) {
666         final SurfaceControl surfaceControl = winAnimator.mSurfaceControl;
667         boolean leakedSurface = false;
668         boolean killedApps = false;
669         EventLogTags.writeWmNoSurfaceMemory(winAnimator.mWin.toString(),
670                 winAnimator.mSession.mPid, operation);
671         final long callingIdentity = Binder.clearCallingIdentity();
672         try {
673             // There was some problem...first, do a validity check of the window list to make sure
674             // we haven't left any dangling surfaces around.
675 
676             Slog.i(TAG_WM, "Out of memory for surface!  Looking for leaks...");
677             final int numDisplays = mChildren.size();
678             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
679                 leakedSurface |= mChildren.get(displayNdx).destroyLeakedSurfaces();
680             }
681 
682             if (!leakedSurface) {
683                 Slog.w(TAG_WM, "No leaked surfaces; killing applications!");
684                 final SparseIntArray pidCandidates = new SparseIntArray();
685                 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
686                     mChildren.get(displayNdx).forAllWindows((w) -> {
687                         if (mWmService.mForceRemoves.contains(w)) {
688                             return;
689                         }
690                         final WindowStateAnimator wsa = w.mWinAnimator;
691                         if (wsa.mSurfaceControl != null) {
692                             pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
693                         }
694                     }, false /* traverseTopToBottom */);
695 
696                     if (pidCandidates.size() > 0) {
697                         int[] pids = new int[pidCandidates.size()];
698                         for (int i = 0; i < pids.length; i++) {
699                             pids[i] = pidCandidates.keyAt(i);
700                         }
701                         try {
702                             if (mWmService.mActivityManager.killPids(pids, "Free memory", secure)) {
703                                 killedApps = true;
704                             }
705                         } catch (RemoteException e) {
706                         }
707                     }
708                 }
709             }
710 
711             if (leakedSurface || killedApps) {
712                 // We managed to reclaim some memory, so get rid of the trouble surface and ask the
713                 // app to request another one.
714                 Slog.w(TAG_WM,
715                         "Looks like we have reclaimed some memory, clearing surface for retry.");
716                 if (surfaceControl != null) {
717                     ProtoLog.i(WM_SHOW_SURFACE_ALLOC,
718                             "SURFACE RECOVER DESTROY: %s", winAnimator.mWin);
719                     SurfaceControl.Transaction t = mWmService.mTransactionFactory.get();
720                     winAnimator.destroySurface(t);
721                     t.apply();
722                     if (winAnimator.mWin.mActivityRecord != null) {
723                         winAnimator.mWin.mActivityRecord.removeStartingWindow();
724                     }
725                 }
726 
727                 try {
728                     winAnimator.mWin.mClient.dispatchGetNewSurface();
729                 } catch (RemoteException e) {
730                 }
731             }
732         } finally {
733             Binder.restoreCallingIdentity(callingIdentity);
734         }
735 
736         return leakedSurface || killedApps;
737     }
738 
739     /**
740      * This method should only be called from {@link WindowSurfacePlacer}. Otherwise the recursion
741      * check and {@link WindowSurfacePlacer#isInLayout()} won't take effect.
742      */
performSurfacePlacement()743     void performSurfacePlacement() {
744         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performSurfacePlacement");
745         try {
746             performSurfacePlacementNoTrace();
747         } finally {
748             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
749         }
750     }
751 
752     // "Something has changed!  Let's make it correct now."
753     // TODO: Super long method that should be broken down...
performSurfacePlacementNoTrace()754     void performSurfacePlacementNoTrace() {
755         if (DEBUG_WINDOW_TRACE) {
756             Slog.v(TAG, "performSurfacePlacementInner: entry. Called by "
757                     + Debug.getCallers(3));
758         }
759 
760         int i;
761 
762         if (mWmService.mFocusMayChange) {
763             mWmService.mFocusMayChange = false;
764             mWmService.updateFocusedWindowLocked(
765                     UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
766         }
767 
768         mDisplayBrightnessOverrides.clear();
769         mUserActivityTimeout = -1;
770         mObscureApplicationContentOnSecondaryDisplays = false;
771         mSustainedPerformanceModeCurrent = false;
772         mWmService.mTransactionSequence++;
773 
774         // TODO(multi-display): recents animation & wallpaper need support multi-display.
775         final DisplayContent defaultDisplay = mWmService.getDefaultDisplayContentLocked();
776         final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
777 
778         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applySurfaceChanges");
779         try {
780             applySurfaceChangesTransaction();
781         } catch (RuntimeException e) {
782             Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
783         } finally {
784             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
785         }
786 
787         // mWmService.mResizingWindows is populated in #applySurfaceChangesTransaction()
788         handleResizingWindows();
789         clearFrameChangingWindows();
790 
791         // Called after #handleResizingWindows to include WindowStateResizeItem if any.
792         mWmService.mAtmService.getLifecycleManager().dispatchPendingTransactions();
793 
794         // Send any pending task-info changes that were queued-up during a layout deferment
795         mWmService.mAtmService.mTaskOrganizerController.dispatchPendingEvents();
796         mWmService.mAtmService.mTaskFragmentOrganizerController.dispatchPendingEvents();
797         mWmService.mSyncEngine.onSurfacePlacement();
798 
799         mWmService.mAtmService.mBackNavigationController
800                 .checkAnimationReady(defaultDisplay.mWallpaperController);
801 
802         for (int displayNdx = 0; displayNdx < mChildren.size(); ++displayNdx) {
803             final DisplayContent displayContent = mChildren.get(displayNdx);
804             if (displayContent.mWallpaperMayChange) {
805                 ProtoLog.v(WM_DEBUG_WALLPAPER, "Wallpaper may change!  Adjusting");
806                 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
807                 if (DEBUG_LAYOUT_REPEATS) {
808                     surfacePlacer.debugLayoutRepeats("WallpaperMayChange",
809                             displayContent.pendingLayoutChanges);
810                 }
811             }
812         }
813 
814         if (mWmService.mFocusMayChange) {
815             mWmService.mFocusMayChange = false;
816             mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
817                     false /*updateInputWindows*/);
818         }
819 
820         if (isLayoutNeeded()) {
821             defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
822             if (DEBUG_LAYOUT_REPEATS) {
823                 surfacePlacer.debugLayoutRepeats("mLayoutNeeded",
824                         defaultDisplay.pendingLayoutChanges);
825             }
826         }
827 
828         // Destroy the surface of any windows that are no longer visible.
829         i = mWmService.mDestroySurface.size();
830         if (i > 0) {
831             do {
832                 i--;
833                 WindowState win = mWmService.mDestroySurface.get(i);
834                 win.mDestroying = false;
835                 final DisplayContent displayContent = win.getDisplayContent();
836                 if (displayContent.mInputMethodWindow == win) {
837                     displayContent.setInputMethodWindowLocked(null);
838                 }
839                 if (displayContent.mWallpaperController.isWallpaperTarget(win)) {
840                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
841                 }
842                 win.destroySurfaceUnchecked();
843             } while (i > 0);
844             mWmService.mDestroySurface.clear();
845         }
846 
847         for (int displayNdx = 0; displayNdx < mChildren.size(); ++displayNdx) {
848             final DisplayContent displayContent = mChildren.get(displayNdx);
849             if (displayContent.pendingLayoutChanges != 0) {
850                 displayContent.setLayoutNeeded();
851             }
852         }
853 
854         // Post these on a handler such that we don't call into power manager service while
855         // holding the window manager lock to avoid lock contention with power manager lock.
856         // Send a copy of the brightness overrides as they may be cleared before being sent out.
857         mHandler.obtainMessage(SET_SCREEN_BRIGHTNESS_OVERRIDE, mDisplayBrightnessOverrides.clone())
858                 .sendToTarget();
859         mHandler.obtainMessage(SET_USER_ACTIVITY_TIMEOUT, mUserActivityTimeout).sendToTarget();
860 
861         if (mSustainedPerformanceModeCurrent != mSustainedPerformanceModeEnabled) {
862             mSustainedPerformanceModeEnabled = mSustainedPerformanceModeCurrent;
863             mWmService.mPowerManagerInternal.setPowerMode(
864                     Mode.SUSTAINED_PERFORMANCE,
865                     mSustainedPerformanceModeEnabled);
866         }
867 
868         if (mUpdateRotation) {
869             ProtoLog.d(WM_DEBUG_ORIENTATION, "Performing post-rotate rotation");
870             mUpdateRotation = updateRotationUnchecked();
871         }
872 
873         if (!mWmService.mWaitingForDrawnCallbacks.isEmpty()
874                 || (!isLayoutNeeded() && !mUpdateRotation)) {
875             mWmService.checkDrawnWindowsLocked();
876         }
877 
878         forAllDisplays(dc -> {
879             dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
880             dc.updateSystemGestureExclusion();
881             dc.updateKeepClearAreas();
882         });
883 
884         // Check to see if we are now in a state where the screen should
885         // be enabled, because the window obscured flags have changed.
886         mWmService.enableScreenIfNeededLocked();
887 
888         mWmService.scheduleAnimationLocked();
889 
890         if (DEBUG_WINDOW_TRACE) Slog.e(TAG, "performSurfacePlacementInner exit");
891     }
892 
applySurfaceChangesTransaction()893     private void applySurfaceChangesTransaction() {
894         // TODO(multi-display): Support these features on secondary screens.
895         final DisplayContent defaultDc = mDefaultDisplay;
896         final DisplayInfo defaultInfo = defaultDc.getDisplayInfo();
897         final int defaultDw = defaultInfo.logicalWidth;
898         final int defaultDh = defaultInfo.logicalHeight;
899         final SurfaceControl.Transaction t = defaultDc.getSyncTransaction();
900         if (mWmService.mWatermark != null) {
901             mWmService.mWatermark.positionSurface(defaultDw, defaultDh, t);
902         }
903         if (mWmService.mStrictModeFlash != null) {
904             mWmService.mStrictModeFlash.positionSurface(defaultDw, defaultDh, t);
905         }
906         if (mWmService.mEmulatorDisplayOverlay != null) {
907             mWmService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
908                     defaultDc.getRotation(), t);
909         }
910 
911         final int count = mChildren.size();
912         for (int j = 0; j < count; ++j) {
913             final DisplayContent dc = mChildren.get(j);
914             dc.applySurfaceChangesTransaction();
915             mDisplayTransactions.append(dc.mDisplayId, dc.getSyncTransaction());
916         }
917 
918         // Give the display manager a chance to adjust properties like display rotation if it needs
919         // to.
920         mWmService.mDisplayManagerInternal.performTraversal(t, mDisplayTransactions);
921         mDisplayTransactions.clear();
922     }
923 
924     /**
925      * Handles resizing windows during surface placement.
926      */
handleResizingWindows()927     private void handleResizingWindows() {
928         for (int i = mWmService.mResizingWindows.size() - 1; i >= 0; i--) {
929             WindowState win = mWmService.mResizingWindows.get(i);
930             if (win.getDisplayContent().mWaitingForConfig) {
931                 // Don't remove this window until rotation has completed and is not waiting for the
932                 // complete configuration.
933                 continue;
934             }
935             win.updateSurfacePositionIfNeeded();
936             win.reportResized();
937             mWmService.mResizingWindows.remove(i);
938         }
939     }
940 
941     /**
942      * Clears frame changing windows after handling moving and resizing windows.
943      */
clearFrameChangingWindows()944     private void clearFrameChangingWindows() {
945         final ArrayList<WindowState> frameChangingWindows = mWmService.mFrameChangingWindows;
946         for (int i = frameChangingWindows.size() - 1; i >= 0; i--) {
947             frameChangingWindows.get(i).updateLastFrames();
948         }
949         frameChangingWindows.clear();
950     }
951 
952     /**
953      * @param w        WindowState this method is applied to.
954      * @param obscured True if there is a window on top of this obscuring the display.
955      * @param syswin   System window?
956      * @return True when the display contains content to show the user. When false, the display
957      * manager may choose to mirror or blank the display.
958      */
handleNotObscuredLocked(WindowState w, boolean obscured, boolean syswin)959     boolean handleNotObscuredLocked(WindowState w, boolean obscured, boolean syswin) {
960         final boolean onScreen = w.isOnScreen();
961         boolean displayHasContent = false;
962 
963         ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON,
964                 "handleNotObscuredLocked w: %s, w.mHasSurface: %b, w.isOnScreen(): %b, w"
965                         + ".isDisplayedLw(): %b, w.mAttrs.userActivityTimeout: %d",
966                 w, w.mHasSurface, onScreen, w.isDisplayed(), w.mAttrs.userActivityTimeout);
967         if (!onScreen) {
968             return false;
969         }
970         if (!syswin && w.mAttrs.userActivityTimeout >= 0 && mUserActivityTimeout < 0) {
971             mUserActivityTimeout = w.mAttrs.userActivityTimeout;
972             ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON, "mUserActivityTimeout set to %d",
973                     mUserActivityTimeout);
974         }
975         if (w.isDrawn() || (w.mActivityRecord != null && w.mActivityRecord.firstWindowDrawn
976                 && w.mActivityRecord.isVisibleRequested())) {
977             if (!syswin && w.mAttrs.screenBrightness >= PowerManager.BRIGHTNESS_MIN
978                     && w.mAttrs.screenBrightness <= PowerManager.BRIGHTNESS_MAX
979                     && !mDisplayBrightnessOverrides.contains(w.getDisplayId())) {
980                 var brightnessOverride = new DisplayBrightnessOverrideRequest();
981                 brightnessOverride.brightness = w.mAttrs.screenBrightness;
982                 brightnessOverride.tag = w.getWindowTag();
983                 mDisplayBrightnessOverrides.put(w.getDisplayId(), brightnessOverride);
984             }
985 
986             // This function assumes that the contents of the default display are processed first
987             // before secondary displays.
988             final DisplayContent displayContent = w.getDisplayContent();
989             if (displayContent != null && displayContent.isDefaultDisplay) {
990                 // While a dream or keyguard is showing, obscure ordinary application content on
991                 // secondary displays (by forcibly enabling mirroring unless there is other content
992                 // we want to show) but still allow opaque keyguard dialogs to be shown.
993                 if (w.isDreamWindow() || mWmService.mPolicy.isKeyguardShowing()) {
994                     mObscureApplicationContentOnSecondaryDisplays = true;
995                 }
996                 displayHasContent = true;
997             } else if (displayContent != null &&
998                     (!mObscureApplicationContentOnSecondaryDisplays
999                             || displayContent.isKeyguardAlwaysUnlocked()
1000                             || (obscured && w.mAttrs.type == TYPE_KEYGUARD_DIALOG))) {
1001                 // Allow full screen keyguard presentation dialogs to be seen, or simply ignore the
1002                 // keyguard if this display is always unlocked.
1003                 displayHasContent = true;
1004             }
1005             if ((w.mAttrs.privateFlags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) {
1006                 mSustainedPerformanceModeCurrent = true;
1007             }
1008         }
1009 
1010         return displayHasContent;
1011     }
1012 
updateRotationUnchecked()1013     boolean updateRotationUnchecked() {
1014         boolean changed = false;
1015         for (int i = mChildren.size() - 1; i >= 0; i--) {
1016             if (mChildren.get(i).getDisplayRotation().updateRotationAndSendNewConfigIfChanged()) {
1017                 changed = true;
1018             }
1019         }
1020         return changed;
1021     }
1022 
1023     private final class MyHandler extends Handler {
1024 
MyHandler(Looper looper)1025         public MyHandler(Looper looper) {
1026             super(looper);
1027         }
1028 
1029         @Override
handleMessage(Message msg)1030         public void handleMessage(Message msg) {
1031             switch (msg.what) {
1032                 case SET_SCREEN_BRIGHTNESS_OVERRIDE:
1033                     var brightnessOverrides =
1034                             (SparseArray<DisplayBrightnessOverrideRequest>) msg.obj;
1035                     mWmService.mDisplayManagerInternal.setScreenBrightnessOverrideFromWindowManager(
1036                             brightnessOverrides);
1037                     break;
1038                 case SET_USER_ACTIVITY_TIMEOUT:
1039                     mWmService.mPowerManagerInternal.
1040                             setUserActivityTimeoutOverrideFromWindowManager((Long) msg.obj);
1041                     break;
1042                 case MSG_SEND_SLEEP_TRANSITION:
1043                     synchronized (mService.mGlobalLock) {
1044                         sendSleepTransition((DisplayContent) msg.obj);
1045                     }
1046                     break;
1047                 default:
1048                     break;
1049             }
1050         }
1051     }
1052 
dumpDisplayContents(PrintWriter pw)1053     void dumpDisplayContents(PrintWriter pw) {
1054         pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
1055         if (mWmService.mDisplayReady) {
1056             final int count = mChildren.size();
1057             for (int i = 0; i < count; ++i) {
1058                 final DisplayContent displayContent = mChildren.get(i);
1059                 displayContent.dump(pw, "  ", true /* dumpAll */);
1060             }
1061         } else {
1062             pw.println("  NO DISPLAY");
1063         }
1064     }
1065 
dumpTopFocusedDisplayId(PrintWriter pw)1066     void dumpTopFocusedDisplayId(PrintWriter pw) {
1067         pw.print("  mTopFocusedDisplayId=");
1068         pw.println(mTopFocusedDisplayId);
1069     }
1070 
dumpLayoutNeededDisplayIds(PrintWriter pw)1071     void dumpLayoutNeededDisplayIds(PrintWriter pw) {
1072         if (!isLayoutNeeded()) {
1073             return;
1074         }
1075         pw.print("  mLayoutNeeded on displays=");
1076         final int count = mChildren.size();
1077         for (int displayNdx = 0; displayNdx < count; ++displayNdx) {
1078             final DisplayContent displayContent = mChildren.get(displayNdx);
1079             if (displayContent.isLayoutNeeded()) {
1080                 pw.print(displayContent.getDisplayId());
1081             }
1082         }
1083         pw.println();
1084     }
1085 
dumpWindowsNoHeader(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows)1086     void dumpWindowsNoHeader(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows) {
1087         final int[] index = new int[1];
1088         forAllWindows((w) -> {
1089             if (windows == null || windows.contains(w)) {
1090                 pw.println("  Window #" + index[0] + " " + w + ":");
1091                 w.dump(pw, "    ", dumpAll || windows != null);
1092                 index[0] = index[0] + 1;
1093             }
1094         }, true /* traverseTopToBottom */);
1095     }
1096 
dumpTokens(PrintWriter pw, boolean dumpAll)1097     void dumpTokens(PrintWriter pw, boolean dumpAll) {
1098         pw.println("  All tokens:");
1099         for (int i = mChildren.size() - 1; i >= 0; --i) {
1100             mChildren.get(i).dumpTokens(pw, dumpAll);
1101         }
1102     }
1103 
1104     @Override
dumpDebug(ProtoOutputStream proto, long fieldId, @WindowTracingLogLevel int logLevel)1105     public void dumpDebug(ProtoOutputStream proto, long fieldId,
1106             @WindowTracingLogLevel int logLevel) {
1107         if (logLevel == WindowTracingLogLevel.CRITICAL && !isVisible()) {
1108             return;
1109         }
1110 
1111         final long token = proto.start(fieldId);
1112         super.dumpDebug(proto, WINDOW_CONTAINER, logLevel);
1113 
1114         mTaskSupervisor.getKeyguardController().dumpDebug(proto, KEYGUARD_CONTROLLER);
1115         proto.write(IS_HOME_RECENTS_COMPONENT,
1116                 mTaskSupervisor.mRecentTasks.isRecentsComponentHomeActivity(mCurrentUser));
1117         proto.end(token);
1118     }
1119 
1120     @Override
getName()1121     String getName() {
1122         return "ROOT";
1123     }
1124 
1125     @Override
removeChild(DisplayContent dc)1126     protected void removeChild(DisplayContent dc) {
1127         super.removeChild(dc);
1128         if (mTopFocusedDisplayId == dc.getDisplayId()) {
1129             mWmService.updateFocusedWindowLocked(
1130                     UPDATE_FOCUS_NORMAL, true /* updateInputWindows */);
1131         }
1132     }
1133 
1134     /**
1135      * For all display at or below this call the callback.
1136      *
1137      * @param callback Callback to be called for every display.
1138      */
forAllDisplays(Consumer<DisplayContent> callback)1139     void forAllDisplays(Consumer<DisplayContent> callback) {
1140         for (int i = mChildren.size() - 1; i >= 0; --i) {
1141             callback.accept(mChildren.get(i));
1142         }
1143     }
1144 
forAllDisplayPolicies(Consumer<DisplayPolicy> callback)1145     void forAllDisplayPolicies(Consumer<DisplayPolicy> callback) {
1146         for (int i = mChildren.size() - 1; i >= 0; --i) {
1147             callback.accept(mChildren.get(i).getDisplayPolicy());
1148         }
1149     }
1150 
1151     /**
1152      * Get current topmost focused IME window in system.
1153      * Will look on all displays in current Z-order.
1154      */
getCurrentInputMethodWindow()1155     WindowState getCurrentInputMethodWindow() {
1156         for (int i = mChildren.size() - 1; i >= 0; --i) {
1157             final DisplayContent displayContent = mChildren.get(i);
1158             if (displayContent.mInputMethodWindow != null) {
1159                 return displayContent.mInputMethodWindow;
1160             }
1161         }
1162         return null;
1163     }
1164 
getDisplayContextsWithNonToastVisibleWindows(int pid, List<Context> outContexts)1165     void getDisplayContextsWithNonToastVisibleWindows(int pid, List<Context> outContexts) {
1166         if (outContexts == null) {
1167             return;
1168         }
1169         for (int i = mChildren.size() - 1; i >= 0; --i) {
1170             DisplayContent dc = mChildren.get(i);
1171             if (dc.getWindow(w -> pid == w.mSession.mPid && w.isVisibleNow()
1172                     && w.mAttrs.type != WindowManager.LayoutParams.TYPE_TOAST) != null) {
1173                 outContexts.add(dc.getDisplayUiContext());
1174             }
1175         }
1176     }
1177 
1178     @Nullable
getDisplayUiContext(int displayId)1179     Context getDisplayUiContext(int displayId) {
1180         return getDisplayContent(displayId) != null
1181                 ? getDisplayContent(displayId).getDisplayUiContext() : null;
1182     }
1183 
setWindowManager(WindowManagerService wm)1184     void setWindowManager(WindowManagerService wm) {
1185         mWindowManager = wm;
1186         mDisplayManager = mService.mContext.getSystemService(DisplayManager.class);
1187         mDisplayManager.registerDisplayListener(this, mService.mUiHandler);
1188         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
1189 
1190         final Display[] displays = mDisplayManager.getDisplays();
1191         for (int displayNdx = 0; displayNdx < displays.length; ++displayNdx) {
1192             final Display display = displays[displayNdx];
1193             final DisplayContent displayContent =
1194                     new DisplayContent(display, this, mDeviceStateController);
1195             addChild(displayContent, POSITION_BOTTOM);
1196             if (displayContent.mDisplayId == DEFAULT_DISPLAY) {
1197                 mDefaultDisplay = displayContent;
1198             }
1199         }
1200 
1201         final TaskDisplayArea defaultTaskDisplayArea = getDefaultTaskDisplayArea();
1202         defaultTaskDisplayArea.getOrCreateRootHomeTask(ON_TOP);
1203         positionChildAt(POSITION_TOP, defaultTaskDisplayArea.mDisplayContent,
1204                 false /* includingParents */);
1205     }
1206 
1207     /**
1208      * Called just before display manager has applied the device state to the displays
1209      * @param deviceState device state as defined by
1210      *        {@link android.hardware.devicestate.DeviceStateManager}
1211      */
onDisplayManagerReceivedDeviceState(int deviceState)1212     void onDisplayManagerReceivedDeviceState(int deviceState) {
1213         mDeviceStateController.onDeviceStateReceivedByDisplayManager(deviceState);
1214     }
1215 
1216     // TODO(multi-display): Look at all callpoints to make sure they make sense in multi-display.
getDefaultDisplay()1217     DisplayContent getDefaultDisplay() {
1218         return mDefaultDisplay;
1219     }
1220 
1221     @NonNull
getDisplayRotationCoordinator()1222     DisplayRotationCoordinator getDisplayRotationCoordinator() {
1223         return mDisplayRotationCoordinator;
1224     }
1225 
1226     /**
1227      * Get the default display area on the device dedicated to app windows. This one should be used
1228      * only as a fallback location for activity launches when no target display area is specified,
1229      * or for cases when multi-instance is not supported yet (like Split-screen, Freeform, PiP or
1230      * Recents).
1231      */
getDefaultTaskDisplayArea()1232     TaskDisplayArea getDefaultTaskDisplayArea() {
1233         return mDefaultDisplay.getDefaultTaskDisplayArea();
1234     }
1235 
1236     /**
1237      * Get an existing instance of {@link DisplayContent} that has the given uniqueId. Unique ID is
1238      * defined in {@link DisplayInfo#uniqueId}.
1239      *
1240      * @param uniqueId the unique ID of the display
1241      * @return the {@link DisplayContent} or {@code null} if nothing is found.
1242      */
getDisplayContent(String uniqueId)1243     DisplayContent getDisplayContent(String uniqueId) {
1244         for (int i = getChildCount() - 1; i >= 0; --i) {
1245             final DisplayContent display = getChildAt(i);
1246             final boolean isValid = display.mDisplay.isValid();
1247             if (isValid && display.mDisplay.getUniqueId().equals(uniqueId)) {
1248                 return display;
1249             }
1250         }
1251 
1252         return null;
1253     }
1254 
1255     // TODO: Look into consolidating with getDisplayContentOrCreate()
getDisplayContent(int displayId)1256     DisplayContent getDisplayContent(int displayId) {
1257         for (int i = getChildCount() - 1; i >= 0; --i) {
1258             final DisplayContent displayContent = getChildAt(i);
1259             if (displayContent.mDisplayId == displayId) {
1260                 return displayContent;
1261             }
1262         }
1263         return null;
1264     }
1265 
1266     /**
1267      * Get an existing instance of {@link DisplayContent} or create new if there is a
1268      * corresponding record in display manager.
1269      */
1270     // TODO: Look into consolidating with getDisplayContent()
1271     @Nullable
getDisplayContentOrCreate(int displayId)1272     DisplayContent getDisplayContentOrCreate(int displayId) {
1273         DisplayContent displayContent = getDisplayContent(displayId);
1274         if (displayContent != null) {
1275             return displayContent;
1276         }
1277         if (mDisplayManager == null) {
1278             // The system isn't fully initialized yet.
1279             return null;
1280         }
1281         final Display display = mDisplayManager.getDisplay(displayId);
1282         if (display == null) {
1283             // The display is not registered in DisplayManager.
1284             return null;
1285         }
1286         // The display hasn't been added to ActivityManager yet, create a new record now.
1287         displayContent = new DisplayContent(display, this, mDeviceStateController);
1288         addChild(displayContent, POSITION_BOTTOM);
1289         return displayContent;
1290     }
1291 
getDefaultDisplayHomeActivityForUser(int userId)1292     ActivityRecord getDefaultDisplayHomeActivityForUser(int userId) {
1293         return getDefaultTaskDisplayArea().getHomeActivityForUser(userId);
1294     }
1295 
startHomeOnAllDisplays(int userId, String reason)1296     boolean startHomeOnAllDisplays(int userId, String reason) {
1297         boolean homeStarted = false;
1298         for (int i = getChildCount() - 1; i >= 0; i--) {
1299             final int displayId = getChildAt(i).mDisplayId;
1300             homeStarted |= startHomeOnDisplay(userId, reason, displayId);
1301         }
1302         return homeStarted;
1303     }
1304 
startHomeOnEmptyDisplays(String reason)1305     void startHomeOnEmptyDisplays(String reason) {
1306         forAllTaskDisplayAreas(taskDisplayArea -> {
1307             if (taskDisplayArea.topRunningActivity() == null) {
1308                 int userId = mWmService.getUserAssignedToDisplay(taskDisplayArea.getDisplayId());
1309                 startHomeOnTaskDisplayArea(userId, reason, taskDisplayArea,
1310                         false /* allowInstrumenting */, false /* fromHomeKey */);
1311             }
1312         });
1313     }
1314 
startHomeOnDisplay(int userId, String reason, int displayId)1315     boolean startHomeOnDisplay(int userId, String reason, int displayId) {
1316         return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */,
1317                 false /* fromHomeKey */);
1318     }
1319 
startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting, boolean fromHomeKey)1320     boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting,
1321             boolean fromHomeKey) {
1322         // Fallback to top focused display or default display if the displayId is invalid.
1323         if (displayId == INVALID_DISPLAY) {
1324             final Task rootTask = getTopDisplayFocusedRootTask();
1325             displayId = rootTask != null ? rootTask.getDisplayId() : DEFAULT_DISPLAY;
1326         }
1327 
1328         final DisplayContent display = getDisplayContentOrCreate(displayId);
1329         return display.reduceOnAllTaskDisplayAreas((taskDisplayArea, result) ->
1330                         result | startHomeOnTaskDisplayArea(userId, reason, taskDisplayArea,
1331                                 allowInstrumenting, fromHomeKey),
1332                 false /* initValue */);
1333     }
1334 
1335     /**
1336      * This starts home activity on display areas that can have system decorations based on
1337      * displayId - default display area always uses primary home component.
1338      * For secondary display areas, the home activity must have category SECONDARY_HOME and then
1339      * resolves according to the priorities listed below.
1340      * - If default home is not set, always use the secondary home defined in the config.
1341      * - Use currently selected primary home activity.
1342      * - Use the activity in the same package as currently selected primary home activity.
1343      * If there are multiple activities matched, use first one.
1344      * - Use the secondary home defined in the config.
1345      */
startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea, boolean allowInstrumenting, boolean fromHomeKey)1346     boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea,
1347             boolean allowInstrumenting, boolean fromHomeKey) {
1348         // Fallback to top focused display area if the provided one is invalid.
1349         if (taskDisplayArea == null) {
1350             final Task rootTask = getTopDisplayFocusedRootTask();
1351             taskDisplayArea = rootTask != null ? rootTask.getDisplayArea()
1352                     : getDefaultTaskDisplayArea();
1353         }
1354 
1355         // When display content mode management flag is enabled, the task display area is marked as
1356         // removed when switching from extended display to mirroring display. We need to restart the
1357         // task display area before starting the home.
1358         if (ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT.isTrue()
1359                 && taskDisplayArea.shouldKeepNoTask()) {
1360             taskDisplayArea.setShouldKeepNoTask(false);
1361         }
1362 
1363         Intent homeIntent = null;
1364         ActivityInfo aInfo = null;
1365         if (taskDisplayArea == getDefaultTaskDisplayArea()
1366                 || mWmService.shouldPlacePrimaryHomeOnDisplay(
1367                         taskDisplayArea.getDisplayId(), userId)) {
1368             homeIntent = mService.getHomeIntent();
1369             aInfo = resolveHomeActivity(userId, homeIntent);
1370         } else if (shouldPlaceSecondaryHomeOnDisplayArea(taskDisplayArea)) {
1371             Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, taskDisplayArea);
1372             aInfo = info.first;
1373             homeIntent = info.second;
1374         }
1375 
1376         if (aInfo == null || homeIntent == null) {
1377             return false;
1378         }
1379 
1380         if (!canStartHomeOnDisplayArea(aInfo, taskDisplayArea, allowInstrumenting)) {
1381             return false;
1382         }
1383 
1384         if (mService.mAmInternal.shouldDelayHomeLaunch(userId)) {
1385             Slog.d(TAG, "ThemeHomeDelay: Home launch was deferred with user " + userId);
1386             return false;
1387         }
1388 
1389         // Updates the home component of the intent.
1390         homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
1391         homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
1392         // Updates the extra information of the intent.
1393         if (fromHomeKey) {
1394             homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true);
1395         }
1396         homeIntent.putExtra(WindowManagerPolicy.EXTRA_START_REASON, reason);
1397 
1398         // Update the reason for ANR debugging to verify if the user activity is the one that
1399         // actually launched.
1400         final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId(
1401                 aInfo.applicationInfo.uid) + ":" + taskDisplayArea.getDisplayId();
1402         mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
1403                 taskDisplayArea);
1404         return true;
1405     }
1406 
1407     /**
1408      * This resolves the home activity info.
1409      *
1410      * @return the home activity info if any.
1411      */
1412     @VisibleForTesting
resolveHomeActivity(int userId, Intent homeIntent)1413     ActivityInfo resolveHomeActivity(int userId, Intent homeIntent) {
1414         final int flags = ActivityManagerService.STOCK_PM_FLAGS;
1415         final ComponentName comp = homeIntent.getComponent();
1416         ActivityInfo aInfo = null;
1417         try {
1418             if (comp != null) {
1419                 // Factory test.
1420                 aInfo = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId);
1421             } else {
1422                 final String resolvedType =
1423                         homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver());
1424                 final ResolveInfo info = mTaskSupervisor.resolveIntent(homeIntent, resolvedType,
1425                         userId, flags, Binder.getCallingUid(), Binder.getCallingPid());
1426                 if (info != null) {
1427                     aInfo = info.activityInfo;
1428                 }
1429             }
1430         } catch (RemoteException e) {
1431             // ignore
1432         }
1433 
1434         if (aInfo == null) {
1435             Slogf.wtf(TAG, new Exception(), "No home screen found for %s and user %d", homeIntent,
1436                     userId);
1437             return null;
1438         }
1439 
1440         aInfo = new ActivityInfo(aInfo);
1441         aInfo.applicationInfo = mService.getAppInfoForUser(aInfo.applicationInfo, userId);
1442         return aInfo;
1443     }
1444 
1445     @VisibleForTesting
resolveSecondaryHomeActivity(int userId, @NonNull TaskDisplayArea taskDisplayArea)1446     Pair<ActivityInfo, Intent> resolveSecondaryHomeActivity(int userId,
1447             @NonNull TaskDisplayArea taskDisplayArea) {
1448         if (taskDisplayArea == getDefaultTaskDisplayArea()) {
1449             throw new IllegalArgumentException(
1450                     "resolveSecondaryHomeActivity: Should not be default task container");
1451         }
1452 
1453         Intent homeIntent = mService.getHomeIntent();
1454         ActivityInfo aInfo = resolveHomeActivity(userId, homeIntent);
1455         boolean lookForSecondaryHomeActivityInPrimaryHomePackage = aInfo != null;
1456 
1457         // Resolve the externally set home activity for this display, if any. If it is unset or
1458         // we fail to resolve it, fallback to the default secondary home activity.
1459         final ComponentName customHomeComponent =
1460                 taskDisplayArea.getDisplayContent() != null
1461                         ? taskDisplayArea.getDisplayContent().getCustomHomeComponent()
1462                         : null;
1463         if (customHomeComponent != null) {
1464             homeIntent.setComponent(customHomeComponent);
1465             ActivityInfo customHomeActivityInfo = resolveHomeActivity(userId, homeIntent);
1466             if (customHomeActivityInfo != null) {
1467                 aInfo = customHomeActivityInfo;
1468                 lookForSecondaryHomeActivityInPrimaryHomePackage = false;
1469             }
1470         }
1471 
1472         if (lookForSecondaryHomeActivityInPrimaryHomePackage) {
1473             // Resolve activities in the same package as currently selected primary home activity.
1474             if (ResolverActivity.class.getName().equals(aInfo.name)) {
1475                 // Always fallback to secondary home component if default home is not set.
1476                 aInfo = null;
1477             } else {
1478                 // Look for secondary home activities in the currently selected default home
1479                 // package.
1480                 homeIntent = mService.getSecondaryHomeIntent(aInfo.applicationInfo.packageName);
1481                 final List<ResolveInfo> resolutions = resolveActivities(userId, homeIntent);
1482                 final int size = resolutions.size();
1483                 final String targetName = aInfo.name;
1484                 aInfo = null;
1485                 for (int i = 0; i < size; i++) {
1486                     ResolveInfo resolveInfo = resolutions.get(i);
1487                     // We need to traverse all resolutions to check if the currently selected
1488                     // default home activity is present.
1489                     if (resolveInfo.activityInfo.name.equals(targetName)) {
1490                         aInfo = resolveInfo.activityInfo;
1491                         break;
1492                     }
1493                 }
1494                 if (aInfo == null && size > 0) {
1495                     // First one is the best.
1496                     aInfo = resolutions.get(0).activityInfo;
1497                 }
1498             }
1499         }
1500 
1501         if (aInfo != null) {
1502             if (!canStartHomeOnDisplayArea(aInfo, taskDisplayArea,
1503                     false /* allowInstrumenting */)) {
1504                 aInfo = null;
1505             }
1506         }
1507 
1508         // Fallback to secondary home component.
1509         if (aInfo == null) {
1510             homeIntent = mService.getSecondaryHomeIntent(null);
1511             aInfo = resolveHomeActivity(userId, homeIntent);
1512         }
1513         return Pair.create(aInfo, homeIntent);
1514     }
1515 
1516     /**
1517      * Retrieve all activities that match the given intent.
1518      * The list should already ordered from best to worst matched.
1519      * {@link android.content.pm.PackageManager#queryIntentActivities}
1520      */
1521     @VisibleForTesting
resolveActivities(int userId, Intent homeIntent)1522     List<ResolveInfo> resolveActivities(int userId, Intent homeIntent) {
1523         List<ResolveInfo> resolutions;
1524         try {
1525             final String resolvedType =
1526                     homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver());
1527             resolutions = AppGlobals.getPackageManager().queryIntentActivities(homeIntent,
1528                     resolvedType, ActivityManagerService.STOCK_PM_FLAGS, userId).getList();
1529 
1530         } catch (RemoteException e) {
1531             resolutions = new ArrayList<>();
1532         }
1533         return resolutions;
1534     }
1535 
resumeHomeActivity(ActivityRecord prev, String reason, TaskDisplayArea taskDisplayArea)1536     boolean resumeHomeActivity(ActivityRecord prev, String reason,
1537             TaskDisplayArea taskDisplayArea) {
1538         if (!mService.isBooting() && !mService.isBooted()) {
1539             // Not ready yet!
1540             return false;
1541         }
1542 
1543         if (taskDisplayArea == null) {
1544             taskDisplayArea = getDefaultTaskDisplayArea();
1545         }
1546 
1547         final ActivityRecord r = taskDisplayArea.getHomeActivity();
1548         final String myReason = reason + " resumeHomeActivity";
1549 
1550         // Only resume home activity if isn't finishing.
1551         if (r != null && !r.finishing) {
1552             r.moveFocusableActivityToTop(myReason);
1553             return resumeFocusedTasksTopActivities(r.getRootTask(), prev);
1554         }
1555         int userId = mWmService.getUserAssignedToDisplay(taskDisplayArea.getDisplayId());
1556         return startHomeOnTaskDisplayArea(userId, myReason, taskDisplayArea,
1557                 false /* allowInstrumenting */, false /* fromHomeKey */);
1558     }
1559 
1560     /**
1561      * Check if the display is valid for primary home activity.
1562      *
1563      * @param displayId The target display ID
1564      * @return {@code true} if allowed to launch, {@code false} otherwise.
1565      */
shouldPlacePrimaryHomeOnDisplay(int displayId)1566     boolean shouldPlacePrimaryHomeOnDisplay(int displayId) {
1567         // No restrictions to default display, vr 2d display or main display for visible users.
1568         return displayId == DEFAULT_DISPLAY || (displayId != INVALID_DISPLAY
1569                 && (displayId == mService.mVr2dDisplayId
1570                 || mWmService.shouldPlacePrimaryHomeOnDisplay(displayId)));
1571     }
1572 
1573     /**
1574      * Check if the display area is valid for secondary home activity.
1575      *
1576      * @param taskDisplayArea The target display area.
1577      * @return {@code true} if allow to launch, {@code false} otherwise.
1578      */
shouldPlaceSecondaryHomeOnDisplayArea(TaskDisplayArea taskDisplayArea)1579     boolean shouldPlaceSecondaryHomeOnDisplayArea(TaskDisplayArea taskDisplayArea) {
1580         if (getDefaultTaskDisplayArea() == taskDisplayArea) {
1581             throw new IllegalArgumentException(
1582                     "shouldPlaceSecondaryHomeOnDisplay: Should not be on default task container");
1583         } else if (taskDisplayArea == null) {
1584             return false;
1585         }
1586 
1587         if (!taskDisplayArea.canHostHomeTask()) {
1588             // Can't launch home on a TaskDisplayArea that does not support root home task
1589             return false;
1590         }
1591 
1592         if (taskDisplayArea.getDisplayId() != DEFAULT_DISPLAY && !mService.mSupportsMultiDisplay) {
1593             // Can't launch home on secondary display if device does not support multi-display.
1594             return false;
1595         }
1596 
1597         final boolean deviceProvisioned = Settings.Global.getInt(
1598                 mService.mContext.getContentResolver(),
1599                 Settings.Global.DEVICE_PROVISIONED, 0) != 0;
1600         if (!deviceProvisioned) {
1601             // Can't launch home on secondary display areas before device is provisioned.
1602             return false;
1603         }
1604 
1605         if (!StorageManager.isCeStorageUnlocked(mCurrentUser)) {
1606             // Can't launch home on secondary display areas if CE storage is still locked.
1607             return false;
1608         }
1609 
1610         final DisplayContent display = taskDisplayArea.getDisplayContent();
1611         if (display == null || display.isRemoved() || !display.isHomeSupported()) {
1612             // Can't launch home on display that doesn't support home.
1613             return false;
1614         }
1615 
1616         return true;
1617     }
1618 
1619     /**
1620      * Check if home activity start should be allowed on a {@link TaskDisplayArea}.
1621      *
1622      * @param homeInfo           {@code ActivityInfo} of the home activity that is going to be
1623      *                           launched.
1624      * @param taskDisplayArea    The target display area.
1625      * @param allowInstrumenting Whether launching home should be allowed if being instrumented.
1626      * @return {@code true} if allow to launch, {@code false} otherwise.
1627      */
canStartHomeOnDisplayArea(ActivityInfo homeInfo, TaskDisplayArea taskDisplayArea, boolean allowInstrumenting)1628     boolean canStartHomeOnDisplayArea(ActivityInfo homeInfo, TaskDisplayArea taskDisplayArea,
1629             boolean allowInstrumenting) {
1630         if (mService.mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
1631                 && mService.mTopAction == null) {
1632             // We are running in factory test mode, but unable to find the factory test app, so
1633             // just sit around displaying the error message and don't try to start anything.
1634             return false;
1635         }
1636 
1637         final WindowProcessController app =
1638                 mService.getProcessController(homeInfo.processName, homeInfo.applicationInfo.uid);
1639         if (!allowInstrumenting && app != null && app.isInstrumenting()) {
1640             // Don't do this if the home app is currently being instrumented.
1641             return false;
1642         }
1643 
1644         if (taskDisplayArea != null && !taskDisplayArea.canHostHomeTask()) {
1645             return false;
1646         }
1647 
1648         final int displayId = taskDisplayArea != null ? taskDisplayArea.getDisplayId()
1649                 : INVALID_DISPLAY;
1650         if (shouldPlacePrimaryHomeOnDisplay(displayId)) {
1651             return true;
1652         }
1653 
1654         if (!shouldPlaceSecondaryHomeOnDisplayArea(taskDisplayArea)) {
1655             return false;
1656         }
1657 
1658         final boolean supportMultipleInstance = homeInfo.launchMode != LAUNCH_SINGLE_TASK
1659                 && homeInfo.launchMode != LAUNCH_SINGLE_INSTANCE;
1660         if (!supportMultipleInstance) {
1661             // Can't launch home on secondary displays if it requested to be single instance.
1662             return false;
1663         }
1664 
1665         return true;
1666     }
1667 
1668     /**
1669      * Ensure all activities visibility, update orientation and configuration.
1670      *
1671      * @param starting                  The currently starting activity or {@code null} if there is
1672      *                                  none.
1673      * @param displayContent            The display where the operation is executed.
1674      * @param deferResume               Whether to defer resume while updating config.
1675      */
ensureVisibilityAndConfig(@ullable ActivityRecord starting, @NonNull DisplayContent displayContent, boolean deferResume)1676     void ensureVisibilityAndConfig(@Nullable ActivityRecord starting,
1677             @NonNull DisplayContent displayContent, boolean deferResume) {
1678         // First ensure visibility without updating the config just yet. We need this to know what
1679         // activities are affecting configuration now.
1680         // Passing null here for 'starting' param value, so that visibility of actual starting
1681         // activity will be properly updated.
1682         ensureActivitiesVisible(null /* starting */, false /* notifyClients */);
1683 
1684         // Force-update the orientation from the WindowManager, since we need the true configuration
1685         // to send to the client now.
1686         final Configuration config =
1687                 displayContent.updateOrientationAndComputeConfig(true /* forceUpdate */);
1688         // Visibilities may change so let the starting activity have a chance to report. Can't do it
1689         // when visibility is changed in each AppWindowToken because it may trigger wrong
1690         // configuration push because the visibility of some activities may not be updated yet.
1691         if (starting != null) {
1692             starting.reportDescendantOrientationChangeIfNeeded();
1693         }
1694 
1695         // Update the configuration of the activities on the display.
1696         displayContent.updateDisplayOverrideConfigurationLocked(config, starting, deferResume);
1697     }
1698 
1699     /**
1700      * @return a list of pairs, containing activities and their task id which are the top ones in
1701      * each visible root task. The first entry will be the focused activity.
1702      *
1703      * <p>NOTE: If the top activity is in the split screen, the other activities in the same split
1704      * screen will also be returned.
1705      */
getTopVisibleActivities()1706     List<ActivityAssistInfo> getTopVisibleActivities() {
1707         final ArrayList<ActivityAssistInfo> topVisibleActivities = new ArrayList<>();
1708         final ArrayList<ActivityAssistInfo> activityAssistInfos = new ArrayList<>();
1709         final Task topFocusedRootTask = getTopDisplayFocusedRootTask();
1710         // Traverse all displays.
1711         forAllRootTasks(rootTask -> {
1712             // Get top activity from a visible root task and add it to the list.
1713             if (rootTask.shouldBeVisible(null /* starting */)) {
1714                 final ActivityRecord top = rootTask.getTopNonFinishingActivity();
1715                 if (top != null) {
1716                     activityAssistInfos.clear();
1717                     activityAssistInfos.add(new ActivityAssistInfo(top));
1718                     // Check if the activity on the split screen.
1719                     top.getTask().forOtherAdjacentTasks(task -> {
1720                         final ActivityRecord adjacentActivityRecord =
1721                                 task.getTopNonFinishingActivity();
1722                         if (adjacentActivityRecord != null) {
1723                             activityAssistInfos.add(
1724                                     new ActivityAssistInfo(adjacentActivityRecord));
1725                         }
1726                     });
1727                     if (rootTask == topFocusedRootTask) {
1728                         topVisibleActivities.addAll(0, activityAssistInfos);
1729                     } else {
1730                         topVisibleActivities.addAll(activityAssistInfos);
1731                     }
1732                 }
1733             }
1734         });
1735         return topVisibleActivities;
1736     }
1737 
1738     @Nullable
getTopDisplayFocusedRootTask()1739     Task getTopDisplayFocusedRootTask() {
1740         for (int i = getChildCount() - 1; i >= 0; --i) {
1741             final Task focusedRootTask = getChildAt(i).getFocusedRootTask();
1742             if (focusedRootTask != null) {
1743                 return focusedRootTask;
1744             }
1745         }
1746         return null;
1747     }
1748 
1749     @Nullable
getTopResumedActivity()1750     ActivityRecord getTopResumedActivity() {
1751         final Task focusedRootTask = getTopDisplayFocusedRootTask();
1752         if (focusedRootTask == null) {
1753             return null;
1754         }
1755         final ActivityRecord resumedActivity = focusedRootTask.getTopResumedActivity();
1756         if (resumedActivity != null && resumedActivity.app != null) {
1757             return resumedActivity;
1758         }
1759         // The top focused root task might not have a resumed activity yet - look on all displays in
1760         // focus order.
1761         return getItemFromTaskDisplayAreas(TaskDisplayArea::getFocusedActivity);
1762     }
1763 
isTopDisplayFocusedRootTask(Task task)1764     boolean isTopDisplayFocusedRootTask(Task task) {
1765         return task != null && task == getTopDisplayFocusedRootTask();
1766     }
1767 
attachApplication(WindowProcessController app)1768     boolean attachApplication(WindowProcessController app) throws RemoteException {
1769         app.mHasEverAttached = true;
1770         final ArrayList<ActivityRecord> activities = mService.mStartingProcessActivities;
1771         RemoteException remoteException = null;
1772         boolean hasActivityStarted = false;
1773         for (int i = activities.size() - 1; i >= 0; i--) {
1774             final ActivityRecord r = activities.get(i);
1775             if (app.mUid != r.info.applicationInfo.uid || !app.mName.equals(r.processName)) {
1776                 // The attaching process does not match the starting activity.
1777                 continue;
1778             }
1779             // Consume the pending record.
1780             activities.remove(i);
1781             final TaskFragment tf = r.getTaskFragment();
1782             if (tf == null || r.finishing || r.app != null
1783                     // Ignore keyguard because the app may use show-when-locked when creating.
1784                     || !r.shouldBeVisible(true /* ignoringKeyguard */)
1785                     || !r.showToCurrentUser()) {
1786                 continue;
1787             }
1788             try {
1789                 final boolean canResume = r.isFocusable() && r == tf.topRunningActivity();
1790                 if (mTaskSupervisor.realStartActivityLocked(r, app, canResume,
1791                         true /* checkConfig */)) {
1792                     hasActivityStarted = true;
1793                 }
1794             } catch (RemoteException e) {
1795                 Slog.w(TAG, "Exception in new process when starting " + r, e);
1796                 remoteException = e;
1797             }
1798         }
1799         if (remoteException != null) {
1800             throw remoteException;
1801         }
1802         return hasActivityStarted;
1803     }
1804 
1805     /**
1806      * Make sure that all activities that need to be visible in the system actually are and update
1807      * their configuration.
1808      */
ensureActivitiesVisible()1809     void ensureActivitiesVisible() {
1810         ensureActivitiesVisible(null /* starting */);
1811     }
1812 
ensureActivitiesVisible(ActivityRecord starting)1813     void ensureActivitiesVisible(ActivityRecord starting) {
1814         ensureActivitiesVisible(starting, true /* notifyClients */);
1815     }
1816 
1817     /**
1818      * @see #ensureActivitiesVisible()
1819      */
ensureActivitiesVisible(ActivityRecord starting, boolean notifyClients)1820     void ensureActivitiesVisible(ActivityRecord starting, boolean notifyClients) {
1821         if (mTaskSupervisor.inActivityVisibilityUpdate()
1822                 || mTaskSupervisor.isRootVisibilityUpdateDeferred()) {
1823             // Don't do recursive work.
1824             return;
1825         }
1826         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "RWC_ensureActivitiesVisible");
1827         mTaskSupervisor.beginActivityVisibilityUpdate();
1828         try {
1829             // First the front root tasks. In case any are not fullscreen and are in front of home.
1830             for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
1831                 final DisplayContent display = getChildAt(displayNdx);
1832                 display.ensureActivitiesVisible(starting, notifyClients);
1833             }
1834         } finally {
1835             mTaskSupervisor.endActivityVisibilityUpdate();
1836             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
1837         }
1838     }
1839 
switchUser(int userId, UserState uss)1840     boolean switchUser(int userId, UserState uss) {
1841         final Task topFocusedRootTask = getTopDisplayFocusedRootTask();
1842         final int focusRootTaskId = topFocusedRootTask != null
1843                 ? topFocusedRootTask.getRootTaskId() : INVALID_TASK_ID;
1844         // Also dismiss the pinned root task whenever we switch users. Removing the pinned root task
1845         // will also cause all tasks to be moved to the fullscreen root task at a position that is
1846         // appropriate.
1847         removeRootTasksInWindowingModes(WINDOWING_MODE_PINNED);
1848 
1849         if (DesktopModeFlags.ENABLE_TOP_VISIBLE_ROOT_TASK_PER_USER_TRACKING.isTrue()) {
1850             final IntArray visibleRootTasks = new IntArray();
1851             forAllRootTasks(rootTask -> {
1852                 if ((mCurrentUser == rootTask.mUserId || rootTask.showForAllUsers())
1853                         && rootTask.isVisible()) {
1854                     visibleRootTasks.add(rootTask.getRootTaskId());
1855                 }
1856             }, /* traverseTopToBottom */ false);
1857             mUserVisibleRootTasks.put(mCurrentUser, visibleRootTasks);
1858         } else {
1859             mUserRootTaskInFront.put(mCurrentUser, focusRootTaskId);
1860         }
1861 
1862         mCurrentUser = userId;
1863 
1864         mTaskSupervisor.mStartingUsers.add(uss);
1865         forAllRootTasks(rootTask -> {
1866             rootTask.switchUser(userId);
1867         });
1868 
1869 
1870         if (topFocusedRootTask != null && isAlwaysVisibleUser(topFocusedRootTask.mUserId)) {
1871             Slog.i(TAG, "Persisting top task because it belongs to an always-visible user");
1872             // For a normal user-switch, we will restore the new user's task. But if the pre-switch
1873             // top task is an always-visible (Communal) one, keep it even after the switch.
1874             if (Flags.enableTopVisibleRootTaskPerUserTracking()) {
1875                 final IntArray rootTasks = mUserVisibleRootTasks.get(mCurrentUser);
1876                 rootTasks.add(focusRootTaskId);
1877                 mUserVisibleRootTasks.put(mCurrentUser, rootTasks);
1878             } else {
1879                 mUserRootTaskInFront.put(mCurrentUser, focusRootTaskId);
1880             }
1881 
1882         }
1883 
1884         final int restoreRootTaskId = mUserRootTaskInFront.get(userId);
1885         final IntArray rootTaskIdsToRestore = mUserVisibleRootTasks.get(userId);
1886         boolean homeInFront = false;
1887         if (Flags.enableTopVisibleRootTaskPerUserTracking()) {
1888             if (rootTaskIdsToRestore == null || rootTaskIdsToRestore.size() == 0) {
1889                 // If there are no root tasks saved, try restore id 0 which should create and launch
1890                 // the home task.
1891                 handleRootTaskLaunchOnUserSwitch(/* restoreRootTaskId */INVALID_TASK_ID);
1892                 homeInFront = true;
1893             } else {
1894                 for (int i = 0; i < rootTaskIdsToRestore.size(); i++) {
1895                     handleRootTaskLaunchOnUserSwitch(rootTaskIdsToRestore.get(i));
1896                 }
1897                 // Check if the top task is type home
1898                 final int topRootTaskId = rootTaskIdsToRestore.get(rootTaskIdsToRestore.size() - 1);
1899                 homeInFront = isHomeTask(topRootTaskId);
1900             }
1901         } else {
1902             handleRootTaskLaunchOnUserSwitch(restoreRootTaskId);
1903             // Check if the top task is type home
1904             homeInFront = isHomeTask(restoreRootTaskId);
1905         }
1906         return homeInFront;
1907     }
1908 
isHomeTask(int taskId)1909     private boolean isHomeTask(int taskId) {
1910         final Task rootTask = getRootTask(taskId);
1911         return rootTask != null && rootTask.isActivityTypeHome();
1912     }
1913 
handleRootTaskLaunchOnUserSwitch(int restoreRootTaskId)1914     private void handleRootTaskLaunchOnUserSwitch(int restoreRootTaskId) {
1915         Task rootTask = getRootTask(restoreRootTaskId);
1916         if (rootTask == null) {
1917             rootTask = getDefaultTaskDisplayArea().getOrCreateRootHomeTask();
1918         }
1919         if (rootTask.isOnHomeDisplay()) {
1920             rootTask.moveToFront("switchUserOnHomeDisplay");
1921         } else {
1922             // Root task was moved to another display while user was swapped out.
1923             resumeHomeActivity(null, "switchUserOnOtherDisplay", getDefaultTaskDisplayArea());
1924         }
1925     }
1926 
1927     /** Returns whether the given user is to be always-visible (e.g. a communal profile). */
isAlwaysVisibleUser(@serIdInt int userId)1928     private boolean isAlwaysVisibleUser(@UserIdInt int userId) {
1929         final UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
1930         final UserProperties properties = umi.getUserProperties(userId);
1931         return properties != null && properties.getAlwaysVisible();
1932     }
1933 
removeUser(int userId)1934     void removeUser(int userId) {
1935         if (Flags.enableTopVisibleRootTaskPerUserTracking()) {
1936             mUserVisibleRootTasks.delete(userId);
1937         } else {
1938             mUserRootTaskInFront.delete(userId);
1939         }
1940     }
1941 
1942     /**
1943      * Update the last used root task id for non-current user (current user's last
1944      * used root task is the focused root task)
1945      */
updateUserRootTask(int userId, Task rootTask)1946     void updateUserRootTask(int userId, Task rootTask) {
1947         if (userId != mCurrentUser) {
1948             if (rootTask == null) {
1949                 rootTask = getDefaultTaskDisplayArea().getOrCreateRootHomeTask();
1950             }
1951 
1952             if (Flags.enableTopVisibleRootTaskPerUserTracking()) {
1953                 final IntArray rootTasks = mUserVisibleRootTasks.get(userId, new IntArray());
1954                 // If root task already exists in the list, move it to the top instead.
1955                 final int rootTaskIndex = rootTasks.indexOf(rootTask.getRootTaskId());
1956                 if (rootTaskIndex != -1) {
1957                     rootTasks.remove(rootTaskIndex);
1958                 }
1959                 rootTasks.add(rootTask.getRootTaskId());
1960                 mUserVisibleRootTasks.put(userId, rootTasks);
1961             } else {
1962                 mUserRootTaskInFront.put(userId, rootTask.getRootTaskId());
1963             }
1964         }
1965     }
1966 
1967     /**
1968      * Move root task with all its existing content to specified task display area.
1969      *
1970      * @param rootTaskId      Id of root task to move.
1971      * @param taskDisplayArea The task display area to move root task to.
1972      * @param onTop           Indicates whether container should be place on top or on bottom.
1973      */
moveRootTaskToTaskDisplayArea(int rootTaskId, TaskDisplayArea taskDisplayArea, boolean onTop)1974     void moveRootTaskToTaskDisplayArea(int rootTaskId, TaskDisplayArea taskDisplayArea,
1975             boolean onTop) {
1976         final Task rootTask = getRootTask(rootTaskId);
1977         if (rootTask == null) {
1978             throw new IllegalArgumentException("moveRootTaskToTaskDisplayArea: Unknown rootTaskId="
1979                     + rootTaskId);
1980         }
1981 
1982         final TaskDisplayArea currentTaskDisplayArea = rootTask.getDisplayArea();
1983         if (currentTaskDisplayArea == null) {
1984             throw new IllegalStateException("moveRootTaskToTaskDisplayArea: rootTask=" + rootTask
1985                     + " is not attached to any task display area.");
1986         }
1987 
1988         if (taskDisplayArea == null) {
1989             throw new IllegalArgumentException(
1990                     "moveRootTaskToTaskDisplayArea: Unknown taskDisplayArea=" + taskDisplayArea);
1991         }
1992 
1993         if (currentTaskDisplayArea == taskDisplayArea) {
1994             throw new IllegalArgumentException("Trying to move rootTask=" + rootTask
1995                     + " to its current taskDisplayArea=" + taskDisplayArea);
1996         }
1997         rootTask.reparent(taskDisplayArea, onTop);
1998 
1999         // Resume focusable root task after reparenting to another display area.
2000         rootTask.resumeNextFocusAfterReparent();
2001 
2002         // TODO(multi-display): resize rootTasks properly if moved from split-screen.
2003     }
2004 
2005     /**
2006      * Move root task with all its existing content to specified display.
2007      *
2008      * @param rootTaskId Id of root task to move.
2009      * @param displayId  Id of display to move root task to.
2010      * @param onTop      Indicates whether container should be place on top or on bottom.
2011      */
moveRootTaskToDisplay(int rootTaskId, int displayId, boolean onTop)2012     void moveRootTaskToDisplay(int rootTaskId, int displayId, boolean onTop) {
2013         final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
2014         if (displayContent == null) {
2015             throw new IllegalArgumentException("moveRootTaskToDisplay: Unknown displayId="
2016                     + displayId);
2017         }
2018 
2019         moveRootTaskToTaskDisplayArea(rootTaskId, displayContent.getDefaultTaskDisplayArea(),
2020                 onTop);
2021     }
2022 
2023     /** Wrapper/Helper for tests */
moveActivityToPinnedRootTask(@onNull ActivityRecord r, String reason)2024     void moveActivityToPinnedRootTask(@NonNull ActivityRecord r, String reason) {
2025         Transition newTransit = (r.mTransitionController.isCollecting()
2026                 || !r.mTransitionController.isShellTransitionsEnabled())
2027                 ? null : r.mTransitionController.createTransition(TRANSIT_PIP);
2028         moveActivityToPinnedRootTaskInner(r, null /* launchIntoPipHostActivity */, reason,
2029                 null /* bounds */, newTransit != null);
2030     }
2031 
moveActivityToPinnedRootTask(@onNull ActivityRecord r, @Nullable ActivityRecord launchIntoPipHostActivity, String reason, @Nullable Rect bounds)2032     void moveActivityToPinnedRootTask(@NonNull ActivityRecord r,
2033             @Nullable ActivityRecord launchIntoPipHostActivity, String reason,
2034             @Nullable Rect bounds) {
2035         moveActivityToPinnedRootTaskInner(r, launchIntoPipHostActivity, reason, bounds,
2036                 false /* requestStart */);
2037     }
2038 
2039     /**
2040      * Moves activity to pinned in the provided transition and also requests start on that
2041      * Transition at an appropriate time.
2042      */
moveActivityToPinnedRootTaskAndRequestStart(@onNull ActivityRecord r, String reason)2043     void moveActivityToPinnedRootTaskAndRequestStart(@NonNull ActivityRecord r, String reason) {
2044         moveActivityToPinnedRootTaskInner(r, null /* launchIntoPipHostActivity */, reason,
2045                 null /* bounds */, true /* requestStart */);
2046     }
2047 
moveActivityToPinnedRootTaskInner(@onNull ActivityRecord r, @Nullable ActivityRecord launchIntoPipHostActivity, String reason, @Nullable Rect bounds, boolean requestStart)2048     private void moveActivityToPinnedRootTaskInner(@NonNull ActivityRecord r,
2049             @Nullable ActivityRecord launchIntoPipHostActivity, String reason,
2050             @Nullable Rect bounds, boolean requestStart) {
2051         final TaskDisplayArea taskDisplayArea = r.getDisplayArea();
2052         final Task task = r.getTask();
2053         final Task rootTask;
2054 
2055         final TransitionController transitionController = task.mTransitionController;
2056 
2057         transitionController.deferTransitionReady();
2058         Transition.ReadyCondition pipChangesApplied = new Transition.ReadyCondition("movedToPip");
2059         transitionController.waitFor(pipChangesApplied);
2060         mService.deferWindowLayout();
2061         boolean localVisibilityDeferred = false;
2062         // If the caller is from WindowOrganizerController, it should be already deferred.
2063         if (!mTaskSupervisor.isRootVisibilityUpdateDeferred()) {
2064             mTaskSupervisor.setDeferRootVisibilityUpdate(true);
2065             localVisibilityDeferred = true;
2066         }
2067         try {
2068             // This will change the root pinned task's windowing mode to its original mode, ensuring
2069             // we only have one root task that is in pinned mode.
2070             final Task rootPinnedTask = taskDisplayArea.getRootPinnedTask();
2071             if (rootPinnedTask != null) {
2072                 transitionController.collect(rootPinnedTask);
2073                 // The new ActivityRecord should replace the existing PiP, so it's more desirable
2074                 // that the old PiP disappears instead of turning to full-screen at the same time,
2075                 // as the Task#dismissPip is trying to do.
2076                 removeRootTasksInWindowingModes(WINDOWING_MODE_PINNED);
2077             }
2078 
2079             transitionController.collect(task);
2080 
2081             // Defer the windowing mode change until after the transition to prevent the activity
2082             // from doing work and changing the activity visuals while animating
2083             // TODO(task-org): Figure-out more structured way to do this long term.
2084             if (!isPip2ExperimentEnabled()) {
2085                 r.setWindowingMode(r.getWindowingMode());
2086             }
2087 
2088             final TaskFragment organizedTf = r.getOrganizedTaskFragment();
2089             final TaskFragment taskFragment = r.getTaskFragment();
2090             final boolean singleActivity = task.getNonFinishingActivityCount() == 1;
2091             if (singleActivity) {
2092                 rootTask = task;
2093 
2094                 // Apply the last recents animation leash transform to the task entering PIP
2095                 rootTask.maybeApplyLastRecentsAnimationTransaction();
2096 
2097                 if (rootTask.getParent() != taskDisplayArea) {
2098                     // root task is nested, but pinned tasks need to be direct children of their
2099                     // display area, so reparent.
2100                     rootTask.reparent(taskDisplayArea, true /* onTop */);
2101                 }
2102 
2103                 rootTask.forAllTaskFragments(tf -> {
2104                     if (!tf.isOrganizedTaskFragment()) {
2105                         return;
2106                     }
2107                     tf.clearAdjacentTaskFragments();
2108                     tf.setCompanionTaskFragment(null /* companionTaskFragment */);
2109                     tf.setAnimationParams(TaskFragmentAnimationParams.DEFAULT);
2110                     if (tf.getTopNonFinishingActivity() != null) {
2111                         // When the Task is entering picture-in-picture, we should clear all
2112                         // override from the client organizer, so the PIP activity can get the
2113                         // correct config from the Task, and prevent conflict with the
2114                         // PipTaskOrganizer. TaskFragmentOrganizer may have requested relative
2115                         // bounds, so reset the relative bounds before update configuration.
2116                         tf.setRelativeEmbeddedBounds(new Rect());
2117                         tf.updateRequestedOverrideConfiguration(EMPTY);
2118                     }
2119                 });
2120             } else {
2121                 // In the case of multiple activities, we will create a new task for it and then
2122                 // move the PIP activity into the task. Note that we explicitly defer the task
2123                 // appear being sent in this case and mark this newly created task to been visible.
2124                 rootTask = new Task.Builder(mService)
2125                         .setActivityType(r.getActivityType())
2126                         .setOnTop(true)
2127                         .setActivityInfo(r.info)
2128                         .setParent(taskDisplayArea)
2129                         .setIntent(r.intent)
2130                         .setDeferTaskAppear(true)
2131                         .setHasBeenVisible(true)
2132                         // In case the activity is in system split screen, or Activity Embedding
2133                         // split, we need to animate the PIP Task from the original TaskFragment
2134                         // bounds, so also setting the windowing mode, otherwise the bounds may
2135                         // be reset to fullscreen.
2136                         .setWindowingMode(taskFragment.getWindowingMode())
2137                         .build();
2138                 // Establish bi-directional link between the original and pinned task.
2139                 r.setLastParentBeforePip(launchIntoPipHostActivity);
2140                 // It's possible the task entering PIP is in freeform, so save the last
2141                 // non-fullscreen bounds. Then when this new PIP task exits PIP, it can restore
2142                 // to its previous freeform bounds.
2143                 rootTask.setLastNonFullscreenBounds(task.mLastNonFullscreenBounds);
2144                 // When creating a new Task for PiP, set its initial bounds as the TaskFragment in
2145                 // case the activity is embedded, so that it can be animated to PiP window from the
2146                 // current bounds.
2147                 // Use Task#setBoundsUnchecked to skip checking windowing mode as the windowing mode
2148                 // will be updated later after this is collected in transition.
2149                 rootTask.setBoundsUnchecked(taskFragment.getBounds());
2150                 // The exit-PIP activity resumes early for seamless transition. In certain
2151                 // scenarios, this introduces unintended addition to recents. To address this,
2152                 // we mark the root task for automatic removal from recents. This ensures that
2153                 // after the pinned activity reparents to its original task, the root task is
2154                 // automatically removed from the recents list.
2155                 rootTask.autoRemoveRecents = true;
2156 
2157                 // Move the last recents animation transaction from original task to the new one.
2158                 if (task.mLastRecentsAnimationTransaction != null) {
2159                     rootTask.setLastRecentsAnimationTransaction(
2160                             task.mLastRecentsAnimationTransaction,
2161                             task.mLastRecentsAnimationOverlay);
2162                     task.clearLastRecentsAnimationTransaction(false /* forceRemoveOverlay */);
2163                 } else {
2164                     // Reset the original task surface
2165                     task.resetSurfaceControlTransforms();
2166                 }
2167 
2168                 // The organized TaskFragment is becoming empty because this activity is reparented
2169                 // to a new PIP Task. In this case, we should notify the organizer about why the
2170                 // TaskFragment becomes empty.
2171                 if (organizedTf != null && organizedTf.getNonFinishingActivityCount() == 1
2172                         && organizedTf.getTopNonFinishingActivity() == r) {
2173                     organizedTf.mClearedTaskFragmentForPip = true;
2174                 }
2175 
2176                 if (isPip2ExperimentEnabled()) {
2177                     transitionController.collectExistenceChange(rootTask);
2178                 } else {
2179                     transitionController.collect(rootTask);
2180                 }
2181 
2182                 if (transitionController.isShellTransitionsEnabled()) {
2183                     // set mode NOW so that when we reparent the activity, it won't be resumed.
2184                     // During recents animations, the original task is "occluded" by launcher but
2185                     // it wasn't paused (due to transient-launch). If we reparent to the (top) task
2186                     // now, it will take focus briefly which confuses the RecentTasks tracker.
2187                     rootTask.setRootTaskWindowingMode(WINDOWING_MODE_PINNED);
2188                 }
2189                 // Temporarily disable focus when reparenting to avoid intermediate focus change
2190                 // (because the task is on top and the activity is resumed), which could cause the
2191                 // task to be added in recents task list unexpectedly.
2192                 rootTask.setFocusable(false);
2193                 // There are multiple activities in the task and moving the top activity should
2194                 // reveal/leave the other activities in their original task.
2195                 // On the other hand, ActivityRecord#onParentChanged takes care of setting the
2196                 // up-to-dated root pinned task information on this newly created root task.
2197                 r.reparent(rootTask, MAX_VALUE, reason);
2198                 rootTask.setFocusable(true);
2199 
2200                 // Ensure the leash of new task is in sync with its current bounds after reparent.
2201                 rootTask.maybeApplyLastRecentsAnimationTransaction();
2202             }
2203 
2204             // TODO(remove-legacy-transit): Move this to the `singleActivity` case when removing
2205             //                              legacy transit.
2206             rootTask.setRootTaskWindowingMode(WINDOWING_MODE_PINNED);
2207             if (isPip2ExperimentEnabled() && bounds != null) {
2208                 // set the final pip bounds in advance if pip2 is enabled
2209                 rootTask.setBounds(bounds);
2210             }
2211 
2212             // Set the launch bounds for launch-into-pip Activity on the root task.
2213             if (r.getOptions() != null && r.getOptions().isLaunchIntoPip()) {
2214                 // Record the snapshot now, it will be later fetched for content-pip animation.
2215                 // We do this early in the process to make sure the right snapshot is used for
2216                 // entering content-pip animation.
2217                 mWindowManager.mTaskSnapshotController.recordSnapshot(task);
2218                 rootTask.setBounds(r.pictureInPictureArgs.getSourceRectHint());
2219             }
2220             rootTask.setDeferTaskAppear(false);
2221 
2222             if (!isPip2ExperimentEnabled()) {
2223                 // After setting this, it is not expected to change activity configuration until the
2224                 // transition animation is finished. So the activity can keep consistent appearance
2225                 // when animating.
2226                 r.mWaitForEnteringPinnedMode = true;
2227             }
2228             // Reset the state that indicates it can enter PiP while pausing after we've moved it
2229             // to the root pinned task
2230             r.supportsEnterPipOnTaskSwitch = false;
2231 
2232             if (organizedTf != null && organizedTf.mClearedTaskFragmentForPip
2233                     && organizedTf.isTaskVisibleRequested()) {
2234                 // Dispatch the pending info to TaskFragmentOrganizer before PIP animation.
2235                 // Otherwise, it will keep waiting for the empty TaskFragment to be non-empty.
2236                 mService.mTaskFragmentOrganizerController.dispatchPendingInfoChangedEvent(
2237                         organizedTf);
2238             }
2239         } finally {
2240             mService.continueWindowLayout();
2241             try {
2242                 if (localVisibilityDeferred) {
2243                     mTaskSupervisor.setDeferRootVisibilityUpdate(false);
2244                     ensureActivitiesVisible();
2245                 }
2246             } finally {
2247                 transitionController.continueTransitionReady();
2248                 pipChangesApplied.meet();
2249             }
2250         }
2251 
2252         // can be null (for now) if shell transitions are disabled or inactive at this time
2253         final Transition transit = transitionController.getCollectingTransition();
2254         if (requestStart && transit != null) {
2255             // Request at end since we want task-organizer events from ensureActivitiesVisible
2256             // to be recognized.
2257             transitionController.requestStartTransition(transit, rootTask,
2258                     null /* remoteTransition */, null /* displayChange */);
2259             // A new transition was created just for this operations. Since the operation is
2260             // complete, mark it as ready.
2261             transit.setReady(rootTask, true /* ready */);
2262         }
2263 
2264         resumeFocusedTasksTopActivities();
2265 
2266         notifyActivityPipModeChanged(r.getTask(), r);
2267 
2268         if (!isPip2ExperimentEnabled()) {
2269             // TODO: b/335866033 Remove the abort PiP on timeout once PiP2 flag is on.
2270             // Set up a timeout callback to potentially abort PiP enter if in an inconsistent state.
2271             scheduleTimeoutAbortPipEnter(rootTask);
2272         }
2273     }
2274 
scheduleTimeoutAbortPipEnter(Task rootTask)2275     private void scheduleTimeoutAbortPipEnter(Task rootTask) {
2276         if (mMaybeAbortPipEnterRunnable != null) {
2277             // If there is an abort enter PiP check pending already remove it and abort
2278             // immediately since we are trying to enter PiP in an inconsistent state
2279             mHandler.removeCallbacks(mMaybeAbortPipEnterRunnable);
2280             mMaybeAbortPipEnterRunnable.run();
2281         }
2282         // Snapshot a throwable early on to display the callstack upon abort later on timeout.
2283         final Throwable enterPipThrowable = new Throwable();
2284         // Set up a timeout to potentially roll back the task change to PINNED mode
2285         // by aborting PiP.
2286         mMaybeAbortPipEnterRunnable = new Runnable() {
2287             @Override
2288             public void run() {
2289                 synchronized (mService.mGlobalLock) {
2290                     if (mTransitionController.inTransition()) {
2291                         // If this task is a part an active transition aborting PiP might break
2292                         // it; so run the timeout callback directly once idle.
2293 
2294                         final Runnable expectedMaybeAbortAtTimeout = mMaybeAbortPipEnterRunnable;
2295                         mTransitionController.mStateValidators.add(() -> {
2296                             // If a second PiP transition comes in, it runs the abort runnable for
2297                             // the first transition pre-emptively, so we need to avoid calling
2298                             // the same runnable twice when validating states.
2299                             if (expectedMaybeAbortAtTimeout != mMaybeAbortPipEnterRunnable) return;
2300                             mMaybeAbortPipEnterRunnable = null;
2301                             run();
2302                         });
2303                         return;
2304                     } else {
2305                         mMaybeAbortPipEnterRunnable = null;
2306                     }
2307                     mService.deferWindowLayout();
2308                     final ActivityRecord top = rootTask.getTopMostActivity();
2309                     final ActivityManager.RunningTaskInfo beforeTaskInfo =
2310                             rootTask.getTaskInfo();
2311                     if (top != null && !top.inPinnedWindowingMode()
2312                             && rootTask.abortPipEnter(top)) {
2313                         Slog.wtf(TAG, "Enter PiP was aborted via a scheduled timeout"
2314                                         + "task_state_before=" + beforeTaskInfo
2315                                         + "task_state_after=" + rootTask.getTaskInfo(),
2316                                 enterPipThrowable);
2317                     }
2318                     mService.continueWindowLayout();
2319                 }
2320             }
2321         };
2322         mHandler.postDelayed(mMaybeAbortPipEnterRunnable, PINNED_TASK_ABORT_TIMEOUT);
2323         Slog.d(TAG, "a delayed check for potentially aborting PiP if "
2324                 + "in a wrong state is scheduled.");
2325     }
2326 
2327 
2328     /**
2329      * Notifies when an activity enters or leaves PIP mode.
2330      *
2331      * @param task the task of {@param r}
2332      * @param r indicates the activity currently in PIP, can be null to indicate no activity is
2333      *          currently in PIP mode.
2334      */
notifyActivityPipModeChanged(@onNull Task task, @Nullable ActivityRecord r)2335     void notifyActivityPipModeChanged(@NonNull Task task, @Nullable ActivityRecord r) {
2336         final boolean inPip = r != null;
2337         if (inPip) {
2338             mService.getTaskChangeNotificationController().notifyActivityPinned(r);
2339         } else {
2340             mService.getTaskChangeNotificationController().notifyActivityUnpinned();
2341         }
2342         mWindowManager.mPolicy.setPipVisibilityLw(inPip);
2343         if (task.getSurfaceControl() != null) {
2344             mWmService.mTransactionFactory.get()
2345                     .setTrustedOverlay(task.getSurfaceControl(), inPip)
2346                     .apply();
2347         }
2348     }
2349 
executeAppTransitionForAllDisplay()2350     void executeAppTransitionForAllDisplay() {
2351         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
2352             final DisplayContent display = getChildAt(displayNdx);
2353             display.mDisplayContent.executeAppTransition();
2354         }
2355     }
2356 
2357     @Nullable
findTask(ActivityRecord r, TaskDisplayArea preferredTaskDisplayArea, boolean includeLaunchedFromBubble)2358     ActivityRecord findTask(ActivityRecord r, TaskDisplayArea preferredTaskDisplayArea,
2359             boolean includeLaunchedFromBubble) {
2360         return findTask(r.getActivityType(), r.taskAffinity, r.intent, r.info,
2361                 preferredTaskDisplayArea, includeLaunchedFromBubble);
2362     }
2363 
2364     @Nullable
findTask(int activityType, String taskAffinity, Intent intent, ActivityInfo info, TaskDisplayArea preferredTaskDisplayArea, boolean includeLaunchedFromBubble)2365     ActivityRecord findTask(int activityType, String taskAffinity, Intent intent, ActivityInfo info,
2366             TaskDisplayArea preferredTaskDisplayArea, boolean includeLaunchedFromBubble) {
2367         ProtoLog.d(WM_DEBUG_TASKS, "Looking for task of type=%s, taskAffinity=%s, intent=%s"
2368                         + ", info=%s, preferredTDA=%s, includeLaunchedFromBubble=%b", activityType,
2369                 taskAffinity, intent, info, preferredTaskDisplayArea, includeLaunchedFromBubble);
2370         mTmpFindTaskResult.init(activityType, taskAffinity, intent, info,
2371                 includeLaunchedFromBubble);
2372 
2373         // Looking up task on preferred display area first
2374         ActivityRecord candidateActivity = null;
2375         if (preferredTaskDisplayArea != null) {
2376             mTmpFindTaskResult.process(preferredTaskDisplayArea);
2377             if (mTmpFindTaskResult.mIdealRecord != null) {
2378                 return mTmpFindTaskResult.mIdealRecord;
2379             } else if (mTmpFindTaskResult.mCandidateRecord != null) {
2380                 candidateActivity = mTmpFindTaskResult.mCandidateRecord;
2381             }
2382         }
2383 
2384         final ActivityRecord idealMatchActivity = getItemFromTaskDisplayAreas(taskDisplayArea -> {
2385             if (taskDisplayArea == preferredTaskDisplayArea) {
2386                 return null;
2387             }
2388 
2389             mTmpFindTaskResult.process(taskDisplayArea);
2390             if (mTmpFindTaskResult.mIdealRecord != null) {
2391                 return mTmpFindTaskResult.mIdealRecord;
2392             }
2393             return null;
2394         });
2395         if (idealMatchActivity != null) {
2396             return idealMatchActivity;
2397         }
2398 
2399         if (WM_DEBUG_TASKS.isEnabled() && candidateActivity == null) {
2400             ProtoLog.d(WM_DEBUG_TASKS, "No task found");
2401         }
2402         return candidateActivity;
2403     }
2404 
2405     /**
2406      * Finish the topmost activities in all leaf tasks that belong to the crashed app.
2407      *
2408      * @param app    The app that crashed.
2409      * @param reason Reason to perform this action.
2410      * @return The finished task which was on top or visible, otherwise {@code null} if the crashed
2411      *         app doesn't have activity in visible task.
2412      */
2413     @Nullable
finishTopCrashedActivities(WindowProcessController app, String reason)2414     Task finishTopCrashedActivities(WindowProcessController app, String reason) {
2415         Task focusedRootTask = getTopDisplayFocusedRootTask();
2416         final Task[] finishedTask = new Task[1];
2417         forAllLeafTasks(leafTask -> {
2418             final boolean recordTopOrVisible = finishedTask[0] == null
2419                     && (focusedRootTask == leafTask.getRootTask() || leafTask.isVisibleRequested());
2420             final Task t = leafTask.finishTopCrashedActivityLocked(app, reason);
2421             if (recordTopOrVisible) {
2422                 finishedTask[0] = t;
2423             }
2424         }, true);
2425         return finishedTask[0];
2426     }
2427 
ensureVisibilityOnVisibleActivityDiedOrCrashed(String reason)2428     void ensureVisibilityOnVisibleActivityDiedOrCrashed(String reason) {
2429         final Task topTask = getTopDisplayFocusedRootTask();
2430         if (topTask != null && topTask.topRunningActivity(true /* focusableOnly */) == null) {
2431             // Move the next focusable task to front.
2432             topTask.adjustFocusToNextFocusableTask(reason);
2433         }
2434         if (!resumeFocusedTasksTopActivities()) {
2435             // It may be nothing to resume because there are pausing activities or all the top
2436             // activities are resumed. Then it still needs to make sure all visible activities are
2437             // running in case the tasks were reordered or there are non-top visible activities.
2438             ensureActivitiesVisible();
2439         }
2440     }
2441 
resumeFocusedTasksTopActivities()2442     boolean resumeFocusedTasksTopActivities() {
2443         return resumeFocusedTasksTopActivities(null, null, null, false /* deferPause */);
2444     }
2445 
resumeFocusedTasksTopActivities( Task targetRootTask, ActivityRecord target)2446     boolean resumeFocusedTasksTopActivities(
2447             Task targetRootTask, ActivityRecord target) {
2448         return resumeFocusedTasksTopActivities(targetRootTask, target, null /* targetOptions */,
2449                 false /* deferPause */);
2450     }
2451 
resumeFocusedTasksTopActivities( Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions, boolean deferPause)2452     boolean resumeFocusedTasksTopActivities(
2453             Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,
2454             boolean deferPause) {
2455         if (!mTaskSupervisor.readyToResume()) {
2456             return false;
2457         }
2458 
2459         boolean result = false;
2460         if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
2461                 || getTopDisplayFocusedRootTask() == targetRootTask)) {
2462             result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,
2463                     deferPause);
2464         }
2465 
2466         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
2467             final DisplayContent display = getChildAt(displayNdx);
2468             final boolean curResult = result;
2469             boolean[] resumedOnDisplay = new boolean[1];
2470             final ActivityRecord topOfDisplay = display.topRunningActivity();
2471             display.forAllRootTasks(rootTask -> {
2472                 final ActivityRecord topRunningActivity = rootTask.topRunningActivity();
2473                 if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) {
2474                     return;
2475                 }
2476                 if (rootTask == targetRootTask) {
2477                     // Simply update the result for targetRootTask because the targetRootTask
2478                     // had already resumed in above. We don't want to resume it again,
2479                     // especially in some cases, it would cause a second launch failure
2480                     // if app process was dead.
2481                     resumedOnDisplay[0] |= curResult;
2482                     return;
2483                 }
2484                 if (topRunningActivity.isState(RESUMED) && topRunningActivity == topOfDisplay) {
2485                     // Kick off any lingering app transitions form the MoveTaskToFront operation,
2486                     // but only consider the top activity on that display.
2487                     rootTask.executeAppTransition(targetOptions);
2488                 } else {
2489                     resumedOnDisplay[0] |= topRunningActivity.makeActiveIfNeeded(target);
2490                 }
2491             });
2492             result |= resumedOnDisplay[0];
2493             if (!resumedOnDisplay[0]) {
2494                 // In cases when there are no valid activities (e.g. device just booted or launcher
2495                 // crashed) it's possible that nothing was resumed on a display. Requesting resume
2496                 // of top activity in focused root task explicitly will make sure that at least home
2497                 // activity is started and resumed, and no recursion occurs.
2498                 final Task focusedRoot = display.getFocusedRootTask();
2499                 if (focusedRoot != null) {
2500                     result |= focusedRoot.resumeTopActivityUncheckedLocked(
2501                             target, targetOptions, false /* skipPause */);
2502                 } else if (targetRootTask == null) {
2503                     result |= resumeHomeActivity(null /* prev */, "no-focusable-task",
2504                             display.getDefaultTaskDisplayArea());
2505                 }
2506             }
2507         }
2508 
2509         return result;
2510     }
2511 
sendSleepTransition(final DisplayContent display)2512     void sendSleepTransition(final DisplayContent display) {
2513         // We don't actually care about collecting anything here. We really just want
2514         // this as a signal to the transition-player.
2515         final Transition transition = new Transition(TRANSIT_SLEEP, 0 /* flags */,
2516                 display.mTransitionController, mWmService.mSyncEngine);
2517         final TransitionController.OnStartCollect sendSleepTransition = (deferred) -> {
2518             if (deferred && !display.shouldSleep()) {
2519                 transition.abort();
2520             } else {
2521                 display.mTransitionController.requestStartTransition(transition,
2522                         null /* trigger */, null /* remote */, null /* display */);
2523                 // Force playing immediately so that unrelated ops can't be collected.
2524                 transition.playNow();
2525             }
2526         };
2527         if (!display.mTransitionController.isCollecting()) {
2528             // Since this bypasses sync, submit directly ignoring whether sync-engine
2529             // is active.
2530             if (mWindowManager.mSyncEngine.hasActiveSync()) {
2531                 Slog.w(TAG, "Ongoing sync outside of a transition.");
2532             }
2533             display.mTransitionController.moveToCollecting(transition);
2534             sendSleepTransition.onCollectStarted(false /* deferred */);
2535         } else {
2536             display.mTransitionController.startCollectOrQueue(transition,
2537                     sendSleepTransition);
2538         }
2539     }
2540 
applySleepTokens(boolean applyToRootTasks)2541     void applySleepTokens(boolean applyToRootTasks) {
2542         boolean scheduledSleepTransition = false;
2543 
2544         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
2545             // Set the sleeping state of the display.
2546             final DisplayContent display = getChildAt(displayNdx);
2547             final boolean displayShouldSleep = display.shouldSleep();
2548             if (displayShouldSleep == display.isSleeping()) {
2549                 continue;
2550             }
2551             final boolean wasSleeping = display.isSleeping();
2552             display.setIsSleeping(displayShouldSleep);
2553 
2554             if (display.mTransitionController.isShellTransitionsEnabled()
2555                     && !scheduledSleepTransition
2556                     // Only care if there are actual sleep tokens.
2557                     && displayShouldSleep && !display.mAllSleepTokens.isEmpty()) {
2558                 scheduledSleepTransition = true;
2559 
2560                 if (!mHandler.hasMessages(MSG_SEND_SLEEP_TRANSITION)) {
2561                     mHandler.sendMessageDelayed(
2562                             mHandler.obtainMessage(MSG_SEND_SLEEP_TRANSITION, display),
2563                             SLEEP_TRANSITION_WAIT_MILLIS);
2564                 }
2565             }
2566 
2567             if (!applyToRootTasks) {
2568                 continue;
2569             }
2570 
2571             // Prepare transition before resume top activity, so it can be collected.
2572             if (!displayShouldSleep && display.mTransitionController.isShellTransitionsEnabled()
2573                     && !display.mTransitionController.isCollecting()) {
2574                 // Use NONE if keyguard is not showing.
2575                 int transit = TRANSIT_NONE;
2576                 Task startTask = null;
2577                 int flags = 0;
2578                 if (display.isKeyguardOccluded()) {
2579                     startTask = display.getTaskOccludingKeyguard();
2580                     flags = TRANSIT_FLAG_KEYGUARD_OCCLUDING;
2581                     transit = WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
2582                 }
2583                 if (wasSleeping) {
2584                     transit = TRANSIT_WAKE;
2585                 }
2586                 display.mTransitionController.requestStartTransition(
2587                         display.mTransitionController.createTransition(transit, flags),
2588                         startTask, null /* remoteTransition */, null /* displayChange */);
2589             }
2590             // Set the sleeping state of the root tasks on the display.
2591             display.forAllRootTasks(rootTask -> {
2592                 if (displayShouldSleep) {
2593                     rootTask.goToSleepIfPossible(false /* shuttingDown */);
2594                 } else {
2595                     rootTask.forAllLeafTasksAndLeafTaskFragments(
2596                             taskFragment -> taskFragment.awakeFromSleeping(),
2597                             true /* traverseTopToBottom */);
2598                     if (rootTask.isFocusedRootTaskOnDisplay()
2599                             && !mTaskSupervisor.getKeyguardController()
2600                             .isKeyguardOrAodShowing(display.mDisplayId)) {
2601                         // If the keyguard is unlocked - resume immediately.
2602                         // It is possible that the display will not be awake at the time we
2603                         // process the keyguard going away, which can happen before the sleep
2604                         // token is released. As a result, it is important we resume the
2605                         // activity here.
2606                         rootTask.resumeTopActivityUncheckedLocked();
2607                     }
2608                     // The visibility update must not be called before resuming the top, so the
2609                     // display orientation can be updated first if needed. Otherwise there may
2610                     // have redundant configuration changes due to apply outdated display
2611                     // orientation (from keyguard) to activity.
2612                     rootTask.ensureActivitiesVisible(null /* starting */);
2613                 }
2614             });
2615         }
2616 
2617         if (!scheduledSleepTransition) {
2618             mHandler.removeMessages(MSG_SEND_SLEEP_TRANSITION);
2619         }
2620     }
2621 
getRootTask(int rooTaskId)2622     protected Task getRootTask(int rooTaskId) {
2623         for (int i = getChildCount() - 1; i >= 0; --i) {
2624             final Task rootTask = getChildAt(i).getRootTask(rooTaskId);
2625             if (rootTask != null) {
2626                 return rootTask;
2627             }
2628         }
2629         return null;
2630     }
2631 
2632     /** @see DisplayContent#getRootTask(int, int) */
getRootTask(int windowingMode, int activityType)2633     Task getRootTask(int windowingMode, int activityType) {
2634         for (int i = getChildCount() - 1; i >= 0; --i) {
2635             final Task rootTask = getChildAt(i).getRootTask(windowingMode, activityType);
2636             if (rootTask != null) {
2637                 return rootTask;
2638             }
2639         }
2640         return null;
2641     }
2642 
getRootTask(int windowingMode, int activityType, int displayId)2643     private Task getRootTask(int windowingMode, int activityType,
2644             int displayId) {
2645         DisplayContent display = getDisplayContent(displayId);
2646         if (display == null) {
2647             return null;
2648         }
2649         return display.getRootTask(windowingMode, activityType);
2650     }
2651 
getRootTaskInfo(Task task)2652     private RootTaskInfo getRootTaskInfo(Task task) {
2653         RootTaskInfo info = new RootTaskInfo();
2654         task.fillTaskInfo(info);
2655 
2656         final DisplayContent displayContent = task.getDisplayContent();
2657         if (displayContent == null) {
2658             // A task might be not attached to a display.
2659             info.position = -1;
2660         } else {
2661             // Find the task z-order among all root tasks on the display from bottom to top.
2662             final int[] taskIndex = new int[1];
2663             final boolean[] hasFound = new boolean[1];
2664             displayContent.forAllRootTasks(rootTask -> {
2665                 if (task == rootTask) {
2666                     hasFound[0] = true;
2667                     return true;
2668                 }
2669                 taskIndex[0]++;
2670                 return false;
2671             }, false /* traverseTopToBottom */);
2672             info.position = hasFound[0] ? taskIndex[0] : -1;
2673         }
2674         info.visible = task.shouldBeVisible(null);
2675         task.getBounds(info.bounds);
2676 
2677         final int numTasks = task.getDescendantTaskCount();
2678         info.childTaskIds = new int[numTasks];
2679         info.childTaskNames = new String[numTasks];
2680         info.childTaskBounds = new Rect[numTasks];
2681         info.childTaskUserIds = new int[numTasks];
2682         final int[] currentIndex = {0};
2683 
2684         task.forAllLeafTasks(t -> {
2685             int i = currentIndex[0];
2686             info.childTaskIds[i] = t.mTaskId;
2687             info.childTaskNames[i] = t.origActivity != null ? t.origActivity.flattenToString()
2688                     : t.realActivity != null ? t.realActivity.flattenToString()
2689                     : t.getTopNonFinishingActivity() != null
2690                     ? t.getTopNonFinishingActivity().packageName : "unknown";
2691             info.childTaskBounds[i] = t.mAtmService.getTaskBounds(t.mTaskId);
2692             info.childTaskUserIds[i] = t.mUserId;
2693             currentIndex[0] = ++i;
2694         }, false /* traverseTopToBottom */);
2695 
2696         final ActivityRecord top = task.topRunningActivity();
2697         info.topActivity = top != null ? top.intent.getComponent() : null;
2698         return info;
2699     }
2700 
getRootTaskInfo(int taskId)2701     RootTaskInfo getRootTaskInfo(int taskId) {
2702         Task task = getRootTask(taskId);
2703         if (task != null) {
2704             return getRootTaskInfo(task);
2705         }
2706         return null;
2707     }
2708 
getRootTaskInfo(int windowingMode, int activityType)2709     RootTaskInfo getRootTaskInfo(int windowingMode, int activityType) {
2710         final Task rootTask = getRootTask(windowingMode, activityType);
2711         return (rootTask != null) ? getRootTaskInfo(rootTask) : null;
2712     }
2713 
getRootTaskInfo(int windowingMode, int activityType, int displayId)2714     RootTaskInfo getRootTaskInfo(int windowingMode, int activityType, int displayId) {
2715         final Task rootTask = getRootTask(windowingMode, activityType, displayId);
2716         return (rootTask != null) ? getRootTaskInfo(rootTask) : null;
2717     }
2718 
2719     /** If displayId == INVALID_DISPLAY, this will get root task infos on all displays */
getAllRootTaskInfos(int displayId)2720     ArrayList<RootTaskInfo> getAllRootTaskInfos(int displayId) {
2721         final ArrayList<RootTaskInfo> list = new ArrayList<>();
2722         if (displayId == INVALID_DISPLAY) {
2723             forAllRootTasks(rootTask -> {
2724                 list.add(getRootTaskInfo(rootTask));
2725             });
2726             return list;
2727         }
2728         final DisplayContent display = getDisplayContent(displayId);
2729         if (display == null) {
2730             return list;
2731         }
2732         display.forAllRootTasks(rootTask -> {
2733             list.add(getRootTaskInfo(rootTask));
2734         });
2735         return list;
2736     }
2737 
2738     @Override
onDisplayAdded(int displayId)2739     public void onDisplayAdded(int displayId) {
2740         if (DEBUG_ROOT_TASK) Slog.v(TAG, "Display added displayId=" + displayId);
2741         synchronized (mService.mGlobalLock) {
2742             final DisplayContent display = getDisplayContentOrCreate(displayId);
2743             if (display == null) {
2744                 return;
2745             }
2746 
2747             if (ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT.isTrue()) {
2748                 if (display.allowContentModeSwitch()) {
2749                     mWindowManager.mDisplayWindowSettings
2750                             .setShouldShowSystemDecorsInternalLocked(display,
2751                                     display.mDisplay.canHostTasks());
2752                 }
2753 
2754                 final boolean inTopology = mWindowManager.mDisplayWindowSettings
2755                         .shouldShowSystemDecorsLocked(display);
2756                 mWmService.mDisplayManagerInternal.onDisplayBelongToTopologyChanged(displayId,
2757                         inTopology);
2758             }
2759 
2760             startSystemDecorations(display, "displayAdded");
2761 
2762             // Drop any cached DisplayInfos associated with this display id - the values are now
2763             // out of date given this display added event.
2764             mWmService.mPossibleDisplayInfoMapper.removePossibleDisplayInfos(displayId);
2765         }
2766     }
2767 
startSystemDecorations(final DisplayContent displayContent, String reason)2768     void startSystemDecorations(final DisplayContent displayContent, String reason) {
2769         // Do not start home before booting, or it may accidentally finish booting before it
2770         // starts. Instead, we expect home activities to be launched when the system is ready
2771         // (ActivityManagerService#systemReady).
2772         if (!mService.isBooted() && !mService.isBooting()) {
2773             return;
2774         }
2775 
2776         startHomeOnDisplay(mCurrentUser, reason, displayContent.getDisplayId());
2777         displayContent.getDisplayPolicy().notifyDisplayAddSystemDecorations();
2778     }
2779 
2780     @Override
onDisplayRemoved(int displayId)2781     public void onDisplayRemoved(int displayId) {
2782         if (DEBUG_ROOT_TASK) Slog.v(TAG, "Display removed displayId=" + displayId);
2783         if (displayId == DEFAULT_DISPLAY) {
2784             throw new IllegalArgumentException("Can't remove the primary display.");
2785         }
2786 
2787         synchronized (mService.mGlobalLock) {
2788             final DisplayContent displayContent = getDisplayContent(displayId);
2789             if (displayContent == null) {
2790                 return;
2791             }
2792             displayContent.remove();
2793             mWmService.mPossibleDisplayInfoMapper.removePossibleDisplayInfos(displayId);
2794         }
2795     }
2796 
2797     @Override
onDisplayChanged(int displayId)2798     public void onDisplayChanged(int displayId) {
2799         if (DEBUG_ROOT_TASK) Slog.v(TAG, "Display changed displayId=" + displayId);
2800         synchronized (mService.mGlobalLock) {
2801             final DisplayContent displayContent = getDisplayContent(displayId);
2802             if (displayContent != null) {
2803                 displayContent.requestDisplayUpdate(
2804                         () -> {
2805                             clearDisplayInfoCaches(displayId);
2806                             if (ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT.isTrue()) {
2807                                 displayContent.onDisplayInfoChangeApplied();
2808                             }
2809                         });
2810             } else {
2811                 clearDisplayInfoCaches(displayId);
2812             }
2813         }
2814     }
2815 
clearDisplayInfoCaches(int displayId)2816     private void clearDisplayInfoCaches(int displayId) {
2817         // Drop any cached DisplayInfos associated with this display id - the values are now
2818         // out of date given this display changed event.
2819         mWmService.mPossibleDisplayInfoMapper.removePossibleDisplayInfos(displayId);
2820         updateDisplayImePolicyCache();
2821     }
2822 
updateDisplayImePolicyCache()2823     void updateDisplayImePolicyCache() {
2824         ArrayMap<Integer, Integer> displayImePolicyMap = new ArrayMap<>();
2825         forAllDisplays(dc -> displayImePolicyMap.put(dc.getDisplayId(), dc.getImePolicy()));
2826         mWmService.mDisplayImePolicyCache = Collections.unmodifiableMap(displayImePolicyMap);
2827     }
2828 
2829     /** Update lists of UIDs that are present on displays and have access to them. */
updateUIDsPresentOnDisplay()2830     void updateUIDsPresentOnDisplay() {
2831         mDisplayAccessUIDs.clear();
2832         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
2833             final DisplayContent displayContent = getChildAt(displayNdx);
2834             // Only bother calculating the allowlist for private displays
2835             if (displayContent.isPrivate()) {
2836                 mDisplayAccessUIDs.append(
2837                         displayContent.mDisplayId, displayContent.getPresentUIDs());
2838             }
2839         }
2840         // Store updated lists in DisplayManager. Callers from outside of AM should get them there.
2841         mDisplayManagerInternal.setDisplayAccessUIDs(mDisplayAccessUIDs);
2842     }
2843 
prepareForShutdown()2844     void prepareForShutdown() {
2845         for (int i = 0; i < getChildCount(); i++) {
2846             createSleepToken("shutdown", getChildAt(i).mDisplayId);
2847         }
2848     }
2849 
createSleepToken(String tag, int displayId)2850     SleepToken createSleepToken(String tag, int displayId) {
2851         final DisplayContent display = getDisplayContent(displayId);
2852         if (display == null) {
2853             throw new IllegalArgumentException("Invalid display: " + displayId);
2854         }
2855 
2856         final int tokenKey = makeSleepTokenKey(tag, displayId);
2857         SleepToken token = mSleepTokens.get(tokenKey);
2858         if (token == null) {
2859             token = new SleepToken(tag, displayId);
2860             mSleepTokens.put(tokenKey, token);
2861             display.mAllSleepTokens.add(token);
2862             ProtoLog.d(WM_DEBUG_SLEEP_TOKEN, "Create SleepToken: tag=%s, displayId=%d",
2863                     tag, displayId);
2864         } else {
2865             throw new RuntimeException("Create the same sleep token twice: " + token);
2866         }
2867         return token;
2868     }
2869 
removeSleepToken(SleepToken token)2870     void removeSleepToken(SleepToken token) {
2871         if (!mSleepTokens.contains(token.mHashKey)) {
2872             Slog.d(TAG, "Remove non-exist sleep token: " + token + " from " + Debug.getCallers(6));
2873         }
2874         mSleepTokens.remove(token.mHashKey);
2875         final DisplayContent display = getDisplayContent(token.mDisplayId);
2876         if (display == null) {
2877             Slog.d(TAG, "Remove sleep token for non-existing display: " + token + " from "
2878                     + Debug.getCallers(6));
2879             return;
2880         }
2881 
2882         ProtoLog.d(WM_DEBUG_SLEEP_TOKEN, "Remove SleepToken: tag=%s, displayId=%d",
2883                 token.mTag, token.mDisplayId);
2884         display.mAllSleepTokens.remove(token);
2885         if (display.mAllSleepTokens.isEmpty()) {
2886             mService.updateSleepIfNeededLocked();
2887         }
2888     }
2889 
addStartingWindowsForVisibleActivities()2890     void addStartingWindowsForVisibleActivities() {
2891         final ArrayList<Task> addedTasks = new ArrayList<>();
2892         forAllActivities((r) -> {
2893             final Task task = r.getTask();
2894             if (r.isVisibleRequested() && r.mStartingData == null && !addedTasks.contains(task)) {
2895                 r.showStartingWindow(true /*taskSwitch*/);
2896                 addedTasks.add(task);
2897             }
2898         });
2899     }
2900 
invalidateTaskLayersAndUpdateOomAdjIfNeeded()2901     void invalidateTaskLayersAndUpdateOomAdjIfNeeded() {
2902         mRankTaskLayersRunnable.mCheckUpdateOomAdj = true;
2903         invalidateTaskLayers();
2904     }
2905 
invalidateTaskLayers()2906     void invalidateTaskLayers() {
2907         if (!mTaskLayersChanged) {
2908             mTaskLayersChanged = true;
2909             mService.mH.post(mRankTaskLayersRunnable);
2910         }
2911     }
2912 
2913     /** Generate oom-score-adjustment rank for all tasks in the system based on z-order. */
rankTaskLayers()2914     void rankTaskLayers() {
2915         if (mTaskLayersChanged) {
2916             mTaskLayersChanged = false;
2917             mService.mH.removeCallbacks(mRankTaskLayersRunnable);
2918         }
2919         mTmpTaskLayerRank = 0;
2920         // Only rank for leaf tasks because the score of activity is based on immediate parent.
2921         forAllLeafTasks(task -> {
2922             final int oldRank = task.mLayerRank;
2923             final int oldRatio = task.mNonOccludedFreeformAreaRatio;
2924             task.mNonOccludedFreeformAreaRatio = 0;
2925             if (task.isVisibleRequested()) {
2926                 task.mLayerRank = ++mTmpTaskLayerRank;
2927                 if (task.inFreeformWindowingMode()) {
2928                     computeNonOccludedFreeformAreaRatio(task);
2929                 }
2930             } else {
2931                 task.mLayerRank = Task.LAYER_RANK_INVISIBLE;
2932             }
2933             if (task.mLayerRank != oldRank
2934                     || task.mNonOccludedFreeformAreaRatio != oldRatio) {
2935                 task.forAllActivities(activity -> {
2936                     if (activity.hasProcess()) {
2937                         mTaskSupervisor.onProcessActivityStateChanged(activity.app,
2938                                 true /* forceBatch */);
2939                     }
2940                 });
2941             }
2942         }, true /* traverseTopToBottom */);
2943         if (mTmpOccludingRegion != null) {
2944             mTmpOccludingRegion.setEmpty();
2945         }
2946         boolean changed = false;
2947         if (!mTaskSupervisor.inActivityVisibilityUpdate()) {
2948             changed = mTaskSupervisor.computeProcessActivityStateBatch();
2949         }
2950         if (mRankTaskLayersRunnable.mCheckUpdateOomAdj) {
2951             mRankTaskLayersRunnable.mCheckUpdateOomAdj = false;
2952             if (changed) {
2953                 mService.updateOomAdj();
2954             }
2955         }
2956     }
2957 
2958     /** This method is called for visible freeform task from top to bottom. */
computeNonOccludedFreeformAreaRatio(@onNull Task task)2959     private void computeNonOccludedFreeformAreaRatio(@NonNull Task task) {
2960         if (!com.android.window.flags.Flags.processPriorityPolicyForMultiWindowMode()) {
2961             return;
2962         }
2963         if (mTmpOccludingRegion == null) {
2964             mTmpOccludingRegion = new Region();
2965             mTmpTaskRegion = new Region();
2966         }
2967         final Rect taskBounds = task.getBounds();
2968         mTmpTaskRegion.set(taskBounds);
2969         // Exclude the area outside the display.
2970         mTmpTaskRegion.op(task.mDisplayContent.getBounds(), Region.Op.INTERSECT);
2971         // Exclude the area covered by the above tasks.
2972         mTmpTaskRegion.op(mTmpOccludingRegion, Region.Op.DIFFERENCE);
2973         task.mNonOccludedFreeformAreaRatio = 100 * RegionUtils.getAreaSize(mTmpTaskRegion)
2974                         / (taskBounds.width() * taskBounds.height());
2975         // Accumulate the occluding region for other visible tasks behind.
2976         mTmpOccludingRegion.op(taskBounds, Region.Op.UNION);
2977     }
2978 
clearOtherAppTimeTrackers(AppTimeTracker except)2979     void clearOtherAppTimeTrackers(AppTimeTracker except) {
2980         forAllActivities(r -> {
2981             if (r.appTimeTracker != except) {
2982                 r.appTimeTracker = null;
2983             }
2984         });
2985     }
2986 
scheduleDestroyAllActivities(String reason)2987     void scheduleDestroyAllActivities(String reason) {
2988         mDestroyAllActivitiesReason = reason;
2989         mService.mH.post(mDestroyAllActivitiesRunnable);
2990     }
2991 
removeAllMaybeAbortPipEnterRunnable()2992     void removeAllMaybeAbortPipEnterRunnable() {
2993         if (mMaybeAbortPipEnterRunnable == null) {
2994             return;
2995         }
2996         mHandler.removeCallbacks(mMaybeAbortPipEnterRunnable);
2997         mMaybeAbortPipEnterRunnable = null;
2998     }
2999 
3000     // Tries to put all activity tasks to sleep. Returns true if all tasks were
3001     // successfully put to sleep.
putTasksToSleep(boolean allowDelay, boolean shuttingDown)3002     boolean putTasksToSleep(boolean allowDelay, boolean shuttingDown) {
3003         final boolean[] result = {true};
3004         forAllRootTasks(task -> {
3005             if (allowDelay) {
3006                 result[0] &= task.goToSleepIfPossible(shuttingDown);
3007             } else {
3008                 task.ensureActivitiesVisible(null /* starting */);
3009             }
3010         });
3011         return result[0];
3012     }
3013 
findActivity(Intent intent, ActivityInfo info, boolean compareIntentFilters)3014     ActivityRecord findActivity(Intent intent, ActivityInfo info, boolean compareIntentFilters) {
3015         ComponentName cls = intent.getComponent();
3016         if (info.targetActivity != null) {
3017             cls = new ComponentName(info.packageName, info.targetActivity);
3018         }
3019         final int userId = UserHandle.getUserId(info.applicationInfo.uid);
3020 
3021         final PooledPredicate p = PooledLambda.obtainPredicate(
3022                 RootWindowContainer::matchesActivity, PooledLambda.__(ActivityRecord.class),
3023                 userId, compareIntentFilters, intent, cls);
3024         final ActivityRecord r = getActivity(p);
3025         p.recycle();
3026         return r;
3027     }
3028 
matchesActivity(ActivityRecord r, int userId, boolean compareIntentFilters, Intent intent, ComponentName cls)3029     private static boolean matchesActivity(ActivityRecord r, int userId,
3030             boolean compareIntentFilters, Intent intent, ComponentName cls) {
3031         if (!r.canBeTopRunning() || r.mUserId != userId) return false;
3032 
3033         if (compareIntentFilters) {
3034             if (r.intent.filterEquals(intent)) {
3035                 return true;
3036             }
3037         } else {
3038             // Compare the target component instead of intent component so we don't miss if the
3039             // activity uses alias.
3040             if (r.mActivityComponent.equals(cls)) {
3041                 return true;
3042             }
3043         }
3044         return false;
3045     }
3046 
hasAwakeDisplay()3047     boolean hasAwakeDisplay() {
3048         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
3049             final DisplayContent display = getChildAt(displayNdx);
3050             if (!display.shouldSleep()) {
3051                 return true;
3052             }
3053         }
3054         return false;
3055     }
3056 
getOrCreateRootTask(@ullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable Task candidateTask, boolean onTop)3057     Task getOrCreateRootTask(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
3058             @Nullable Task candidateTask, boolean onTop) {
3059         return getOrCreateRootTask(r, options, candidateTask, null /* sourceTask */, onTop,
3060                 null /* launchParams */, 0 /* launchFlags */);
3061     }
3062 
3063     /**
3064      * Returns the right root task to use for launching factoring in all the input parameters.
3065      *
3066      * @param r              The activity we are trying to launch. Can be null.
3067      * @param options        The activity options used to the launch. Can be null.
3068      * @param candidateTask  The possible task the activity might be launched in. Can be null.
3069      * @param sourceTask     The task requesting to start activity. Can be null.
3070      * @param launchParams   The resolved launch params to use.
3071      * @param launchFlags    The launch flags for this launch.
3072      * @param realCallingPid The pid from {@link ActivityStarter#setRealCallingPid}
3073      * @param realCallingUid The uid from {@link ActivityStarter#setRealCallingUid}
3074      * @return The root task to use for the launch.
3075      */
getOrCreateRootTask(@ullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable Task candidateTask, @Nullable Task sourceTask, boolean onTop, @Nullable LaunchParamsController.LaunchParams launchParams, int launchFlags)3076     Task getOrCreateRootTask(@Nullable ActivityRecord r,
3077             @Nullable ActivityOptions options, @Nullable Task candidateTask,
3078             @Nullable Task sourceTask, boolean onTop,
3079             @Nullable LaunchParamsController.LaunchParams launchParams, int launchFlags) {
3080         // First preference goes to the launch root task set in the activity options.
3081         if (options != null) {
3082             final Task candidateRoot = Task.fromWindowContainerToken(options.getLaunchRootTask());
3083             if (candidateRoot != null && canLaunchOnDisplay(r, candidateRoot)) {
3084                 return candidateRoot;
3085             }
3086         }
3087 
3088         // Next preference goes to the task id set in the activity options.
3089         if (options != null) {
3090             final int candidateTaskId = options.getLaunchTaskId();
3091             if (candidateTaskId != INVALID_TASK_ID) {
3092                 // Temporarily set the task id to invalid in case in re-entry.
3093                 options.setLaunchTaskId(INVALID_TASK_ID);
3094                 final Task task = anyTaskForId(candidateTaskId,
3095                         MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE, options, onTop);
3096                 options.setLaunchTaskId(candidateTaskId);
3097                 if (canLaunchOnDisplay(r, task)) {
3098                     return task.getRootTask();
3099                 }
3100             }
3101         }
3102 
3103         // Next preference goes to the TaskDisplayArea candidate from launchParams
3104         // or activity options.
3105         TaskDisplayArea taskDisplayArea = null;
3106         if (launchParams != null && launchParams.mPreferredTaskDisplayArea != null) {
3107             taskDisplayArea = launchParams.mPreferredTaskDisplayArea;
3108         } else if (options != null) {
3109             final WindowContainerToken daToken = options.getLaunchTaskDisplayArea();
3110             taskDisplayArea = daToken != null
3111                     ? (TaskDisplayArea) WindowContainer.fromBinder(daToken.asBinder()) : null;
3112             if (taskDisplayArea == null) {
3113                 final int launchDisplayId = options.getLaunchDisplayId();
3114                 if (launchDisplayId != INVALID_DISPLAY) {
3115                     final DisplayContent displayContent = getDisplayContent(launchDisplayId);
3116                     if (displayContent != null) {
3117                         taskDisplayArea = displayContent.getDefaultTaskDisplayArea();
3118                     }
3119                 }
3120             }
3121         }
3122 
3123         final int activityType = resolveActivityType(r, options, candidateTask);
3124         if (taskDisplayArea != null) {
3125             if (canLaunchOnDisplay(r, taskDisplayArea.getDisplayId())) {
3126                 return taskDisplayArea.getOrCreateRootTask(r, options, candidateTask,
3127                         sourceTask, launchParams, launchFlags, activityType, onTop);
3128             } else {
3129                 taskDisplayArea = null;
3130             }
3131         }
3132 
3133         // Give preference to the root task and display of the input task and activity if they
3134         // match the mode we want to launch into.
3135         Task rootTask = null;
3136         if (candidateTask != null) {
3137             rootTask = candidateTask.getRootTask();
3138         }
3139         if (rootTask == null && r != null) {
3140             rootTask = r.getRootTask();
3141         }
3142         int windowingMode = launchParams != null ? launchParams.mWindowingMode
3143                 : WindowConfiguration.WINDOWING_MODE_UNDEFINED;
3144         if (rootTask != null) {
3145             taskDisplayArea = rootTask.getDisplayArea();
3146             if (taskDisplayArea != null
3147                     && canLaunchOnDisplay(r, taskDisplayArea.mDisplayContent.mDisplayId)) {
3148                 if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
3149                     windowingMode = taskDisplayArea.resolveWindowingMode(r, options, candidateTask);
3150                 }
3151                 // Always allow organized tasks that created by organizer since the activity type
3152                 // of an organized task is decided by the activity type of its top child, which
3153                 // could be incompatible with the given windowing mode and activity type.
3154                 if (rootTask.isCompatible(windowingMode, activityType)
3155                         || rootTask.mCreatedByOrganizer) {
3156                     return rootTask;
3157                 }
3158             } else {
3159                 taskDisplayArea = null;
3160             }
3161 
3162         }
3163 
3164         // Falling back to default task container
3165         if (taskDisplayArea == null) {
3166             taskDisplayArea = getDefaultTaskDisplayArea();
3167         }
3168         return taskDisplayArea.getOrCreateRootTask(r, options, candidateTask, sourceTask,
3169                 launchParams, launchFlags, activityType, onTop);
3170     }
3171 
canLaunchOnDisplay(ActivityRecord r, Task task)3172     private boolean canLaunchOnDisplay(ActivityRecord r, Task task) {
3173         if (task == null) {
3174             Slog.w(TAG, "canLaunchOnDisplay(), invalid task: " + task);
3175             return false;
3176         }
3177 
3178         if (!task.isAttached()) {
3179             Slog.w(TAG, "canLaunchOnDisplay(), Task is not attached: " + task);
3180             return false;
3181         }
3182 
3183         return canLaunchOnDisplay(r, task.getTaskDisplayArea().getDisplayId());
3184     }
3185 
3186     /** @return true if activity record is null or can be launched on provided display. */
canLaunchOnDisplay(ActivityRecord r, int displayId)3187     private boolean canLaunchOnDisplay(ActivityRecord r, int displayId) {
3188         if (r == null) {
3189             return true;
3190         }
3191         if (!r.canBeLaunchedOnDisplay(displayId)) {
3192             Slog.w(TAG, "Not allow to launch " + r + " on display " + displayId);
3193             return false;
3194         }
3195         return true;
3196     }
3197 
resolveActivityType(@ullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable Task task)3198     int resolveActivityType(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
3199             @Nullable Task task) {
3200         // Preference is given to the activity type for the activity then the task since the type
3201         // once set shouldn't change.
3202         int activityType = r != null ? r.getActivityType() : ACTIVITY_TYPE_UNDEFINED;
3203         if (activityType == ACTIVITY_TYPE_UNDEFINED && task != null) {
3204             activityType = task.getActivityType();
3205         }
3206         if (activityType != ACTIVITY_TYPE_UNDEFINED) {
3207             return activityType;
3208         }
3209         if (options != null) {
3210             activityType = options.getLaunchActivityType();
3211         }
3212         return activityType != ACTIVITY_TYPE_UNDEFINED ? activityType : ACTIVITY_TYPE_STANDARD;
3213     }
3214 
3215     /**
3216      * Get next focusable root task in the system. This will search through the root task on the
3217      * same display as the current focused root task, looking for a focusable and visible root task,
3218      * different from the target root task. If no valid candidates will be found, it will then go
3219      * through all displays and root tasks in last-focused order.
3220      *
3221      * @param currentFocus  The root task that previously had focus.
3222      * @param ignoreCurrent If we should ignore {@param currentFocus} when searching for next
3223      *                      candidate.
3224      * @return Next focusable {@link Task}, {@code null} if not found.
3225      */
getNextFocusableRootTask(@onNull Task currentFocus, boolean ignoreCurrent)3226     Task getNextFocusableRootTask(@NonNull Task currentFocus, boolean ignoreCurrent) {
3227         // First look for next focusable root task on the same display
3228         TaskDisplayArea preferredDisplayArea = currentFocus.getDisplayArea();
3229         if (preferredDisplayArea == null) {
3230             // Root task is currently detached because it is being removed. Use the previous
3231             // display it was on.
3232             preferredDisplayArea = getDisplayContent(currentFocus.mPrevDisplayId)
3233                     .getDefaultTaskDisplayArea();
3234         }
3235         final Task preferredFocusableRootTask = preferredDisplayArea.getNextFocusableRootTask(
3236                 currentFocus, ignoreCurrent);
3237         if (preferredFocusableRootTask != null) {
3238             return preferredFocusableRootTask;
3239         }
3240 
3241         if (preferredDisplayArea.mDisplayContent.isHomeSupported()) {
3242             // Stop looking for focusable root task on other displays because the preferred display
3243             // supports home. Home activity would be launched on the same display if no focusable
3244             // root task found.
3245             return null;
3246         }
3247 
3248         // Now look through all displays
3249         for (int i = getChildCount() - 1; i >= 0; --i) {
3250             final DisplayContent display = getChildAt(i);
3251             if (display == preferredDisplayArea.mDisplayContent) {
3252                 // We've already checked this one
3253                 continue;
3254             }
3255             final Task nextFocusableRootTask = display.getDefaultTaskDisplayArea()
3256                     .getNextFocusableRootTask(currentFocus, ignoreCurrent);
3257             if (nextFocusableRootTask != null) {
3258                 return nextFocusableRootTask;
3259             }
3260         }
3261 
3262         return null;
3263     }
3264 
closeSystemDialogActivities(String reason)3265     void closeSystemDialogActivities(String reason) {
3266         forAllActivities((r) -> {
3267             if ((r.info.flags & ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0
3268                     || shouldCloseAssistant(r, reason)) {
3269                 r.finishIfPossible(reason, true /* oomAdj */);
3270             }
3271         });
3272     }
3273 
3274     /**
3275      * Returns {@code true} if {@code uid} has a visible window that's above the window of type
3276      * {@link WindowManager.LayoutParams#TYPE_NOTIFICATION_SHADE} and {@code uid} is not owner of
3277      * the window of type {@link WindowManager.LayoutParams#TYPE_NOTIFICATION_SHADE}.
3278      *
3279      * If there is no window with type {@link WindowManager.LayoutParams#TYPE_NOTIFICATION_SHADE},
3280      * it returns {@code false}.
3281      */
hasVisibleWindowAboveButDoesNotOwnNotificationShade(int uid)3282     boolean hasVisibleWindowAboveButDoesNotOwnNotificationShade(int uid) {
3283         boolean[] visibleWindowFound = {false};
3284         // We only return true if we found the notification shade (ie. window of type
3285         // TYPE_NOTIFICATION_SHADE). Usually, it should always be there, but if for some reason
3286         // it isn't, we should better be on the safe side and return false for this.
3287         return forAllWindows(w -> {
3288             if (w.mOwnerUid == uid && w.isVisible()) {
3289                 visibleWindowFound[0] = true;
3290             }
3291             if (w.mAttrs.type == TYPE_NOTIFICATION_SHADE) {
3292                 return visibleWindowFound[0] && w.mOwnerUid != uid;
3293             }
3294             return false;
3295         }, true /* traverseTopToBottom */);
3296     }
3297 
3298     private boolean shouldCloseAssistant(ActivityRecord r, String reason) {
3299         if (!r.isActivityTypeAssistant()) return false;
3300         if (reason == SYSTEM_DIALOG_REASON_ASSIST) return false;
3301         // When the assistant is configured to be on top of the dream, it will have higher z-order
3302         // than other activities. If it is also opaque, it will prevent other activities from
3303         // starting. We want to close the assistant on closeSystemDialogs to allow other activities
3304         // to start, e.g. on home button press.
3305         return mWmService.mAssistantOnTopOfDream;
3306     }
3307 
3308     FinishDisabledPackageActivitiesHelper mFinishDisabledPackageActivitiesHelper =
3309             new FinishDisabledPackageActivitiesHelper();
3310 
3311     class FinishDisabledPackageActivitiesHelper implements Predicate<ActivityRecord> {
3312         private String mPackageName;
3313         private Set<String> mFilterByClasses;
3314         private boolean mDoit;
3315         private boolean mEvenPersistent;
3316         private int mUserId;
3317         private boolean mOnlyRemoveNoProcess;
3318         private Task mLastTask;
3319         private final ArrayList<ActivityRecord> mCollectedActivities = new ArrayList<>();
3320 
3321         private void reset(String packageName, Set<String> filterByClasses,
3322                 boolean doit, boolean evenPersistent, int userId, boolean onlyRemoveNoProcess) {
3323             mPackageName = packageName;
3324             mFilterByClasses = filterByClasses;
3325             mDoit = doit;
3326             mEvenPersistent = evenPersistent;
3327             mUserId = userId;
3328             mOnlyRemoveNoProcess = onlyRemoveNoProcess;
3329             mLastTask = null;
3330         }
3331 
3332         boolean process(String packageName, Set<String> filterByClasses,
3333                 boolean doit, boolean evenPersistent, int userId, boolean onlyRemoveNoProcess) {
3334             reset(packageName, filterByClasses, doit, evenPersistent, userId, onlyRemoveNoProcess);
3335             forAllActivities(this);
3336 
3337             boolean didSomething = false;
3338             final int size = mCollectedActivities.size();
3339             // Keep the finishing order from top to bottom.
3340             for (int i = 0; i < size; i++) {
3341                 final ActivityRecord r = mCollectedActivities.get(i);
3342                 if (mOnlyRemoveNoProcess) {
3343                     if (!r.hasProcess()) {
3344                         didSomething = true;
3345                         Slog.i(TAG, "  Force removing " + r);
3346                         r.cleanUp(false /* cleanServices */, false /* setState */);
3347                         r.removeFromHistory("force-stop");
3348                     }
3349                 } else {
3350                     didSomething = true;
3351                     Slog.i(TAG, "  Force finishing " + r);
3352                     r.finishIfPossible("force-stop", true /* oomAdj */);
3353                 }
3354             }
3355             mCollectedActivities.clear();
3356 
3357             return didSomething;
3358         }
3359 
3360         @Override
3361         public boolean test(ActivityRecord r) {
3362             final boolean sameComponent =
3363                     (r.packageName.equals(mPackageName) && (mFilterByClasses == null
3364                             || mFilterByClasses.contains(r.mActivityComponent.getClassName())))
3365                             || (mPackageName == null && r.mUserId == mUserId);
3366             final boolean noProcess = !r.hasProcess();
3367             if ((mUserId == UserHandle.USER_ALL || r.mUserId == mUserId)
3368                     && (sameComponent || r.getTask() == mLastTask)
3369                     && (noProcess || mEvenPersistent || !r.app.isPersistent())) {
3370                 if (!mDoit) {
3371                     if (r.finishing) {
3372                         // If this activity is just finishing, then it is not
3373                         // interesting as far as something to stop.
3374                         return false;
3375                     }
3376                     return true;
3377                 }
3378                 mCollectedActivities.add(r);
3379                 mLastTask = r.getTask();
3380             }
3381 
3382             return false;
3383         }
3384     }
3385 
3386     /** @return true if some activity was finished (or would have finished if doit were true). */
3387     boolean finishDisabledPackageActivities(String packageName, Set<String> filterByClasses,
3388             boolean doit, boolean evenPersistent, int userId, boolean onlyRemoveNoProcess) {
3389         return mFinishDisabledPackageActivitiesHelper.process(packageName, filterByClasses, doit,
3390                 evenPersistent, userId, onlyRemoveNoProcess);
3391     }
3392 
3393     void updateActivityApplicationInfo(ApplicationInfo aInfo) {
3394         final String packageName = aInfo.packageName;
3395         final int userId = UserHandle.getUserId(aInfo.uid);
3396         forAllActivities(r -> {
3397             if (r.mUserId == userId && packageName.equals(r.packageName)) {
3398                 r.updateApplicationInfo(aInfo);
3399             }
3400         });
3401     }
3402 
3403     void updateActivityApplicationInfo(int userId,
3404             ArrayMap<String, ApplicationInfo> applicationInfoByPackage) {
3405         forAllActivities(r -> {
3406             if (r.mUserId != userId) {
3407                 return;
3408             }
3409 
3410             final ApplicationInfo aInfo = applicationInfoByPackage.get(r.packageName);
3411             if (aInfo != null) {
3412                 r.updateApplicationInfo(aInfo);
3413             }
3414         });
3415     }
3416 
3417     void finishVoiceTask(IVoiceInteractionSession session) {
3418         final IBinder binder = session.asBinder();
3419         forAllLeafTasks(t -> t.finishIfVoiceTask(binder), true /* traverseTopToBottom */);
3420     }
3421 
3422     /**
3423      * Removes root tasks in the input windowing modes from the system if they are of activity type
3424      * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
3425      */
3426     void removeRootTasksInWindowingModes(int... windowingModes) {
3427         for (int i = getChildCount() - 1; i >= 0; --i) {
3428             getChildAt(i).removeRootTasksInWindowingModes(windowingModes);
3429         }
3430     }
3431 
3432     void removeRootTasksWithActivityTypes(int... activityTypes) {
3433         for (int i = getChildCount() - 1; i >= 0; --i) {
3434             getChildAt(i).removeRootTasksWithActivityTypes(activityTypes);
3435         }
3436     }
3437 
3438     ActivityRecord topRunningActivity() {
3439         for (int i = getChildCount() - 1; i >= 0; --i) {
3440             final ActivityRecord topActivity = getChildAt(i).topRunningActivity();
3441             if (topActivity != null) {
3442                 return topActivity;
3443             }
3444         }
3445         return null;
3446     }
3447 
3448     /** Returns the top direct activity if it should be idle but has not yet been reported. */
3449     @Nullable
3450     private static ActivityRecord getNotYetIdleActivity(@NonNull TaskFragment visibleTf) {
3451         for (int i = visibleTf.getChildCount() - 1; i >= 0; i--) {
3452             final ActivityRecord r = visibleTf.getChildAt(i).asActivityRecord();
3453             if (r == null || r.finishing) {
3454                 continue;
3455             }
3456             if (!r.idle && (r.isState(RESUMED)
3457                     // Its process is not attached yet and it may resume later.
3458                     || (r.app == null && r.isFocusable()))) {
3459                 return r;
3460             }
3461             // Only check the top running activity.
3462             break;
3463         }
3464         return null;
3465     }
3466 
3467     boolean allResumedActivitiesIdle() {
3468         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
3469             final DisplayContent display = getChildAt(displayNdx);
3470             if (display.isSleeping()) {
3471                 // No resumed activities while display is sleeping.
3472                 continue;
3473             }
3474 
3475             final boolean foundNotIdle = display.forAllLeafTasks(task -> {
3476                 if (!task.isVisibleRequested()) {
3477                     return false;
3478                 }
3479                 final ActivityRecord notIdle = getNotYetIdleActivity(task);
3480                 if (notIdle != null) {
3481                     ProtoLog.d(WM_DEBUG_STATES, "allResumedActivitiesIdle: %s not idle", notIdle);
3482                     return true;
3483                 }
3484                 if (task.isLeafTaskFragment()) {
3485                     // The task doesn't contain child TaskFragment.
3486                     return false;
3487                 }
3488                 return task.forAllLeafTaskFragments(tf -> {
3489                     if (!tf.isVisibleRequested()) {
3490                         return false;
3491                     }
3492                     final ActivityRecord tfNotIdle = getNotYetIdleActivity(tf);
3493                     if (tfNotIdle != null) {
3494                         ProtoLog.d(WM_DEBUG_STATES, "allResumedActivitiesIdle: %s not idle",
3495                                 tfNotIdle);
3496                         return true;
3497                     }
3498                     return false;
3499                 });
3500             });
3501             if (foundNotIdle) {
3502                 return false;
3503             }
3504             if (mTransitionController.hasTransientLaunch(display)) {
3505                 // Not idle if the transient transition animation is running.
3506                 return false;
3507             }
3508         }
3509         // End power mode launch when idle.
3510         mService.endPowerMode(ActivityTaskManagerService.POWER_MODE_REASON_START_ACTIVITY);
3511         return true;
3512     }
3513 
3514     boolean allResumedActivitiesVisible() {
3515         boolean[] foundResumed = {false};
3516         final boolean foundInvisibleResumedActivity = forAllRootTasks(rootTask -> {
3517             final ActivityRecord r = rootTask.getTopResumedActivity();
3518             if (r != null) {
3519                 if (!r.nowVisible) {
3520                     return true;
3521                 }
3522                 foundResumed[0] = true;
3523             }
3524             return false;
3525         });
3526         if (foundInvisibleResumedActivity) {
3527             return false;
3528         }
3529         return foundResumed[0];
3530     }
3531 
3532     boolean allPausedActivitiesComplete() {
3533         boolean[] pausing = {true};
3534         final boolean hasActivityNotCompleted = forAllLeafTasks(task -> {
3535             final ActivityRecord r = task.getTopPausingActivity();
3536             if (r != null && !r.isState(PAUSED, STOPPED, STOPPING, FINISHING)) {
3537                 ProtoLog.d(WM_DEBUG_STATES, "allPausedActivitiesComplete: "
3538                         + "r=%s state=%s", r, r.getState());
3539                 if (WM_DEBUG_STATES.isEnabled()) {
3540                     pausing[0] = false;
3541                 } else {
3542                     return true;
3543                 }
3544             }
3545             return false;
3546         });
3547         if (hasActivityNotCompleted) {
3548             return false;
3549         }
3550         return pausing[0];
3551     }
3552 
3553     /**
3554      * Find all tasks containing {@param userId} and intercept them with an activity
3555      * to block out the contents and possibly start a credential-confirming intent.
3556      *
3557      * @param userId user handle for the locked managed profile.
3558      */
3559     void lockAllProfileTasks(@UserIdInt int userId) {
3560         forAllLeafTasks(task -> {
3561             final ActivityRecord top = task.topRunningActivity();
3562             if (top != null && !top.finishing
3563                     && ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER.equals(top.intent.getAction())
3564                     && top.packageName.equals(
3565                             mService.getSysUiServiceComponentLocked().getPackageName())) {
3566                 // Do nothing since the task is already secure by sysui.
3567                 return;
3568             }
3569 
3570             if (task.getActivity(activity -> !activity.finishing && activity.mUserId == userId)
3571                     != null) {
3572                 mService.getTaskChangeNotificationController().notifyTaskProfileLocked(
3573                         task.getTaskInfo(), userId);
3574             }
3575         }, true /* traverseTopToBottom */);
3576     }
3577 
3578     Task anyTaskForId(int id) {
3579         return anyTaskForId(id, MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE);
3580     }
3581 
3582     Task anyTaskForId(int id, @RootWindowContainer.AnyTaskForIdMatchTaskMode int matchMode) {
3583         return anyTaskForId(id, matchMode, null, !ON_TOP);
3584     }
3585 
3586     /**
3587      * Returns a {@link Task} for the input id if available. {@code null} otherwise.
3588      *
3589      * @param id        Id of the task we would like returned.
3590      * @param matchMode The mode to match the given task id in.
3591      * @param aOptions  The activity options to use for restoration. Can be null.
3592      * @param onTop     If the root task for the task should be the topmost on the display.
3593      */
3594     Task anyTaskForId(int id, @RootWindowContainer.AnyTaskForIdMatchTaskMode int matchMode,
3595             @Nullable ActivityOptions aOptions, boolean onTop) {
3596         // If options are set, ensure that we are attempting to actually restore a task
3597         if (matchMode != MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE && aOptions != null) {
3598             throw new IllegalArgumentException("Should not specify activity options for non-restore"
3599                     + " lookup");
3600         }
3601 
3602         final PooledPredicate p = PooledLambda.obtainPredicate(
3603                 Task::isTaskId, PooledLambda.__(Task.class), id);
3604         Task task = getTask(p);
3605         p.recycle();
3606 
3607         if (task != null) {
3608             if (aOptions != null) {
3609                 // Resolve the root task the task should be placed in now based on options
3610                 // and reparent if needed.
3611                 // TODO(b/229927851) For split-screen, setLaunchRootTask is no longer the "root"
3612                 // task, consider to rename methods like "parentTask" instead of "rootTask".
3613                 final Task targetRootTask =
3614                         getOrCreateRootTask(null, aOptions, task, onTop);
3615                 // When launch with ActivityOptions#getLaunchRootTask, the "root task" just mean the
3616                 // parent of current launch, not the "root task" in hierarchy.
3617                 if (targetRootTask != null && task.getRootTask() != targetRootTask
3618                         && task.getParent() != targetRootTask) {
3619                     final int reparentMode = onTop
3620                             ? REPARENT_MOVE_ROOT_TASK_TO_FRONT : REPARENT_LEAVE_ROOT_TASK_IN_PLACE;
3621                     task.reparent(targetRootTask, onTop, reparentMode, ANIMATE, DEFER_RESUME,
3622                             "anyTaskForId");
3623                 }
3624             }
3625             return task;
3626         }
3627 
3628         // If we are matching root task tasks only, return now
3629         if (matchMode == MATCH_ATTACHED_TASK_ONLY) {
3630             return null;
3631         }
3632 
3633         // Otherwise, check the recent tasks and return if we find it there and we are not restoring
3634         // the task from recents
3635         if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents");
3636         task = mTaskSupervisor.mRecentTasks.getTask(id);
3637 
3638         if (task == null) {
3639             if (DEBUG_RECENTS) {
3640                 Slog.d(TAG_RECENTS, "\tDidn't find task id=" + id + " in recents");
3641             }
3642 
3643             return null;
3644         }
3645 
3646         if (matchMode == MATCH_ATTACHED_TASK_OR_RECENT_TASKS) {
3647             return task;
3648         }
3649 
3650         // Implicitly, this case is MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE
3651         if (!mTaskSupervisor.restoreRecentTaskLocked(task, aOptions, onTop)) {
3652             if (DEBUG_RECENTS) {
3653                 Slog.w(TAG_RECENTS,
3654                         "Couldn't restore task id=" + id + " found in recents");
3655             }
3656             return null;
3657         }
3658         if (DEBUG_RECENTS) Slog.w(TAG_RECENTS, "Restored task id=" + id + " from in recents");
3659         return task;
3660     }
3661 
3662     @VisibleForTesting
3663     void getRunningTasks(int maxNum, List<ActivityManager.RunningTaskInfo> list,
3664             int flags, int callingUid, ArraySet<Integer> profileIds, int displayId) {
3665         WindowContainer root = this;
3666         if (displayId != INVALID_DISPLAY) {
3667             root = getDisplayContent(displayId);
3668             if (root == null) {
3669                 return;
3670             }
3671         }
3672         mTaskSupervisor.getRunningTasks().getTasks(maxNum, list, flags, mService.getRecentTasks(),
3673                 root, callingUid, profileIds);
3674     }
3675 
3676     void startPowerModeLaunchIfNeeded(boolean forceSend, ActivityRecord targetActivity) {
3677         if (!forceSend && targetActivity != null && targetActivity.app != null) {
3678             // Set power mode when the activity's process is different than the current top resumed
3679             // activity on all display areas, or if there are no resumed activities in the system.
3680             boolean[] noResumedActivities = {true};
3681             boolean[] allFocusedProcessesDiffer = {true};
3682             forAllTaskDisplayAreas(taskDisplayArea -> {
3683                 final ActivityRecord resumedActivity = taskDisplayArea.getFocusedActivity();
3684                 final WindowProcessController resumedActivityProcess =
3685                         resumedActivity == null ? null : resumedActivity.app;
3686 
3687                 noResumedActivities[0] &= resumedActivityProcess == null;
3688                 if (resumedActivityProcess != null) {
3689                     allFocusedProcessesDiffer[0] &=
3690                             !resumedActivityProcess.equals(targetActivity.app);
3691                 }
3692             });
3693             if (!noResumedActivities[0] && !allFocusedProcessesDiffer[0]) {
3694                 // All focused activities are resumed and the process of the target activity is
3695                 // the same as them, e.g. delivering new intent to the current top.
3696                 return;
3697             }
3698         }
3699 
3700         int reason = ActivityTaskManagerService.POWER_MODE_REASON_START_ACTIVITY;
3701         // If the activity is launching while keyguard is locked (including occluded), the activity
3702         // may be visible until its first relayout is done (e.g. apply show-when-lock flag). To
3703         // avoid power mode from being cleared before that, add a special reason to consider whether
3704         // the unknown visibility is resolved. The case from SystemUI is excluded because it should
3705         // rely on keyguard-going-away.
3706         final boolean isKeyguardLocked = (targetActivity != null)
3707                 ? targetActivity.isKeyguardLocked() : mDefaultDisplay.isKeyguardLocked();
3708         if (isKeyguardLocked && targetActivity != null
3709                 && !targetActivity.isLaunchSourceType(ActivityRecord.LAUNCH_SOURCE_TYPE_SYSTEMUI)) {
3710             final ActivityOptions opts = targetActivity.getOptions();
3711             if (opts == null || opts.getSourceInfo() == null
3712                     || opts.getSourceInfo().type != ActivityOptions.SourceInfo.TYPE_LOCKSCREEN) {
3713                 reason |= ActivityTaskManagerService.POWER_MODE_REASON_UNKNOWN_VISIBILITY;
3714             }
3715         }
3716         mService.startPowerMode(reason);
3717     }
3718 
3719     /**
3720      * Iterate over all task fragments, to see if there exists one that meets the
3721      * PermissionPolicyService's criteria to show a permission dialog.
3722      */
3723     public int getTaskToShowPermissionDialogOn(String pkgName, int uid) {
3724         PermissionPolicyInternal pPi = mService.getPermissionPolicyInternal();
3725         if (pPi == null) {
3726             return INVALID_TASK_ID;
3727         }
3728 
3729         final int[] validTaskId = {INVALID_TASK_ID};
3730         forAllLeafTaskFragments(fragment -> {
3731             ActivityRecord record = fragment.getActivity((r) -> {
3732                 // skip hidden (or about to hide) apps, or the permission dialog
3733                 return r.canBeTopRunning() && r.isVisibleRequested()
3734                         && !pPi.isIntentToPermissionDialog(r.intent);
3735             });
3736             if (record != null && record.isUid(uid)
3737                     && Objects.equals(pkgName, record.packageName)
3738                     && pPi.shouldShowNotificationDialogForTask(record.getTask().getTaskInfo(),
3739                     pkgName, record.launchedFromPackage, record.intent, record.getName())) {
3740                 validTaskId[0] = record.getTask().mTaskId;
3741                 return true;
3742             }
3743             return false;
3744         });
3745 
3746         return validTaskId[0];
3747     }
3748 
3749     /**
3750      * Dumps the activities matching the given {@param name} in the either the focused root task
3751      * or all visible root tasks if {@param dumpVisibleRootTasksOnly} is true.
3752      */
3753     ArrayList<ActivityRecord> getDumpActivities(String name, boolean dumpVisibleRootTasksOnly,
3754             boolean dumpFocusedRootTaskOnly, @UserIdInt int userId) {
3755         if (dumpFocusedRootTaskOnly) {
3756             final Task topFocusedRootTask = getTopDisplayFocusedRootTask();
3757             if (topFocusedRootTask != null) {
3758                 return topFocusedRootTask.getDumpActivitiesLocked(name, userId);
3759             } else {
3760                 return new ArrayList<>();
3761             }
3762         } else {
3763             final RecentTasks recentTasks = mWindowManager.mAtmService.getRecentTasks();
3764             final int recentsComponentUid = recentTasks != null
3765                     ? recentTasks.getRecentsComponentUid()
3766                     : -1;
3767             final ArrayList<ActivityRecord> activities = new ArrayList<>();
3768             forAllLeafTasks(task -> {
3769                 final boolean isRecents = (task.effectiveUid == recentsComponentUid);
3770                 if (!dumpVisibleRootTasksOnly || task.shouldBeVisible(null) || isRecents) {
3771                     activities.addAll(task.getDumpActivitiesLocked(name, userId));
3772                 }
3773                 return false;
3774             });
3775             return activities;
3776         }
3777     }
3778 
3779     @Override
3780     public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
3781         super.dump(pw, prefix, dumpAll);
3782         pw.print(prefix);
3783         pw.println("topDisplayFocusedRootTask=" + getTopDisplayFocusedRootTask());
3784         for (int i = getChildCount() - 1; i >= 0; --i) {
3785             final DisplayContent display = getChildAt(i);
3786             display.dump(pw, prefix, dumpAll);
3787         }
3788     }
3789 
3790     /**
3791      * Dump all connected displays' configurations.
3792      *
3793      * @param prefix Prefix to apply to each line of the dump.
3794      */
3795     void dumpDisplayConfigs(PrintWriter pw, String prefix) {
3796         pw.print(prefix);
3797         pw.println("Display override configurations:");
3798         final int displayCount = getChildCount();
3799         for (int i = 0; i < displayCount; i++) {
3800             final DisplayContent displayContent = getChildAt(i);
3801             pw.print(prefix);
3802             pw.print("  ");
3803             pw.print(displayContent.mDisplayId);
3804             pw.print(": ");
3805             pw.println(displayContent.getRequestedOverrideConfiguration());
3806         }
3807     }
3808 
3809     boolean dumpActivities(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient,
3810             String dumpPackage, int displayIdFilter) {
3811         boolean[] printed = {false};
3812         boolean[] needSep = {false};
3813         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
3814             DisplayContent displayContent = getChildAt(displayNdx);
3815             if (printed[0]) {
3816                 pw.println();
3817             }
3818             if (displayIdFilter != Display.INVALID_DISPLAY
3819                     && displayContent.mDisplayId != displayIdFilter) {
3820                 continue;
3821             }
3822             pw.print("Display #");
3823             pw.print(displayContent.mDisplayId);
3824             pw.println(" (activities from top to bottom):");
3825             displayContent.forAllRootTasks(rootTask -> {
3826                 if (needSep[0]) {
3827                     pw.println();
3828                 }
3829                 needSep[0] = rootTask.dump(fd, pw, dumpAll, dumpClient, dumpPackage, false);
3830                 printed[0] |= needSep[0];
3831             });
3832             displayContent.forAllTaskDisplayAreas(taskDisplayArea -> {
3833                 printed[0] |= printThisActivity(pw, taskDisplayArea.getFocusedActivity(),
3834                         dumpPackage, needSep[0], "    Resumed: ", () ->
3835                                 pw.println("  Resumed activities in task display areas"
3836                                         + " (from top to bottom):"));
3837             });
3838         }
3839 
3840         printed[0] |= dumpHistoryList(fd, pw, mTaskSupervisor.mFinishingActivities, "  ",
3841                 "Fin", false, !dumpAll,
3842                 false, dumpPackage, true,
3843                 () -> pw.println("  Activities waiting to finish:"), null);
3844         printed[0] |= dumpHistoryList(fd, pw, mTaskSupervisor.mStoppingActivities, "  ",
3845                 "Stop", false, !dumpAll,
3846                 false, dumpPackage, true,
3847                 () -> pw.println("  Activities waiting to stop:"), null);
3848 
3849         return printed[0];
3850     }
3851 
3852     private static int makeSleepTokenKey(String tag, int displayId) {
3853         final String tokenKey = tag + displayId;
3854         return tokenKey.hashCode();
3855     }
3856 
3857     static final class SleepToken {
3858         private final String mTag;
3859         private final long mAcquireTime;
3860         private final int mDisplayId;
3861         final int mHashKey;
3862 
3863         SleepToken(String tag, int displayId) {
3864             mTag = tag;
3865             mDisplayId = displayId;
3866             mAcquireTime = SystemClock.uptimeMillis();
3867             mHashKey = makeSleepTokenKey(mTag, mDisplayId);
3868         }
3869 
3870         @Override
3871         public String toString() {
3872             return "{\"" + mTag + "\", display " + mDisplayId
3873                     + ", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}";
3874         }
3875 
3876         void writeTagToProto(ProtoOutputStream proto, long fieldId) {
3877             proto.write(fieldId, mTag);
3878         }
3879     }
3880 
3881     private class RankTaskLayersRunnable implements Runnable {
3882         boolean mCheckUpdateOomAdj;
3883 
3884         @Override
3885         public void run() {
3886             synchronized (mService.mGlobalLock) {
3887                 if (mTaskLayersChanged) {
3888                     mTaskLayersChanged = false;
3889                     rankTaskLayers();
3890                 }
3891             }
3892         }
3893     }
3894 }
3895