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