• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
20 import static android.Manifest.permission.INPUT_CONSUMER;
21 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
22 import static android.Manifest.permission.MANAGE_APP_TOKENS;
23 import static android.Manifest.permission.READ_FRAME_BUFFER;
24 import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
25 import static android.Manifest.permission.RESTRICTED_VR_ACCESS;
26 import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
27 import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
28 import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
29 import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
30 import static android.app.StatusBarManager.DISABLE_MASK;
31 import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
32 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
33 import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
34 import static android.content.pm.PackageManager.FEATURE_PC;
35 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
36 import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
37 import static android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE;
38 import static android.os.Process.SYSTEM_UID;
39 import static android.os.Process.myPid;
40 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
41 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
42 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW;
43 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
44 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
45 import static android.provider.Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR;
46 import static android.provider.Settings.Global.DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH;
47 import static android.view.Display.DEFAULT_DISPLAY;
48 import static android.view.Display.INVALID_DISPLAY;
49 import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
50 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
51 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
52 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
53 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
54 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
55 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
56 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
57 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
58 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
59 import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
60 import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
61 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
62 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
63 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
64 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
65 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
66 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
67 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
68 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
69 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
70 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
71 import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
72 import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
73 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
74 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
75 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
76 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
77 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
78 import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
79 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
80 import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED;
81 import static android.view.WindowManager.TRANSIT_NONE;
82 import static android.view.WindowManager.TRANSIT_RELAUNCH;
83 import static android.view.WindowManagerGlobal.ADD_OKAY;
84 import static android.view.WindowManagerGlobal.RELAYOUT_RES_BLAST_SYNC;
85 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
86 import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID;
87 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW;
88 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN;
89 
90 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
91 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT;
92 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
93 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
94 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
95 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON;
96 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
97 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
98 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
99 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
100 import static com.android.internal.protolog.ProtoLogGroup.WM_ERROR;
101 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
102 import static com.android.internal.util.LatencyTracker.ACTION_ROTATE_SCREEN;
103 import static com.android.server.LockGuard.INDEX_WINDOW;
104 import static com.android.server.LockGuard.installLock;
105 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
106 import static com.android.server.wm.ActivityTaskManagerService.POWER_MODE_REASON_FREEZE_DISPLAY;
107 import static com.android.server.wm.DisplayContent.IME_TARGET_CONTROL;
108 import static com.android.server.wm.DisplayContent.IME_TARGET_INPUT;
109 import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
110 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL;
111 import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
112 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
113 import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
114 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
115 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
116 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
117 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
118 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
119 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
120 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
121 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
122 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
123 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_VERBOSE_TRANSACTIONS;
124 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
125 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
126 import static com.android.server.wm.WindowManagerServiceDumpProto.DISPLAY_FROZEN;
127 import static com.android.server.wm.WindowManagerServiceDumpProto.FOCUSED_APP;
128 import static com.android.server.wm.WindowManagerServiceDumpProto.FOCUSED_DISPLAY_ID;
129 import static com.android.server.wm.WindowManagerServiceDumpProto.FOCUSED_WINDOW;
130 import static com.android.server.wm.WindowManagerServiceDumpProto.HARD_KEYBOARD_AVAILABLE;
131 import static com.android.server.wm.WindowManagerServiceDumpProto.INPUT_METHOD_WINDOW;
132 import static com.android.server.wm.WindowManagerServiceDumpProto.POLICY;
133 import static com.android.server.wm.WindowManagerServiceDumpProto.ROOT_WINDOW_CONTAINER;
134 
135 import android.Manifest;
136 import android.Manifest.permission;
137 import android.animation.ValueAnimator;
138 import android.annotation.IntDef;
139 import android.annotation.NonNull;
140 import android.annotation.Nullable;
141 import android.annotation.RequiresPermission;
142 import android.app.ActivityManager;
143 import android.app.ActivityManagerInternal;
144 import android.app.ActivityTaskManager;
145 import android.app.ActivityThread;
146 import android.app.AppOpsManager;
147 import android.app.IActivityManager;
148 import android.app.IActivityTaskManager;
149 import android.app.IAssistDataReceiver;
150 import android.app.WindowConfiguration;
151 import android.content.BroadcastReceiver;
152 import android.content.ContentResolver;
153 import android.content.Context;
154 import android.content.Intent;
155 import android.content.IntentFilter;
156 import android.content.pm.ApplicationInfo;
157 import android.content.pm.PackageManager;
158 import android.content.pm.PackageManagerInternal;
159 import android.content.pm.TestUtilityService;
160 import android.content.res.Configuration;
161 import android.content.res.TypedArray;
162 import android.database.ContentObserver;
163 import android.graphics.Bitmap;
164 import android.graphics.Insets;
165 import android.graphics.Matrix;
166 import android.graphics.Point;
167 import android.graphics.Rect;
168 import android.graphics.RectF;
169 import android.graphics.Region;
170 import android.hardware.configstore.V1_0.ISurfaceFlingerConfigs;
171 import android.hardware.configstore.V1_0.OptionalBool;
172 import android.hardware.display.DisplayManager;
173 import android.hardware.display.DisplayManagerInternal;
174 import android.hardware.input.InputManager;
175 import android.hardware.input.InputManagerInternal;
176 import android.net.Uri;
177 import android.os.Binder;
178 import android.os.Build;
179 import android.os.Bundle;
180 import android.os.Debug;
181 import android.os.Handler;
182 import android.os.HandlerExecutor;
183 import android.os.IBinder;
184 import android.os.IRemoteCallback;
185 import android.os.Looper;
186 import android.os.Message;
187 import android.os.Parcel;
188 import android.os.ParcelFileDescriptor;
189 import android.os.PowerManager;
190 import android.os.PowerManager.ServiceType;
191 import android.os.PowerManagerInternal;
192 import android.os.PowerSaveState;
193 import android.os.RemoteCallback;
194 import android.os.RemoteException;
195 import android.os.ResultReceiver;
196 import android.os.ServiceManager;
197 import android.os.ShellCallback;
198 import android.os.StrictMode;
199 import android.os.SystemClock;
200 import android.os.SystemProperties;
201 import android.os.SystemService;
202 import android.os.Trace;
203 import android.os.UserHandle;
204 import android.os.WorkSource;
205 import android.provider.Settings;
206 import android.service.vr.IVrManager;
207 import android.service.vr.IVrStateCallbacks;
208 import android.sysprop.SurfaceFlingerProperties;
209 import android.text.format.DateUtils;
210 import android.util.ArrayMap;
211 import android.util.ArraySet;
212 import android.util.DisplayMetrics;
213 import android.util.EventLog;
214 import android.util.MergedConfiguration;
215 import android.util.Slog;
216 import android.util.SparseArray;
217 import android.util.SparseBooleanArray;
218 import android.util.TimeUtils;
219 import android.util.TypedValue;
220 import android.util.proto.ProtoOutputStream;
221 import android.view.Choreographer;
222 import android.view.Display;
223 import android.view.DisplayInfo;
224 import android.view.Gravity;
225 import android.view.IAppTransitionAnimationSpecsFuture;
226 import android.view.ICrossWindowBlurEnabledListener;
227 import android.view.IDisplayFoldListener;
228 import android.view.IDisplayWindowInsetsController;
229 import android.view.IDisplayWindowListener;
230 import android.view.IDisplayWindowRotationController;
231 import android.view.IInputFilter;
232 import android.view.IOnKeyguardExitResult;
233 import android.view.IPinnedTaskListener;
234 import android.view.IRecentsAnimationRunner;
235 import android.view.IRotationWatcher;
236 import android.view.IScrollCaptureResponseListener;
237 import android.view.ISystemGestureExclusionListener;
238 import android.view.IWallpaperVisibilityListener;
239 import android.view.IWindow;
240 import android.view.IWindowId;
241 import android.view.IWindowManager;
242 import android.view.IWindowSession;
243 import android.view.IWindowSessionCallback;
244 import android.view.InputApplicationHandle;
245 import android.view.InputChannel;
246 import android.view.InputDevice;
247 import android.view.InputEvent;
248 import android.view.InputWindowHandle;
249 import android.view.InsetsSourceControl;
250 import android.view.InsetsState;
251 import android.view.KeyEvent;
252 import android.view.MagnificationSpec;
253 import android.view.MotionEvent;
254 import android.view.PointerIcon;
255 import android.view.RemoteAnimationAdapter;
256 import android.view.ScrollCaptureResponse;
257 import android.view.Surface;
258 import android.view.SurfaceControl;
259 import android.view.SurfaceSession;
260 import android.view.View;
261 import android.view.WindowContentFrameStats;
262 import android.view.WindowInsets;
263 import android.view.WindowManager;
264 import android.view.WindowManager.DisplayImePolicy;
265 import android.view.WindowManager.LayoutParams;
266 import android.view.WindowManager.RemoveContentMode;
267 import android.view.WindowManagerGlobal;
268 import android.view.WindowManagerPolicyConstants.PointerEventListener;
269 import android.view.displayhash.DisplayHash;
270 import android.view.displayhash.VerifiedDisplayHash;
271 import android.window.ClientWindowFrames;
272 import android.window.TaskSnapshot;
273 
274 import com.android.internal.R;
275 import com.android.internal.annotations.VisibleForTesting;
276 import com.android.internal.os.IResultReceiver;
277 import com.android.internal.policy.IKeyguardDismissCallback;
278 import com.android.internal.policy.IShortcutService;
279 import com.android.internal.policy.KeyInterceptionInfo;
280 import com.android.internal.protolog.ProtoLogImpl;
281 import com.android.internal.protolog.common.ProtoLog;
282 import com.android.internal.util.DumpUtils;
283 import com.android.internal.util.FastPrintWriter;
284 import com.android.internal.util.LatencyTracker;
285 import com.android.internal.util.function.pooled.PooledConsumer;
286 import com.android.internal.util.function.pooled.PooledLambda;
287 import com.android.internal.view.WindowManagerPolicyThread;
288 import com.android.server.AnimationThread;
289 import com.android.server.DisplayThread;
290 import com.android.server.FgThread;
291 import com.android.server.LocalServices;
292 import com.android.server.UiThread;
293 import com.android.server.Watchdog;
294 import com.android.server.input.InputManagerService;
295 import com.android.server.policy.WindowManagerPolicy;
296 import com.android.server.policy.WindowManagerPolicy.ScreenOffListener;
297 import com.android.server.power.ShutdownThread;
298 import com.android.server.utils.DeviceConfigInterface;
299 import com.android.server.utils.PriorityDump;
300 
301 import java.io.BufferedWriter;
302 import java.io.DataInputStream;
303 import java.io.File;
304 import java.io.FileDescriptor;
305 import java.io.FileInputStream;
306 import java.io.FileNotFoundException;
307 import java.io.IOException;
308 import java.io.OutputStream;
309 import java.io.OutputStreamWriter;
310 import java.io.PrintWriter;
311 import java.io.StringWriter;
312 import java.lang.annotation.Retention;
313 import java.lang.annotation.RetentionPolicy;
314 import java.net.Socket;
315 import java.text.DateFormat;
316 import java.util.ArrayList;
317 import java.util.Arrays;
318 import java.util.Collections;
319 import java.util.Date;
320 import java.util.HashMap;
321 import java.util.List;
322 import java.util.Map;
323 import java.util.NoSuchElementException;
324 import java.util.Objects;
325 import java.util.Optional;
326 import java.util.function.Function;
327 import java.util.function.Supplier;
328 
329 /** {@hide} */
330 public class WindowManagerService extends IWindowManager.Stub
331         implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
332     private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowManagerService" : TAG_WM;
333 
334     private static final String WM_USE_BLAST_ADAPTER_FLAG = "wm_use_blast_adapter";
335 
336     static final int LAYOUT_REPEAT_THRESHOLD = 4;
337 
338     static final boolean PROFILE_ORIENTATION = false;
339 
340     /** How much to multiply the policy's type layer, to reserve room
341      * for multiple windows of the same type and Z-ordering adjustment
342      * with TYPE_LAYER_OFFSET. */
343     static final int TYPE_LAYER_MULTIPLIER = 10000;
344 
345     /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
346      * or below others in the same layer. */
347     static final int TYPE_LAYER_OFFSET = 1000;
348 
349     /** How much to increment the layer for each window, to reserve room
350      * for effect surfaces between them.
351      */
352     static final int WINDOW_LAYER_MULTIPLIER = 5;
353 
354     /**
355      * Animation thumbnail is as far as possible below the window above
356      * the thumbnail (or in other words as far as possible above the window
357      * below it).
358      */
359     static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER - 1;
360 
361     /** The maximum length we will accept for a loaded animation duration:
362      * this is 10 seconds.
363      */
364     static final int MAX_ANIMATION_DURATION = 10 * 1000;
365 
366     /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
367     static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000;
368 
369     /** Amount of time (in milliseconds) to delay before declaring a window replacement timeout. */
370     static final int WINDOW_REPLACEMENT_TIMEOUT_DURATION = 2000;
371 
372     /** Amount of time to allow a last ANR message to exist before freeing the memory. */
373     static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours
374 
375     // Maximum number of milliseconds to wait for input devices to be enumerated before
376     // proceding with safe mode detection.
377     private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000;
378 
379     // Poll interval in milliseconds for watching boot animation finished.
380     // TODO(b/159045990) Migrate to SystemService.waitForState with dedicated thread.
381     private static final int BOOT_ANIMATION_POLL_INTERVAL = 50;
382 
383     // The name of the boot animation service in init.rc.
384     private static final String BOOT_ANIMATION_SERVICE = "bootanim";
385 
386     static final int UPDATE_FOCUS_NORMAL = 0;
387     /** Caller will assign layers */
388     static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
389     /** Caller is performing surface placement */
390     static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
391     /** Caller will performSurfacePlacement */
392     static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
393     /** Indicates we are removing the focused window when updating the focus. */
394     static final int UPDATE_FOCUS_REMOVING_FOCUS = 4;
395 
396     private static final String SYSTEM_SECURE = "ro.secure";
397     private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
398 
399     private static final String DENSITY_OVERRIDE = "ro.config.density_override";
400     private static final String SIZE_OVERRIDE = "ro.config.size_override";
401 
402     private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
403 
404     // Used to indicate that if there is already a transition set, it should be preserved when
405     // trying to apply a new one.
406     private static final boolean ALWAYS_KEEP_CURRENT = true;
407 
408     static final int LOGTAG_INPUT_FOCUS = 62001;
409 
410     /**
411      * Restrict ability of activities overriding transition animation in a way such that
412      * an activity can do it only when the transition happens within a same task.
413      *
414      * @see android.app.Activity#overridePendingTransition(int, int)
415      */
416     private static final String DISABLE_CUSTOM_TASK_ANIMATION_PROPERTY =
417             "persist.wm.disable_custom_task_animation";
418 
419     /**
420      * @see #DISABLE_CUSTOM_TASK_ANIMATION_PROPERTY
421      */
422     static boolean sDisableCustomTaskAnimationProperty =
423             SystemProperties.getBoolean(DISABLE_CUSTOM_TASK_ANIMATION_PROPERTY, true);
424 
425     /**
426      * Use WMShell for app transition.
427      */
428     public static final String ENABLE_SHELL_TRANSITIONS = "persist.debug.shell_transit";
429 
430     /**
431      * @see #ENABLE_SHELL_TRANSITIONS
432      */
433     public static final boolean sEnableShellTransitions =
434             SystemProperties.getBoolean(ENABLE_SHELL_TRANSITIONS, false);
435 
436     /**
437      * Run Keyguard animation as remote animation in System UI instead of local animation in
438      * the server process.
439      *
440      * 0: Runs all keyguard animation as local animation
441      * 1: Only runs keyguard going away animation as remote animation
442      * 2: Runs all keyguard animation as remote animation
443      */
444     private static final String ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY =
445             "persist.wm.enable_remote_keyguard_animation";
446 
447     private static final int sEnableRemoteKeyguardAnimation =
448             SystemProperties.getInt(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, 0);
449 
450     /**
451      * @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
452      */
453     public static final boolean sEnableRemoteKeyguardGoingAwayAnimation = !sEnableShellTransitions
454             && sEnableRemoteKeyguardAnimation >= 1;
455 
456     /**
457      * @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
458      */
459     public static final boolean sEnableRemoteKeyguardOccludeAnimation = !sEnableShellTransitions
460             && sEnableRemoteKeyguardAnimation >= 2;
461 
462     /**
463      * Allows a fullscreen windowing mode activity to launch in its desired orientation directly
464      * when the display has different orientation.
465      */
466     static final boolean ENABLE_FIXED_ROTATION_TRANSFORM =
467             SystemProperties.getBoolean("persist.wm.fixed_rotation_transform", true);
468 
469     // Enums for animation scale update types.
470     @Retention(RetentionPolicy.SOURCE)
471     @IntDef({WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE, ANIMATION_DURATION_SCALE})
472     private @interface UpdateAnimationScaleMode {};
473     private static final int WINDOW_ANIMATION_SCALE = 0;
474     private static final int TRANSITION_ANIMATION_SCALE = 1;
475     private static final int ANIMATION_DURATION_SCALE = 2;
476 
477     private static final int ANIMATION_COMPLETED_TIMEOUT_MS = 5000;
478 
479     final WindowManagerConstants mConstants;
480 
481     final WindowTracing mWindowTracing;
482 
483     private final DisplayAreaPolicy.Provider mDisplayAreaPolicyProvider;
484 
485     final private KeyguardDisableHandler mKeyguardDisableHandler;
486 
487     // VR Vr2d Display Id.
488     int mVr2dDisplayId = INVALID_DISPLAY;
489     boolean mVrModeEnabled = false;
490 
491     /* If true, shadows drawn around the window will be rendered by the system compositor. If
492      * false, shadows will be drawn by the client by setting an elevation on the root view and
493      * the contents will be inset by the shadow radius. */
494     boolean mRenderShadowsInCompositor = false;
495 
496     /**
497      * Tracks a map of input tokens to info that is used to decide whether to intercept
498      * a key event.
499      */
500     final Map<IBinder, KeyInterceptionInfo> mKeyInterceptionInfoForToken =
501             Collections.synchronizedMap(new ArrayMap<>());
502 
503     final StartingSurfaceController mStartingSurfaceController;
504 
505     private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
506         @Override
507         public void onVrStateChanged(boolean enabled) {
508             synchronized (mGlobalLock) {
509                 mVrModeEnabled = enabled;
510                 final PooledConsumer c = PooledLambda.obtainConsumer(
511                         DisplayPolicy::onVrStateChangedLw, PooledLambda.__(), enabled);
512                 mRoot.forAllDisplayPolicies(c);
513                 c.recycle();
514             }
515         }
516     };
517 
518     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
519         @Override
520         public void onReceive(Context context, Intent intent) {
521             switch (intent.getAction()) {
522                 case ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED:
523                     mKeyguardDisableHandler.updateKeyguardEnabled(getSendingUserId());
524                     break;
525             }
526         }
527     };
528     final WindowSurfacePlacer mWindowPlacerLocked;
529 
530     private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() {
531         @Override
532         public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args,
533                 boolean asProto) {
534             doDump(fd, pw, new String[] {"-a"}, asProto);
535         }
536 
537         @Override
538         public void dump(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
539             doDump(fd, pw, args, asProto);
540         }
541     };
542 
543     /**
544      * Current user when multi-user is enabled. Don't show windows of
545      * non-current user. Also see mCurrentProfileIds.
546      */
547     int mCurrentUserId;
548     /**
549      * Users that are profiles of the current user. These are also allowed to show windows
550      * on the current user.
551      */
552     int[] mCurrentProfileIds = new int[] {};
553 
554     final Context mContext;
555 
556     final boolean mHasPermanentDpad;
557     final long mDrawLockTimeoutMillis;
558     final boolean mAllowAnimationsInLowPowerMode;
559 
560     final boolean mAllowBootMessages;
561 
562     // Indicates whether the Assistant should show on top of the Dream (respectively, above
563     // everything else on screen). Otherwise, it will be put under always-on-top stacks.
564     final boolean mAssistantOnTopOfDream;
565 
566     final boolean mLimitedAlphaCompositing;
567     final int mMaxUiWidth;
568 
569     @VisibleForTesting
570     WindowManagerPolicy mPolicy;
571 
572     final IActivityManager mActivityManager;
573     // TODO: Probably not needed once activities are fully in WM.
574     final IActivityTaskManager mActivityTaskManager;
575     final ActivityManagerInternal mAmInternal;
576     final ActivityTaskManagerInternal mAtmInternal;
577 
578     final AppOpsManager mAppOps;
579     final PackageManagerInternal mPmInternal;
580     private final TestUtilityService mTestUtilityService;
581 
582     final DisplayWindowSettingsProvider mDisplayWindowSettingsProvider;
583     final DisplayWindowSettings mDisplayWindowSettings;
584 
585     /** If the system should display notifications for apps displaying an alert window. */
586     boolean mShowAlertWindowNotifications = true;
587 
588     /**
589      * All currently active sessions with clients.
590      */
591     final ArraySet<Session> mSessions = new ArraySet<>();
592 
593     /** Mapping from an IWindow IBinder to the server's Window object. */
594     final HashMap<IBinder, WindowState> mWindowMap = new HashMap<>();
595 
596     /** Mapping from an InputWindowHandle token to the server's Window object. */
597     final HashMap<IBinder, WindowState> mInputToWindowMap = new HashMap<>();
598 
599     /** Global service lock used by the package the owns this service. */
600     final WindowManagerGlobalLock mGlobalLock;
601 
602     /**
603      * List of app window tokens that are waiting for replacing windows. If the
604      * replacement doesn't come in time the stale windows needs to be disposed of.
605      */
606     final ArrayList<ActivityRecord> mWindowReplacementTimeouts = new ArrayList<>();
607 
608     /**
609      * Windows that are being resized.  Used so we can tell the client about
610      * the resize after closing the transaction in which we resized the
611      * underlying surface.
612      */
613     final ArrayList<WindowState> mResizingWindows = new ArrayList<>();
614 
615     /**
616      * Windows whose animations have ended and now must be removed.
617      */
618     final ArrayList<WindowState> mPendingRemove = new ArrayList<>();
619 
620     /**
621      * Used when processing mPendingRemove to avoid working on the original array.
622      */
623     WindowState[] mPendingRemoveTmp = new WindowState[20];
624 
625     // TODO: use WindowProcessController once go/wm-unified is done.
626     /** Mapping of process pids to configurations */
627     final SparseArray<Configuration> mProcessConfigurations = new SparseArray<>();
628 
629     /**
630      * Windows whose surface should be destroyed.
631      */
632     final ArrayList<WindowState> mDestroySurface = new ArrayList<>();
633 
634     /**
635      * This is set when we have run out of memory, and will either be an empty
636      * list or contain windows that need to be force removed.
637      */
638     final ArrayList<WindowState> mForceRemoves = new ArrayList<>();
639 
640     /**
641      * The callbacks to make when the windows all have been drawn for a given
642      * {@link WindowContainer}.
643      */
644     final HashMap<WindowContainer, Runnable> mWaitingForDrawnCallbacks = new HashMap<>();
645 
646     /** List of window currently causing non-system overlay windows to be hidden. */
647     private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<>();
648 
649     AccessibilityController mAccessibilityController;
650     private RecentsAnimationController mRecentsAnimationController;
651 
652     Watermark mWatermark;
653     StrictModeFlash mStrictModeFlash;
654     EmulatorDisplayOverlay mEmulatorDisplayOverlay;
655 
656     final float[] mTmpFloats = new float[9];
657     final Rect mTmpRect = new Rect();
658     final Rect mTmpRect2 = new Rect();
659     final Rect mTmpRect3 = new Rect();
660     final RectF mTmpRectF = new RectF();
661 
662     final Matrix mTmpTransform = new Matrix();
663 
664     boolean mDisplayReady;
665     boolean mSafeMode;
666     boolean mDisplayEnabled = false;
667     boolean mSystemBooted = false;
668     boolean mForceDisplayEnabled = false;
669     boolean mShowingBootMessages = false;
670     boolean mSystemReady = false;
671     boolean mBootAnimationStopped = false;
672     long mBootWaitForWindowsStartTime = -1;
673 
674     // Following variables are for debugging screen wakelock only.
675     WindowState mLastWakeLockHoldingWindow = null;
676     WindowState mLastWakeLockObscuringWindow = null;
677 
678     /** Dump of the windows and app tokens at the time of the last ANR. Cleared after
679      * LAST_ANR_LIFETIME_DURATION_MSECS */
680     String mLastANRState;
681 
682     // The root of the device window hierarchy.
683     RootWindowContainer mRoot;
684 
685     // Whether the system should use BLAST for ViewRootImpl
686     final boolean mUseBLAST;
687     // Whether to enable BLASTSyncEngine Transaction passing.
688     final boolean mUseBLASTSync = true;
689 
690     final BLASTSyncEngine mSyncEngine;
691 
692     boolean mIsPc;
693     /**
694      * Flag that indicates that desktop mode is forced for public secondary screens.
695      *
696      * This includes several settings:
697      * - Set freeform windowing mode on external screen if it's supported and enabled.
698      * - Enable system decorations and IME on external screen.
699      * - TODO: Show mouse pointer on external screen.
700      */
701     boolean mForceDesktopModeOnExternalDisplays;
702 
703     boolean mDisableTransitionAnimation;
704 
705     class RotationWatcher {
706         final IRotationWatcher mWatcher;
707         final IBinder.DeathRecipient mDeathRecipient;
708         final int mDisplayId;
RotationWatcher(IRotationWatcher watcher, IBinder.DeathRecipient deathRecipient, int displayId)709         RotationWatcher(IRotationWatcher watcher, IBinder.DeathRecipient deathRecipient,
710                 int displayId) {
711             mWatcher = watcher;
712             mDeathRecipient = deathRecipient;
713             mDisplayId = displayId;
714         }
715     }
716 
717     ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<>();
718     final WallpaperVisibilityListeners mWallpaperVisibilityListeners =
719             new WallpaperVisibilityListeners();
720 
721     IDisplayWindowRotationController mDisplayRotationController = null;
722     private final DeathRecipient mDisplayRotationControllerDeath =
723             () -> mDisplayRotationController = null;
724 
725     final DisplayWindowListenerController mDisplayNotificationController;
726 
727     boolean mDisplayFrozen = false;
728     long mDisplayFreezeTime = 0;
729     int mLastDisplayFreezeDuration = 0;
730     Object mLastFinishedFreezeSource = null;
731     boolean mSwitchingUser = false;
732 
733     final static int WINDOWS_FREEZING_SCREENS_NONE = 0;
734     final static int WINDOWS_FREEZING_SCREENS_ACTIVE = 1;
735     final static int WINDOWS_FREEZING_SCREENS_TIMEOUT = 2;
736     int mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
737 
738     boolean mClientFreezingScreen = false;
739     int mAppsFreezingScreen = 0;
740 
741     @VisibleForTesting
742     boolean mPerDisplayFocusEnabled;
743 
744     // State while inside of layoutAndPlaceSurfacesLocked().
745     boolean mFocusMayChange;
746 
747     // This is held as long as we have the screen frozen, to give us time to
748     // perform a rotation animation when turning off shows the lock screen which
749     // changes the orientation.
750     private final PowerManager.WakeLock mScreenFrozenLock;
751 
752     final TaskSnapshotController mTaskSnapshotController;
753 
754     final BlurController mBlurController;
755 
756     boolean mIsTouchDevice;
757     boolean mIsFakeTouchDevice;
758 
759     final H mH = new H();
760 
761     /**
762      * Handler for things to run that have direct impact on an animation, i.e. animation tick,
763      * layout, starting window creation, whereas {@link H} runs things that are still important, but
764      * not as critical.
765      */
766     final Handler mAnimationHandler = new Handler(AnimationThread.getHandler().getLooper());
767 
768     boolean mHardKeyboardAvailable;
769     WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
770     SettingsObserver mSettingsObserver;
771     final EmbeddedWindowController mEmbeddedWindowController;
772     final AnrController mAnrController;
773 
774     private final DisplayHashController mDisplayHashController;
775 
776     @VisibleForTesting
777     final WindowContextListenerController mWindowContextListenerController =
778             new WindowContextListenerController();
779 
780     @VisibleForTesting
781     final class SettingsObserver extends ContentObserver {
782         private final Uri mDisplayInversionEnabledUri =
783                 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
784         private final Uri mWindowAnimationScaleUri =
785                 Settings.Global.getUriFor(Settings.Global.WINDOW_ANIMATION_SCALE);
786         private final Uri mTransitionAnimationScaleUri =
787                 Settings.Global.getUriFor(Settings.Global.TRANSITION_ANIMATION_SCALE);
788         private final Uri mAnimationDurationScaleUri =
789                 Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE);
790         private final Uri mImmersiveModeConfirmationsUri =
791                 Settings.Secure.getUriFor(Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS);
792         private final Uri mPolicyControlUri =
793                 Settings.Global.getUriFor(Settings.Global.POLICY_CONTROL);
794         private final Uri mPointerLocationUri =
795                 Settings.System.getUriFor(Settings.System.POINTER_LOCATION);
796         private final Uri mForceDesktopModeOnExternalDisplaysUri = Settings.Global.getUriFor(
797                         Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS);
798         private final Uri mFreeformWindowUri = Settings.Global.getUriFor(
799                 Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT);
800         private final Uri mForceResizableUri = Settings.Global.getUriFor(
801                 DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES);
802         private final Uri mDevEnableNonResizableMultiWindowUri = Settings.Global.getUriFor(
803                 DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW);
804         private final Uri mRenderShadowsInCompositorUri = Settings.Global.getUriFor(
805                 DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR);
806         private final Uri mDisplaySettingsPathUri = Settings.Global.getUriFor(
807                 DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH);
808 
SettingsObserver()809         public SettingsObserver() {
810             super(new Handler());
811             ContentResolver resolver = mContext.getContentResolver();
812             resolver.registerContentObserver(mDisplayInversionEnabledUri, false, this,
813                     UserHandle.USER_ALL);
814             resolver.registerContentObserver(mWindowAnimationScaleUri, false, this,
815                     UserHandle.USER_ALL);
816             resolver.registerContentObserver(mTransitionAnimationScaleUri, false, this,
817                     UserHandle.USER_ALL);
818             resolver.registerContentObserver(mAnimationDurationScaleUri, false, this,
819                     UserHandle.USER_ALL);
820             resolver.registerContentObserver(mImmersiveModeConfirmationsUri, false, this,
821                     UserHandle.USER_ALL);
822             resolver.registerContentObserver(mPolicyControlUri, false, this, UserHandle.USER_ALL);
823             resolver.registerContentObserver(mPointerLocationUri, false, this, UserHandle.USER_ALL);
824             resolver.registerContentObserver(mForceDesktopModeOnExternalDisplaysUri, false, this,
825                     UserHandle.USER_ALL);
826             resolver.registerContentObserver(mFreeformWindowUri, false, this, UserHandle.USER_ALL);
827             resolver.registerContentObserver(mForceResizableUri, false, this, UserHandle.USER_ALL);
828             resolver.registerContentObserver(mDevEnableNonResizableMultiWindowUri, false, this,
829                     UserHandle.USER_ALL);
830             resolver.registerContentObserver(mRenderShadowsInCompositorUri, false, this,
831                     UserHandle.USER_ALL);
832             resolver.registerContentObserver(mDisplaySettingsPathUri, false, this,
833                     UserHandle.USER_ALL);
834         }
835 
836         @Override
onChange(boolean selfChange, Uri uri)837         public void onChange(boolean selfChange, Uri uri) {
838             if (uri == null) {
839                 return;
840             }
841 
842             if (mImmersiveModeConfirmationsUri.equals(uri) || mPolicyControlUri.equals(uri)) {
843                 updateSystemUiSettings(true /* handleChange */);
844                 return;
845             }
846 
847             if (mPointerLocationUri.equals(uri)) {
848                 updatePointerLocation();
849                 return;
850             }
851 
852             if (mForceDesktopModeOnExternalDisplaysUri.equals(uri)) {
853                 updateForceDesktopModeOnExternalDisplays();
854                 return;
855             }
856 
857             if (mFreeformWindowUri.equals(uri)) {
858                 updateFreeformWindowManagement();
859                 return;
860             }
861 
862             if (mForceResizableUri.equals(uri)) {
863                 updateForceResizableTasks();
864                 return;
865             }
866 
867             if (mDevEnableNonResizableMultiWindowUri.equals(uri)) {
868                 updateDevEnableNonResizableMultiWindow();
869                 return;
870             }
871 
872             if (mRenderShadowsInCompositorUri.equals(uri)) {
873                 setShadowRenderer();
874                 return;
875             }
876 
877             if (mDisplaySettingsPathUri.equals(uri)) {
878                 updateDisplaySettingsLocation();
879                 return;
880             }
881 
882             @UpdateAnimationScaleMode
883             final int mode;
884             if (mWindowAnimationScaleUri.equals(uri)) {
885                 mode = WINDOW_ANIMATION_SCALE;
886             } else if (mTransitionAnimationScaleUri.equals(uri)) {
887                 mode = TRANSITION_ANIMATION_SCALE;
888             } else if (mAnimationDurationScaleUri.equals(uri)) {
889                 mode = ANIMATION_DURATION_SCALE;
890             } else {
891                 // Ignoring unrecognized content changes
892                 return;
893             }
894             Message m = mH.obtainMessage(H.UPDATE_ANIMATION_SCALE, mode, 0);
895             mH.sendMessage(m);
896         }
897 
loadSettings()898         void loadSettings() {
899             updateSystemUiSettings(false /* handleChange */);
900             updatePointerLocation();
901         }
902 
updateSystemUiSettings(boolean handleChange)903         void updateSystemUiSettings(boolean handleChange) {
904             synchronized (mGlobalLock) {
905                 boolean changed = false;
906                 if (handleChange) {
907                     changed = getDefaultDisplayContentLocked().getDisplayPolicy()
908                             .onSystemUiSettingsChanged();
909                 } else {
910                     ImmersiveModeConfirmation.loadSetting(mCurrentUserId, mContext);
911                 }
912                 if (changed) {
913                     mWindowPlacerLocked.requestTraversal();
914                 }
915             }
916         }
917 
updatePointerLocation()918         void updatePointerLocation() {
919             ContentResolver resolver = mContext.getContentResolver();
920             final boolean enablePointerLocation = Settings.System.getIntForUser(resolver,
921                     Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT) != 0;
922 
923             if (mPointerLocationEnabled == enablePointerLocation) {
924                 return;
925             }
926             mPointerLocationEnabled = enablePointerLocation;
927             synchronized (mGlobalLock) {
928                 final PooledConsumer c = PooledLambda.obtainConsumer(
929                         DisplayPolicy::setPointerLocationEnabled, PooledLambda.__(),
930                         mPointerLocationEnabled);
931                 mRoot.forAllDisplayPolicies(c);
932                 c.recycle();
933             }
934         }
935 
updateForceDesktopModeOnExternalDisplays()936         void updateForceDesktopModeOnExternalDisplays() {
937             ContentResolver resolver = mContext.getContentResolver();
938             final boolean enableForceDesktopMode = Settings.Global.getInt(resolver,
939                     DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS, 0) != 0;
940             if (mForceDesktopModeOnExternalDisplays == enableForceDesktopMode) {
941                 return;
942             }
943             setForceDesktopModeOnExternalDisplays(enableForceDesktopMode);
944         }
945 
updateFreeformWindowManagement()946         void updateFreeformWindowManagement() {
947             ContentResolver resolver = mContext.getContentResolver();
948             final boolean freeformWindowManagement = mContext.getPackageManager().hasSystemFeature(
949                     FEATURE_FREEFORM_WINDOW_MANAGEMENT) || Settings.Global.getInt(
950                     resolver, DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0;
951 
952             if (mAtmService.mSupportsFreeformWindowManagement != freeformWindowManagement) {
953                 mAtmService.mSupportsFreeformWindowManagement = freeformWindowManagement;
954                 synchronized (mGlobalLock) {
955                     // Notify the root window container that the display settings value may change.
956                     mRoot.onSettingsRetrieved();
957                 }
958             }
959         }
960 
updateForceResizableTasks()961         void updateForceResizableTasks() {
962             ContentResolver resolver = mContext.getContentResolver();
963             final boolean forceResizable = Settings.Global.getInt(resolver,
964                     DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
965 
966             mAtmService.mForceResizableActivities = forceResizable;
967         }
968 
updateDevEnableNonResizableMultiWindow()969         void updateDevEnableNonResizableMultiWindow() {
970             ContentResolver resolver = mContext.getContentResolver();
971             final boolean devEnableNonResizableMultiWindow = Settings.Global.getInt(resolver,
972                     DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW, 0) != 0;
973 
974             mAtmService.mDevEnableNonResizableMultiWindow = devEnableNonResizableMultiWindow;
975         }
976 
updateDisplaySettingsLocation()977         void updateDisplaySettingsLocation() {
978             final ContentResolver resolver = mContext.getContentResolver();
979             final String filePath = Settings.Global.getString(resolver,
980                     DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH);
981             synchronized (mGlobalLock) {
982                 mDisplayWindowSettingsProvider.setBaseSettingsFilePath(filePath);
983                 mRoot.forAllDisplays(display -> {
984                     mDisplayWindowSettings.applySettingsToDisplayLocked(display);
985                     display.reconfigureDisplayLocked();
986                 });
987             }
988         }
989     }
990 
setShadowRenderer()991     private void setShadowRenderer() {
992         mRenderShadowsInCompositor = Settings.Global.getInt(mContext.getContentResolver(),
993                 DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR, 1) != 0;
994     }
995 
996     PowerManager mPowerManager;
997     PowerManagerInternal mPowerManagerInternal;
998 
999     private float mWindowAnimationScaleSetting = 1.0f;
1000     private float mTransitionAnimationScaleSetting = 1.0f;
1001     private float mAnimatorDurationScaleSetting = 1.0f;
1002     private boolean mAnimationsDisabled = false;
1003     boolean mPointerLocationEnabled = false;
1004 
1005     final LetterboxConfiguration mLetterboxConfiguration;
1006 
1007     final InputManagerService mInputManager;
1008     final DisplayManagerInternal mDisplayManagerInternal;
1009     final DisplayManager mDisplayManager;
1010     final ActivityTaskManagerService mAtmService;
1011 
1012     /** Indicates whether this device supports wide color gamut / HDR rendering */
1013     private boolean mHasWideColorGamutSupport;
1014     private boolean mHasHdrSupport;
1015 
1016     /** Who is holding the screen on. */
1017     private Session mHoldingScreenOn;
1018     private PowerManager.WakeLock mHoldingScreenWakeLock;
1019 
1020     /** Whether or not a layout can cause a wake up when theater mode is enabled. */
1021     boolean mAllowTheaterModeWakeFromLayout;
1022 
1023     final TaskPositioningController mTaskPositioningController;
1024     final DragDropController mDragDropController;
1025 
1026     /** For frozen screen animations. */
1027     private int mExitAnimId, mEnterAnimId;
1028 
1029     /** The display that the rotation animation is applying to. */
1030     private int mFrozenDisplayId;
1031 
1032     /** Skip repeated ActivityRecords initialization. Note that AppWindowsToken's version of this
1033      * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
1034     int mTransactionSequence;
1035 
1036     final WindowAnimator mAnimator;
1037     SurfaceAnimationRunner mSurfaceAnimationRunner;
1038 
1039     /**
1040      * Keeps track of which animations got transferred to which animators. Entries will get cleaned
1041      * up when the animation finishes.
1042      */
1043     final ArrayMap<AnimationAdapter, SurfaceAnimator> mAnimationTransferMap = new ArrayMap<>();
1044 
1045     private WindowContentFrameStats mTempWindowRenderStats;
1046 
1047     final LatencyTracker mLatencyTracker;
1048 
1049     /**
1050      * Whether the UI is currently running in touch mode (not showing
1051      * navigational focus because the user is directly pressing the screen).
1052      */
1053     private boolean mInTouchMode;
1054 
1055     private ViewServer mViewServer;
1056     final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>();
1057     boolean mWindowsChanged = false;
1058 
1059     public interface WindowChangeListener {
windowsChanged()1060         public void windowsChanged();
focusChanged()1061         public void focusChanged();
1062     }
1063 
1064     final Configuration mTempConfiguration = new Configuration();
1065 
1066     final HighRefreshRateDenylist mHighRefreshRateDenylist;
1067 
1068     // If true, only the core apps and services are being launched because the device
1069     // is in a special boot mode, such as being encrypted or waiting for a decryption password.
1070     // For example, when this flag is true, there will be no wallpaper service.
1071     final boolean mOnlyCore;
1072 
1073     static WindowManagerThreadPriorityBooster sThreadPriorityBooster =
1074             new WindowManagerThreadPriorityBooster();
1075 
1076     Function<SurfaceSession, SurfaceControl.Builder> mSurfaceControlFactory;
1077     Supplier<SurfaceControl.Transaction> mTransactionFactory;
1078     final Supplier<Surface> mSurfaceFactory;
1079 
1080     private final SurfaceControl.Transaction mTransaction;
1081 
boostPriorityForLockedSection()1082     static void boostPriorityForLockedSection() {
1083         sThreadPriorityBooster.boost();
1084     }
1085 
resetPriorityAfterLockedSection()1086     static void resetPriorityAfterLockedSection() {
1087         sThreadPriorityBooster.reset();
1088     }
1089 
openSurfaceTransaction()1090     void openSurfaceTransaction() {
1091         try {
1092             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "openSurfaceTransaction");
1093             SurfaceControl.openTransaction();
1094         } finally {
1095             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
1096         }
1097     }
1098 
1099     /**
1100      * Closes a surface transaction.
1101      * @param where debug string indicating where the transaction originated
1102      */
closeSurfaceTransaction(String where)1103     void closeSurfaceTransaction(String where) {
1104         try {
1105             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "closeSurfaceTransaction");
1106             SurfaceControl.closeTransaction();
1107             mWindowTracing.logState(where);
1108         } finally {
1109             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
1110         }
1111     }
1112 
1113     /** Listener to notify activity manager about app transitions. */
1114     final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier
1115             = new WindowManagerInternal.AppTransitionListener() {
1116 
1117         @Override
1118         public void onAppTransitionCancelledLocked(boolean keyguardGoingAway) {
1119         }
1120 
1121         @Override
1122         public void onAppTransitionFinishedLocked(IBinder token) {
1123             final ActivityRecord atoken = mRoot.getActivityRecord(token);
1124             if (atoken == null) {
1125                 return;
1126             }
1127 
1128             // While running a recents animation, this will get called early because we show the
1129             // recents animation target activity immediately when the animation starts. Defer the
1130             // mLaunchTaskBehind updates until recents animation finishes.
1131             if (atoken.mLaunchTaskBehind && !isRecentsAnimationTarget(atoken)) {
1132                 mAtmService.mTaskSupervisor.scheduleLaunchTaskBehindComplete(atoken.token);
1133                 atoken.mLaunchTaskBehind = false;
1134             } else {
1135                 atoken.updateReportedVisibilityLocked();
1136                 // We should also defer sending the finished callback until the recents animation
1137                 // successfully finishes.
1138                 if (atoken.mEnteringAnimation && !isRecentsAnimationTarget(atoken)) {
1139                     atoken.mEnteringAnimation = false;
1140                     if (atoken.attachedToProcess()) {
1141                         try {
1142                             atoken.app.getThread().scheduleEnterAnimationComplete(atoken.appToken);
1143                         } catch (RemoteException e) {
1144                         }
1145                     }
1146                 }
1147             }
1148         }
1149     };
1150 
1151     final ArrayList<AppFreezeListener> mAppFreezeListeners = new ArrayList<>();
1152 
1153     interface AppFreezeListener {
onAppFreezeTimeout()1154         void onAppFreezeTimeout();
1155     }
1156 
1157     private static WindowManagerService sInstance;
getInstance()1158     static WindowManagerService getInstance() {
1159         return sInstance;
1160     }
1161 
main(final Context context, final InputManagerService im, final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy, ActivityTaskManagerService atm)1162     public static WindowManagerService main(final Context context, final InputManagerService im,
1163             final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
1164             ActivityTaskManagerService atm) {
1165         return main(context, im, showBootMsgs, onlyCore, policy, atm,
1166                 new DisplayWindowSettingsProvider(), SurfaceControl.Transaction::new, Surface::new,
1167                 SurfaceControl.Builder::new);
1168     }
1169 
1170     /**
1171      * Creates and returns an instance of the WindowManagerService. This call allows the caller
1172      * to override factories that can be used to stub native calls during test.
1173      */
1174     @VisibleForTesting
main(final Context context, final InputManagerService im, final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy, ActivityTaskManagerService atm, DisplayWindowSettingsProvider displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory, Supplier<Surface> surfaceFactory, Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory)1175     public static WindowManagerService main(final Context context, final InputManagerService im,
1176             final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
1177             ActivityTaskManagerService atm, DisplayWindowSettingsProvider
1178             displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory,
1179             Supplier<Surface> surfaceFactory,
1180             Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
1181         DisplayThread.getHandler().runWithScissors(() ->
1182                 sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
1183                         atm, displayWindowSettingsProvider, transactionFactory, surfaceFactory,
1184                         surfaceControlFactory), 0);
1185         return sInstance;
1186     }
1187 
initPolicy()1188     private void initPolicy() {
1189         UiThread.getHandler().runWithScissors(new Runnable() {
1190             @Override
1191             public void run() {
1192                 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
1193                 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
1194             }
1195         }, 0);
1196     }
1197 
1198     @Override
onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver result)1199     public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
1200             String[] args, ShellCallback callback, ResultReceiver result) {
1201         new WindowManagerShellCommand(this).exec(this, in, out, err, args, callback, result);
1202     }
1203 
WindowManagerService(Context context, InputManagerService inputManager, boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy, ActivityTaskManagerService atm, DisplayWindowSettingsProvider displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory, Supplier<Surface> surfaceFactory, Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory)1204     private WindowManagerService(Context context, InputManagerService inputManager,
1205             boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
1206             ActivityTaskManagerService atm, DisplayWindowSettingsProvider
1207             displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory,
1208             Supplier<Surface> surfaceFactory,
1209             Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
1210         installLock(this, INDEX_WINDOW);
1211         mGlobalLock = atm.getGlobalLock();
1212         mAtmService = atm;
1213         mContext = context;
1214         mIsPc = mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
1215         mAllowBootMessages = showBootMsgs;
1216         mOnlyCore = onlyCore;
1217         mLimitedAlphaCompositing = context.getResources().getBoolean(
1218                 com.android.internal.R.bool.config_sf_limitedAlpha);
1219         mHasPermanentDpad = context.getResources().getBoolean(
1220                 com.android.internal.R.bool.config_hasPermanentDpad);
1221         mInTouchMode = context.getResources().getBoolean(
1222                 com.android.internal.R.bool.config_defaultInTouchMode);
1223         inputManager.setInTouchMode(mInTouchMode);
1224         mDrawLockTimeoutMillis = context.getResources().getInteger(
1225                 com.android.internal.R.integer.config_drawLockTimeoutMillis);
1226         mAllowAnimationsInLowPowerMode = context.getResources().getBoolean(
1227                 com.android.internal.R.bool.config_allowAnimationsInLowPowerMode);
1228         mMaxUiWidth = context.getResources().getInteger(
1229                 com.android.internal.R.integer.config_maxUiWidth);
1230         mDisableTransitionAnimation = context.getResources().getBoolean(
1231                 com.android.internal.R.bool.config_disableTransitionAnimation);
1232         mPerDisplayFocusEnabled = context.getResources().getBoolean(
1233                 com.android.internal.R.bool.config_perDisplayFocusEnabled);
1234         mAssistantOnTopOfDream = context.getResources().getBoolean(
1235                 com.android.internal.R.bool.config_assistantOnTopOfDream);
1236 
1237         mLetterboxConfiguration = new LetterboxConfiguration(context);
1238 
1239         mInputManager = inputManager; // Must be before createDisplayContentLocked.
1240         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
1241 
1242         mSurfaceControlFactory = surfaceControlFactory;
1243         mTransactionFactory = transactionFactory;
1244         mSurfaceFactory = surfaceFactory;
1245         mTransaction = mTransactionFactory.get();
1246 
1247         mPolicy = policy;
1248         mAnimator = new WindowAnimator(this);
1249         mRoot = new RootWindowContainer(this);
1250 
1251         final ContentResolver resolver = context.getContentResolver();
1252         mUseBLAST = Settings.Global.getInt(resolver,
1253             Settings.Global.DEVELOPMENT_USE_BLAST_ADAPTER_VR, 1) == 1;
1254 
1255         mSyncEngine = new BLASTSyncEngine(this);
1256 
1257         mWindowPlacerLocked = new WindowSurfacePlacer(this);
1258         mTaskSnapshotController = new TaskSnapshotController(this);
1259 
1260         mWindowTracing = WindowTracing.createDefaultAndStartLooper(this,
1261                 Choreographer.getInstance());
1262 
1263         LocalServices.addService(WindowManagerPolicy.class, mPolicy);
1264 
1265         mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
1266 
1267         mKeyguardDisableHandler = KeyguardDisableHandler.create(mContext, mPolicy, mH);
1268 
1269         mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1270         mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
1271 
1272         if (mPowerManagerInternal != null) {
1273             mPowerManagerInternal.registerLowPowerModeObserver(
1274                     new PowerManagerInternal.LowPowerModeListener() {
1275                 @Override
1276                 public int getServiceType() {
1277                     return ServiceType.ANIMATION;
1278                 }
1279 
1280                 @Override
1281                 public void onLowPowerModeChanged(PowerSaveState result) {
1282                     synchronized (mGlobalLock) {
1283                         final boolean enabled = result.batterySaverEnabled;
1284                         if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
1285                             mAnimationsDisabled = enabled;
1286                             dispatchNewAnimatorScaleLocked(null);
1287                         }
1288                     }
1289                 }
1290             });
1291             mAnimationsDisabled = mPowerManagerInternal
1292                     .getLowPowerState(ServiceType.ANIMATION).batterySaverEnabled;
1293         }
1294         mScreenFrozenLock = mPowerManager.newWakeLock(
1295                 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
1296         mScreenFrozenLock.setReferenceCounted(false);
1297 
1298         mDisplayNotificationController = new DisplayWindowListenerController(this);
1299 
1300         mActivityManager = ActivityManager.getService();
1301         mActivityTaskManager = ActivityTaskManager.getService();
1302         mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
1303         mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
1304         mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
1305         AppOpsManager.OnOpChangedInternalListener opListener =
1306                 new AppOpsManager.OnOpChangedInternalListener() {
1307                     @Override public void onOpChanged(int op, String packageName) {
1308                         updateAppOpsState();
1309                     }
1310                 };
1311         mAppOps.startWatchingMode(OP_SYSTEM_ALERT_WINDOW, null, opListener);
1312         mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener);
1313 
1314         mPmInternal = LocalServices.getService(PackageManagerInternal.class);
1315         mTestUtilityService = LocalServices.getService(TestUtilityService.class);
1316         final IntentFilter suspendPackagesFilter = new IntentFilter();
1317         suspendPackagesFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
1318         suspendPackagesFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
1319         context.registerReceiverAsUser(new BroadcastReceiver() {
1320             @Override
1321             public void onReceive(Context context, Intent intent) {
1322                 final String[] affectedPackages =
1323                         intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
1324                 final boolean suspended =
1325                         Intent.ACTION_PACKAGES_SUSPENDED.equals(intent.getAction());
1326                 updateHiddenWhileSuspendedState(new ArraySet<>(Arrays.asList(affectedPackages)),
1327                         suspended);
1328             }
1329         }, UserHandle.ALL, suspendPackagesFilter, null, null);
1330 
1331         // Get persisted window scale setting
1332         mWindowAnimationScaleSetting = Settings.Global.getFloat(resolver,
1333                 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
1334         mTransitionAnimationScaleSetting = Settings.Global.getFloat(resolver,
1335                 Settings.Global.TRANSITION_ANIMATION_SCALE,
1336                 context.getResources().getFloat(
1337                         R.dimen.config_appTransitionAnimationDurationScaleDefault));
1338 
1339         setAnimatorDurationScale(Settings.Global.getFloat(resolver,
1340                 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting));
1341 
1342         mForceDesktopModeOnExternalDisplays = Settings.Global.getInt(resolver,
1343                 DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS, 0) != 0;
1344 
1345         final String displaySettingsPath = Settings.Global.getString(resolver,
1346                 DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH);
1347         mDisplayWindowSettingsProvider = displayWindowSettingsProvider;
1348         if (displaySettingsPath != null) {
1349             mDisplayWindowSettingsProvider.setBaseSettingsFilePath(displaySettingsPath);
1350         }
1351         mDisplayWindowSettings = new DisplayWindowSettings(this, mDisplayWindowSettingsProvider);
1352 
1353         IntentFilter filter = new IntentFilter();
1354         // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
1355         filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
1356         mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
1357 
1358         mLatencyTracker = LatencyTracker.getInstance(context);
1359 
1360         mSettingsObserver = new SettingsObserver();
1361 
1362         mHoldingScreenWakeLock = mPowerManager.newWakeLock(
1363                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
1364         mHoldingScreenWakeLock.setReferenceCounted(false);
1365 
1366         mSurfaceAnimationRunner = new SurfaceAnimationRunner(mTransactionFactory,
1367                 mPowerManagerInternal);
1368 
1369         mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
1370                 com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
1371 
1372         mTaskPositioningController = new TaskPositioningController(
1373                 this, mInputManager, mActivityTaskManager, mH.getLooper());
1374         mDragDropController = new DragDropController(this, mH.getLooper());
1375 
1376         mHighRefreshRateDenylist = HighRefreshRateDenylist.create(context.getResources());
1377 
1378         mConstants = new WindowManagerConstants(this, DeviceConfigInterface.REAL);
1379         mConstants.start(new HandlerExecutor(mH));
1380 
1381         LocalServices.addService(WindowManagerInternal.class, new LocalService());
1382         mEmbeddedWindowController = new EmbeddedWindowController(mAtmService);
1383 
1384         mDisplayAreaPolicyProvider = DisplayAreaPolicy.Provider.fromResources(
1385                 mContext.getResources());
1386 
1387         mDisplayHashController = new DisplayHashController(mContext);
1388         setGlobalShadowSettings();
1389         mAnrController = new AnrController(this);
1390         mStartingSurfaceController = new StartingSurfaceController(this);
1391 
1392         mBlurController = new BlurController(mContext, mPowerManager);
1393     }
1394 
getDisplayAreaPolicyProvider()1395     DisplayAreaPolicy.Provider getDisplayAreaPolicyProvider() {
1396         return mDisplayAreaPolicyProvider;
1397     }
1398 
setGlobalShadowSettings()1399     private void setGlobalShadowSettings() {
1400         final TypedArray a = mContext.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
1401         float lightY = a.getDimension(R.styleable.Lighting_lightY, 0);
1402         float lightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
1403         float lightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
1404         float ambientShadowAlpha = a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0);
1405         float spotShadowAlpha = a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0);
1406         float[] ambientColor = {0.f, 0.f, 0.f, ambientShadowAlpha};
1407         float[] spotColor = {0.f, 0.f, 0.f, spotShadowAlpha};
1408         SurfaceControl.setGlobalShadowSettings(ambientColor, spotColor, lightY, lightZ,
1409                 lightRadius);
1410         setShadowRenderer();
1411     }
1412 
1413     /**
1414      * Called after all entities (such as the {@link ActivityManagerService}) have been set up and
1415      * associated with the {@link WindowManagerService}.
1416      */
onInitReady()1417     public void onInitReady() {
1418         initPolicy();
1419 
1420         // Add ourself to the Watchdog monitors.
1421         Watchdog.getInstance().addMonitor(this);
1422         createWatermark();
1423         showEmulatorDisplayOverlayIfNeeded();
1424     }
1425 
getInputManagerCallback()1426     public InputManagerCallback getInputManagerCallback() {
1427         return mInputManagerCallback;
1428     }
1429 
1430     @Override
onTransact(int code, Parcel data, Parcel reply, int flags)1431     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1432             throws RemoteException {
1433         try {
1434             return super.onTransact(code, data, reply, flags);
1435         } catch (RuntimeException e) {
1436             // The window manager only throws security exceptions, so let's
1437             // log all others.
1438             if (!(e instanceof SecurityException)) {
1439                 ProtoLog.wtf(WM_ERROR, "Window Manager Crash %s", e);
1440             }
1441             throw e;
1442         }
1443     }
1444 
excludeWindowTypeFromTapOutTask(int windowType)1445     static boolean excludeWindowTypeFromTapOutTask(int windowType) {
1446         switch (windowType) {
1447             case TYPE_STATUS_BAR:
1448             case TYPE_NOTIFICATION_SHADE:
1449             case TYPE_NAVIGATION_BAR:
1450             case TYPE_INPUT_METHOD_DIALOG:
1451             case TYPE_VOLUME_OVERLAY:
1452                 return true;
1453         }
1454         return false;
1455     }
1456 
addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility, int displayId, int requestUserId, InsetsState requestedVisibility, InputChannel outInputChannel, InsetsState outInsetsState, InsetsSourceControl[] outActiveControls)1457     public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
1458             int displayId, int requestUserId, InsetsState requestedVisibility,
1459             InputChannel outInputChannel, InsetsState outInsetsState,
1460             InsetsSourceControl[] outActiveControls) {
1461         Arrays.fill(outActiveControls, null);
1462         int[] appOp = new int[1];
1463         final boolean isRoundedCornerOverlay = (attrs.privateFlags
1464                 & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0;
1465         int res = mPolicy.checkAddPermission(attrs.type, isRoundedCornerOverlay, attrs.packageName,
1466                 appOp);
1467         if (res != ADD_OKAY) {
1468             return res;
1469         }
1470 
1471         WindowState parentWindow = null;
1472         final int callingUid = Binder.getCallingUid();
1473         final int callingPid = Binder.getCallingPid();
1474         final long origId = Binder.clearCallingIdentity();
1475         final int type = attrs.type;
1476 
1477         synchronized (mGlobalLock) {
1478             if (!mDisplayReady) {
1479                 throw new IllegalStateException("Display has not been initialialized");
1480             }
1481 
1482             final DisplayContent displayContent = getDisplayContentOrCreate(displayId, attrs.token);
1483 
1484             if (displayContent == null) {
1485                 ProtoLog.w(WM_ERROR, "Attempted to add window to a display that does "
1486                         + "not exist: %d. Aborting.", displayId);
1487                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
1488             }
1489             if (!displayContent.hasAccess(session.mUid)) {
1490                 ProtoLog.w(WM_ERROR,
1491                         "Attempted to add window to a display for which the application "
1492                                 + "does not have access: %d.  Aborting.",
1493                         displayContent.getDisplayId());
1494                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
1495             }
1496 
1497             if (mWindowMap.containsKey(client.asBinder())) {
1498                 ProtoLog.w(WM_ERROR, "Window %s is already added", client);
1499                 return WindowManagerGlobal.ADD_DUPLICATE_ADD;
1500             }
1501 
1502             if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
1503                 parentWindow = windowForClientLocked(null, attrs.token, false);
1504                 if (parentWindow == null) {
1505                     ProtoLog.w(WM_ERROR, "Attempted to add window with token that is not a window: "
1506                             + "%s.  Aborting.", attrs.token);
1507                     return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
1508                 }
1509                 if (parentWindow.mAttrs.type >= FIRST_SUB_WINDOW
1510                         && parentWindow.mAttrs.type <= LAST_SUB_WINDOW) {
1511                     ProtoLog.w(WM_ERROR, "Attempted to add window with token that is a sub-window: "
1512                             + "%s.  Aborting.", attrs.token);
1513                     return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
1514                 }
1515             }
1516 
1517             if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) {
1518                 ProtoLog.w(WM_ERROR,
1519                         "Attempted to add private presentation window to a non-private display.  "
1520                                 + "Aborting.");
1521                 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
1522             }
1523 
1524             if (type == TYPE_PRESENTATION && !displayContent.getDisplay().isPublicPresentation()) {
1525                 ProtoLog.w(WM_ERROR,
1526                         "Attempted to add presentation window to a non-suitable display.  "
1527                                 + "Aborting.");
1528                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
1529             }
1530 
1531             int userId = UserHandle.getUserId(session.mUid);
1532             if (requestUserId != userId) {
1533                 try {
1534                     mAmInternal.handleIncomingUser(callingPid, callingUid, requestUserId,
1535                             false /*allowAll*/, ALLOW_NON_FULL, null, null);
1536                 } catch (Exception exp) {
1537                     ProtoLog.w(WM_ERROR, "Trying to add window with invalid user=%d",
1538                             requestUserId);
1539                     return WindowManagerGlobal.ADD_INVALID_USER;
1540                 }
1541                 // It's fine to use this userId
1542                 userId = requestUserId;
1543             }
1544 
1545             ActivityRecord activity = null;
1546             final boolean hasParent = parentWindow != null;
1547             // Use existing parent window token for child windows since they go in the same token
1548             // as there parent window so we can apply the same policy on them.
1549             WindowToken token = displayContent.getWindowToken(
1550                     hasParent ? parentWindow.mAttrs.token : attrs.token);
1551             // If this is a child window, we want to apply the same type checking rules as the
1552             // parent window type.
1553             final int rootType = hasParent ? parentWindow.mAttrs.type : type;
1554 
1555             boolean addToastWindowRequiresToken = false;
1556 
1557             final IBinder windowContextToken = attrs.mWindowContextToken;
1558 
1559             if (token == null) {
1560                 if (!unprivilegedAppCanCreateTokenWith(parentWindow, callingUid, type,
1561                         rootType, attrs.token, attrs.packageName)) {
1562                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1563                 }
1564                 if (hasParent) {
1565                     // Use existing parent window token for child windows.
1566                     token = parentWindow.mToken;
1567                 } else if (mWindowContextListenerController.hasListener(windowContextToken)) {
1568                     // Respect the window context token if the user provided it.
1569                     final IBinder binder = attrs.token != null ? attrs.token : windowContextToken;
1570                     final Bundle options = mWindowContextListenerController
1571                             .getOptions(windowContextToken);
1572                     token = new WindowToken.Builder(this, binder, type)
1573                             .setDisplayContent(displayContent)
1574                             .setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow)
1575                             .setRoundedCornerOverlay(isRoundedCornerOverlay)
1576                             .setFromClientToken(true)
1577                             .setOptions(options)
1578                             .build();
1579                 } else {
1580                     final IBinder binder = attrs.token != null ? attrs.token : client.asBinder();
1581                     token = new WindowToken.Builder(this, binder, type)
1582                             .setDisplayContent(displayContent)
1583                             .setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow)
1584                             .setRoundedCornerOverlay(isRoundedCornerOverlay)
1585                             .build();
1586                 }
1587             } else if (rootType >= FIRST_APPLICATION_WINDOW
1588                     && rootType <= LAST_APPLICATION_WINDOW) {
1589                 activity = token.asActivityRecord();
1590                 if (activity == null) {
1591                     ProtoLog.w(WM_ERROR, "Attempted to add window with non-application token "
1592                             + ".%s Aborting.", token);
1593                     return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
1594                 } else if (activity.getParent() == null) {
1595                     ProtoLog.w(WM_ERROR, "Attempted to add window with exiting application token "
1596                             + ".%s Aborting.", token);
1597                     return WindowManagerGlobal.ADD_APP_EXITING;
1598                 } else if (type == TYPE_APPLICATION_STARTING) {
1599                     if (activity.mStartingWindow != null) {
1600                         ProtoLog.w(WM_ERROR, "Attempted to add starting window to "
1601                                 + "token with already existing starting window");
1602                         return WindowManagerGlobal.ADD_DUPLICATE_ADD;
1603                     }
1604                     if (activity.mStartingData == null) {
1605                         ProtoLog.w(WM_ERROR, "Attempted to add starting window to "
1606                                 + "token but already cleaned");
1607                         return WindowManagerGlobal.ADD_DUPLICATE_ADD;
1608                     }
1609                 }
1610             } else if (rootType == TYPE_INPUT_METHOD) {
1611                 if (token.windowType != TYPE_INPUT_METHOD) {
1612                     ProtoLog.w(WM_ERROR, "Attempted to add input method window with bad token "
1613                             + "%s.  Aborting.", attrs.token);
1614                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1615                 }
1616             } else if (rootType == TYPE_VOICE_INTERACTION) {
1617                 if (token.windowType != TYPE_VOICE_INTERACTION) {
1618                     ProtoLog.w(WM_ERROR, "Attempted to add voice interaction window with bad token "
1619                             + "%s.  Aborting.", attrs.token);
1620                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1621                 }
1622             } else if (rootType == TYPE_WALLPAPER) {
1623                 if (token.windowType != TYPE_WALLPAPER) {
1624                     ProtoLog.w(WM_ERROR, "Attempted to add wallpaper window with bad token "
1625                             + "%s.  Aborting.", attrs.token);
1626                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1627                 }
1628             } else if (rootType == TYPE_ACCESSIBILITY_OVERLAY) {
1629                 if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) {
1630                     ProtoLog.w(WM_ERROR,
1631                             "Attempted to add Accessibility overlay window with bad token "
1632                                     + "%s.  Aborting.", attrs.token);
1633                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1634                 }
1635             } else if (type == TYPE_TOAST) {
1636                 // Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
1637                 addToastWindowRequiresToken = doesAddToastWindowRequireToken(attrs.packageName,
1638                         callingUid, parentWindow);
1639                 if (addToastWindowRequiresToken && token.windowType != TYPE_TOAST) {
1640                     ProtoLog.w(WM_ERROR, "Attempted to add a toast window with bad token "
1641                             + "%s.  Aborting.", attrs.token);
1642                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1643                 }
1644             } else if (type == TYPE_QS_DIALOG) {
1645                 if (token.windowType != TYPE_QS_DIALOG) {
1646                     ProtoLog.w(WM_ERROR, "Attempted to add QS dialog window with bad token "
1647                             + "%s.  Aborting.", attrs.token);
1648                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1649                 }
1650             } else if (token.asActivityRecord() != null) {
1651                 ProtoLog.w(WM_ERROR, "Non-null activity for system window of rootType=%d",
1652                         rootType);
1653                 // It is not valid to use an app token with other system types; we will
1654                 // instead make a new token for it (as if null had been passed in for the token).
1655                 attrs.token = null;
1656                 token = new WindowToken.Builder(this, client.asBinder(), type)
1657                         .setDisplayContent(displayContent)
1658                         .setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow)
1659                         .build();
1660             }
1661 
1662             final WindowState win = new WindowState(this, session, client, token, parentWindow,
1663                     appOp[0], attrs, viewVisibility, session.mUid, userId,
1664                     session.mCanAddInternalSystemWindow);
1665             if (win.mDeathRecipient == null) {
1666                 // Client has apparently died, so there is no reason to
1667                 // continue.
1668                 ProtoLog.w(WM_ERROR, "Adding window client %s"
1669                         + " that is dead, aborting.", client.asBinder());
1670                 return WindowManagerGlobal.ADD_APP_EXITING;
1671             }
1672 
1673             if (win.getDisplayContent() == null) {
1674                 ProtoLog.w(WM_ERROR, "Adding window to Display that has been removed.");
1675                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
1676             }
1677 
1678             final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
1679             displayPolicy.adjustWindowParamsLw(win, win.mAttrs);
1680             win.updateRequestedVisibility(requestedVisibility);
1681 
1682             res = displayPolicy.validateAddingWindowLw(attrs, callingPid, callingUid);
1683             if (res != ADD_OKAY) {
1684                 return res;
1685             }
1686 
1687             final boolean openInputChannels = (outInputChannel != null
1688                     && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
1689             if  (openInputChannels) {
1690                 win.openInputChannel(outInputChannel);
1691             }
1692 
1693             // If adding a toast requires a token for this app we always schedule hiding
1694             // toast windows to make sure they don't stick around longer then necessary.
1695             // We hide instead of remove such windows as apps aren't prepared to handle
1696             // windows being removed under them.
1697             //
1698             // If the app is older it can add toasts without a token and hence overlay
1699             // other apps. To be maximally compatible with these apps we will hide the
1700             // window after the toast timeout only if the focused window is from another
1701             // UID, otherwise we allow unlimited duration. When a UID looses focus we
1702             // schedule hiding all of its toast windows.
1703             if (type == TYPE_TOAST) {
1704                 if (!displayContent.canAddToastWindowForUid(callingUid)) {
1705                     ProtoLog.w(WM_ERROR, "Adding more than one toast window for UID at a time.");
1706                     return WindowManagerGlobal.ADD_DUPLICATE_ADD;
1707                 }
1708                 // Make sure this happens before we moved focus as one can make the
1709                 // toast focusable to force it not being hidden after the timeout.
1710                 // Focusable toasts are always timed out to prevent a focused app to
1711                 // show a focusable toasts while it has focus which will be kept on
1712                 // the screen after the activity goes away.
1713                 if (addToastWindowRequiresToken
1714                         || (attrs.flags & FLAG_NOT_FOCUSABLE) == 0
1715                         || displayContent.mCurrentFocus == null
1716                         || displayContent.mCurrentFocus.mOwnerUid != callingUid) {
1717                     mH.sendMessageDelayed(
1718                             mH.obtainMessage(H.WINDOW_HIDE_TIMEOUT, win),
1719                             win.mAttrs.hideTimeoutMilliseconds);
1720                 }
1721             }
1722 
1723             // Switch to listen to the {@link WindowToken token}'s configuration changes when
1724             // adding a window to the window context. Filter sub window type here because the sub
1725             // window must be attached to the parent window, which is attached to the window context
1726             // created window token.
1727             if (!win.isChildWindow()
1728                     && mWindowContextListenerController.hasListener(windowContextToken)) {
1729                 final int windowContextType = mWindowContextListenerController
1730                         .getWindowType(windowContextToken);
1731                 if (type != windowContextType) {
1732                     ProtoLog.w(WM_ERROR, "Window types in WindowContext and"
1733                             + " LayoutParams.type should match! Type from LayoutParams is %d,"
1734                             + " but type from WindowContext is %d", type, windowContextType);
1735                     return WindowManagerGlobal.ADD_INVALID_TYPE;
1736                 }
1737                 final Bundle options = mWindowContextListenerController
1738                         .getOptions(windowContextToken);
1739                 mWindowContextListenerController.registerWindowContainerListener(
1740                         windowContextToken, token, callingUid, type, options);
1741             }
1742 
1743             // From now on, no exceptions or errors allowed!
1744 
1745             res = ADD_OKAY;
1746 
1747             if (mUseBLAST) {
1748                 res |= WindowManagerGlobal.ADD_FLAG_USE_BLAST;
1749             }
1750 
1751             if (displayContent.mCurrentFocus == null) {
1752                 displayContent.mWinAddedSinceNullFocus.add(win);
1753             }
1754 
1755             if (excludeWindowTypeFromTapOutTask(type)) {
1756                 displayContent.mTapExcludedWindows.add(win);
1757             }
1758 
1759             win.attach();
1760             mWindowMap.put(client.asBinder(), win);
1761             win.initAppOpsState();
1762 
1763             final boolean suspended = mPmInternal.isPackageSuspended(win.getOwningPackage(),
1764                     UserHandle.getUserId(win.getOwningUid()));
1765             win.setHiddenWhileSuspended(suspended);
1766 
1767             final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty();
1768             win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);
1769 
1770             final ActivityRecord tokenActivity = token.asActivityRecord();
1771             if (type == TYPE_APPLICATION_STARTING && tokenActivity != null) {
1772                 tokenActivity.mStartingWindow = win;
1773                 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "addWindow: %s startingWindow=%s",
1774                         activity, win);
1775             }
1776 
1777             boolean imMayMove = true;
1778 
1779             win.mToken.addWindow(win);
1780             displayPolicy.addWindowLw(win, attrs);
1781             if (type == TYPE_INPUT_METHOD) {
1782                 displayContent.setInputMethodWindowLocked(win);
1783                 imMayMove = false;
1784             } else if (type == TYPE_INPUT_METHOD_DIALOG) {
1785                 displayContent.computeImeTarget(true /* updateImeTarget */);
1786                 imMayMove = false;
1787             } else {
1788                 if (type == TYPE_WALLPAPER) {
1789                     displayContent.mWallpaperController.clearLastWallpaperTimeoutTime();
1790                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1791                 } else if (win.hasWallpaper()) {
1792                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1793                 } else if (displayContent.mWallpaperController.isBelowWallpaperTarget(win)) {
1794                     // If there is currently a wallpaper being shown, and
1795                     // the base layer of the new window is below the current
1796                     // layer of the target window, then adjust the wallpaper.
1797                     // This is to avoid a new window being placed between the
1798                     // wallpaper and its target.
1799                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1800                 }
1801             }
1802 
1803             final WindowStateAnimator winAnimator = win.mWinAnimator;
1804             winAnimator.mEnterAnimationPending = true;
1805             winAnimator.mEnteringAnimation = true;
1806             // Check if we need to prepare a transition for replacing window first.
1807             if (activity != null && activity.isVisible()
1808                     && !prepareWindowReplacementTransition(activity)) {
1809                 // If not, check if need to set up a dummy transition during display freeze
1810                 // so that the unfreeze wait for the apps to draw. This might be needed if
1811                 // the app is relaunching.
1812                 prepareNoneTransitionForRelaunching(activity);
1813             }
1814 
1815             if (displayPolicy.getLayoutHint(win.mAttrs, token, outInsetsState,
1816                     win.isClientLocal())) {
1817                 res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_SYSTEM_BARS;
1818             }
1819 
1820             if (mInTouchMode) {
1821                 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
1822             }
1823             if (win.mActivityRecord == null || win.mActivityRecord.isClientVisible()) {
1824                 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
1825             }
1826 
1827             displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
1828 
1829             boolean focusChanged = false;
1830             if (win.canReceiveKeys()) {
1831                 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
1832                         false /*updateInputWindows*/);
1833                 if (focusChanged) {
1834                     imMayMove = false;
1835                 }
1836             }
1837 
1838             if (imMayMove) {
1839                 displayContent.computeImeTarget(true /* updateImeTarget */);
1840             }
1841 
1842             // Don't do layout here, the window must call
1843             // relayout to be displayed, so we'll do it there.
1844             win.getParent().assignChildLayers();
1845 
1846             if (focusChanged) {
1847                 displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus,
1848                         false /*updateInputWindows*/);
1849             }
1850             displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
1851 
1852             ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addWindow: New client %s"
1853                     + ": window=%s Callers=%s", client.asBinder(), win, Debug.getCallers(5));
1854 
1855             if (win.isVisibleOrAdding() && displayContent.updateOrientation()) {
1856                 displayContent.sendNewConfiguration();
1857             }
1858 
1859             // This window doesn't have a frame yet. Don't let this window cause the insets change.
1860             displayContent.getInsetsStateController().updateAboveInsetsState(
1861                     win, false /* notifyInsetsChanged */);
1862 
1863             getInsetsSourceControls(win, outActiveControls);
1864         }
1865 
1866         Binder.restoreCallingIdentity(origId);
1867 
1868         return res;
1869     }
1870 
unprivilegedAppCanCreateTokenWith(WindowState parentWindow, int callingUid, int type, int rootType, IBinder tokenForLog, String packageName)1871     private boolean unprivilegedAppCanCreateTokenWith(WindowState parentWindow,
1872             int callingUid, int type, int rootType, IBinder tokenForLog, String packageName) {
1873         if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
1874             ProtoLog.w(WM_ERROR, "Attempted to add application window with unknown token "
1875                     + "%s.  Aborting.", tokenForLog);
1876             return false;
1877         }
1878         if (rootType == TYPE_INPUT_METHOD) {
1879             ProtoLog.w(WM_ERROR, "Attempted to add input method window with unknown token "
1880                     + "%s.  Aborting.", tokenForLog);
1881             return false;
1882         }
1883         if (rootType == TYPE_VOICE_INTERACTION) {
1884             ProtoLog.w(WM_ERROR,
1885                     "Attempted to add voice interaction window with unknown token "
1886                             + "%s.  Aborting.", tokenForLog);
1887             return false;
1888         }
1889         if (rootType == TYPE_WALLPAPER) {
1890             ProtoLog.w(WM_ERROR, "Attempted to add wallpaper window with unknown token "
1891                     + "%s.  Aborting.", tokenForLog);
1892             return false;
1893         }
1894         if (rootType == TYPE_QS_DIALOG) {
1895             ProtoLog.w(WM_ERROR, "Attempted to add QS dialog window with unknown token "
1896                     + "%s.  Aborting.", tokenForLog);
1897             return false;
1898         }
1899         if (rootType == TYPE_ACCESSIBILITY_OVERLAY) {
1900             ProtoLog.w(WM_ERROR,
1901                     "Attempted to add Accessibility overlay window with unknown token "
1902                             + "%s.  Aborting.", tokenForLog);
1903             return false;
1904         }
1905         if (type == TYPE_TOAST) {
1906             // Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
1907             if (doesAddToastWindowRequireToken(packageName, callingUid, parentWindow)) {
1908                 ProtoLog.w(WM_ERROR, "Attempted to add a toast window with unknown token "
1909                         + "%s.  Aborting.", tokenForLog);
1910                 return false;
1911             }
1912         }
1913         return true;
1914     }
1915 
1916     /**
1917      * Get existing {@link DisplayContent} or create a new one if the display is registered in
1918      * DisplayManager.
1919      *
1920      * NOTE: This should only be used in cases when there is a chance that a {@link DisplayContent}
1921      * that corresponds to a display just added to DisplayManager has not yet been created. This
1922      * usually means that the call of this method was initiated from outside of Activity or Window
1923      * Manager. In most cases the regular getter should be used.
1924      * @param displayId The preferred display Id.
1925      * @param token The window token associated with the window we are trying to get display for.
1926      *              if not null then the display of the window token will be returned. Set to null
1927      *              is there isn't an a token associated with the request.
1928      * @see RootWindowContainer#getDisplayContent(int)
1929      */
getDisplayContentOrCreate(int displayId, IBinder token)1930     private DisplayContent getDisplayContentOrCreate(int displayId, IBinder token) {
1931         if (token != null) {
1932             final WindowToken wToken = mRoot.getWindowToken(token);
1933             if (wToken != null) {
1934                 return wToken.getDisplayContent();
1935             }
1936         }
1937 
1938         return mRoot.getDisplayContentOrCreate(displayId);
1939     }
1940 
doesAddToastWindowRequireToken(String packageName, int callingUid, WindowState attachedWindow)1941     private boolean doesAddToastWindowRequireToken(String packageName, int callingUid,
1942             WindowState attachedWindow) {
1943         // Try using the target SDK of the root window
1944         if (attachedWindow != null) {
1945             return attachedWindow.mActivityRecord != null
1946                     && attachedWindow.mActivityRecord.mTargetSdk >= Build.VERSION_CODES.O;
1947         } else {
1948             // Otherwise, look at the package
1949             try {
1950                 ApplicationInfo appInfo = mContext.getPackageManager()
1951                         .getApplicationInfoAsUser(packageName, 0,
1952                                 UserHandle.getUserId(callingUid));
1953                 if (appInfo.uid != callingUid) {
1954                     throw new SecurityException("Package " + packageName + " not in UID "
1955                             + callingUid);
1956                 }
1957                 if (appInfo.targetSdkVersion >= Build.VERSION_CODES.O) {
1958                     return true;
1959                 }
1960             } catch (PackageManager.NameNotFoundException e) {
1961                 /* ignore */
1962             }
1963         }
1964         return false;
1965     }
1966 
1967     /**
1968      * Returns true if we're done setting up any transitions.
1969      */
prepareWindowReplacementTransition(ActivityRecord activity)1970     private boolean prepareWindowReplacementTransition(ActivityRecord activity) {
1971         activity.clearAllDrawn();
1972         final WindowState replacedWindow = activity.getReplacingWindow();
1973         if (replacedWindow == null) {
1974             // We expect to already receive a request to remove the old window. If it did not
1975             // happen, let's just simply add a window.
1976             return false;
1977         }
1978         // We use the visible frame, because we want the animation to morph the window from what
1979         // was visible to the user to the final destination of the new window.
1980         final Rect frame = new Rect(replacedWindow.getFrame());
1981         frame.inset(replacedWindow.getInsetsStateWithVisibilityOverride().calculateVisibleInsets(
1982                 frame, replacedWindow.mAttrs.softInputMode));
1983         // We treat this as if this activity was opening, so we can trigger the app transition
1984         // animation and piggy-back on existing transition animation infrastructure.
1985         final DisplayContent dc = activity.getDisplayContent();
1986         dc.mOpeningApps.add(activity);
1987         dc.prepareAppTransition(TRANSIT_RELAUNCH);
1988         dc.mAppTransition.overridePendingAppTransitionClipReveal(frame.left, frame.top,
1989                 frame.width(), frame.height());
1990         dc.executeAppTransition();
1991         return true;
1992     }
1993 
prepareNoneTransitionForRelaunching(ActivityRecord activity)1994     private void prepareNoneTransitionForRelaunching(ActivityRecord activity) {
1995         // Set up a none-transition and add the app to opening apps, so that the display
1996         // unfreeze wait for the apps to be drawn.
1997         // Note that if the display unfroze already because app unfreeze timed out,
1998         // we don't set up the transition anymore and just let it go.
1999         final DisplayContent dc = activity.getDisplayContent();
2000         if (mDisplayFrozen && !dc.mOpeningApps.contains(activity) && activity.isRelaunching()) {
2001             dc.mOpeningApps.add(activity);
2002             dc.prepareAppTransition(TRANSIT_NONE);
2003             dc.executeAppTransition();
2004         }
2005     }
2006 
2007     /**
2008      * Set whether screen capture is disabled for all windows of a specific user from
2009      * the device policy cache.
2010      */
2011     @Override
refreshScreenCaptureDisabled(int userId)2012     public void refreshScreenCaptureDisabled(int userId) {
2013         int callingUid = Binder.getCallingUid();
2014         if (callingUid != SYSTEM_UID) {
2015             throw new SecurityException("Only system can call refreshScreenCaptureDisabled.");
2016         }
2017 
2018         synchronized (mGlobalLock) {
2019             // Update secure surface for all windows belonging to this user.
2020             mRoot.setSecureSurfaceState(userId);
2021         }
2022     }
2023 
removeWindow(Session session, IWindow client)2024     void removeWindow(Session session, IWindow client) {
2025         synchronized (mGlobalLock) {
2026             WindowState win = windowForClientLocked(session, client, false);
2027             if (win != null) {
2028                 win.removeIfPossible();
2029                 return;
2030             }
2031 
2032             // Remove embedded window map if the token belongs to an embedded window
2033             mEmbeddedWindowController.remove(client);
2034         }
2035     }
2036 
2037     /**
2038      * Performs some centralized bookkeeping clean-up on the window that is being removed.
2039      * NOTE: Should only be called from {@link WindowState#removeImmediately()}
2040      * TODO: Maybe better handled with a method {@link WindowContainer#removeChild} if we can
2041      * figure-out a good way to have all parents of a WindowState doing the same thing without
2042      * forgetting to add the wiring when a new parent of WindowState is added.
2043      */
postWindowRemoveCleanupLocked(WindowState win)2044     void postWindowRemoveCleanupLocked(WindowState win) {
2045         ProtoLog.v(WM_DEBUG_ADD_REMOVE, "postWindowRemoveCleanupLocked: %s", win);
2046         mWindowMap.remove(win.mClient.asBinder());
2047 
2048         final DisplayContent dc = win.getDisplayContent();
2049         dc.getDisplayRotation().markForSeamlessRotation(win, false /* seamlesslyRotated */);
2050 
2051         win.resetAppOpsState();
2052 
2053         if (dc.mCurrentFocus == null) {
2054             dc.mWinRemovedSinceNullFocus.add(win);
2055         }
2056         mEmbeddedWindowController.onWindowRemoved(win);
2057         mPendingRemove.remove(win);
2058         mResizingWindows.remove(win);
2059         updateNonSystemOverlayWindowsVisibilityIfNeeded(win, false /* surfaceShown */);
2060         mWindowsChanged = true;
2061         ProtoLog.v(WM_DEBUG_WINDOW_MOVEMENT, "Final remove of window: %s", win);
2062 
2063         final DisplayContent displayContent = win.getDisplayContent();
2064         if (displayContent.mInputMethodWindow == win) {
2065             displayContent.setInputMethodWindowLocked(null);
2066         }
2067 
2068         final WindowToken token = win.mToken;
2069         final ActivityRecord activity = win.mActivityRecord;
2070         ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Removing %s from %s", win, token);
2071         // Window will already be removed from token before this post clean-up method is called.
2072         if (token.isEmpty()) {
2073             if (!token.mPersistOnEmpty) {
2074                 token.removeImmediately();
2075             } else if (activity != null) {
2076                 // TODO: Should this be moved into ActivityRecord.removeWindow? Might go away after
2077                 // re-factor.
2078                 activity.firstWindowDrawn = false;
2079                 activity.clearAllDrawn();
2080                 final Task rootTask = activity.getRootTask();
2081                 if (rootTask != null) {
2082                     rootTask.mExitingActivities.remove(activity);
2083                 }
2084             }
2085         }
2086 
2087         if (activity != null) {
2088             activity.postWindowRemoveStartingWindowCleanup(win);
2089         }
2090 
2091         if (win.mAttrs.type == TYPE_WALLPAPER) {
2092             dc.mWallpaperController.clearLastWallpaperTimeoutTime();
2093             dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2094         } else if (win.hasWallpaper()) {
2095             dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2096         }
2097 
2098         if (dc != null && !mWindowPlacerLocked.isInLayout()) {
2099             dc.assignWindowLayers(true /* setLayoutNeeded */);
2100             mWindowPlacerLocked.performSurfacePlacement();
2101             if (win.mActivityRecord != null) {
2102                 win.mActivityRecord.updateReportedVisibilityLocked();
2103             }
2104         }
2105 
2106         dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
2107     }
2108 
updateHiddenWhileSuspendedState(ArraySet<String> packages, boolean suspended)2109     private void updateHiddenWhileSuspendedState(ArraySet<String> packages, boolean suspended) {
2110         synchronized (mGlobalLock) {
2111             mRoot.updateHiddenWhileSuspendedState(packages, suspended);
2112         }
2113     }
2114 
updateAppOpsState()2115     private void updateAppOpsState() {
2116         synchronized (mGlobalLock) {
2117             mRoot.updateAppOpsState();
2118         }
2119     }
2120 
logSurface(WindowState w, String msg, boolean withStackTrace)2121     static void logSurface(WindowState w, String msg, boolean withStackTrace) {
2122         String str = "  SURFACE " + msg + ": " + w;
2123         if (withStackTrace) {
2124             logWithStack(TAG, str);
2125         } else {
2126             Slog.i(TAG_WM, str);
2127         }
2128     }
2129 
logWithStack(String tag, String s)2130     static void logWithStack(String tag, String s) {
2131         RuntimeException e = null;
2132         if (SHOW_STACK_CRAWLS) {
2133             e = new RuntimeException();
2134             e.fillInStackTrace();
2135         }
2136         Slog.i(tag, s, e);
2137     }
2138 
setInsetsWindow(Session session, IWindow client, int touchableInsets, Rect contentInsets, Rect visibleInsets, Region touchableRegion)2139     void setInsetsWindow(Session session, IWindow client, int touchableInsets, Rect contentInsets,
2140             Rect visibleInsets, Region touchableRegion) {
2141         int uid = Binder.getCallingUid();
2142         final long origId = Binder.clearCallingIdentity();
2143         try {
2144             synchronized (mGlobalLock) {
2145                 WindowState w = windowForClientLocked(session, client, false);
2146                 if (DEBUG_LAYOUT) Slog.d(TAG, "setInsetsWindow " + w
2147                         + ", contentInsets=" + w.mGivenContentInsets + " -> " + contentInsets
2148                         + ", visibleInsets=" + w.mGivenVisibleInsets + " -> " + visibleInsets
2149                         + ", touchableRegion=" + w.mGivenTouchableRegion + " -> " + touchableRegion
2150                         + ", touchableInsets " + w.mTouchableInsets + " -> " + touchableInsets);
2151                 if (w != null) {
2152                     w.mGivenInsetsPending = false;
2153                     w.mGivenContentInsets.set(contentInsets);
2154                     w.mGivenVisibleInsets.set(visibleInsets);
2155                     w.mGivenTouchableRegion.set(touchableRegion);
2156                     w.mTouchableInsets = touchableInsets;
2157                     if (w.mGlobalScale != 1) {
2158                         w.mGivenContentInsets.scale(w.mGlobalScale);
2159                         w.mGivenVisibleInsets.scale(w.mGlobalScale);
2160                         w.mGivenTouchableRegion.scale(w.mGlobalScale);
2161                     }
2162                     w.setDisplayLayoutNeeded();
2163                     mWindowPlacerLocked.performSurfacePlacement();
2164 
2165                     // We need to report touchable region changes to accessibility.
2166                     if (mAccessibilityController != null) {
2167                         mAccessibilityController.onSomeWindowResizedOrMovedWithCallingUid(
2168                                 uid, w.getDisplayContent().getDisplayId());
2169                     }
2170                 }
2171             }
2172         } finally {
2173             Binder.restoreCallingIdentity(origId);
2174         }
2175     }
2176 
onRectangleOnScreenRequested(IBinder token, Rect rectangle)2177     public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
2178         synchronized (mGlobalLock) {
2179             if (mAccessibilityController != null) {
2180                 WindowState window = mWindowMap.get(token);
2181                 if (window != null) {
2182                     mAccessibilityController.onRectangleOnScreenRequested(
2183                             window.getDisplayId(), rectangle);
2184                 }
2185             }
2186         }
2187     }
2188 
getWindowId(IBinder token)2189     public IWindowId getWindowId(IBinder token) {
2190         synchronized (mGlobalLock) {
2191             WindowState window = mWindowMap.get(token);
2192             return window != null ? window.mWindowId : null;
2193         }
2194     }
2195 
pokeDrawLock(Session session, IBinder token)2196     public void pokeDrawLock(Session session, IBinder token) {
2197         synchronized (mGlobalLock) {
2198             WindowState window = windowForClientLocked(session, token, false);
2199             if (window != null) {
2200                 window.pokeDrawLockLw(mDrawLockTimeoutMillis);
2201             }
2202         }
2203     }
2204 
hasStatusBarPermission(int pid, int uid)2205     private boolean hasStatusBarPermission(int pid, int uid) {
2206         return mContext.checkPermission(permission.STATUS_BAR, pid, uid)
2207                         == PackageManager.PERMISSION_GRANTED;
2208     }
2209 
relayoutWindow(Session session, IWindow client, LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, long frameNumber, ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState, InsetsSourceControl[] outActiveControls, Point outSurfaceSize)2210     public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,
2211             int requestedWidth, int requestedHeight, int viewVisibility, int flags,
2212             long frameNumber, ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
2213             SurfaceControl outSurfaceControl, InsetsState outInsetsState,
2214             InsetsSourceControl[] outActiveControls, Point outSurfaceSize) {
2215         Arrays.fill(outActiveControls, null);
2216         int result = 0;
2217         boolean configChanged;
2218         final int pid = Binder.getCallingPid();
2219         final int uid = Binder.getCallingUid();
2220         final long origId = Binder.clearCallingIdentity();
2221         synchronized (mGlobalLock) {
2222             final WindowState win = windowForClientLocked(session, client, false);
2223             if (win == null) {
2224                 return 0;
2225             }
2226             final DisplayContent displayContent = win.getDisplayContent();
2227             final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
2228 
2229             WindowStateAnimator winAnimator = win.mWinAnimator;
2230             if (viewVisibility != View.GONE) {
2231                 win.setRequestedSize(requestedWidth, requestedHeight);
2232             }
2233 
2234             win.setFrameNumber(frameNumber);
2235 
2236             int attrChanges = 0;
2237             int flagChanges = 0;
2238             int privateFlagChanges = 0;
2239             if (attrs != null) {
2240                 displayPolicy.adjustWindowParamsLw(win, attrs);
2241                 win.mToken.adjustWindowParams(win, attrs);
2242                 int disableFlags =
2243                         (attrs.systemUiVisibility | attrs.subtreeSystemUiVisibility) & DISABLE_MASK;
2244                 if (disableFlags != 0 && !hasStatusBarPermission(pid, uid)) {
2245                     disableFlags = 0;
2246                 }
2247                 win.mDisableFlags = disableFlags;
2248                 if (win.mAttrs.type != attrs.type) {
2249                     throw new IllegalArgumentException(
2250                             "Window type can not be changed after the window is added.");
2251                 }
2252                 if (!Arrays.equals(win.mAttrs.providesInsetsTypes, attrs.providesInsetsTypes)) {
2253                     throw new IllegalArgumentException(
2254                             "Insets types can not be changed after the window is added.");
2255                 }
2256 
2257                 flagChanges = win.mAttrs.flags ^ attrs.flags;
2258                 privateFlagChanges = win.mAttrs.privateFlags ^ attrs.privateFlags;
2259                 attrChanges = win.mAttrs.copyFrom(attrs);
2260                 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
2261                         | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
2262                     win.mLayoutNeeded = true;
2263                 }
2264                 if (win.mActivityRecord != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0
2265                         || (flagChanges & FLAG_DISMISS_KEYGUARD) != 0)) {
2266                     win.mActivityRecord.checkKeyguardFlagsChanged();
2267                 }
2268                 if (((attrChanges & LayoutParams.ACCESSIBILITY_TITLE_CHANGED) != 0)
2269                         && (mAccessibilityController != null)) {
2270                     // No move or resize, but the controller checks for title changes as well
2271                     mAccessibilityController.onSomeWindowResizedOrMovedWithCallingUid(
2272                             uid, win.getDisplayContent().getDisplayId());
2273                 }
2274 
2275                 if ((privateFlagChanges & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
2276                     updateNonSystemOverlayWindowsVisibilityIfNeeded(
2277                             win, win.mWinAnimator.getShown());
2278                 }
2279                 if ((attrChanges & (WindowManager.LayoutParams.PRIVATE_FLAGS_CHANGED)) != 0) {
2280                     winAnimator.setColorSpaceAgnosticLocked((win.mAttrs.privateFlags
2281                             & WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
2282                 }
2283             }
2284 
2285             if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility
2286                     + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
2287             if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
2288                 winAnimator.mAlpha = attrs.alpha;
2289             }
2290             win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);
2291 
2292             if (win.mAttrs.surfaceInsets.left != 0
2293                     || win.mAttrs.surfaceInsets.top != 0
2294                     || win.mAttrs.surfaceInsets.right != 0
2295                     || win.mAttrs.surfaceInsets.bottom != 0) {
2296                 winAnimator.setOpaqueLocked(false);
2297             }
2298 
2299             final int oldVisibility = win.mViewVisibility;
2300 
2301             // If the window is becoming visible, visibleOrAdding may change which may in turn
2302             // change the IME target.
2303             final boolean becameVisible =
2304                     (oldVisibility == View.INVISIBLE || oldVisibility == View.GONE)
2305                             && viewVisibility == View.VISIBLE;
2306             boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0
2307                     || becameVisible;
2308             boolean focusMayChange = win.mViewVisibility != viewVisibility
2309                     || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
2310                     || (!win.mRelayoutCalled);
2311 
2312             boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
2313                     && win.hasWallpaper();
2314             wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
2315             if ((flagChanges & FLAG_SECURE) != 0 && winAnimator.mSurfaceController != null) {
2316                 winAnimator.mSurfaceController.setSecure(win.isSecureLocked());
2317             }
2318 
2319             win.mRelayoutCalled = true;
2320             win.mInRelayout = true;
2321 
2322             win.setViewVisibility(viewVisibility);
2323             ProtoLog.i(WM_DEBUG_SCREEN_ON,
2324                     "Relayout %s: oldVis=%d newVis=%d. %s", win, oldVisibility,
2325                             viewVisibility, new RuntimeException().fillInStackTrace());
2326 
2327 
2328             win.setDisplayLayoutNeeded();
2329             win.mGivenInsetsPending = (flags & WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
2330 
2331             // We should only relayout if the view is visible, it is a starting window, or the
2332             // associated appToken is not hidden.
2333             final boolean shouldRelayout = viewVisibility == View.VISIBLE &&
2334                     (win.mActivityRecord == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
2335                             || win.mActivityRecord.isClientVisible());
2336 
2337             // If we are not currently running the exit animation, we need to see about starting
2338             // one.
2339             // We don't want to animate visibility of windows which are pending replacement.
2340             // In the case of activity relaunch child windows could request visibility changes as
2341             // they are detached from the main application window during the tear down process.
2342             // If we satisfied these visibility changes though, we would cause a visual glitch
2343             // hiding the window before it's replacement was available. So we just do nothing on
2344             // our side.
2345             // This must be called before the call to performSurfacePlacement.
2346             if (!shouldRelayout && winAnimator.hasSurface() && !win.mAnimatingExit) {
2347                 if (DEBUG_VISIBILITY) {
2348                     Slog.i(TAG_WM,
2349                             "Relayout invis " + win + ": mAnimatingExit=" + win.mAnimatingExit);
2350                 }
2351                 result |= RELAYOUT_RES_SURFACE_CHANGED;
2352                 if (!win.mWillReplaceWindow) {
2353                     // When FLAG_SHOW_WALLPAPER flag is removed from a window, we usually set a flag
2354                     // in DC#pendingLayoutChanges and update the wallpaper target later.
2355                     // However it's possible that FLAG_SHOW_WALLPAPER flag is removed from a window
2356                     // when the window is about to exit, so we update the wallpaper target
2357                     // immediately here. Otherwise this window will be stuck in exiting and its
2358                     // surface remains on the screen.
2359                     // TODO(b/189856716): Allow destroying surface even if it belongs to the
2360                     //  keyguard target.
2361                     if (wallpaperMayMove) {
2362                         displayContent.mWallpaperController.adjustWallpaperWindows();
2363                     }
2364                     focusMayChange = tryStartExitingAnimation(win, winAnimator, focusMayChange);
2365                 }
2366             }
2367 
2368             // Create surfaceControl before surface placement otherwise layout will be skipped
2369             // (because WS.isGoneForLayout() is true when there is no surface.
2370             if (shouldRelayout) {
2371                 try {
2372                     result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
2373                 } catch (Exception e) {
2374                     displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
2375 
2376                     ProtoLog.w(WM_ERROR,
2377                             "Exception thrown when creating surface for client %s (%s). %s",
2378                             client, win.mAttrs.getTitle(), e);
2379                     Binder.restoreCallingIdentity(origId);
2380                     return 0;
2381                 }
2382             }
2383 
2384             // We may be deferring layout passes at the moment, but since the client is interested
2385             // in the new out values right now we need to force a layout.
2386             mWindowPlacerLocked.performSurfacePlacement(true /* force */);
2387 
2388             if (shouldRelayout) {
2389                 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_1");
2390 
2391                 result = win.relayoutVisibleWindow(result);
2392 
2393                 if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
2394                     focusMayChange = true;
2395                 }
2396                 if (win.mAttrs.type == TYPE_INPUT_METHOD
2397                         && displayContent.mInputMethodWindow == null) {
2398                     displayContent.setInputMethodWindowLocked(win);
2399                     imMayMove = true;
2400                 }
2401                 win.adjustStartingWindowFlags();
2402                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2403             } else {
2404                 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_2");
2405 
2406                 winAnimator.mEnterAnimationPending = false;
2407                 winAnimator.mEnteringAnimation = false;
2408 
2409                 if (viewVisibility == View.VISIBLE && winAnimator.hasSurface()) {
2410                     // We already told the client to go invisible, but the message may not be
2411                     // handled yet, or it might want to draw a last frame. If we already have a
2412                     // surface, let the client use that, but don't create new surface at this point.
2413                     Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: getSurface");
2414                     winAnimator.mSurfaceController.getSurfaceControl(outSurfaceControl);
2415                     Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2416                 } else {
2417                     if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win);
2418 
2419                     try {
2420                         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wmReleaseOutSurface_"
2421                                 + win.mAttrs.getTitle());
2422                         outSurfaceControl.release();
2423                     } finally {
2424                         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2425                     }
2426                 }
2427 
2428                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2429             }
2430 
2431             if (focusMayChange) {
2432                 if (updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/)) {
2433                     imMayMove = false;
2434                 }
2435             }
2436 
2437             // updateFocusedWindowLocked() already assigned layers so we only need to
2438             // reassign them at this point if the IM window state gets shuffled
2439             boolean toBeDisplayed = (result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
2440             if (imMayMove) {
2441                 displayContent.computeImeTarget(true /* updateImeTarget */);
2442                 if (toBeDisplayed) {
2443                     // Little hack here -- we -should- be able to rely on the function to return
2444                     // true if the IME has moved and needs its layer recomputed. However, if the IME
2445                     // was hidden and isn't actually moved in the list, its layer may be out of data
2446                     // so we make sure to recompute it.
2447                     displayContent.assignWindowLayers(false /* setLayoutNeeded */);
2448                 }
2449             }
2450 
2451             if (wallpaperMayMove) {
2452                 displayContent.pendingLayoutChanges |=
2453                         WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2454             }
2455 
2456             if (win.mActivityRecord != null) {
2457                 displayContent.mUnknownAppVisibilityController.notifyRelayouted(win.mActivityRecord);
2458             }
2459 
2460             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: updateOrientation");
2461             configChanged = displayContent.updateOrientation();
2462             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2463 
2464             final DisplayInfo rotatedDisplayInfo =
2465                     win.mToken.getFixedRotationTransformDisplayInfo();
2466             if (rotatedDisplayInfo != null) {
2467                 outSurfaceControl.setTransformHint(rotatedDisplayInfo.rotation);
2468             } else {
2469                 // We have to update the transform hint of display here, but we need to get if from
2470                 // SurfaceFlinger, so set it as rotation of display for most cases, then
2471                 // SurfaceFlinger would still update the transform hint of display in next frame.
2472                 outSurfaceControl.setTransformHint(displayContent.getDisplayInfo().rotation);
2473             }
2474 
2475             if (toBeDisplayed && win.mIsWallpaper) {
2476                 displayContent.mWallpaperController.updateWallpaperOffset(win, false /* sync */);
2477             }
2478             if (win.mActivityRecord != null) {
2479                 win.mActivityRecord.updateReportedVisibilityLocked();
2480             }
2481             if (displayPolicy.areSystemBarsForcedShownLw(win)) {
2482                 result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS;
2483             }
2484             if (!win.isGoneForLayout()) {
2485                 win.mResizedWhileGone = false;
2486             }
2487 
2488             win.fillClientWindowFramesAndConfiguration(outFrames, mergedConfiguration,
2489                     false /* useLatestConfig */, shouldRelayout);
2490 
2491             // Set resize-handled here because the values are sent back to the client.
2492             win.onResizeHandled();
2493 
2494             outInsetsState.set(win.getCompatInsetsState(), win.isClientLocal());
2495             if (DEBUG) {
2496                 Slog.v(TAG_WM, "Relayout given client " + client.asBinder()
2497                         + ", requestedWidth=" + requestedWidth
2498                         + ", requestedHeight=" + requestedHeight
2499                         + ", viewVisibility=" + viewVisibility
2500                         + "\nRelayout returning frame=" + outFrames.frame
2501                         + ", surface=" + outSurfaceControl);
2502             }
2503 
2504             ProtoLog.v(WM_DEBUG_FOCUS, "Relayout of %s: focusMayChange=%b",
2505                     win, focusMayChange);
2506 
2507             result |= mInTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0;
2508 
2509             if (DEBUG_LAYOUT) {
2510                 Slog.v(TAG_WM, "Relayout complete " + win + ": outFrames=" + outFrames);
2511             }
2512             win.mInRelayout = false;
2513 
2514             if (mUseBLASTSync && win.useBLASTSync() && viewVisibility != View.GONE) {
2515                 win.prepareDrawHandlers();
2516                 win.markRedrawForSyncReported();
2517                 result |= RELAYOUT_RES_BLAST_SYNC;
2518             }
2519 
2520             if (configChanged) {
2521                 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
2522                         "relayoutWindow: postNewConfigurationToHandler");
2523                 displayContent.sendNewConfiguration();
2524                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2525             }
2526             if (winAnimator.mSurfaceController != null) {
2527                 win.calculateSurfaceBounds(win.getAttrs(), mTmpRect);
2528                 outSurfaceSize.set(mTmpRect.width(), mTmpRect.height());
2529             }
2530             getInsetsSourceControls(win, outActiveControls);
2531         }
2532 
2533         Binder.restoreCallingIdentity(origId);
2534         return result;
2535     }
2536 
getInsetsSourceControls(WindowState win, InsetsSourceControl[] outControls)2537     private void getInsetsSourceControls(WindowState win, InsetsSourceControl[] outControls) {
2538         final InsetsSourceControl[] controls =
2539                 win.getDisplayContent().getInsetsStateController().getControlsForDispatch(win);
2540         if (controls != null) {
2541             final int length = Math.min(controls.length, outControls.length);
2542             for (int i = 0; i < length; i++) {
2543                 // We will leave the critical section before returning the leash to the client,
2544                 // so we need to copy the leash to prevent others release the one that we are
2545                 // about to return.
2546                 if (controls[i] != null) {
2547                     // This source control is an extra copy if the client is not local. By setting
2548                     // PARCELABLE_WRITE_RETURN_VALUE, the leash will be released at the end of
2549                     // SurfaceControl.writeToParcel.
2550                     outControls[i] = new InsetsSourceControl(controls[i]);
2551                     outControls[i].setParcelableFlags(PARCELABLE_WRITE_RETURN_VALUE);
2552                 }
2553             }
2554         }
2555     }
2556 
tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator, boolean focusMayChange)2557     private boolean tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator,
2558             boolean focusMayChange) {
2559         // Try starting an animation; if there isn't one, we
2560         // can destroy the surface right away.
2561         int transit = WindowManagerPolicy.TRANSIT_EXIT;
2562         if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
2563             transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2564         }
2565         if (mAtmService.getTransitionController().inTransition(win)) {
2566             focusMayChange = true;
2567             win.mAnimatingExit = true;
2568         } else if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) {
2569             focusMayChange = true;
2570             win.mAnimatingExit = true;
2571         } else if (win.mDisplayContent.okToAnimate() && win.isAnimating(TRANSITION | PARENTS,
2572                 WindowState.EXIT_ANIMATING_TYPES)) {
2573             // Currently in a hide animation... turn this into
2574             // an exit.
2575             win.mAnimatingExit = true;
2576         } else if (win.mDisplayContent.okToAnimate()
2577                 && win.mDisplayContent.mWallpaperController.isWallpaperTarget(win)) {
2578             // If the wallpaper is currently behind this
2579             // window, we need to change both of them inside
2580             // of a transaction to avoid artifacts.
2581             win.mAnimatingExit = true;
2582         } else {
2583             boolean stopped = win.mActivityRecord != null ? win.mActivityRecord.mAppStopped : true;
2584             // We set mDestroying=true so ActivityRecord#notifyAppStopped in-to destroy surfaces
2585             // will later actually destroy the surface if we do not do so here. Normally we leave
2586             // this to the exit animation.
2587             win.mDestroying = true;
2588             win.destroySurface(false, stopped);
2589         }
2590         if (mAccessibilityController != null) {
2591             mAccessibilityController.onWindowTransition(win, transit);
2592         }
2593 
2594         return focusMayChange;
2595     }
2596 
createSurfaceControl(SurfaceControl outSurfaceControl, int result, WindowState win, WindowStateAnimator winAnimator)2597     private int createSurfaceControl(SurfaceControl outSurfaceControl, int result,
2598             WindowState win, WindowStateAnimator winAnimator) {
2599         if (!win.mHasSurface) {
2600             result |= RELAYOUT_RES_SURFACE_CHANGED;
2601         }
2602 
2603         WindowSurfaceController surfaceController;
2604         try {
2605             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl");
2606             surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type);
2607         } finally {
2608             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2609         }
2610         if (surfaceController != null) {
2611             surfaceController.getSurfaceControl(outSurfaceControl);
2612             ProtoLog.i(WM_SHOW_TRANSACTIONS, "OUT SURFACE %s: copied", outSurfaceControl);
2613 
2614         } else {
2615             // For some reason there isn't a surface.  Clear the
2616             // caller's object so they see the same state.
2617             ProtoLog.w(WM_ERROR, "Failed to create surface control for %s", win);
2618             outSurfaceControl.release();
2619         }
2620 
2621         return result;
2622     }
2623 
outOfMemoryWindow(Session session, IWindow client)2624     public boolean outOfMemoryWindow(Session session, IWindow client) {
2625         final long origId = Binder.clearCallingIdentity();
2626 
2627         try {
2628             synchronized (mGlobalLock) {
2629                 WindowState win = windowForClientLocked(session, client, false);
2630                 if (win == null) {
2631                     return false;
2632                 }
2633                 return mRoot.reclaimSomeSurfaceMemory(win.mWinAnimator, "from-client", false);
2634             }
2635         } finally {
2636             Binder.restoreCallingIdentity(origId);
2637         }
2638     }
2639 
finishDrawingWindow(Session session, IWindow client, @Nullable SurfaceControl.Transaction postDrawTransaction)2640     void finishDrawingWindow(Session session, IWindow client,
2641             @Nullable SurfaceControl.Transaction postDrawTransaction) {
2642         final long origId = Binder.clearCallingIdentity();
2643         try {
2644             synchronized (mGlobalLock) {
2645                 WindowState win = windowForClientLocked(session, client, false);
2646                 ProtoLog.d(WM_DEBUG_ADD_REMOVE, "finishDrawingWindow: %s mDrawState=%s",
2647                         win, (win != null ? win.mWinAnimator.drawStateToString() : "null"));
2648                 if (win != null && win.finishDrawing(postDrawTransaction)) {
2649                     if (win.hasWallpaper()) {
2650                         win.getDisplayContent().pendingLayoutChanges |=
2651                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2652                     }
2653                     win.setDisplayLayoutNeeded();
2654                     mWindowPlacerLocked.requestTraversal();
2655                 }
2656             }
2657         } finally {
2658             Binder.restoreCallingIdentity(origId);
2659         }
2660     }
2661 
checkCallingPermission(String permission, String func)2662     boolean checkCallingPermission(String permission, String func) {
2663         return checkCallingPermission(permission, func, true /* printLog */);
2664     }
2665 
checkCallingPermission(String permission, String func, boolean printLog)2666     boolean checkCallingPermission(String permission, String func, boolean printLog) {
2667         // Quick check: if the calling permission is me, it's all okay.
2668         if (Binder.getCallingPid() == myPid()) {
2669             return true;
2670         }
2671 
2672         if (mContext.checkCallingPermission(permission)
2673                 == PackageManager.PERMISSION_GRANTED) {
2674             return true;
2675         }
2676         if (printLog) {
2677             ProtoLog.w(WM_ERROR, "Permission Denial: %s from pid=%d, uid=%d requires %s",
2678                     func, Binder.getCallingPid(), Binder.getCallingUid(), permission);
2679         }
2680         return false;
2681     }
2682 
2683     @Override
addWindowToken(@onNull IBinder binder, int type, int displayId, @Nullable Bundle options)2684     public void addWindowToken(@NonNull IBinder binder, int type, int displayId,
2685             @Nullable Bundle options) {
2686         if (!checkCallingPermission(MANAGE_APP_TOKENS, "addWindowToken()")) {
2687             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2688         }
2689 
2690         synchronized (mGlobalLock) {
2691             final DisplayContent dc = getDisplayContentOrCreate(displayId, null /* token */);
2692             if (dc == null) {
2693                 ProtoLog.w(WM_ERROR, "addWindowToken: Attempted to add token: %s"
2694                         + " for non-exiting displayId=%d", binder, displayId);
2695                 return;
2696             }
2697 
2698             WindowToken token = dc.getWindowToken(binder);
2699             if (token != null) {
2700                 ProtoLog.w(WM_ERROR, "addWindowToken: Attempted to add binder token: %s"
2701                         + " for already created window token: %s"
2702                         + " displayId=%d", binder, token, displayId);
2703                 return;
2704             }
2705             if (type == TYPE_WALLPAPER) {
2706                 new WallpaperWindowToken(this, binder, true, dc,
2707                         true /* ownerCanManageAppTokens */, options);
2708             } else {
2709                 new WindowToken.Builder(this, binder, type)
2710                         .setDisplayContent(dc)
2711                         .setPersistOnEmpty(true)
2712                         .setOwnerCanManageAppTokens(true)
2713                         .setOptions(options)
2714                         .build();
2715             }
2716         }
2717     }
2718 
2719     @Override
attachWindowContextToDisplayArea(IBinder clientToken, int type, int displayId, Bundle options)2720     public boolean attachWindowContextToDisplayArea(IBinder clientToken, int type, int displayId,
2721             Bundle options) {
2722         final boolean callerCanManageAppTokens = checkCallingPermission(MANAGE_APP_TOKENS,
2723                 "attachWindowContextToDisplayArea", false /* printLog */);
2724         final int callingUid = Binder.getCallingUid();
2725         final long origId = Binder.clearCallingIdentity();
2726         try {
2727             synchronized (mGlobalLock) {
2728                 final DisplayContent dc = mRoot.getDisplayContentOrCreate(displayId);
2729                 if (dc == null) {
2730                     ProtoLog.w(WM_ERROR, "attachWindowContextToDisplayArea: trying to attach"
2731                             + " to a non-existing display:%d", displayId);
2732                     return false;
2733                 }
2734                 // TODO(b/155340867): Investigate if we still need roundedCornerOverlay after
2735                 // the feature b/155340867 is completed.
2736                 final DisplayArea da = dc.findAreaForWindowType(type, options,
2737                         callerCanManageAppTokens, false /* roundedCornerOverlay */);
2738                 mWindowContextListenerController.registerWindowContainerListener(clientToken, da,
2739                         callingUid, type, options);
2740                 return true;
2741             }
2742         } finally {
2743             Binder.restoreCallingIdentity(origId);
2744         }
2745     }
2746 
2747     @Override
attachWindowContextToWindowToken(IBinder clientToken, IBinder token)2748     public void attachWindowContextToWindowToken(IBinder clientToken, IBinder token) {
2749         final boolean callerCanManageAppTokens = checkCallingPermission(MANAGE_APP_TOKENS,
2750                 "attachWindowContextToWindowToken", false /* printLog */);
2751         final int callingUid = Binder.getCallingUid();
2752         final long origId = Binder.clearCallingIdentity();
2753         try {
2754             synchronized (mGlobalLock) {
2755                 final WindowToken windowToken = mRoot.getWindowToken(token);
2756                 if (windowToken == null) {
2757                     ProtoLog.w(WM_ERROR, "Then token:%s is invalid. It might be "
2758                             + "removed", token);
2759                     return;
2760                 }
2761                 final int type = mWindowContextListenerController.getWindowType(clientToken);
2762                 if (type == INVALID_WINDOW_TYPE) {
2763                     throw new IllegalArgumentException("The clientToken:" + clientToken
2764                             + " should have been attached.");
2765                 }
2766                 if (type != windowToken.windowType) {
2767                     throw new IllegalArgumentException("The WindowToken's type should match"
2768                             + " the created WindowContext's type. WindowToken's type is "
2769                             + windowToken.windowType + ", while WindowContext's is " + type);
2770                 }
2771                 if (!mWindowContextListenerController.assertCallerCanModifyListener(clientToken,
2772                         callerCanManageAppTokens, callingUid)) {
2773                     return;
2774                 }
2775                 mWindowContextListenerController.registerWindowContainerListener(clientToken,
2776                         windowToken, callingUid, windowToken.windowType, windowToken.mOptions);
2777             }
2778         } finally {
2779             Binder.restoreCallingIdentity(origId);
2780         }
2781     }
2782 
2783     @Override
detachWindowContextFromWindowContainer(IBinder clientToken)2784     public void detachWindowContextFromWindowContainer(IBinder clientToken) {
2785         final boolean callerCanManageAppTokens = checkCallingPermission(MANAGE_APP_TOKENS,
2786                 "detachWindowContextFromWindowContainer", false /* printLog */);
2787         final int callingUid = Binder.getCallingUid();
2788         final long origId = Binder.clearCallingIdentity();
2789         try {
2790             synchronized (mGlobalLock) {
2791                 if (!mWindowContextListenerController.assertCallerCanModifyListener(clientToken,
2792                         callerCanManageAppTokens, callingUid)) {
2793                     return;
2794                 }
2795                 final WindowContainer wc = mWindowContextListenerController
2796                         .getContainer(clientToken);
2797 
2798                 mWindowContextListenerController.unregisterWindowContainerListener(clientToken);
2799 
2800                 final WindowToken token = wc.asWindowToken();
2801                 if (token != null && token.isFromClient()) {
2802                     removeWindowToken(token.token, token.getDisplayContent().getDisplayId());
2803                 }
2804             }
2805         } finally {
2806             Binder.restoreCallingIdentity(origId);
2807         }
2808     }
2809 
2810     /** Returns {@code true} if this binder is a registered window token. */
2811     @Override
isWindowToken(IBinder binder)2812     public boolean isWindowToken(IBinder binder) {
2813         synchronized (mGlobalLock) {
2814             return mRoot.getWindowToken(binder) != null;
2815         }
2816 
2817     }
2818 
2819     @Override
removeWindowToken(IBinder binder, int displayId)2820     public void removeWindowToken(IBinder binder, int displayId) {
2821         if (!checkCallingPermission(MANAGE_APP_TOKENS, "removeWindowToken()")) {
2822             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2823         }
2824         final long origId = Binder.clearCallingIdentity();
2825         try {
2826             synchronized (mGlobalLock) {
2827                 final DisplayContent dc = mRoot.getDisplayContent(displayId);
2828 
2829                 if (dc == null) {
2830                     ProtoLog.w(WM_ERROR, "removeWindowToken: Attempted to remove token: %s"
2831                             + " for non-exiting displayId=%d", binder, displayId);
2832                     return;
2833                 }
2834                 final WindowToken token = dc.removeWindowToken(binder);
2835                 if (token == null) {
2836                     ProtoLog.w(WM_ERROR,
2837                             "removeWindowToken: Attempted to remove non-existing token: %s",
2838                             binder);
2839                     return;
2840                 }
2841                 dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
2842             }
2843         } finally {
2844             Binder.restoreCallingIdentity(origId);
2845         }
2846     }
2847 
2848     /** @see WindowManagerInternal#moveWindowTokenToDisplay(IBinder, int)  */
moveWindowTokenToDisplay(IBinder binder, int displayId)2849     public void moveWindowTokenToDisplay(IBinder binder, int displayId) {
2850         synchronized (mGlobalLock) {
2851             final DisplayContent dc = mRoot.getDisplayContentOrCreate(displayId);
2852             if (dc == null) {
2853                 ProtoLog.w(WM_ERROR, "moveWindowTokenToDisplay: Attempted to move token: %s"
2854                         + " to non-exiting displayId=%d", binder, displayId);
2855                 return;
2856             }
2857             final WindowToken token = mRoot.getWindowToken(binder);
2858             if (token == null) {
2859                 ProtoLog.w(WM_ERROR,
2860                         "moveWindowTokenToDisplay: Attempted to move non-existing token: %s",
2861                         binder);
2862                 return;
2863             }
2864             if (token.getDisplayContent() == dc) {
2865                 ProtoLog.w(WM_ERROR,
2866                         "moveWindowTokenToDisplay: Cannot move to the original display "
2867                                 + "for token: %s", binder);
2868                 return;
2869             }
2870             dc.reParentWindowToken(token);
2871         }
2872     }
2873 
setNewDisplayOverrideConfiguration(Configuration overrideConfig, @NonNull DisplayContent dc)2874     void setNewDisplayOverrideConfiguration(Configuration overrideConfig,
2875             @NonNull DisplayContent dc) {
2876         if (dc.mWaitingForConfig) {
2877             dc.mWaitingForConfig = false;
2878             mLastFinishedFreezeSource = "new-config";
2879         }
2880 
2881         mRoot.setDisplayOverrideConfigurationIfNeeded(overrideConfig, dc);
2882     }
2883 
2884     // TODO(multi-display): remove when no default display use case.
prepareAppTransitionNone()2885     void prepareAppTransitionNone() {
2886         if (!checkCallingPermission(MANAGE_APP_TOKENS, "prepareAppTransition()")) {
2887             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2888         }
2889         getDefaultDisplayContentLocked().prepareAppTransition(TRANSIT_NONE);
2890     }
2891 
2892     @Override
overridePendingAppTransitionMultiThumbFuture( IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback, boolean scaleUp, int displayId)2893     public void overridePendingAppTransitionMultiThumbFuture(
2894             IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback,
2895             boolean scaleUp, int displayId) {
2896         synchronized (mGlobalLock) {
2897             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
2898             if (displayContent == null) {
2899                 Slog.w(TAG, "Attempted to call overridePendingAppTransitionMultiThumbFuture"
2900                         + " for the display " + displayId + " that does not exist.");
2901                 return;
2902             }
2903             displayContent.mAppTransition.overridePendingAppTransitionMultiThumbFuture(specsFuture,
2904                     callback, scaleUp);
2905         }
2906     }
2907 
2908     @Override
overridePendingAppTransitionRemote(RemoteAnimationAdapter remoteAnimationAdapter, int displayId)2909     public void overridePendingAppTransitionRemote(RemoteAnimationAdapter remoteAnimationAdapter,
2910             int displayId) {
2911         if (!checkCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
2912                 "overridePendingAppTransitionRemote()")) {
2913             throw new SecurityException(
2914                     "Requires CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS permission");
2915         }
2916         synchronized (mGlobalLock) {
2917             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
2918             if (displayContent == null) {
2919                 Slog.w(TAG, "Attempted to call overridePendingAppTransitionRemote"
2920                         + " for the display " + displayId + " that does not exist.");
2921                 return;
2922             }
2923             remoteAnimationAdapter.setCallingPidUid(Binder.getCallingPid(), Binder.getCallingUid());
2924             displayContent.mAppTransition.overridePendingAppTransitionRemote(
2925                     remoteAnimationAdapter);
2926         }
2927     }
2928 
2929     @Override
endProlongedAnimations()2930     public void endProlongedAnimations() {
2931         // TODO: Remove once clients are updated.
2932     }
2933 
2934     // TODO(multi-display): remove when no default display use case.
2935     // (i.e. KeyguardController / RecentsAnimation)
executeAppTransition()2936     public void executeAppTransition() {
2937         if (!checkCallingPermission(MANAGE_APP_TOKENS, "executeAppTransition()")) {
2938             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2939         }
2940         getDefaultDisplayContentLocked().executeAppTransition();
2941     }
2942 
initializeRecentsAnimation(int targetActivityType, IRecentsAnimationRunner recentsAnimationRunner, RecentsAnimationController.RecentsAnimationCallbacks callbacks, int displayId, SparseBooleanArray recentTaskIds, ActivityRecord targetActivity)2943     void initializeRecentsAnimation(int targetActivityType,
2944             IRecentsAnimationRunner recentsAnimationRunner,
2945             RecentsAnimationController.RecentsAnimationCallbacks callbacks, int displayId,
2946             SparseBooleanArray recentTaskIds, ActivityRecord targetActivity) {
2947         mRecentsAnimationController = new RecentsAnimationController(this, recentsAnimationRunner,
2948                 callbacks, displayId);
2949         mRoot.getDisplayContent(displayId).mAppTransition.updateBooster();
2950         mRecentsAnimationController.initialize(targetActivityType, recentTaskIds, targetActivity);
2951     }
2952 
2953     @VisibleForTesting
setRecentsAnimationController(RecentsAnimationController controller)2954     void setRecentsAnimationController(RecentsAnimationController controller) {
2955         mRecentsAnimationController = controller;
2956     }
2957 
getRecentsAnimationController()2958     RecentsAnimationController getRecentsAnimationController() {
2959         return mRecentsAnimationController;
2960     }
2961 
cancelRecentsAnimation( @ecentsAnimationController.ReorderMode int reorderMode, String reason)2962     void cancelRecentsAnimation(
2963             @RecentsAnimationController.ReorderMode int reorderMode, String reason) {
2964         if (mRecentsAnimationController != null) {
2965             // This call will call through to cleanupAnimation() below after the animation is
2966             // canceled
2967             mRecentsAnimationController.cancelAnimation(reorderMode, reason);
2968         }
2969     }
2970 
cleanupRecentsAnimation(@ecentsAnimationController.ReorderMode int reorderMode)2971     void cleanupRecentsAnimation(@RecentsAnimationController.ReorderMode int reorderMode) {
2972         if (mRecentsAnimationController != null) {
2973             final RecentsAnimationController controller = mRecentsAnimationController;
2974             mRecentsAnimationController = null;
2975             controller.cleanupAnimation(reorderMode);
2976             // TODO(mult-display): currently only default display support recents animation.
2977             getDefaultDisplayContentLocked().mAppTransition.updateBooster();
2978         }
2979     }
2980 
isRecentsAnimationTarget(ActivityRecord r)2981     boolean isRecentsAnimationTarget(ActivityRecord r) {
2982         return mRecentsAnimationController != null && mRecentsAnimationController.isTargetApp(r);
2983     }
2984 
setWindowOpaqueLocked(IBinder token, boolean isOpaque)2985     void setWindowOpaqueLocked(IBinder token, boolean isOpaque) {
2986         final ActivityRecord wtoken = mRoot.getActivityRecord(token);
2987         if (wtoken != null) {
2988             wtoken.setMainWindowOpaque(isOpaque);
2989         }
2990     }
2991 
isValidPictureInPictureAspectRatio(DisplayContent displayContent, float aspectRatio)2992     boolean isValidPictureInPictureAspectRatio(DisplayContent displayContent, float aspectRatio) {
2993         return displayContent.getPinnedTaskController().isValidPictureInPictureAspectRatio(
2994                 aspectRatio);
2995     }
2996 
getRootTaskBounds(int windowingMode, int activityType, Rect bounds)2997     void getRootTaskBounds(int windowingMode, int activityType, Rect bounds) {
2998         final Task rootTask = mRoot.getRootTask(windowingMode, activityType);
2999         if (rootTask != null) {
3000             rootTask.getBounds(bounds);
3001             return;
3002         }
3003         bounds.setEmpty();
3004     }
3005 
3006     /**
3007      * Notifies window manager that {@link DisplayPolicy#isShowingDreamLw} has changed.
3008      */
notifyShowingDreamChanged()3009     public void notifyShowingDreamChanged() {
3010         // TODO(multi-display): support show dream in multi-display.
3011         notifyKeyguardFlagsChanged(null /* callback */, DEFAULT_DISPLAY);
3012     }
3013 
3014     @Override
notifyKeyguardTrustedChanged()3015     public void notifyKeyguardTrustedChanged() {
3016         mAtmInternal.notifyKeyguardTrustedChanged();
3017     }
3018 
3019     @Override
screenTurningOff(int displayId, ScreenOffListener listener)3020     public void screenTurningOff(int displayId, ScreenOffListener listener) {
3021         mTaskSnapshotController.screenTurningOff(displayId, listener);
3022     }
3023 
3024     @Override
triggerAnimationFailsafe()3025     public void triggerAnimationFailsafe() {
3026         mH.sendEmptyMessage(H.ANIMATION_FAILSAFE);
3027     }
3028 
3029     @Override
onKeyguardShowingAndNotOccludedChanged()3030     public void onKeyguardShowingAndNotOccludedChanged() {
3031         mH.sendEmptyMessage(H.RECOMPUTE_FOCUS);
3032     }
3033 
3034     @Override
onPowerKeyDown(boolean isScreenOn)3035     public void onPowerKeyDown(boolean isScreenOn) {
3036         final PooledConsumer c = PooledLambda.obtainConsumer(
3037                 DisplayPolicy::onPowerKeyDown, PooledLambda.__(), isScreenOn);
3038         mRoot.forAllDisplayPolicies(c);
3039         c.recycle();
3040     }
3041 
3042     @Override
onUserSwitched()3043     public void onUserSwitched() {
3044         mSettingsObserver.updateSystemUiSettings(true /* handleChange */);
3045         synchronized (mGlobalLock) {
3046             // force a re-application of focused window sysui visibility on each display.
3047             mRoot.forAllDisplayPolicies(DisplayPolicy::resetSystemUiVisibilityLw);
3048         }
3049     }
3050 
3051     @Override
moveDisplayToTop(int displayId)3052     public void moveDisplayToTop(int displayId) {
3053         synchronized (mGlobalLock) {
3054             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
3055             if (displayContent != null && mRoot.getTopChild() != displayContent) {
3056                 displayContent.getParent().positionChildAt(WindowContainer.POSITION_TOP,
3057                         displayContent, true /* includingParents */);
3058             }
3059         }
3060         syncInputTransactions(true /* waitForAnimations */);
3061     }
3062 
3063     /**
3064      * Notifies activity manager that some Keyguard flags have changed and that it needs to
3065      * reevaluate the visibilities of the activities.
3066      * @param callback Runnable to be called when activity manager is done reevaluating visibilities
3067      */
notifyKeyguardFlagsChanged(@ullable Runnable callback, int displayId)3068     void notifyKeyguardFlagsChanged(@Nullable Runnable callback, int displayId) {
3069         mAtmInternal.notifyKeyguardFlagsChanged(callback, displayId);
3070     }
3071 
3072 
3073     // -------------------------------------------------------------
3074     // Misc IWindowSession methods
3075     // -------------------------------------------------------------
3076 
3077     @Override
startFreezingScreen(int exitAnim, int enterAnim)3078     public void startFreezingScreen(int exitAnim, int enterAnim) {
3079         if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
3080                 "startFreezingScreen()")) {
3081             throw new SecurityException("Requires FREEZE_SCREEN permission");
3082         }
3083 
3084         synchronized (mGlobalLock) {
3085             if (!mClientFreezingScreen) {
3086                 mClientFreezingScreen = true;
3087                 final long origId = Binder.clearCallingIdentity();
3088                 try {
3089                     startFreezingDisplay(exitAnim, enterAnim);
3090                     mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
3091                     mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
3092                 } finally {
3093                     Binder.restoreCallingIdentity(origId);
3094                 }
3095             }
3096         }
3097     }
3098 
3099     @Override
stopFreezingScreen()3100     public void stopFreezingScreen() {
3101         if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
3102                 "stopFreezingScreen()")) {
3103             throw new SecurityException("Requires FREEZE_SCREEN permission");
3104         }
3105 
3106         synchronized (mGlobalLock) {
3107             if (mClientFreezingScreen) {
3108                 mClientFreezingScreen = false;
3109                 mLastFinishedFreezeSource = "client";
3110                 final long origId = Binder.clearCallingIdentity();
3111                 try {
3112                     stopFreezingDisplayLocked();
3113                 } finally {
3114                     Binder.restoreCallingIdentity(origId);
3115                 }
3116             }
3117         }
3118     }
3119 
3120     @Override
disableKeyguard(IBinder token, String tag, int userId)3121     public void disableKeyguard(IBinder token, String tag, int userId) {
3122         userId = mAmInternal.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
3123                 userId, false /* allowAll */, ALLOW_FULL_ONLY, "disableKeyguard", null);
3124         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
3125             != PackageManager.PERMISSION_GRANTED) {
3126             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
3127         }
3128         final int callingUid = Binder.getCallingUid();
3129         final long origIdentity = Binder.clearCallingIdentity();
3130         try {
3131             mKeyguardDisableHandler.disableKeyguard(token, tag, callingUid, userId);
3132         } finally {
3133             Binder.restoreCallingIdentity(origIdentity);
3134         }
3135     }
3136 
3137     @Override
reenableKeyguard(IBinder token, int userId)3138     public void reenableKeyguard(IBinder token, int userId) {
3139         userId = mAmInternal.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
3140                 userId, false /* allowAll */, ALLOW_FULL_ONLY, "reenableKeyguard", null);
3141         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
3142             != PackageManager.PERMISSION_GRANTED) {
3143             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
3144         }
3145         Objects.requireNonNull(token, "token is null");
3146         final int callingUid = Binder.getCallingUid();
3147         final long origIdentity = Binder.clearCallingIdentity();
3148         try {
3149             mKeyguardDisableHandler.reenableKeyguard(token, callingUid, userId);
3150         } finally {
3151             Binder.restoreCallingIdentity(origIdentity);
3152         }
3153     }
3154 
3155     /**
3156      * @see android.app.KeyguardManager#exitKeyguardSecurely
3157      */
3158     @Override
exitKeyguardSecurely(final IOnKeyguardExitResult callback)3159     public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
3160         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
3161             != PackageManager.PERMISSION_GRANTED) {
3162             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
3163         }
3164 
3165         if (callback == null) {
3166             throw new IllegalArgumentException("callback == null");
3167         }
3168 
3169         mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
3170             @Override
3171             public void onKeyguardExitResult(boolean success) {
3172                 try {
3173                     callback.onKeyguardExitResult(success);
3174                 } catch (RemoteException e) {
3175                     // Client has died, we don't care.
3176                 }
3177             }
3178         });
3179     }
3180 
3181     @Override
isKeyguardLocked()3182     public boolean isKeyguardLocked() {
3183         return mPolicy.isKeyguardLocked();
3184     }
3185 
isKeyguardShowingAndNotOccluded()3186     public boolean isKeyguardShowingAndNotOccluded() {
3187         return mPolicy.isKeyguardShowingAndNotOccluded();
3188     }
3189 
3190     @Override
isKeyguardSecure(int userId)3191     public boolean isKeyguardSecure(int userId) {
3192         if (userId != UserHandle.getCallingUserId()
3193                 && !checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS,
3194                 "isKeyguardSecure")) {
3195             throw new SecurityException("Requires INTERACT_ACROSS_USERS permission");
3196         }
3197 
3198         final long origId = Binder.clearCallingIdentity();
3199         try {
3200             return mPolicy.isKeyguardSecure(userId);
3201         } finally {
3202             Binder.restoreCallingIdentity(origId);
3203         }
3204     }
3205 
3206     @Override
dismissKeyguard(IKeyguardDismissCallback callback, CharSequence message)3207     public void dismissKeyguard(IKeyguardDismissCallback callback, CharSequence message) {
3208         if (!checkCallingPermission(permission.CONTROL_KEYGUARD, "dismissKeyguard")) {
3209             throw new SecurityException("Requires CONTROL_KEYGUARD permission");
3210         }
3211         if (mAtmInternal.isDreaming()) {
3212             mAtmService.mTaskSupervisor.wakeUp("dismissKeyguard");
3213         }
3214         synchronized (mGlobalLock) {
3215             mPolicy.dismissKeyguardLw(callback, message);
3216         }
3217     }
3218 
3219     @Override
setSwitchingUser(boolean switching)3220     public void setSwitchingUser(boolean switching) {
3221         if (!checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
3222                 "setSwitchingUser()")) {
3223             throw new SecurityException("Requires INTERACT_ACROSS_USERS_FULL permission");
3224         }
3225         mPolicy.setSwitchingUser(switching);
3226         synchronized (mGlobalLock) {
3227             mSwitchingUser = switching;
3228         }
3229     }
3230 
3231     @RequiresPermission(Manifest.permission.INTERNAL_SYSTEM_WINDOW)
3232     @Override
showGlobalActions()3233     public void showGlobalActions() {
3234         if (!checkCallingPermission(Manifest.permission.INTERNAL_SYSTEM_WINDOW,
3235                 "showGlobalActions()")) {
3236             throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
3237         }
3238         mPolicy.showGlobalActions();
3239     }
3240 
3241     @Override
closeSystemDialogs(String reason)3242     public void closeSystemDialogs(String reason) {
3243         int callingPid = Binder.getCallingPid();
3244         int callingUid = Binder.getCallingUid();
3245         if (!mAtmInternal.checkCanCloseSystemDialogs(callingPid, callingUid, null)) {
3246             return;
3247         }
3248         synchronized (mGlobalLock) {
3249             mRoot.closeSystemDialogs(reason);
3250         }
3251     }
3252 
fixScale(float scale)3253     static float fixScale(float scale) {
3254         if (scale < 0) scale = 0;
3255         else if (scale > 20) scale = 20;
3256         return Math.abs(scale);
3257     }
3258 
3259     @Override
setAnimationScale(int which, float scale)3260     public void setAnimationScale(int which, float scale) {
3261         if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
3262                 "setAnimationScale()")) {
3263             throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
3264         }
3265 
3266         scale = fixScale(scale);
3267         switch (which) {
3268             case 0: mWindowAnimationScaleSetting = scale; break;
3269             case 1: mTransitionAnimationScaleSetting = scale; break;
3270             case 2: mAnimatorDurationScaleSetting = scale; break;
3271         }
3272 
3273         // Persist setting
3274         mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
3275     }
3276 
3277     @Override
setAnimationScales(float[] scales)3278     public void setAnimationScales(float[] scales) {
3279         if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
3280                 "setAnimationScale()")) {
3281             throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
3282         }
3283 
3284         if (scales != null) {
3285             if (scales.length >= 1) {
3286                 mWindowAnimationScaleSetting = fixScale(scales[0]);
3287             }
3288             if (scales.length >= 2) {
3289                 mTransitionAnimationScaleSetting = fixScale(scales[1]);
3290             }
3291             if (scales.length >= 3) {
3292                 mAnimatorDurationScaleSetting = fixScale(scales[2]);
3293                 dispatchNewAnimatorScaleLocked(null);
3294             }
3295         }
3296 
3297         // Persist setting
3298         mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
3299     }
3300 
setAnimatorDurationScale(float scale)3301     private void setAnimatorDurationScale(float scale) {
3302         mAnimatorDurationScaleSetting = scale;
3303         ValueAnimator.setDurationScale(scale);
3304     }
3305 
getWindowAnimationScaleLocked()3306     public float getWindowAnimationScaleLocked() {
3307         return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting;
3308     }
3309 
getTransitionAnimationScaleLocked()3310     public float getTransitionAnimationScaleLocked() {
3311         return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting;
3312     }
3313 
3314     @Override
getAnimationScale(int which)3315     public float getAnimationScale(int which) {
3316         switch (which) {
3317             case 0: return mWindowAnimationScaleSetting;
3318             case 1: return mTransitionAnimationScaleSetting;
3319             case 2: return mAnimatorDurationScaleSetting;
3320         }
3321         return 0;
3322     }
3323 
3324     @Override
getAnimationScales()3325     public float[] getAnimationScales() {
3326         return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting,
3327                 mAnimatorDurationScaleSetting };
3328     }
3329 
3330     @Override
getCurrentAnimatorScale()3331     public float getCurrentAnimatorScale() {
3332         synchronized (mGlobalLock) {
3333             return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting;
3334         }
3335     }
3336 
dispatchNewAnimatorScaleLocked(Session session)3337     void dispatchNewAnimatorScaleLocked(Session session) {
3338         mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget();
3339     }
3340 
3341     @Override
registerPointerEventListener(PointerEventListener listener, int displayId)3342     public void registerPointerEventListener(PointerEventListener listener, int displayId) {
3343         synchronized (mGlobalLock) {
3344             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
3345             if (displayContent != null) {
3346                 displayContent.registerPointerEventListener(listener);
3347             }
3348         }
3349     }
3350 
3351     @Override
unregisterPointerEventListener(PointerEventListener listener, int displayId)3352     public void unregisterPointerEventListener(PointerEventListener listener, int displayId) {
3353         synchronized (mGlobalLock) {
3354             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
3355             if (displayContent != null) {
3356                 displayContent.unregisterPointerEventListener(listener);
3357             }
3358         }
3359     }
3360 
3361     // Called by window manager policy. Not exposed externally.
3362     @Override
getLidState()3363     public int getLidState() {
3364         int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
3365                 InputManagerService.SW_LID);
3366         if (sw > 0) {
3367             // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
3368             return LID_CLOSED;
3369         } else if (sw == 0) {
3370             // Switch state: AKEY_STATE_UP.
3371             return LID_OPEN;
3372         } else {
3373             // Switch state: AKEY_STATE_UNKNOWN.
3374             return LID_ABSENT;
3375         }
3376     }
3377 
3378     // Called by window manager policy. Not exposed externally.
3379     @Override
lockDeviceNow()3380     public void lockDeviceNow() {
3381         lockNow(null);
3382     }
3383 
3384     // Called by window manager policy. Not exposed externally.
3385     @Override
getCameraLensCoverState()3386     public int getCameraLensCoverState() {
3387         int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
3388                 InputManagerService.SW_CAMERA_LENS_COVER);
3389         if (sw > 0) {
3390             // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
3391             return CAMERA_LENS_COVERED;
3392         } else if (sw == 0) {
3393             // Switch state: AKEY_STATE_UP.
3394             return CAMERA_LENS_UNCOVERED;
3395         } else {
3396             // Switch state: AKEY_STATE_UNKNOWN.
3397             return CAMERA_LENS_COVER_ABSENT;
3398         }
3399     }
3400 
3401     // Called by window manager policy.  Not exposed externally.
3402     @Override
switchKeyboardLayout(int deviceId, int direction)3403     public void switchKeyboardLayout(int deviceId, int direction) {
3404         mInputManager.switchKeyboardLayout(deviceId, direction);
3405     }
3406 
3407     // Called by window manager policy.  Not exposed externally.
3408     @Override
shutdown(boolean confirm)3409     public void shutdown(boolean confirm) {
3410         // Pass in the UI context, since ShutdownThread requires it (to show UI).
3411         ShutdownThread.shutdown(ActivityThread.currentActivityThread().getSystemUiContext(),
3412                 PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
3413     }
3414 
3415     // Called by window manager policy.  Not exposed externally.
3416     @Override
reboot(boolean confirm)3417     public void reboot(boolean confirm) {
3418         // Pass in the UI context, since ShutdownThread requires it (to show UI).
3419         ShutdownThread.reboot(ActivityThread.currentActivityThread().getSystemUiContext(),
3420                 PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
3421     }
3422 
3423     // Called by window manager policy.  Not exposed externally.
3424     @Override
rebootSafeMode(boolean confirm)3425     public void rebootSafeMode(boolean confirm) {
3426         // Pass in the UI context, since ShutdownThread requires it (to show UI).
3427         ShutdownThread.rebootSafeMode(ActivityThread.currentActivityThread().getSystemUiContext(),
3428                 confirm);
3429     }
3430 
setCurrentProfileIds(final int[] currentProfileIds)3431     public void setCurrentProfileIds(final int[] currentProfileIds) {
3432         synchronized (mGlobalLock) {
3433             mCurrentProfileIds = currentProfileIds;
3434         }
3435     }
3436 
setCurrentUser(final int newUserId, final int[] currentProfileIds)3437     public void setCurrentUser(final int newUserId, final int[] currentProfileIds) {
3438         synchronized (mGlobalLock) {
3439             mCurrentUserId = newUserId;
3440             mCurrentProfileIds = currentProfileIds;
3441             mPolicy.setCurrentUserLw(newUserId);
3442             mKeyguardDisableHandler.setCurrentUser(newUserId);
3443 
3444             // Hide windows that should not be seen by the new user.
3445             mRoot.switchUser(newUserId);
3446             mWindowPlacerLocked.performSurfacePlacement();
3447 
3448             // Notify whether the root docked task exists for the current user
3449             final DisplayContent displayContent = getDefaultDisplayContentLocked();
3450 
3451             mRoot.forAllDisplays(dc -> dc.mAppTransition.setCurrentUser(newUserId));
3452 
3453             // If the display is already prepared, update the density.
3454             // Otherwise, we'll update it when it's prepared.
3455             if (mDisplayReady) {
3456                 final int forcedDensity = getForcedDisplayDensityForUserLocked(newUserId);
3457                 final int targetDensity = forcedDensity != 0 ? forcedDensity
3458                         : displayContent.mInitialDisplayDensity;
3459                 displayContent.setForcedDensity(targetDensity, UserHandle.USER_CURRENT);
3460             }
3461         }
3462     }
3463 
3464     /* Called by WindowState */
isCurrentProfile(int userId)3465     boolean isCurrentProfile(int userId) {
3466         if (userId == mCurrentUserId) return true;
3467         for (int i = 0; i < mCurrentProfileIds.length; i++) {
3468             if (mCurrentProfileIds[i] == userId) return true;
3469         }
3470         return false;
3471     }
3472 
enableScreenAfterBoot()3473     public void enableScreenAfterBoot() {
3474         synchronized (mGlobalLock) {
3475             ProtoLog.i(WM_DEBUG_BOOT, "enableScreenAfterBoot: mDisplayEnabled=%b "
3476                             + "mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. "
3477                             + "%s",
3478                     mDisplayEnabled, mForceDisplayEnabled, mShowingBootMessages, mSystemBooted,
3479                     new RuntimeException("here").fillInStackTrace());
3480             if (mSystemBooted) {
3481                 return;
3482             }
3483             mSystemBooted = true;
3484             hideBootMessagesLocked();
3485             // If the screen still doesn't come up after 30 seconds, give
3486             // up and turn it on.
3487             mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30 * 1000);
3488         }
3489 
3490         mPolicy.systemBooted();
3491 
3492         performEnableScreen();
3493     }
3494 
3495     @Override
enableScreenIfNeeded()3496     public void enableScreenIfNeeded() {
3497         synchronized (mGlobalLock) {
3498             enableScreenIfNeededLocked();
3499         }
3500     }
3501 
enableScreenIfNeededLocked()3502     void enableScreenIfNeededLocked() {
3503         ProtoLog.i(WM_DEBUG_BOOT, "enableScreenIfNeededLocked: mDisplayEnabled=%b "
3504                         + "mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. "
3505                         + "%s",
3506                 mDisplayEnabled, mForceDisplayEnabled, mShowingBootMessages, mSystemBooted,
3507                 new RuntimeException("here").fillInStackTrace());
3508         if (mDisplayEnabled) {
3509             return;
3510         }
3511         if (!mSystemBooted && !mShowingBootMessages) {
3512             return;
3513         }
3514         mH.sendEmptyMessage(H.ENABLE_SCREEN);
3515     }
3516 
performBootTimeout()3517     public void performBootTimeout() {
3518         synchronized (mGlobalLock) {
3519             if (mDisplayEnabled) {
3520                 return;
3521             }
3522             ProtoLog.w(WM_ERROR, "***** BOOT TIMEOUT: forcing display enabled");
3523             mForceDisplayEnabled = true;
3524         }
3525         performEnableScreen();
3526     }
3527 
3528     /**
3529      * Called when System UI has been started.
3530      */
onSystemUiStarted()3531     public void onSystemUiStarted() {
3532         mPolicy.onSystemUiStarted();
3533     }
3534 
performEnableScreen()3535     private void performEnableScreen() {
3536         synchronized (mGlobalLock) {
3537             ProtoLog.i(WM_DEBUG_BOOT, "performEnableScreen: mDisplayEnabled=%b"
3538                             + " mForceDisplayEnabled=%b" + " mShowingBootMessages=%b"
3539                             + " mSystemBooted=%b mOnlyCore=%b. %s", mDisplayEnabled,
3540                     mForceDisplayEnabled, mShowingBootMessages, mSystemBooted, mOnlyCore,
3541                     new RuntimeException("here").fillInStackTrace());
3542             if (mDisplayEnabled) {
3543                 return;
3544             }
3545             if (!mSystemBooted && !mShowingBootMessages) {
3546                 return;
3547             }
3548 
3549             if (!mShowingBootMessages && !mPolicy.canDismissBootAnimation()) {
3550                 return;
3551             }
3552 
3553             // Don't enable the screen until all existing windows have been drawn.
3554             if (!mForceDisplayEnabled) {
3555                 if (mBootWaitForWindowsStartTime < 0) {
3556                     // First time we will start waiting for all windows to be drawn.
3557                     mBootWaitForWindowsStartTime = SystemClock.elapsedRealtime();
3558                 }
3559                 for (int i = mRoot.getChildCount() - 1; i >= 0; i--) {
3560                     if (mRoot.getChildAt(i).shouldWaitForSystemDecorWindowsOnBoot()) {
3561                         return;
3562                     }
3563                 }
3564                 long waitTime = SystemClock.elapsedRealtime() - mBootWaitForWindowsStartTime;
3565                 mBootWaitForWindowsStartTime = -1;
3566                 if (waitTime > 10) {
3567                     ProtoLog.i(WM_DEBUG_BOOT,
3568                             "performEnableScreen: Waited %dms for all windows to be drawn",
3569                             waitTime);
3570                 }
3571             }
3572 
3573             if (!mBootAnimationStopped) {
3574                 Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
3575                 // stop boot animation
3576                 // formerly we would just kill the process, but we now ask it to exit so it
3577                 // can choose where to stop the animation.
3578                 SystemProperties.set("service.bootanim.exit", "1");
3579                 mBootAnimationStopped = true;
3580             }
3581 
3582             if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {
3583                 ProtoLog.i(WM_DEBUG_BOOT, "performEnableScreen: Waiting for anim complete");
3584                 return;
3585             }
3586 
3587             try {
3588                 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
3589                 if (surfaceFlinger != null) {
3590                     ProtoLog.i(WM_ERROR, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
3591                     Parcel data = Parcel.obtain();
3592                     data.writeInterfaceToken("android.ui.ISurfaceComposer");
3593                     surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
3594                             data, null, 0);
3595                     data.recycle();
3596                 }
3597             } catch (RemoteException ex) {
3598                 ProtoLog.e(WM_ERROR, "Boot completed: SurfaceFlinger is dead!");
3599             }
3600 
3601             EventLogTags.writeWmBootAnimationDone(SystemClock.uptimeMillis());
3602             Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
3603             mDisplayEnabled = true;
3604             ProtoLog.i(WM_DEBUG_SCREEN_ON, "******************** ENABLING SCREEN!");
3605 
3606             // Enable input dispatch.
3607             mInputManagerCallback.setEventDispatchingLw(mEventDispatchingEnabled);
3608         }
3609 
3610         try {
3611             mActivityManager.bootAnimationComplete();
3612         } catch (RemoteException e) {
3613         }
3614 
3615         mPolicy.enableScreenAfterBoot();
3616 
3617         // Make sure the last requested orientation has been applied.
3618         updateRotationUnchecked(false, false);
3619     }
3620 
checkBootAnimationCompleteLocked()3621     private boolean checkBootAnimationCompleteLocked() {
3622         if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) {
3623             mH.removeMessages(H.CHECK_IF_BOOT_ANIMATION_FINISHED);
3624             mH.sendEmptyMessageDelayed(H.CHECK_IF_BOOT_ANIMATION_FINISHED,
3625                     BOOT_ANIMATION_POLL_INTERVAL);
3626             ProtoLog.i(WM_DEBUG_BOOT, "checkBootAnimationComplete: Waiting for anim complete");
3627             return false;
3628         }
3629         ProtoLog.i(WM_DEBUG_BOOT, "checkBootAnimationComplete: Animation complete!");
3630         return true;
3631     }
3632 
showBootMessage(final CharSequence msg, final boolean always)3633     public void showBootMessage(final CharSequence msg, final boolean always) {
3634         boolean first = false;
3635         synchronized (mGlobalLock) {
3636             ProtoLog.i(WM_DEBUG_BOOT, "showBootMessage: msg=%s always=%b"
3637                             + " mAllowBootMessages=%b mShowingBootMessages=%b"
3638                             + " mSystemBooted=%b. %s", msg, always, mAllowBootMessages,
3639                     mShowingBootMessages, mSystemBooted,
3640                     new RuntimeException("here").fillInStackTrace());
3641             if (!mAllowBootMessages) {
3642                 return;
3643             }
3644             if (!mShowingBootMessages) {
3645                 if (!always) {
3646                     return;
3647                 }
3648                 first = true;
3649             }
3650             if (mSystemBooted) {
3651                 return;
3652             }
3653             mShowingBootMessages = true;
3654             mPolicy.showBootMessage(msg, always);
3655         }
3656         if (first) {
3657             performEnableScreen();
3658         }
3659     }
3660 
hideBootMessagesLocked()3661     public void hideBootMessagesLocked() {
3662         ProtoLog.i(WM_DEBUG_BOOT, "hideBootMessagesLocked: mDisplayEnabled=%b"
3663                         + " mForceDisplayEnabled=%b mShowingBootMessages=%b"
3664                         + " mSystemBooted=%b. %s", mDisplayEnabled, mForceDisplayEnabled,
3665                 mShowingBootMessages, mSystemBooted,
3666                 new RuntimeException("here").fillInStackTrace());
3667         if (mShowingBootMessages) {
3668             mShowingBootMessages = false;
3669             mPolicy.hideBootMessages();
3670         }
3671     }
3672 
3673     @Override
setInTouchMode(boolean mode)3674     public void setInTouchMode(boolean mode) {
3675         synchronized (mGlobalLock) {
3676             mInTouchMode = mode;
3677         }
3678         mInputManager.setInTouchMode(mode);
3679     }
3680 
getInTouchMode()3681     boolean getInTouchMode() {
3682         synchronized (mGlobalLock) {
3683             return mInTouchMode;
3684         }
3685     }
3686 
showEmulatorDisplayOverlayIfNeeded()3687     public void showEmulatorDisplayOverlayIfNeeded() {
3688         if (mContext.getResources().getBoolean(
3689                 com.android.internal.R.bool.config_windowEnableCircularEmulatorDisplayOverlay)
3690                 && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false)
3691                 && Build.IS_EMULATOR) {
3692             mH.sendMessage(mH.obtainMessage(H.SHOW_EMULATOR_DISPLAY_OVERLAY));
3693         }
3694     }
3695 
showEmulatorDisplayOverlay()3696     public void showEmulatorDisplayOverlay() {
3697         synchronized (mGlobalLock) {
3698 
3699             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, ">>> showEmulatorDisplayOverlay");
3700             if (mEmulatorDisplayOverlay == null) {
3701                 mEmulatorDisplayOverlay = new EmulatorDisplayOverlay(mContext,
3702                         getDefaultDisplayContentLocked(),
3703                         mPolicy.getWindowLayerFromTypeLw(WindowManager.LayoutParams.TYPE_POINTER)
3704                                 * TYPE_LAYER_MULTIPLIER + 10, mTransaction);
3705             }
3706             mEmulatorDisplayOverlay.setVisibility(true, mTransaction);
3707             mTransaction.apply();
3708         }
3709     }
3710 
3711     // TODO: more accounting of which pid(s) turned it on, keep count,
3712     // only allow disables from pids which have count on, etc.
3713     @Override
showStrictModeViolation(boolean on)3714     public void showStrictModeViolation(boolean on) {
3715         final int pid = Binder.getCallingPid();
3716         if (on) {
3717             // Show the visualization, and enqueue a second message to tear it
3718             // down if we don't hear back from the app.
3719             mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 1, pid));
3720             mH.sendMessageDelayed(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 0, pid),
3721                     DateUtils.SECOND_IN_MILLIS);
3722         } else {
3723             mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 0, pid));
3724         }
3725     }
3726 
showStrictModeViolation(int arg, int pid)3727     private void showStrictModeViolation(int arg, int pid) {
3728         final boolean on = arg != 0;
3729         synchronized (mGlobalLock) {
3730             // Ignoring requests to enable the red border from clients which aren't on screen.
3731             // (e.g. Broadcast Receivers in the background..)
3732             if (on && !mRoot.canShowStrictModeViolation(pid)) {
3733                 return;
3734             }
3735 
3736             if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM, ">>> showStrictModeViolation");
3737             // TODO: Modify this to use the surface trace once it is not going baffling.
3738             // b/31532461
3739             // TODO(multi-display): support multiple displays
3740             if (mStrictModeFlash == null) {
3741                 mStrictModeFlash = new StrictModeFlash(getDefaultDisplayContentLocked(),
3742                         mTransaction);
3743             }
3744             mStrictModeFlash.setVisibility(on, mTransaction);
3745             mTransaction.apply();
3746         }
3747     }
3748 
3749     @Override
setStrictModeVisualIndicatorPreference(String value)3750     public void setStrictModeVisualIndicatorPreference(String value) {
3751         SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
3752     }
3753 
3754     @Override
screenshotWallpaper()3755     public Bitmap screenshotWallpaper() {
3756         if (!checkCallingPermission(READ_FRAME_BUFFER, "screenshotWallpaper()")) {
3757             throw new SecurityException("Requires READ_FRAME_BUFFER permission");
3758         }
3759         try {
3760             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "screenshotWallpaper");
3761             synchronized (mGlobalLock) {
3762                 // TODO(b/115486823) Screenshot at secondary displays if needed.
3763                 final DisplayContent dc = mRoot.getDisplayContent(DEFAULT_DISPLAY);
3764                 return dc.mWallpaperController.screenshotWallpaperLocked();
3765             }
3766         } finally {
3767             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
3768         }
3769     }
3770 
3771     /**
3772      * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
3773      * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
3774      * of the target image.
3775      */
3776     @Override
requestAssistScreenshot(final IAssistDataReceiver receiver)3777     public boolean requestAssistScreenshot(final IAssistDataReceiver receiver) {
3778         if (!checkCallingPermission(READ_FRAME_BUFFER, "requestAssistScreenshot()")) {
3779             throw new SecurityException("Requires READ_FRAME_BUFFER permission");
3780         }
3781 
3782         final Bitmap bm;
3783         synchronized (mGlobalLock) {
3784             final DisplayContent displayContent = mRoot.getDisplayContent(DEFAULT_DISPLAY);
3785             if (displayContent == null) {
3786                 if (DEBUG_SCREENSHOT) {
3787                     Slog.i(TAG_WM, "Screenshot returning null. No Display for displayId="
3788                             + DEFAULT_DISPLAY);
3789                 }
3790                 bm = null;
3791             } else {
3792                 bm = displayContent.screenshotDisplayLocked();
3793             }
3794         }
3795 
3796         FgThread.getHandler().post(() -> {
3797             try {
3798                 receiver.onHandleAssistScreenshot(bm);
3799             } catch (RemoteException e) {
3800             }
3801         });
3802 
3803         return true;
3804     }
3805 
3806     /**
3807      * Retrieves a snapshot. If restoreFromDisk equals equals {@code true}, DO NOT HOLD THE WINDOW
3808      * MANAGER LOCK WHEN CALLING THIS METHOD!
3809      */
getTaskSnapshot(int taskId, int userId, boolean isLowResolution, boolean restoreFromDisk)3810     public TaskSnapshot getTaskSnapshot(int taskId, int userId, boolean isLowResolution,
3811             boolean restoreFromDisk) {
3812         return mTaskSnapshotController.getSnapshot(taskId, userId, restoreFromDisk,
3813                 isLowResolution);
3814     }
3815 
3816     /**
3817      * In case a task write/delete operation was lost because the system crashed, this makes sure to
3818      * clean up the directory to remove obsolete files.
3819      *
3820      * @param persistentTaskIds A set of task ids that exist in our in-memory model.
3821      * @param runningUserIds The ids of the list of users that have tasks loaded in our in-memory
3822      *                       model.
3823      */
removeObsoleteTaskFiles(ArraySet<Integer> persistentTaskIds, int[] runningUserIds)3824     public void removeObsoleteTaskFiles(ArraySet<Integer> persistentTaskIds, int[] runningUserIds) {
3825         synchronized (mGlobalLock) {
3826             mTaskSnapshotController.removeObsoleteTaskFiles(persistentTaskIds, runningUserIds);
3827         }
3828     }
3829 
3830     @Override
setFixedToUserRotation(int displayId, int fixedToUserRotation)3831     public void setFixedToUserRotation(int displayId, int fixedToUserRotation) {
3832         if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
3833                 "setFixedToUserRotation()")) {
3834             throw new SecurityException("Requires SET_ORIENTATION permission");
3835         }
3836         final long origId = Binder.clearCallingIdentity();
3837         try {
3838             synchronized (mGlobalLock) {
3839                 final DisplayContent display = mRoot.getDisplayContent(displayId);
3840                 if (display == null) {
3841                     Slog.w(TAG, "Trying to set fixed to user rotation for a missing display.");
3842                     return;
3843                 }
3844                 display.getDisplayRotation().setFixedToUserRotation(fixedToUserRotation);
3845             }
3846         } finally {
3847             Binder.restoreCallingIdentity(origId);
3848         }
3849     }
3850 
getFixedToUserRotation(int displayId)3851     int getFixedToUserRotation(int displayId) {
3852         synchronized (mGlobalLock) {
3853             final DisplayContent display = mRoot.getDisplayContent(displayId);
3854             if (display == null) {
3855                 Slog.w(TAG, "Trying to get fixed to user rotation for a missing display.");
3856                 return -1;
3857             }
3858             return display.getDisplayRotation().getFixedToUserRotationMode();
3859         }
3860     }
3861 
3862     @Override
setIgnoreOrientationRequest(int displayId, boolean ignoreOrientationRequest)3863     public void setIgnoreOrientationRequest(int displayId, boolean ignoreOrientationRequest) {
3864         if (!checkCallingPermission(
3865                 android.Manifest.permission.SET_ORIENTATION, "setIgnoreOrientationRequest()")) {
3866             throw new SecurityException("Requires SET_ORIENTATION permission");
3867         }
3868 
3869         final long origId = Binder.clearCallingIdentity();
3870         try {
3871             synchronized (mGlobalLock) {
3872                 final DisplayContent display = mRoot.getDisplayContent(displayId);
3873                 if (display == null) {
3874                     Slog.w(TAG, "Trying to setIgnoreOrientationRequest() for a missing display.");
3875                     return;
3876                 }
3877                 display.setIgnoreOrientationRequest(ignoreOrientationRequest);
3878             }
3879         } finally {
3880             Binder.restoreCallingIdentity(origId);
3881         }
3882     }
3883 
getIgnoreOrientationRequest(int displayId)3884     boolean getIgnoreOrientationRequest(int displayId) {
3885         synchronized (mGlobalLock) {
3886             final DisplayContent display = mRoot.getDisplayContent(displayId);
3887             if (display == null) {
3888                 Slog.w(TAG, "Trying to getIgnoreOrientationRequest() for a missing display.");
3889                 return false;
3890             }
3891             return display.getIgnoreOrientationRequest();
3892         }
3893     }
3894 
3895     @Override
freezeRotation(int rotation)3896     public void freezeRotation(int rotation) {
3897         freezeDisplayRotation(Display.DEFAULT_DISPLAY, rotation);
3898     }
3899 
3900     /**
3901      * Freeze rotation changes.  (Enable "rotation lock".)
3902      * Persists across reboots.
3903      * @param displayId The ID of the display to freeze.
3904      * @param rotation The desired rotation to freeze to, or -1 to use the current rotation.
3905      */
3906     @Override
freezeDisplayRotation(int displayId, int rotation)3907     public void freezeDisplayRotation(int displayId, int rotation) {
3908         // TODO(multi-display): Track which display is rotated.
3909         if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
3910                 "freezeRotation()")) {
3911             throw new SecurityException("Requires SET_ORIENTATION permission");
3912         }
3913         if (rotation < -1 || rotation > Surface.ROTATION_270) {
3914             throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
3915                     + "rotation constant.");
3916         }
3917 
3918         final long origId = Binder.clearCallingIdentity();
3919         try {
3920             synchronized (mGlobalLock) {
3921                 final DisplayContent display = mRoot.getDisplayContent(displayId);
3922                 if (display == null) {
3923                     Slog.w(TAG, "Trying to freeze rotation for a missing display.");
3924                     return;
3925                 }
3926                 display.getDisplayRotation().freezeRotation(rotation);
3927             }
3928         } finally {
3929             Binder.restoreCallingIdentity(origId);
3930         }
3931 
3932         updateRotationUnchecked(false, false);
3933     }
3934 
3935     @Override
thawRotation()3936     public void thawRotation() {
3937         thawDisplayRotation(Display.DEFAULT_DISPLAY);
3938     }
3939 
3940     /**
3941      * Thaw rotation changes.  (Disable "rotation lock".)
3942      * Persists across reboots.
3943      */
3944     @Override
thawDisplayRotation(int displayId)3945     public void thawDisplayRotation(int displayId) {
3946         if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
3947                 "thawRotation()")) {
3948             throw new SecurityException("Requires SET_ORIENTATION permission");
3949         }
3950 
3951         ProtoLog.v(WM_DEBUG_ORIENTATION, "thawRotation: mRotation=%d", getDefaultDisplayRotation());
3952 
3953         final long origId = Binder.clearCallingIdentity();
3954         try {
3955             synchronized (mGlobalLock) {
3956                 final DisplayContent display = mRoot.getDisplayContent(displayId);
3957                 if (display == null) {
3958                     Slog.w(TAG, "Trying to thaw rotation for a missing display.");
3959                     return;
3960                 }
3961                 display.getDisplayRotation().thawRotation();
3962             }
3963         } finally {
3964             Binder.restoreCallingIdentity(origId);
3965         }
3966 
3967         updateRotationUnchecked(false, false);
3968     }
3969 
3970     @Override
isRotationFrozen()3971     public boolean isRotationFrozen() {
3972         return isDisplayRotationFrozen(Display.DEFAULT_DISPLAY);
3973     }
3974 
3975     @Override
isDisplayRotationFrozen(int displayId)3976     public boolean isDisplayRotationFrozen(int displayId) {
3977         synchronized (mGlobalLock) {
3978             final DisplayContent display = mRoot.getDisplayContent(displayId);
3979             if (display == null) {
3980                 Slog.w(TAG, "Trying to check if rotation is frozen on a missing display.");
3981                 return false;
3982             }
3983             return display.getDisplayRotation().isRotationFrozen();
3984         }
3985     }
3986 
getDisplayUserRotation(int displayId)3987     int getDisplayUserRotation(int displayId) {
3988         synchronized (mGlobalLock) {
3989             final DisplayContent display = mRoot.getDisplayContent(displayId);
3990             if (display == null) {
3991                 Slog.w(TAG, "Trying to get user rotation of a missing display.");
3992                 return -1;
3993             }
3994             return display.getDisplayRotation().getUserRotation();
3995         }
3996     }
3997 
3998     /**
3999      * Recalculate the current rotation.
4000      *
4001      * Called by the window manager policy whenever the state of the system changes
4002      * such that the current rotation might need to be updated, such as when the
4003      * device is docked or rotated into a new posture.
4004      */
4005     @Override
updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout)4006     public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
4007         updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
4008     }
4009 
updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout)4010     private void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
4011         ProtoLog.v(WM_DEBUG_ORIENTATION, "updateRotationUnchecked:"
4012                         + " alwaysSendConfiguration=%b forceRelayout=%b",
4013                 alwaysSendConfiguration, forceRelayout);
4014 
4015         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation");
4016 
4017         final long origId = Binder.clearCallingIdentity();
4018 
4019         try {
4020             synchronized (mGlobalLock) {
4021                 boolean layoutNeeded = false;
4022                 final int displayCount = mRoot.mChildren.size();
4023                 for (int i = 0; i < displayCount; ++i) {
4024                     final DisplayContent displayContent = mRoot.mChildren.get(i);
4025                     Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: display");
4026                     final boolean rotationChanged = displayContent.updateRotationUnchecked();
4027                     Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
4028 
4029                     if (rotationChanged) {
4030                         mAtmService.getTaskChangeNotificationController()
4031                                 .notifyOnActivityRotation(displayContent.mDisplayId);
4032                     }
4033 
4034                     final boolean pendingRemoteRotation = rotationChanged
4035                             && (displayContent.getDisplayRotation().isWaitingForRemoteRotation()
4036                             || mAtmService.getTransitionController().isCollecting());
4037                     // Even if alwaysSend, we are waiting for a transition or remote to provide
4038                     // rotated configuration, so we can't update configuration yet.
4039                     if (!pendingRemoteRotation) {
4040                         if (!rotationChanged || forceRelayout) {
4041                             displayContent.setLayoutNeeded();
4042                             layoutNeeded = true;
4043                         }
4044                         if (rotationChanged || alwaysSendConfiguration) {
4045                             displayContent.sendNewConfiguration();
4046                         }
4047                     }
4048                 }
4049 
4050                 if (layoutNeeded) {
4051                     Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
4052                             "updateRotation: performSurfacePlacement");
4053                     mWindowPlacerLocked.performSurfacePlacement();
4054                     Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
4055                 }
4056             }
4057         } finally {
4058             Binder.restoreCallingIdentity(origId);
4059             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
4060         }
4061     }
4062 
4063     @Override
getDefaultDisplayRotation()4064     public int getDefaultDisplayRotation() {
4065         synchronized (mGlobalLock) {
4066             return getDefaultDisplayContentLocked().getRotation();
4067         }
4068     }
4069 
4070     @Override
setDisplayWindowRotationController(IDisplayWindowRotationController controller)4071     public void setDisplayWindowRotationController(IDisplayWindowRotationController controller) {
4072         mAtmService.enforceTaskPermission("setDisplayWindowRotationController");
4073         try {
4074             synchronized (mGlobalLock) {
4075                 if (mDisplayRotationController != null) {
4076                     mDisplayRotationController.asBinder().unlinkToDeath(
4077                             mDisplayRotationControllerDeath, 0);
4078                     mDisplayRotationController = null;
4079                 }
4080                 controller.asBinder().linkToDeath(mDisplayRotationControllerDeath, 0);
4081                 mDisplayRotationController = controller;
4082             }
4083         } catch (RemoteException e) {
4084             throw new RuntimeException("Unable to set rotation controller");
4085         }
4086     }
4087 
4088     @Override
addShellRoot(int displayId, IWindow client, @WindowManager.ShellRootLayer int shellRootLayer)4089     public SurfaceControl addShellRoot(int displayId, IWindow client,
4090             @WindowManager.ShellRootLayer int shellRootLayer) {
4091         if (mContext.checkCallingOrSelfPermission(MANAGE_APP_TOKENS)
4092                 != PackageManager.PERMISSION_GRANTED) {
4093             throw new SecurityException("Must hold permission " + MANAGE_APP_TOKENS);
4094         }
4095         final long origId = Binder.clearCallingIdentity();
4096         try {
4097             synchronized (mGlobalLock) {
4098                 final DisplayContent dc = mRoot.getDisplayContent(displayId);
4099                 if (dc == null) {
4100                     return null;
4101                 }
4102                 return dc.addShellRoot(client, shellRootLayer);
4103             }
4104         } finally {
4105             Binder.restoreCallingIdentity(origId);
4106         }
4107     }
4108 
4109     @Override
setShellRootAccessibilityWindow(int displayId, @WindowManager.ShellRootLayer int shellRootLayer, IWindow target)4110     public void setShellRootAccessibilityWindow(int displayId,
4111             @WindowManager.ShellRootLayer int shellRootLayer, IWindow target) {
4112         if (mContext.checkCallingOrSelfPermission(MANAGE_APP_TOKENS)
4113                 != PackageManager.PERMISSION_GRANTED) {
4114             throw new SecurityException("Must hold permission " + MANAGE_APP_TOKENS);
4115         }
4116         final long origId = Binder.clearCallingIdentity();
4117         try {
4118             synchronized (mGlobalLock) {
4119                 final DisplayContent dc = mRoot.getDisplayContent(displayId);
4120                 if (dc == null) {
4121                     return;
4122                 }
4123                 ShellRoot root = dc.mShellRoots.get(shellRootLayer);
4124                 if (root == null) {
4125                     return;
4126                 }
4127                 root.setAccessibilityWindow(target);
4128             }
4129         } finally {
4130             Binder.restoreCallingIdentity(origId);
4131         }
4132     }
4133 
4134     @Override
setDisplayWindowInsetsController( int displayId, IDisplayWindowInsetsController insetsController)4135     public void setDisplayWindowInsetsController(
4136             int displayId, IDisplayWindowInsetsController insetsController) {
4137         if (mContext.checkCallingOrSelfPermission(MANAGE_APP_TOKENS)
4138                 != PackageManager.PERMISSION_GRANTED) {
4139             throw new SecurityException("Must hold permission " + MANAGE_APP_TOKENS);
4140         }
4141         final long origId = Binder.clearCallingIdentity();
4142         try {
4143             synchronized (mGlobalLock) {
4144                 final DisplayContent dc = mRoot.getDisplayContent(displayId);
4145                 if (dc == null) {
4146                     return;
4147                 }
4148                 dc.setRemoteInsetsController(insetsController);
4149             }
4150         } finally {
4151             Binder.restoreCallingIdentity(origId);
4152         }
4153     }
4154 
4155     @Override
modifyDisplayWindowInsets(int displayId, InsetsState state)4156     public void modifyDisplayWindowInsets(int displayId, InsetsState state) {
4157         if (mContext.checkCallingOrSelfPermission(MANAGE_APP_TOKENS)
4158                 != PackageManager.PERMISSION_GRANTED) {
4159             throw new SecurityException("Must hold permission " + MANAGE_APP_TOKENS);
4160         }
4161         final long origId = Binder.clearCallingIdentity();
4162         try {
4163             synchronized (mGlobalLock) {
4164                 final DisplayContent dc = mRoot.getDisplayContent(displayId);
4165                 if (dc == null || dc.mRemoteInsetsControlTarget == null) {
4166                     return;
4167                 }
4168                 dc.mRemoteInsetsControlTarget.updateRequestedVisibility(state);
4169                 dc.getInsetsStateController().onInsetsModified(dc.mRemoteInsetsControlTarget);
4170             }
4171         } finally {
4172             Binder.restoreCallingIdentity(origId);
4173         }
4174     }
4175 
4176     @Override
watchRotation(IRotationWatcher watcher, int displayId)4177     public int watchRotation(IRotationWatcher watcher, int displayId) {
4178         final DisplayContent displayContent;
4179         synchronized (mGlobalLock) {
4180             displayContent = mRoot.getDisplayContent(displayId);
4181         }
4182         if (displayContent == null) {
4183             throw new IllegalArgumentException("Trying to register rotation event "
4184                     + "for invalid display: " + displayId);
4185         }
4186 
4187         final IBinder watcherBinder = watcher.asBinder();
4188         IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
4189             @Override
4190             public void binderDied() {
4191                 synchronized (mGlobalLock) {
4192                     for (int i=0; i<mRotationWatchers.size(); i++) {
4193                         if (watcherBinder == mRotationWatchers.get(i).mWatcher.asBinder()) {
4194                             RotationWatcher removed = mRotationWatchers.remove(i);
4195                             IBinder binder = removed.mWatcher.asBinder();
4196                             if (binder != null) {
4197                                 binder.unlinkToDeath(this, 0);
4198                             }
4199                             i--;
4200                         }
4201                     }
4202                 }
4203             }
4204         };
4205 
4206         synchronized (mGlobalLock) {
4207             try {
4208                 watcher.asBinder().linkToDeath(dr, 0);
4209                 mRotationWatchers.add(new RotationWatcher(watcher, dr, displayId));
4210             } catch (RemoteException e) {
4211                 // Client died, no cleanup needed.
4212             }
4213 
4214             return displayContent.getRotation();
4215         }
4216     }
4217 
4218     @Override
removeRotationWatcher(IRotationWatcher watcher)4219     public void removeRotationWatcher(IRotationWatcher watcher) {
4220         final IBinder watcherBinder = watcher.asBinder();
4221         synchronized (mGlobalLock) {
4222             for (int i=0; i<mRotationWatchers.size(); i++) {
4223                 RotationWatcher rotationWatcher = mRotationWatchers.get(i);
4224                 if (watcherBinder == rotationWatcher.mWatcher.asBinder()) {
4225                     RotationWatcher removed = mRotationWatchers.remove(i);
4226                     IBinder binder = removed.mWatcher.asBinder();
4227                     if (binder != null) {
4228                         binder.unlinkToDeath(removed.mDeathRecipient, 0);
4229                     }
4230                     i--;
4231                 }
4232             }
4233         }
4234     }
4235 
4236     @Override
registerWallpaperVisibilityListener(IWallpaperVisibilityListener listener, int displayId)4237     public boolean registerWallpaperVisibilityListener(IWallpaperVisibilityListener listener,
4238             int displayId) {
4239         synchronized (mGlobalLock) {
4240             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
4241             if (displayContent == null) {
4242                 throw new IllegalArgumentException("Trying to register visibility event "
4243                         + "for invalid display: " + displayId);
4244             }
4245             mWallpaperVisibilityListeners.registerWallpaperVisibilityListener(listener, displayId);
4246             return displayContent.mWallpaperController.isWallpaperVisible();
4247         }
4248     }
4249 
4250     @Override
unregisterWallpaperVisibilityListener(IWallpaperVisibilityListener listener, int displayId)4251     public void unregisterWallpaperVisibilityListener(IWallpaperVisibilityListener listener,
4252             int displayId) {
4253         synchronized (mGlobalLock) {
4254             mWallpaperVisibilityListeners
4255                     .unregisterWallpaperVisibilityListener(listener, displayId);
4256         }
4257     }
4258 
4259     @Override
registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener, int displayId)4260     public void registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener,
4261             int displayId) {
4262         synchronized (mGlobalLock) {
4263             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
4264             if (displayContent == null) {
4265                 throw new IllegalArgumentException("Trying to register visibility event "
4266                         + "for invalid display: " + displayId);
4267             }
4268             displayContent.registerSystemGestureExclusionListener(listener);
4269         }
4270     }
4271 
4272     @Override
unregisterSystemGestureExclusionListener(ISystemGestureExclusionListener listener, int displayId)4273     public void unregisterSystemGestureExclusionListener(ISystemGestureExclusionListener listener,
4274             int displayId) {
4275         synchronized (mGlobalLock) {
4276             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
4277             if (displayContent == null) {
4278                 throw new IllegalArgumentException("Trying to register visibility event "
4279                         + "for invalid display: " + displayId);
4280             }
4281             displayContent.unregisterSystemGestureExclusionListener(listener);
4282         }
4283     }
4284 
reportSystemGestureExclusionChanged(Session session, IWindow window, List<Rect> exclusionRects)4285     void reportSystemGestureExclusionChanged(Session session, IWindow window,
4286             List<Rect> exclusionRects) {
4287         synchronized (mGlobalLock) {
4288             final WindowState win = windowForClientLocked(session, window, true);
4289             if (win.setSystemGestureExclusion(exclusionRects)) {
4290                 win.getDisplayContent().updateSystemGestureExclusion();
4291             }
4292         }
4293     }
4294 
4295     @Override
registerDisplayFoldListener(IDisplayFoldListener listener)4296     public void registerDisplayFoldListener(IDisplayFoldListener listener) {
4297         mPolicy.registerDisplayFoldListener(listener);
4298     }
4299 
4300     @Override
unregisterDisplayFoldListener(IDisplayFoldListener listener)4301     public void unregisterDisplayFoldListener(IDisplayFoldListener listener) {
4302         mPolicy.unregisterDisplayFoldListener(listener);
4303     }
4304 
4305     /**
4306      * Overrides the folded area.
4307      *
4308      * @param area the overriding folded area or an empty {@code Rect} to clear the override.
4309      */
setOverrideFoldedArea(@onNull Rect area)4310     void setOverrideFoldedArea(@NonNull Rect area) {
4311         if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
4312                 != PackageManager.PERMISSION_GRANTED) {
4313             throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
4314         }
4315 
4316         final long origId = Binder.clearCallingIdentity();
4317         try {
4318             synchronized (mGlobalLock) {
4319                 mPolicy.setOverrideFoldedArea(area);
4320             }
4321         } finally {
4322             Binder.restoreCallingIdentity(origId);
4323         }
4324     }
4325 
4326     /**
4327      * Get the display folded area.
4328      */
getFoldedArea()4329     @NonNull Rect getFoldedArea() {
4330         final long origId = Binder.clearCallingIdentity();
4331         try {
4332             synchronized (mGlobalLock) {
4333                 return mPolicy.getFoldedArea();
4334             }
4335         } finally {
4336             Binder.restoreCallingIdentity(origId);
4337         }
4338     }
4339 
4340     /** Registers a hierarchy listener that gets callbacks when the hierarchy changes. */
4341     @Override
registerDisplayWindowListener(IDisplayWindowListener listener)4342     public void registerDisplayWindowListener(IDisplayWindowListener listener) {
4343         mAtmService.enforceTaskPermission("registerDisplayWindowListener");
4344         final long ident = Binder.clearCallingIdentity();
4345         try {
4346             mDisplayNotificationController.registerListener(listener);
4347         } finally {
4348             Binder.restoreCallingIdentity(ident);
4349         }
4350     }
4351 
4352     /** Unregister a hierarchy listener so that it stops receiving callbacks. */
4353     @Override
unregisterDisplayWindowListener(IDisplayWindowListener listener)4354     public void unregisterDisplayWindowListener(IDisplayWindowListener listener) {
4355         mAtmService.enforceTaskPermission("unregisterDisplayWindowListener");
4356         mDisplayNotificationController.unregisterListener(listener);
4357     }
4358 
4359     @Override
getPreferredOptionsPanelGravity(int displayId)4360     public int getPreferredOptionsPanelGravity(int displayId) {
4361         synchronized (mGlobalLock) {
4362             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
4363             if (displayContent == null) {
4364                 return Gravity.CENTER | Gravity.BOTTOM;
4365             }
4366             return displayContent.getPreferredOptionsPanelGravity();
4367         }
4368     }
4369 
4370     /**
4371      * Starts the view server on the specified port.
4372      *
4373      * @param port The port to listener to.
4374      *
4375      * @return True if the server was successfully started, false otherwise.
4376      *
4377      * @see com.android.server.wm.ViewServer
4378      * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
4379      */
4380     @Override
startViewServer(int port)4381     public boolean startViewServer(int port) {
4382         if (isSystemSecure()) {
4383             return false;
4384         }
4385 
4386         if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
4387             return false;
4388         }
4389 
4390         if (port < 1024) {
4391             return false;
4392         }
4393 
4394         if (mViewServer != null) {
4395             if (!mViewServer.isRunning()) {
4396                 try {
4397                     return mViewServer.start();
4398                 } catch (IOException e) {
4399                     ProtoLog.w(WM_ERROR, "View server did not start");
4400                 }
4401             }
4402             return false;
4403         }
4404 
4405         try {
4406             mViewServer = new ViewServer(this, port);
4407             return mViewServer.start();
4408         } catch (IOException e) {
4409             ProtoLog.w(WM_ERROR, "View server did not start");
4410         }
4411         return false;
4412     }
4413 
isSystemSecure()4414     private boolean isSystemSecure() {
4415         return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
4416                 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
4417     }
4418 
4419     /**
4420      * Stops the view server if it exists.
4421      *
4422      * @return True if the server stopped, false if it wasn't started or
4423      *         couldn't be stopped.
4424      *
4425      * @see com.android.server.wm.ViewServer
4426      */
4427     @Override
stopViewServer()4428     public boolean stopViewServer() {
4429         if (isSystemSecure()) {
4430             return false;
4431         }
4432 
4433         if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
4434             return false;
4435         }
4436 
4437         if (mViewServer != null) {
4438             return mViewServer.stop();
4439         }
4440         return false;
4441     }
4442 
4443     /**
4444      * Indicates whether the view server is running.
4445      *
4446      * @return True if the server is running, false otherwise.
4447      *
4448      * @see com.android.server.wm.ViewServer
4449      */
4450     @Override
isViewServerRunning()4451     public boolean isViewServerRunning() {
4452         if (isSystemSecure()) {
4453             return false;
4454         }
4455 
4456         if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
4457             return false;
4458         }
4459 
4460         return mViewServer != null && mViewServer.isRunning();
4461     }
4462 
4463     /**
4464      * Lists all available windows in the system. The listing is written in the specified Socket's
4465      * output stream with the following syntax: windowHashCodeInHexadecimal windowName
4466      * Each line of the output represents a different window.
4467      *
4468      * @param client The remote client to send the listing to.
4469      * @return false if an error occurred, true otherwise.
4470      */
viewServerListWindows(Socket client)4471     boolean viewServerListWindows(Socket client) {
4472         if (isSystemSecure()) {
4473             return false;
4474         }
4475 
4476         boolean result = true;
4477 
4478         final ArrayList<WindowState> windows = new ArrayList();
4479         synchronized (mGlobalLock) {
4480             mRoot.forAllWindows(w -> {
4481                 windows.add(w);
4482             }, false /* traverseTopToBottom */);
4483         }
4484 
4485         BufferedWriter out = null;
4486 
4487         // Any uncaught exception will crash the system process
4488         try {
4489             OutputStream clientStream = client.getOutputStream();
4490             out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
4491 
4492             final int count = windows.size();
4493             for (int i = 0; i < count; i++) {
4494                 final WindowState w = windows.get(i);
4495                 out.write(Integer.toHexString(System.identityHashCode(w)));
4496                 out.write(' ');
4497                 out.append(w.mAttrs.getTitle());
4498                 out.write('\n');
4499             }
4500 
4501             out.write("DONE.\n");
4502             out.flush();
4503         } catch (Exception e) {
4504             result = false;
4505         } finally {
4506             if (out != null) {
4507                 try {
4508                     out.close();
4509                 } catch (IOException e) {
4510                     result = false;
4511                 }
4512             }
4513         }
4514 
4515         return result;
4516     }
4517 
4518     // TODO(multidisplay): Extend to multiple displays.
4519     /**
4520      * Returns the focused window in the following format:
4521      * windowHashCodeInHexadecimal windowName
4522      *
4523      * @param client The remote client to send the listing to.
4524      * @return False if an error occurred, true otherwise.
4525      */
viewServerGetFocusedWindow(Socket client)4526     boolean viewServerGetFocusedWindow(Socket client) {
4527         if (isSystemSecure()) {
4528             return false;
4529         }
4530 
4531         boolean result = true;
4532 
4533         WindowState focusedWindow = getFocusedWindow();
4534 
4535         BufferedWriter out = null;
4536 
4537         // Any uncaught exception will crash the system process
4538         try {
4539             OutputStream clientStream = client.getOutputStream();
4540             out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
4541 
4542             if(focusedWindow != null) {
4543                 out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
4544                 out.write(' ');
4545                 out.append(focusedWindow.mAttrs.getTitle());
4546             }
4547             out.write('\n');
4548             out.flush();
4549         } catch (Exception e) {
4550             result = false;
4551         } finally {
4552             if (out != null) {
4553                 try {
4554                     out.close();
4555                 } catch (IOException e) {
4556                     result = false;
4557                 }
4558             }
4559         }
4560 
4561         return result;
4562     }
4563 
4564     /**
4565      * Sends a command to a target window. The result of the command, if any, will be
4566      * written in the output stream of the specified socket.
4567      *
4568      * The parameters must follow this syntax:
4569      * windowHashcode extra
4570      *
4571      * Where XX is the length in characeters of the windowTitle.
4572      *
4573      * The first parameter is the target window. The window with the specified hashcode
4574      * will be the target. If no target can be found, nothing happens. The extra parameters
4575      * will be delivered to the target window and as parameters to the command itself.
4576      *
4577      * @param client The remote client to sent the result, if any, to.
4578      * @param command The command to execute.
4579      * @param parameters The command parameters.
4580      *
4581      * @return True if the command was successfully delivered, false otherwise. This does
4582      *         not indicate whether the command itself was successful.
4583      */
viewServerWindowCommand(Socket client, String command, String parameters)4584     boolean viewServerWindowCommand(Socket client, String command, String parameters) {
4585         if (isSystemSecure()) {
4586             return false;
4587         }
4588 
4589         boolean success = true;
4590         Parcel data = null;
4591         Parcel reply = null;
4592 
4593         BufferedWriter out = null;
4594 
4595         // Any uncaught exception will crash the system process
4596         try {
4597             // Find the hashcode of the window
4598             int index = parameters.indexOf(' ');
4599             if (index == -1) {
4600                 index = parameters.length();
4601             }
4602             final String code = parameters.substring(0, index);
4603             int hashCode = (int) Long.parseLong(code, 16);
4604 
4605             // Extract the command's parameter after the window description
4606             if (index < parameters.length()) {
4607                 parameters = parameters.substring(index + 1);
4608             } else {
4609                 parameters = "";
4610             }
4611 
4612             final WindowState window = findWindow(hashCode);
4613             if (window == null) {
4614                 return false;
4615             }
4616 
4617             data = Parcel.obtain();
4618             data.writeInterfaceToken("android.view.IWindow");
4619             data.writeString(command);
4620             data.writeString(parameters);
4621             data.writeInt(1);
4622             ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
4623 
4624             reply = Parcel.obtain();
4625 
4626             final IBinder binder = window.mClient.asBinder();
4627             // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
4628             binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
4629 
4630             reply.readException();
4631 
4632             if (!client.isOutputShutdown()) {
4633                 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
4634                 out.write("DONE\n");
4635                 out.flush();
4636             }
4637 
4638         } catch (Exception e) {
4639             ProtoLog.w(WM_ERROR, "Could not send command %s with parameters %s. %s", command,
4640                     parameters, e);
4641             success = false;
4642         } finally {
4643             if (data != null) {
4644                 data.recycle();
4645             }
4646             if (reply != null) {
4647                 reply.recycle();
4648             }
4649             if (out != null) {
4650                 try {
4651                     out.close();
4652                 } catch (IOException e) {
4653 
4654                 }
4655             }
4656         }
4657 
4658         return success;
4659     }
4660 
addWindowChangeListener(WindowChangeListener listener)4661     public void addWindowChangeListener(WindowChangeListener listener) {
4662         synchronized (mGlobalLock) {
4663             mWindowChangeListeners.add(listener);
4664         }
4665     }
4666 
removeWindowChangeListener(WindowChangeListener listener)4667     public void removeWindowChangeListener(WindowChangeListener listener) {
4668         synchronized (mGlobalLock) {
4669             mWindowChangeListeners.remove(listener);
4670         }
4671     }
4672 
notifyWindowsChanged()4673     private void notifyWindowsChanged() {
4674         WindowChangeListener[] windowChangeListeners;
4675         synchronized (mGlobalLock) {
4676             if(mWindowChangeListeners.isEmpty()) {
4677                 return;
4678             }
4679             windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
4680             windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
4681         }
4682         int N = windowChangeListeners.length;
4683         for(int i = 0; i < N; i++) {
4684             windowChangeListeners[i].windowsChanged();
4685         }
4686     }
4687 
notifyFocusChanged()4688     private void notifyFocusChanged() {
4689         WindowChangeListener[] windowChangeListeners;
4690         synchronized (mGlobalLock) {
4691             if(mWindowChangeListeners.isEmpty()) {
4692                 return;
4693             }
4694             windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
4695             windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
4696         }
4697         int N = windowChangeListeners.length;
4698         for(int i = 0; i < N; i++) {
4699             windowChangeListeners[i].focusChanged();
4700         }
4701     }
4702 
findWindow(int hashCode)4703     private WindowState findWindow(int hashCode) {
4704         if (hashCode == -1) {
4705             // TODO(multidisplay): Extend to multiple displays.
4706             return getFocusedWindow();
4707         }
4708 
4709         synchronized (mGlobalLock) {
4710             return mRoot.getWindow((w) -> System.identityHashCode(w) == hashCode);
4711         }
4712     }
4713 
computeNewConfiguration(int displayId)4714     public Configuration computeNewConfiguration(int displayId) {
4715         synchronized (mGlobalLock) {
4716             return computeNewConfigurationLocked(displayId);
4717         }
4718     }
4719 
computeNewConfigurationLocked(int displayId)4720     private Configuration computeNewConfigurationLocked(int displayId) {
4721         if (!mDisplayReady) {
4722             return null;
4723         }
4724         final Configuration config = new Configuration();
4725         final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
4726         displayContent.computeScreenConfiguration(config);
4727         return config;
4728     }
4729 
notifyHardKeyboardStatusChange()4730     void notifyHardKeyboardStatusChange() {
4731         final boolean available;
4732         final WindowManagerInternal.OnHardKeyboardStatusChangeListener listener;
4733         synchronized (mGlobalLock) {
4734             listener = mHardKeyboardStatusChangeListener;
4735             available = mHardKeyboardAvailable;
4736         }
4737         if (listener != null) {
4738             listener.onHardKeyboardStatusChange(available);
4739         }
4740     }
4741 
4742     // -------------------------------------------------------------
4743     // Input Events and Focus Management
4744     // -------------------------------------------------------------
4745 
4746     final InputManagerCallback mInputManagerCallback = new InputManagerCallback(this);
4747     private boolean mEventDispatchingEnabled;
4748 
4749     @Override
setEventDispatching(boolean enabled)4750     public void setEventDispatching(boolean enabled) {
4751         if (!checkCallingPermission(MANAGE_APP_TOKENS, "setEventDispatching()")) {
4752             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4753         }
4754 
4755         synchronized (mGlobalLock) {
4756             mEventDispatchingEnabled = enabled;
4757             if (mDisplayEnabled) {
4758                 mInputManagerCallback.setEventDispatchingLw(enabled);
4759             }
4760         }
4761     }
4762 
getFocusedWindow()4763     private WindowState getFocusedWindow() {
4764         synchronized (mGlobalLock) {
4765             return getFocusedWindowLocked();
4766         }
4767     }
4768 
getFocusedWindowLocked()4769     private WindowState getFocusedWindowLocked() {
4770         // Return the focused window in the focused display.
4771         return mRoot.getTopFocusedDisplayContent().mCurrentFocus;
4772     }
4773 
getImeFocusRootTaskLocked()4774     Task getImeFocusRootTaskLocked() {
4775         // Don't use mCurrentFocus.getStack() because it returns home stack for system windows.
4776         // Also don't use mInputMethodTarget's stack, because some window with FLAG_NOT_FOCUSABLE
4777         // and FLAG_ALT_FOCUSABLE_IM flags both set might be set to IME target so they're moved
4778         // to make room for IME, but the window is not the focused window that's taking input.
4779         // TODO (b/111080190): Consider the case of multiple IMEs on multi-display.
4780         final DisplayContent topFocusedDisplay = mRoot.getTopFocusedDisplayContent();
4781         final ActivityRecord focusedApp = topFocusedDisplay.mFocusedApp;
4782         return (focusedApp != null && focusedApp.getTask() != null)
4783                 ? focusedApp.getTask().getRootTask() : null;
4784     }
4785 
detectSafeMode()4786     public boolean detectSafeMode() {
4787         if (!mInputManagerCallback.waitForInputDevicesReady(
4788                 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
4789             ProtoLog.w(WM_ERROR, "Devices still not ready after waiting %d"
4790                             + " milliseconds before attempting to detect safe mode.",
4791                     INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS);
4792         }
4793 
4794         if (Settings.Global.getInt(
4795                 mContext.getContentResolver(), Settings.Global.SAFE_BOOT_DISALLOWED, 0) != 0) {
4796             return false;
4797         }
4798 
4799         int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
4800                 KeyEvent.KEYCODE_MENU);
4801         int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
4802         int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
4803                 KeyEvent.KEYCODE_DPAD_CENTER);
4804         int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
4805                 InputManagerService.BTN_MOUSE);
4806         int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
4807                 KeyEvent.KEYCODE_VOLUME_DOWN);
4808         mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
4809                 || volumeDownState > 0;
4810         try {
4811             if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0
4812                     || SystemProperties.getInt(ShutdownThread.RO_SAFEMODE_PROPERTY, 0) != 0) {
4813                 mSafeMode = true;
4814                 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
4815             }
4816         } catch (IllegalArgumentException e) {
4817         }
4818         if (mSafeMode) {
4819             ProtoLog.i(WM_ERROR, "SAFE MODE ENABLED (menu=%d s=%d dpad=%d"
4820                     + " trackball=%d)", menuState, sState, dpadState, trackballState);
4821             // May already be set if (for instance) this process has crashed
4822             if (SystemProperties.getInt(ShutdownThread.RO_SAFEMODE_PROPERTY, 0) == 0) {
4823                 SystemProperties.set(ShutdownThread.RO_SAFEMODE_PROPERTY, "1");
4824             }
4825         } else {
4826             ProtoLog.i(WM_ERROR, "SAFE MODE not enabled");
4827         }
4828         mPolicy.setSafeMode(mSafeMode);
4829         return mSafeMode;
4830     }
4831 
displayReady()4832     public void displayReady() {
4833         synchronized (mGlobalLock) {
4834             if (mMaxUiWidth > 0) {
4835                 mRoot.forAllDisplays(displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth));
4836             }
4837             applyForcedPropertiesForDefaultDisplay();
4838             mAnimator.ready();
4839             mDisplayReady = true;
4840             // Reconfigure all displays to make sure that forced properties and
4841             // DisplayWindowSettings are applied.
4842             mRoot.forAllDisplays(DisplayContent::reconfigureDisplayLocked);
4843             mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
4844                     PackageManager.FEATURE_TOUCHSCREEN);
4845             mIsFakeTouchDevice = mContext.getPackageManager().hasSystemFeature(
4846                     PackageManager.FEATURE_FAKETOUCH);
4847         }
4848 
4849         try {
4850             mActivityTaskManager.updateConfiguration(null);
4851         } catch (RemoteException e) {
4852         }
4853     }
4854 
systemReady()4855     public void systemReady() {
4856         mSystemReady = true;
4857         mPolicy.systemReady();
4858         mRoot.forAllDisplayPolicies(DisplayPolicy::systemReady);
4859         mTaskSnapshotController.systemReady();
4860         mHasWideColorGamutSupport = queryWideColorGamutSupport();
4861         mHasHdrSupport = queryHdrSupport();
4862         UiThread.getHandler().post(mSettingsObserver::loadSettings);
4863         IVrManager vrManager = IVrManager.Stub.asInterface(
4864                 ServiceManager.getService(Context.VR_SERVICE));
4865         if (vrManager != null) {
4866             try {
4867                 final boolean vrModeEnabled = vrManager.getVrModeState();
4868                 synchronized (mGlobalLock) {
4869                     vrManager.registerListener(mVrStateCallbacks);
4870                     if (vrModeEnabled) {
4871                         mVrModeEnabled = vrModeEnabled;
4872                         mVrStateCallbacks.onVrStateChanged(vrModeEnabled);
4873                     }
4874                 }
4875             } catch (RemoteException e) {
4876                 // Ignore, we cannot do anything if we failed to register VR mode listener
4877             }
4878         }
4879     }
4880 
queryWideColorGamutSupport()4881     private static boolean queryWideColorGamutSupport() {
4882         boolean defaultValue = false;
4883         Optional<Boolean> hasWideColorProp = SurfaceFlingerProperties.has_wide_color_display();
4884         if (hasWideColorProp.isPresent()) {
4885             return hasWideColorProp.get();
4886         }
4887         try {
4888             ISurfaceFlingerConfigs surfaceFlinger = ISurfaceFlingerConfigs.getService();
4889             OptionalBool hasWideColor = surfaceFlinger.hasWideColorDisplay();
4890             if (hasWideColor != null) {
4891                 return hasWideColor.value;
4892             }
4893         } catch (RemoteException e) {
4894             // Ignore, we're in big trouble if we can't talk to SurfaceFlinger's config store
4895         } catch (NoSuchElementException e) {
4896             return defaultValue;
4897         }
4898         return false;
4899     }
4900 
queryHdrSupport()4901     private static boolean queryHdrSupport() {
4902         boolean defaultValue = false;
4903         Optional<Boolean> hasHdrProp = SurfaceFlingerProperties.has_HDR_display();
4904         if (hasHdrProp.isPresent()) {
4905             return hasHdrProp.get();
4906         }
4907         try {
4908             ISurfaceFlingerConfigs surfaceFlinger = ISurfaceFlingerConfigs.getService();
4909             OptionalBool hasHdr = surfaceFlinger.hasHDRDisplay();
4910             if (hasHdr != null) {
4911                 return hasHdr.value;
4912             }
4913         } catch (RemoteException e) {
4914             // Ignore, we're in big trouble if we can't talk to SurfaceFlinger's config store
4915         } catch (NoSuchElementException e) {
4916             return defaultValue;
4917         }
4918         return false;
4919     }
4920 
reportFocusChanged(IBinder oldToken, IBinder newToken)4921     void reportFocusChanged(IBinder oldToken, IBinder newToken) {
4922         WindowState lastFocus;
4923         WindowState newFocus;
4924         synchronized (mGlobalLock) {
4925             lastFocus = mInputToWindowMap.get(oldToken);
4926             newFocus = mInputToWindowMap.get(newToken);
4927             ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "Focus changing: %s -> %s", lastFocus, newFocus);
4928         }
4929 
4930         if (newFocus != null) {
4931             mAnrController.onFocusChanged(newFocus);
4932             newFocus.reportFocusChangedSerialized(true);
4933             notifyFocusChanged();
4934         }
4935 
4936         if (lastFocus != null) {
4937             lastFocus.reportFocusChangedSerialized(false);
4938         }
4939     }
4940 
4941     // -------------------------------------------------------------
4942     // Async Handler
4943     // -------------------------------------------------------------
4944 
4945     final class H extends android.os.Handler {
4946         public static final int WINDOW_FREEZE_TIMEOUT = 11;
4947 
4948         public static final int PERSIST_ANIMATION_SCALE = 14;
4949         public static final int FORCE_GC = 15;
4950         public static final int ENABLE_SCREEN = 16;
4951         public static final int APP_FREEZE_TIMEOUT = 17;
4952         public static final int REPORT_WINDOWS_CHANGE = 19;
4953 
4954         public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
4955         public static final int BOOT_TIMEOUT = 23;
4956         public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
4957         public static final int SHOW_STRICT_MODE_VIOLATION = 25;
4958 
4959         public static final int CLIENT_FREEZE_TIMEOUT = 30;
4960         public static final int NOTIFY_ACTIVITY_DRAWN = 32;
4961 
4962         public static final int ALL_WINDOWS_DRAWN = 33;
4963 
4964         public static final int NEW_ANIMATOR_SCALE = 34;
4965 
4966         public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36;
4967 
4968         public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37;
4969         public static final int RESET_ANR_MESSAGE = 38;
4970         public static final int WALLPAPER_DRAW_PENDING_TIMEOUT = 39;
4971 
4972         public static final int UPDATE_MULTI_WINDOW_STACKS = 41;
4973 
4974         public static final int WINDOW_REPLACEMENT_TIMEOUT = 46;
4975 
4976         public static final int UPDATE_ANIMATION_SCALE = 51;
4977         public static final int WINDOW_HIDE_TIMEOUT = 52;
4978         public static final int RESTORE_POINTER_ICON = 55;
4979         public static final int SET_HAS_OVERLAY_UI = 58;
4980         public static final int ANIMATION_FAILSAFE = 60;
4981         public static final int RECOMPUTE_FOCUS = 61;
4982         public static final int ON_POINTER_DOWN_OUTSIDE_FOCUS = 62;
4983         public static final int LAYOUT_AND_ASSIGN_WINDOW_LAYERS_IF_NEEDED = 63;
4984         public static final int WINDOW_STATE_BLAST_SYNC_TIMEOUT = 64;
4985 
4986         /**
4987          * Used to denote that an integer field in a message will not be used.
4988          */
4989         public static final int UNUSED = 0;
4990 
4991         @Override
handleMessage(Message msg)4992         public void handleMessage(Message msg) {
4993             if (DEBUG_WINDOW_TRACE) {
4994                 Slog.v(TAG_WM, "handleMessage: entry what=" + msg.what);
4995             }
4996             switch (msg.what) {
4997                 case WINDOW_FREEZE_TIMEOUT: {
4998                     final DisplayContent displayContent = (DisplayContent) msg.obj;
4999                     synchronized (mGlobalLock) {
5000                         displayContent.onWindowFreezeTimeout();
5001                     }
5002                     break;
5003                 }
5004 
5005                 case PERSIST_ANIMATION_SCALE: {
5006                     Settings.Global.putFloat(mContext.getContentResolver(),
5007                             Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
5008                     Settings.Global.putFloat(mContext.getContentResolver(),
5009                             Settings.Global.TRANSITION_ANIMATION_SCALE,
5010                             mTransitionAnimationScaleSetting);
5011                     Settings.Global.putFloat(mContext.getContentResolver(),
5012                             Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting);
5013                     break;
5014                 }
5015 
5016                 case UPDATE_ANIMATION_SCALE: {
5017                     @UpdateAnimationScaleMode
5018                     final int mode = msg.arg1;
5019                     switch (mode) {
5020                         case WINDOW_ANIMATION_SCALE: {
5021                             mWindowAnimationScaleSetting = Settings.Global.getFloat(
5022                                     mContext.getContentResolver(),
5023                                     Settings.Global.WINDOW_ANIMATION_SCALE,
5024                                     mWindowAnimationScaleSetting);
5025                             break;
5026                         }
5027                         case TRANSITION_ANIMATION_SCALE: {
5028                             mTransitionAnimationScaleSetting = Settings.Global.getFloat(
5029                                     mContext.getContentResolver(),
5030                                     Settings.Global.TRANSITION_ANIMATION_SCALE,
5031                                     mTransitionAnimationScaleSetting);
5032                             break;
5033                         }
5034                         case ANIMATION_DURATION_SCALE: {
5035                             mAnimatorDurationScaleSetting = Settings.Global.getFloat(
5036                                     mContext.getContentResolver(),
5037                                     Settings.Global.ANIMATOR_DURATION_SCALE,
5038                                     mAnimatorDurationScaleSetting);
5039                             dispatchNewAnimatorScaleLocked(null);
5040                             break;
5041                         }
5042                     }
5043                     break;
5044                 }
5045 
5046                 case FORCE_GC: {
5047                     synchronized (mGlobalLock) {
5048                         // Since we're holding both mWindowMap and mAnimator we don't need to
5049                         // hold mAnimator.mLayoutToAnim.
5050                         if (mAnimator.isAnimationScheduled()) {
5051                             // If we are animating, don't do the gc now but
5052                             // delay a bit so we don't interrupt the animation.
5053                             sendEmptyMessageDelayed(H.FORCE_GC, 2000);
5054                             return;
5055                         }
5056                         // If we are currently rotating the display, it will
5057                         // schedule a new message when done.
5058                         if (mDisplayFrozen) {
5059                             return;
5060                         }
5061                     }
5062                     Runtime.getRuntime().gc();
5063                     break;
5064                 }
5065 
5066                 case ENABLE_SCREEN: {
5067                     performEnableScreen();
5068                     break;
5069                 }
5070 
5071                 case APP_FREEZE_TIMEOUT: {
5072                     synchronized (mGlobalLock) {
5073                         ProtoLog.w(WM_ERROR, "App freeze timeout expired.");
5074                         mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
5075                         for (int i = mAppFreezeListeners.size() - 1; i >= 0; --i) {
5076                             mAppFreezeListeners.get(i).onAppFreezeTimeout();
5077                         }
5078                     }
5079                     break;
5080                 }
5081 
5082                 case CLIENT_FREEZE_TIMEOUT: {
5083                     synchronized (mGlobalLock) {
5084                         if (mClientFreezingScreen) {
5085                             mClientFreezingScreen = false;
5086                             mLastFinishedFreezeSource = "client-timeout";
5087                             stopFreezingDisplayLocked();
5088                         }
5089                     }
5090                     break;
5091                 }
5092 
5093                 case REPORT_WINDOWS_CHANGE: {
5094                     if (mWindowsChanged) {
5095                         synchronized (mGlobalLock) {
5096                             mWindowsChanged = false;
5097                         }
5098                         notifyWindowsChanged();
5099                     }
5100                     break;
5101                 }
5102 
5103                 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
5104                     notifyHardKeyboardStatusChange();
5105                     break;
5106                 }
5107 
5108                 case BOOT_TIMEOUT: {
5109                     performBootTimeout();
5110                     break;
5111                 }
5112 
5113                 case WAITING_FOR_DRAWN_TIMEOUT: {
5114                     Runnable callback = null;
5115                     final WindowContainer container = (WindowContainer) msg.obj;
5116                     synchronized (mGlobalLock) {
5117                         ProtoLog.w(WM_ERROR, "Timeout waiting for drawn: undrawn=%s",
5118                                 container.mWaitingForDrawn);
5119                         container.mWaitingForDrawn.clear();
5120                         callback = mWaitingForDrawnCallbacks.remove(container);
5121                     }
5122                     if (callback != null) {
5123                         callback.run();
5124                     }
5125                     break;
5126                 }
5127 
5128                 case SHOW_STRICT_MODE_VIOLATION: {
5129                     showStrictModeViolation(msg.arg1, msg.arg2);
5130                     break;
5131                 }
5132 
5133                 case SHOW_EMULATOR_DISPLAY_OVERLAY: {
5134                     showEmulatorDisplayOverlay();
5135                     break;
5136                 }
5137 
5138                 case NOTIFY_ACTIVITY_DRAWN: {
5139                     final ActivityRecord activity = (ActivityRecord) msg.obj;
5140                     synchronized (mGlobalLock) {
5141                         if (activity.isAttached()) {
5142                             activity.getRootTask().notifyActivityDrawnLocked(activity);
5143                         }
5144                     }
5145                     break;
5146                 }
5147                 case ALL_WINDOWS_DRAWN: {
5148                     Runnable callback;
5149                     final WindowContainer container = (WindowContainer) msg.obj;
5150                     synchronized (mGlobalLock) {
5151                         callback = mWaitingForDrawnCallbacks.remove(container);
5152                     }
5153                     if (callback != null) {
5154                         callback.run();
5155                     }
5156                     break;
5157                 }
5158                 case NEW_ANIMATOR_SCALE: {
5159                     float scale = getCurrentAnimatorScale();
5160                     ValueAnimator.setDurationScale(scale);
5161                     Session session = (Session)msg.obj;
5162                     if (session != null) {
5163                         try {
5164                             session.mCallback.onAnimatorScaleChanged(scale);
5165                         } catch (RemoteException e) {
5166                         }
5167                     } else {
5168                         ArrayList<IWindowSessionCallback> callbacks
5169                                 = new ArrayList<IWindowSessionCallback>();
5170                         synchronized (mGlobalLock) {
5171                             for (int i=0; i<mSessions.size(); i++) {
5172                                 callbacks.add(mSessions.valueAt(i).mCallback);
5173                             }
5174 
5175                         }
5176                         for (int i=0; i<callbacks.size(); i++) {
5177                             try {
5178                                 callbacks.get(i).onAnimatorScaleChanged(scale);
5179                             } catch (RemoteException e) {
5180                             }
5181                         }
5182                     }
5183                     break;
5184                 }
5185                 case CHECK_IF_BOOT_ANIMATION_FINISHED: {
5186                     final boolean bootAnimationComplete;
5187                     synchronized (mGlobalLock) {
5188                         ProtoLog.i(WM_DEBUG_BOOT, "CHECK_IF_BOOT_ANIMATION_FINISHED:");
5189                         bootAnimationComplete = checkBootAnimationCompleteLocked();
5190                     }
5191                     if (bootAnimationComplete) {
5192                         performEnableScreen();
5193                     }
5194                     break;
5195                 }
5196                 case RESET_ANR_MESSAGE: {
5197                     synchronized (mGlobalLock) {
5198                         mLastANRState = null;
5199                     }
5200                     mAtmInternal.clearSavedANRState();
5201                     break;
5202                 }
5203                 case WALLPAPER_DRAW_PENDING_TIMEOUT: {
5204                     synchronized (mGlobalLock) {
5205                         final WallpaperController wallpaperController =
5206                                 (WallpaperController) msg.obj;
5207                         if (wallpaperController != null
5208                                 && wallpaperController.processWallpaperDrawPendingTimeout()) {
5209                             mWindowPlacerLocked.performSurfacePlacement();
5210                         }
5211                     }
5212                     break;
5213                 }
5214                 case UPDATE_MULTI_WINDOW_STACKS: {
5215                     synchronized (mGlobalLock) {
5216                         final DisplayContent displayContent = (DisplayContent) msg.obj;
5217                         if (displayContent != null) {
5218                             displayContent.adjustForImeIfNeeded();
5219                         }
5220                     }
5221                     break;
5222                 }
5223                 case WINDOW_REPLACEMENT_TIMEOUT: {
5224                     synchronized (mGlobalLock) {
5225                         for (int i = mWindowReplacementTimeouts.size() - 1; i >= 0; i--) {
5226                             final ActivityRecord activity = mWindowReplacementTimeouts.get(i);
5227                             activity.onWindowReplacementTimeout();
5228                         }
5229                         mWindowReplacementTimeouts.clear();
5230                     }
5231                     break;
5232                 }
5233                 case WINDOW_HIDE_TIMEOUT: {
5234                     final WindowState window = (WindowState) msg.obj;
5235                     synchronized (mGlobalLock) {
5236                         // TODO: This is all about fixing b/21693547
5237                         // where partially initialized Toasts get stuck
5238                         // around and keep the screen on. We'd like
5239                         // to just remove the toast...but this can cause clients
5240                         // who miss the timeout due to normal circumstances (e.g.
5241                         // running under debugger) to crash (b/29105388). The windows will
5242                         // eventually be removed when the client process finishes.
5243                         // The best we can do for now is remove the FLAG_KEEP_SCREEN_ON
5244                         // and prevent the symptoms of b/21693547. Since apps don't
5245                         // support windows being removed under them we hide the window
5246                         // and it will be removed when the app dies.
5247                         window.mAttrs.flags &= ~FLAG_KEEP_SCREEN_ON;
5248                         window.hidePermanentlyLw();
5249                         window.setDisplayLayoutNeeded();
5250                         mWindowPlacerLocked.performSurfacePlacement();
5251                     }
5252                     break;
5253                 }
5254                 case RESTORE_POINTER_ICON: {
5255                     synchronized (mGlobalLock) {
5256                         restorePointerIconLocked((DisplayContent)msg.obj, msg.arg1, msg.arg2);
5257                     }
5258                     break;
5259                 }
5260                 case SET_HAS_OVERLAY_UI: {
5261                     mAmInternal.setHasOverlayUi(msg.arg1, msg.arg2 == 1);
5262                     break;
5263                 }
5264                 case ANIMATION_FAILSAFE: {
5265                     synchronized (mGlobalLock) {
5266                         if (mRecentsAnimationController != null) {
5267                             mRecentsAnimationController.scheduleFailsafe();
5268                         }
5269                     }
5270                     break;
5271                 }
5272                 case RECOMPUTE_FOCUS: {
5273                     synchronized (mGlobalLock) {
5274                         updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
5275                                 true /* updateInputWindows */);
5276                     }
5277                     break;
5278                 }
5279                 case ON_POINTER_DOWN_OUTSIDE_FOCUS: {
5280                     synchronized (mGlobalLock) {
5281                         final IBinder touchedToken = (IBinder) msg.obj;
5282                         onPointerDownOutsideFocusLocked(touchedToken);
5283                     }
5284                     break;
5285                 }
5286                 case LAYOUT_AND_ASSIGN_WINDOW_LAYERS_IF_NEEDED: {
5287                     synchronized (mGlobalLock) {
5288                         final DisplayContent displayContent = (DisplayContent) msg.obj;
5289                         displayContent.layoutAndAssignWindowLayersIfNeeded();
5290                     }
5291                     break;
5292                 }
5293                 case WINDOW_STATE_BLAST_SYNC_TIMEOUT: {
5294                     synchronized (mGlobalLock) {
5295                         final WindowState ws = (WindowState) msg.obj;
5296                         ws.immediatelyNotifyBlastSync();
5297                     }
5298                     break;
5299                 }
5300             }
5301             if (DEBUG_WINDOW_TRACE) {
5302                 Slog.v(TAG_WM, "handleMessage: exit");
5303             }
5304         }
5305 
5306         /** Remove the previous messages with the same 'what' and 'obj' then send the new one. */
sendNewMessageDelayed(int what, Object obj, long delayMillis)5307         void sendNewMessageDelayed(int what, Object obj, long delayMillis) {
5308             removeMessages(what, obj);
5309             sendMessageDelayed(obtainMessage(what, obj), delayMillis);
5310         }
5311     }
5312 
5313     // -------------------------------------------------------------
5314     // IWindowManager API
5315     // -------------------------------------------------------------
5316 
5317     @Override
openSession(IWindowSessionCallback callback)5318     public IWindowSession openSession(IWindowSessionCallback callback) {
5319         return new Session(this, callback);
5320     }
5321 
5322     @Override
useBLAST()5323     public boolean useBLAST() {
5324         return mUseBLAST;
5325     }
5326 
useBLASTSync()5327     public boolean useBLASTSync() {
5328         return mUseBLASTSync;
5329     }
5330 
5331     @Override
getInitialDisplaySize(int displayId, Point size)5332     public void getInitialDisplaySize(int displayId, Point size) {
5333         synchronized (mGlobalLock) {
5334             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
5335             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
5336                 size.x = displayContent.mInitialDisplayWidth;
5337                 size.y = displayContent.mInitialDisplayHeight;
5338             }
5339         }
5340     }
5341 
5342     @Override
getBaseDisplaySize(int displayId, Point size)5343     public void getBaseDisplaySize(int displayId, Point size) {
5344         synchronized (mGlobalLock) {
5345             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
5346             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
5347                 size.x = displayContent.mBaseDisplayWidth;
5348                 size.y = displayContent.mBaseDisplayHeight;
5349             }
5350         }
5351     }
5352 
5353     @Override
setForcedDisplaySize(int displayId, int width, int height)5354     public void setForcedDisplaySize(int displayId, int width, int height) {
5355         if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
5356                 != PackageManager.PERMISSION_GRANTED) {
5357             throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
5358         }
5359 
5360         final long ident = Binder.clearCallingIdentity();
5361         try {
5362             synchronized (mGlobalLock) {
5363                 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
5364                 if (displayContent != null) {
5365                     displayContent.setForcedSize(width, height);
5366                 }
5367             }
5368         } finally {
5369             Binder.restoreCallingIdentity(ident);
5370         }
5371     }
5372 
5373     @Override
setForcedDisplayScalingMode(int displayId, int mode)5374     public void setForcedDisplayScalingMode(int displayId, int mode) {
5375         if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
5376                 != PackageManager.PERMISSION_GRANTED) {
5377             throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
5378         }
5379 
5380         final long ident = Binder.clearCallingIdentity();
5381         try {
5382             synchronized (mGlobalLock) {
5383                 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
5384                 if (displayContent != null) {
5385                     displayContent.setForcedScalingMode(mode);
5386                 }
5387             }
5388         } finally {
5389             Binder.restoreCallingIdentity(ident);
5390         }
5391     }
5392 
5393     /** The global settings only apply to default display. */
applyForcedPropertiesForDefaultDisplay()5394     private boolean applyForcedPropertiesForDefaultDisplay() {
5395         boolean changed = false;
5396         final DisplayContent displayContent = getDefaultDisplayContentLocked();
5397         // Display size.
5398         String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
5399                 Settings.Global.DISPLAY_SIZE_FORCED);
5400         if (sizeStr == null || sizeStr.length() == 0) {
5401             sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
5402         }
5403         if (sizeStr != null && sizeStr.length() > 0) {
5404             final int pos = sizeStr.indexOf(',');
5405             if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
5406                 int width, height;
5407                 try {
5408                     width = Integer.parseInt(sizeStr.substring(0, pos));
5409                     height = Integer.parseInt(sizeStr.substring(pos + 1));
5410                     if (displayContent.mBaseDisplayWidth != width
5411                             || displayContent.mBaseDisplayHeight != height) {
5412                         ProtoLog.i(WM_ERROR, "FORCED DISPLAY SIZE: %dx%d", width, height);
5413                         displayContent.updateBaseDisplayMetrics(width, height,
5414                                 displayContent.mBaseDisplayDensity);
5415                         changed = true;
5416                     }
5417                 } catch (NumberFormatException ex) {
5418                 }
5419             }
5420         }
5421 
5422         // Display density.
5423         final int density = getForcedDisplayDensityForUserLocked(mCurrentUserId);
5424         if (density != 0 && density != displayContent.mBaseDisplayDensity) {
5425             displayContent.mBaseDisplayDensity = density;
5426             changed = true;
5427         }
5428 
5429         // Display scaling mode.
5430         int mode = Settings.Global.getInt(mContext.getContentResolver(),
5431                 Settings.Global.DISPLAY_SCALING_FORCE, 0);
5432         if (displayContent.mDisplayScalingDisabled != (mode != 0)) {
5433             ProtoLog.i(WM_ERROR, "FORCED DISPLAY SCALING DISABLED");
5434             displayContent.mDisplayScalingDisabled = true;
5435             changed = true;
5436         }
5437         return changed;
5438     }
5439 
5440     @Override
clearForcedDisplaySize(int displayId)5441     public void clearForcedDisplaySize(int displayId) {
5442         if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
5443                 != PackageManager.PERMISSION_GRANTED) {
5444             throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
5445         }
5446 
5447         final long ident = Binder.clearCallingIdentity();
5448         try {
5449             synchronized (mGlobalLock) {
5450                 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
5451                 if (displayContent != null) {
5452                     displayContent.setForcedSize(displayContent.mInitialDisplayWidth,
5453                             displayContent.mInitialDisplayHeight);
5454                 }
5455             }
5456         } finally {
5457             Binder.restoreCallingIdentity(ident);
5458         }
5459     }
5460 
5461     @Override
getInitialDisplayDensity(int displayId)5462     public int getInitialDisplayDensity(int displayId) {
5463         synchronized (mGlobalLock) {
5464             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
5465             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
5466                 return displayContent.mInitialDisplayDensity;
5467             }
5468         }
5469         return -1;
5470     }
5471 
5472     @Override
getBaseDisplayDensity(int displayId)5473     public int getBaseDisplayDensity(int displayId) {
5474         synchronized (mGlobalLock) {
5475             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
5476             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
5477                 return displayContent.mBaseDisplayDensity;
5478             }
5479         }
5480         return -1;
5481     }
5482 
5483     @Override
setForcedDisplayDensityForUser(int displayId, int density, int userId)5484     public void setForcedDisplayDensityForUser(int displayId, int density, int userId) {
5485         if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
5486                 != PackageManager.PERMISSION_GRANTED) {
5487             throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
5488         }
5489 
5490         final int targetUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
5491                 Binder.getCallingUid(), userId, false, true, "setForcedDisplayDensityForUser",
5492                 null);
5493         final long ident = Binder.clearCallingIdentity();
5494         try {
5495             synchronized (mGlobalLock) {
5496                 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
5497                 if (displayContent != null) {
5498                     displayContent.setForcedDensity(density, targetUserId);
5499                 }
5500             }
5501         } finally {
5502             Binder.restoreCallingIdentity(ident);
5503         }
5504     }
5505 
5506     @Override
clearForcedDisplayDensityForUser(int displayId, int userId)5507     public void clearForcedDisplayDensityForUser(int displayId, int userId) {
5508         if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
5509                 != PackageManager.PERMISSION_GRANTED) {
5510             throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
5511         }
5512 
5513         final int callingUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
5514                 Binder.getCallingUid(), userId, false, true, "clearForcedDisplayDensityForUser",
5515                 null);
5516         final long ident = Binder.clearCallingIdentity();
5517         try {
5518             synchronized (mGlobalLock) {
5519                 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
5520                 if (displayContent != null) {
5521                     displayContent.setForcedDensity(displayContent.mInitialDisplayDensity,
5522                             callingUserId);
5523                 }
5524             }
5525         } finally {
5526             Binder.restoreCallingIdentity(ident);
5527         }
5528     }
5529 
5530     /**
5531      * @param userId the ID of the user
5532      * @return the forced display density for the specified user, if set, or
5533      *         {@code 0} if not set
5534      */
getForcedDisplayDensityForUserLocked(int userId)5535     private int getForcedDisplayDensityForUserLocked(int userId) {
5536         String densityStr = Settings.Secure.getStringForUser(mContext.getContentResolver(),
5537                 Settings.Secure.DISPLAY_DENSITY_FORCED, userId);
5538         if (densityStr == null || densityStr.length() == 0) {
5539             densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
5540         }
5541         if (densityStr != null && densityStr.length() > 0) {
5542             try {
5543                 return Integer.parseInt(densityStr);
5544             } catch (NumberFormatException ex) {
5545             }
5546         }
5547         return 0;
5548     }
5549 
5550     @Override
startWindowTrace()5551     public void startWindowTrace(){
5552         mWindowTracing.startTrace(null /* printwriter */);
5553     }
5554 
5555     @Override
stopWindowTrace()5556     public void stopWindowTrace(){
5557         mWindowTracing.stopTrace(null /* printwriter */);
5558     }
5559 
5560     @Override
isWindowTraceEnabled()5561     public boolean isWindowTraceEnabled() {
5562         return mWindowTracing.isEnabled();
5563     }
5564 
5565     @Override
registerCrossWindowBlurEnabledListener( ICrossWindowBlurEnabledListener listener)5566     public boolean registerCrossWindowBlurEnabledListener(
5567                 ICrossWindowBlurEnabledListener listener) {
5568         return mBlurController.registerCrossWindowBlurEnabledListener(listener);
5569     }
5570 
5571     @Override
unregisterCrossWindowBlurEnabledListener( ICrossWindowBlurEnabledListener listener)5572     public void unregisterCrossWindowBlurEnabledListener(
5573                 ICrossWindowBlurEnabledListener listener) {
5574         mBlurController.unregisterCrossWindowBlurEnabledListener(listener);
5575     }
5576 
5577     // -------------------------------------------------------------
5578     // Internals
5579     // -------------------------------------------------------------
5580 
windowForClientLocked(Session session, IWindow client, boolean throwOnError)5581     final WindowState windowForClientLocked(Session session, IWindow client, boolean throwOnError) {
5582         return windowForClientLocked(session, client.asBinder(), throwOnError);
5583     }
5584 
windowForClientLocked(Session session, IBinder client, boolean throwOnError)5585     final WindowState windowForClientLocked(Session session, IBinder client, boolean throwOnError) {
5586         WindowState win = mWindowMap.get(client);
5587         if (DEBUG) Slog.v(TAG_WM, "Looking up client " + client + ": " + win);
5588         if (win == null) {
5589             if (throwOnError) {
5590                 throw new IllegalArgumentException(
5591                         "Requested window " + client + " does not exist");
5592             }
5593             ProtoLog.w(WM_ERROR, "Failed looking up window session=%s callers=%s", session,
5594                     Debug.getCallers(3));
5595             return null;
5596         }
5597         if (session != null && win.mSession != session) {
5598             if (throwOnError) {
5599                 throw new IllegalArgumentException("Requested window " + client + " is in session "
5600                         + win.mSession + ", not " + session);
5601             }
5602             ProtoLog.w(WM_ERROR, "Failed looking up window session=%s callers=%s", session,
5603                     Debug.getCallers(3));
5604             return null;
5605         }
5606 
5607         return win;
5608     }
5609 
makeWindowFreezingScreenIfNeededLocked(WindowState w)5610     void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
5611         // If the screen is currently frozen or off, then keep
5612         // it frozen/off until this window draws at its new
5613         // orientation.
5614         if (!w.mToken.okToDisplay() && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
5615             ProtoLog.v(WM_DEBUG_ORIENTATION, "Changing surface while display frozen: %s", w);
5616             w.setOrientationChanging(true);
5617             if (mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_NONE) {
5618                 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
5619                 // XXX should probably keep timeout from
5620                 // when we first froze the display.
5621                 mH.sendNewMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, w.getDisplayContent(),
5622                         WINDOW_FREEZE_TIMEOUT_DURATION);
5623             }
5624         }
5625     }
5626 
checkDrawnWindowsLocked()5627     void checkDrawnWindowsLocked() {
5628         if (mWaitingForDrawnCallbacks.isEmpty()) {
5629             return;
5630         }
5631         mWaitingForDrawnCallbacks.forEach((container, callback) -> {
5632             for (int j = container.mWaitingForDrawn.size() - 1; j >= 0; j--) {
5633                 final WindowState win = (WindowState) container.mWaitingForDrawn.get(j);
5634                 ProtoLog.i(WM_DEBUG_SCREEN_ON,
5635                         "Waiting for drawn %s: removed=%b visible=%b mHasSurface=%b drawState=%d",
5636                         win, win.mRemoved, win.isVisible(), win.mHasSurface,
5637                         win.mWinAnimator.mDrawState);
5638                 if (win.mRemoved || !win.mHasSurface || !win.isVisibleByPolicy()) {
5639                     // Window has been removed or hidden; no draw will now happen, so stop waiting.
5640                     ProtoLog.w(WM_DEBUG_SCREEN_ON, "Aborted waiting for drawn: %s", win);
5641                     container.mWaitingForDrawn.remove(win);
5642                 } else if (win.hasDrawn()) {
5643                     // Window is now drawn (and shown).
5644                     ProtoLog.d(WM_DEBUG_SCREEN_ON, "Window drawn win=%s", win);
5645                     container.mWaitingForDrawn.remove(win);
5646                 }
5647             }
5648             if (container.mWaitingForDrawn.isEmpty()) {
5649                 ProtoLog.d(WM_DEBUG_SCREEN_ON, "All windows drawn!");
5650                 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, container);
5651                 mH.sendMessage(mH.obtainMessage(H.ALL_WINDOWS_DRAWN, container));
5652             }
5653         });
5654     }
5655 
setHoldScreenLocked(final Session newHoldScreen)5656     void setHoldScreenLocked(final Session newHoldScreen) {
5657         final boolean hold = newHoldScreen != null;
5658 
5659         if (hold && mHoldingScreenOn != newHoldScreen) {
5660             mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
5661         }
5662         mHoldingScreenOn = newHoldScreen;
5663 
5664         final boolean state = mHoldingScreenWakeLock.isHeld();
5665         if (hold != state) {
5666             if (hold) {
5667                 ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON, "Acquiring screen wakelock due to %s",
5668                             mRoot.mHoldScreenWindow);
5669                 mLastWakeLockHoldingWindow = mRoot.mHoldScreenWindow;
5670                 mLastWakeLockObscuringWindow = null;
5671                 mHoldingScreenWakeLock.acquire();
5672                 mPolicy.keepScreenOnStartedLw();
5673             } else {
5674                 ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by %s",
5675                             mRoot.mObscuringWindow);
5676                 mLastWakeLockHoldingWindow = null;
5677                 mLastWakeLockObscuringWindow = mRoot.mObscuringWindow;
5678                 mPolicy.keepScreenOnStoppedLw();
5679                 mHoldingScreenWakeLock.release();
5680             }
5681         }
5682     }
5683 
requestTraversal()5684     void requestTraversal() {
5685         mWindowPlacerLocked.requestTraversal();
5686     }
5687 
5688     /** Note that Locked in this case is on mLayoutToAnim */
scheduleAnimationLocked()5689     void scheduleAnimationLocked() {
5690         if (mAnimator != null) {
5691             mAnimator.scheduleAnimation();
5692         }
5693     }
5694 
updateFocusedWindowLocked(int mode, boolean updateInputWindows)5695     boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
5696         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
5697         boolean changed = mRoot.updateFocusedWindowLocked(mode, updateInputWindows);
5698         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
5699         return changed;
5700     }
5701 
startFreezingDisplay(int exitAnim, int enterAnim)5702     void startFreezingDisplay(int exitAnim, int enterAnim) {
5703         startFreezingDisplay(exitAnim, enterAnim, getDefaultDisplayContentLocked());
5704     }
5705 
startFreezingDisplay(int exitAnim, int enterAnim, DisplayContent displayContent)5706     void startFreezingDisplay(int exitAnim, int enterAnim, DisplayContent displayContent) {
5707         startFreezingDisplay(exitAnim, enterAnim, displayContent,
5708                 ROTATION_UNDEFINED /* overrideOriginalRotation */);
5709     }
5710 
startFreezingDisplay(int exitAnim, int enterAnim, DisplayContent displayContent, int overrideOriginalRotation)5711     void startFreezingDisplay(int exitAnim, int enterAnim, DisplayContent displayContent,
5712             int overrideOriginalRotation) {
5713         if (mDisplayFrozen || displayContent.getDisplayRotation().isRotatingSeamlessly()) {
5714             return;
5715         }
5716 
5717         if (!displayContent.isReady() || !mPolicy.isScreenOn() || !displayContent.okToAnimate()) {
5718             // No need to freeze the screen before the display is ready,  if the screen is off,
5719             // or we can't currently animate.
5720             return;
5721         }
5722 
5723         ProtoLog.d(WM_DEBUG_ORIENTATION,
5724                             "startFreezingDisplayLocked: exitAnim=%d enterAnim=%d called by %s",
5725                             exitAnim, enterAnim, Debug.getCallers(8));
5726         mScreenFrozenLock.acquire();
5727         // Apply launch power mode to reduce screen frozen time because orientation change may
5728         // relaunch activity and redraw windows. This may also help speed up user switching.
5729         mAtmService.startLaunchPowerMode(POWER_MODE_REASON_FREEZE_DISPLAY);
5730 
5731         mDisplayFrozen = true;
5732         mDisplayFreezeTime = SystemClock.elapsedRealtime();
5733         mLastFinishedFreezeSource = null;
5734 
5735         // {@link mDisplayFrozen} prevents us from freezing on multiple displays at the same time.
5736         // As a result, we only track the display that has initially froze the screen.
5737         mFrozenDisplayId = displayContent.getDisplayId();
5738 
5739         mInputManagerCallback.freezeInputDispatchingLw();
5740 
5741         if (displayContent.mAppTransition.isTransitionSet()) {
5742             displayContent.mAppTransition.freeze();
5743         }
5744 
5745         if (PROFILE_ORIENTATION) {
5746             File file = new File("/data/system/frozen");
5747             Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
5748         }
5749 
5750         mLatencyTracker.onActionStart(ACTION_ROTATE_SCREEN);
5751         mExitAnimId = exitAnim;
5752         mEnterAnimId = enterAnim;
5753 
5754         displayContent.updateDisplayInfo();
5755         final int originalRotation = overrideOriginalRotation != ROTATION_UNDEFINED
5756                 ? overrideOriginalRotation
5757                 : displayContent.getDisplayInfo().rotation;
5758         displayContent.setRotationAnimation(new ScreenRotationAnimation(displayContent,
5759                 originalRotation));
5760     }
5761 
stopFreezingDisplayLocked()5762     void stopFreezingDisplayLocked() {
5763         if (!mDisplayFrozen) {
5764             return;
5765         }
5766 
5767         final DisplayContent displayContent = mRoot.getDisplayContent(mFrozenDisplayId);
5768         final int numOpeningApps;
5769         final boolean waitingForConfig;
5770         final boolean waitingForRemoteRotation;
5771         if (displayContent != null) {
5772             numOpeningApps = displayContent.mOpeningApps.size();
5773             waitingForConfig = displayContent.mWaitingForConfig;
5774             waitingForRemoteRotation =
5775                     displayContent.getDisplayRotation().isWaitingForRemoteRotation();
5776         } else {
5777             waitingForConfig = waitingForRemoteRotation = false;
5778             numOpeningApps = 0;
5779         }
5780         if (waitingForConfig || waitingForRemoteRotation || mAppsFreezingScreen > 0
5781                 || mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_ACTIVE
5782                 || mClientFreezingScreen || numOpeningApps > 0) {
5783             ProtoLog.d(WM_DEBUG_ORIENTATION, "stopFreezingDisplayLocked: Returning "
5784                     + "waitingForConfig=%b, waitingForRemoteRotation=%b, "
5785                     + "mAppsFreezingScreen=%d, mWindowsFreezingScreen=%d, "
5786                     + "mClientFreezingScreen=%b, mOpeningApps.size()=%d",
5787                     waitingForConfig, waitingForRemoteRotation,
5788                     mAppsFreezingScreen, mWindowsFreezingScreen,
5789                     mClientFreezingScreen, numOpeningApps);
5790             return;
5791         }
5792 
5793         ProtoLog.d(WM_DEBUG_ORIENTATION,
5794                     "stopFreezingDisplayLocked: Unfreezing now");
5795 
5796 
5797         // We must make a local copy of the displayId as it can be potentially overwritten later on
5798         // in this method. For example, {@link startFreezingDisplayLocked} may be called as a result
5799         // of update rotation, but we reference the frozen display after that call in this method.
5800         mFrozenDisplayId = INVALID_DISPLAY;
5801         mDisplayFrozen = false;
5802         mInputManagerCallback.thawInputDispatchingLw();
5803         mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
5804         StringBuilder sb = new StringBuilder(128);
5805         sb.append("Screen frozen for ");
5806         TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
5807         if (mLastFinishedFreezeSource != null) {
5808             sb.append(" due to ");
5809             sb.append(mLastFinishedFreezeSource);
5810         }
5811         ProtoLog.i(WM_ERROR, "%s", sb.toString());
5812         mH.removeMessages(H.APP_FREEZE_TIMEOUT);
5813         mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
5814         if (PROFILE_ORIENTATION) {
5815             Debug.stopMethodTracing();
5816         }
5817 
5818         boolean updateRotation = false;
5819 
5820         ScreenRotationAnimation screenRotationAnimation = displayContent == null ? null
5821                 : displayContent.getRotationAnimation();
5822         if (screenRotationAnimation != null && screenRotationAnimation.hasScreenshot()) {
5823             ProtoLog.i(WM_DEBUG_ORIENTATION, "**** Dismissing screen rotation animation");
5824             DisplayInfo displayInfo = displayContent.getDisplayInfo();
5825             // Get rotation animation again, with new top window
5826             if (!displayContent.getDisplayRotation().validateRotationAnimation(
5827                     mExitAnimId, mEnterAnimId, false /* forceDefault */)) {
5828                 mExitAnimId = mEnterAnimId = 0;
5829             }
5830             if (screenRotationAnimation.dismiss(mTransaction, MAX_ANIMATION_DURATION,
5831                     getTransitionAnimationScaleLocked(), displayInfo.logicalWidth,
5832                         displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
5833                 mTransaction.apply();
5834             } else {
5835                 screenRotationAnimation.kill();
5836                 displayContent.setRotationAnimation(null);
5837                 updateRotation = true;
5838             }
5839         } else {
5840             if (screenRotationAnimation != null) {
5841                 screenRotationAnimation.kill();
5842                 displayContent.setRotationAnimation(null);
5843             }
5844             updateRotation = true;
5845         }
5846 
5847         boolean configChanged;
5848 
5849         // While the display is frozen we don't re-compute the orientation
5850         // to avoid inconsistent states.  However, something interesting
5851         // could have actually changed during that time so re-evaluate it
5852         // now to catch that.
5853         configChanged = displayContent != null && displayContent.updateOrientation();
5854 
5855         // A little kludge: a lot could have happened while the
5856         // display was frozen, so now that we are coming back we
5857         // do a gc so that any remote references the system
5858         // processes holds on others can be released if they are
5859         // no longer needed.
5860         mH.removeMessages(H.FORCE_GC);
5861         mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
5862 
5863         mScreenFrozenLock.release();
5864 
5865         if (updateRotation && displayContent != null) {
5866             ProtoLog.d(WM_DEBUG_ORIENTATION, "Performing post-rotate rotation");
5867             configChanged |= displayContent.updateRotationUnchecked();
5868         }
5869 
5870         if (configChanged) {
5871             displayContent.sendNewConfiguration();
5872         }
5873         mAtmService.endLaunchPowerMode(POWER_MODE_REASON_FREEZE_DISPLAY);
5874         mLatencyTracker.onActionEnd(ACTION_ROTATE_SCREEN);
5875     }
5876 
getPropertyInt(String[] tokens, int index, int defUnits, int defDps, DisplayMetrics dm)5877     static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
5878             DisplayMetrics dm) {
5879         if (index < tokens.length) {
5880             String str = tokens[index];
5881             if (str != null && str.length() > 0) {
5882                 try {
5883                     int val = Integer.parseInt(str);
5884                     return val;
5885                 } catch (Exception e) {
5886                 }
5887             }
5888         }
5889         if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
5890             return defDps;
5891         }
5892         int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
5893         return val;
5894     }
5895 
createWatermark()5896     void createWatermark() {
5897         if (mWatermark != null) {
5898             return;
5899         }
5900 
5901         File file = new File("/system/etc/setup.conf");
5902         FileInputStream in = null;
5903         DataInputStream ind = null;
5904         try {
5905             in = new FileInputStream(file);
5906             ind = new DataInputStream(in);
5907             String line = ind.readLine();
5908             if (line != null) {
5909                 String[] toks = line.split("%");
5910                 if (toks != null && toks.length > 0) {
5911                     // TODO(multi-display): Show watermarks on secondary displays.
5912                     final DisplayContent displayContent = getDefaultDisplayContentLocked();
5913                     mWatermark = new Watermark(displayContent, displayContent.mRealDisplayMetrics,
5914                             toks, mTransaction);
5915                     mTransaction.apply();
5916                 }
5917             }
5918         } catch (FileNotFoundException e) {
5919         } catch (IOException e) {
5920         } finally {
5921             if (ind != null) {
5922                 try {
5923                     ind.close();
5924                 } catch (IOException e) {
5925                 }
5926             } else if (in != null) {
5927                 try {
5928                     in.close();
5929                 } catch (IOException e) {
5930                 }
5931             }
5932         }
5933     }
5934 
5935     @Override
setRecentsVisibility(boolean visible)5936     public void setRecentsVisibility(boolean visible) {
5937         if (!checkCallingPermission(
5938                 android.Manifest.permission.STATUS_BAR, "setRecentsVisibility()")) {
5939             throw new SecurityException("Requires STATUS_BAR permission");
5940         }
5941         synchronized (mGlobalLock) {
5942             mPolicy.setRecentsVisibilityLw(visible);
5943         }
5944     }
5945 
5946     @Override
hideTransientBars(int displayId)5947     public void hideTransientBars(int displayId) {
5948         if (!checkCallingPermission(
5949                 android.Manifest.permission.STATUS_BAR, "hideTransientBars()")) {
5950             throw new SecurityException("Requires STATUS_BAR permission");
5951         }
5952 
5953         synchronized (mGlobalLock) {
5954             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
5955             if (displayContent != null) {
5956                 displayContent.getInsetsPolicy().hideTransient();
5957             } else {
5958                 Slog.w(TAG, "hideTransientBars with invalid displayId=" + displayId);
5959             }
5960         }
5961     }
5962 
5963     @Override
updateStaticPrivacyIndicatorBounds(int displayId, Rect[] staticBounds)5964     public void updateStaticPrivacyIndicatorBounds(int displayId,
5965             Rect[] staticBounds) {
5966         synchronized (mGlobalLock) {
5967             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
5968             if (displayContent != null) {
5969                 displayContent.updatePrivacyIndicatorBounds(staticBounds);
5970             } else {
5971                 Slog.w(TAG, "updateStaticPrivacyIndicatorBounds with invalid displayId="
5972                         + displayId);
5973             }
5974         }
5975     }
5976 
setNavBarVirtualKeyHapticFeedbackEnabled(boolean enabled)5977     public void setNavBarVirtualKeyHapticFeedbackEnabled(boolean enabled) {
5978         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
5979                 != PackageManager.PERMISSION_GRANTED) {
5980             throw new SecurityException("Caller does not hold permission "
5981                     + android.Manifest.permission.STATUS_BAR);
5982         }
5983 
5984         synchronized (mGlobalLock) {
5985             mPolicy.setNavBarVirtualKeyHapticFeedbackEnabledLw(enabled);
5986         }
5987     }
5988 
5989     /**
5990      * Used by ActivityManager to determine where to position an app with aspect ratio shorter then
5991      * the screen is.
5992      * @see DisplayPolicy#getNavBarPosition()
5993      */
5994     @Override
5995     @WindowManagerPolicy.NavigationBarPosition
getNavBarPosition(int displayId)5996     public int getNavBarPosition(int displayId) {
5997         synchronized (mGlobalLock) {
5998             // Perform layout if it was scheduled before to make sure that we get correct nav bar
5999             // position when doing rotations.
6000             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
6001             if (displayContent == null) {
6002                 Slog.w(TAG, "getNavBarPosition with invalid displayId=" + displayId
6003                         + " callers=" + Debug.getCallers(3));
6004                 return NAV_BAR_INVALID;
6005             }
6006             displayContent.performLayout(false /* initial */,
6007                     false /* updateInputWindows */);
6008             return displayContent.getDisplayPolicy().getNavBarPosition();
6009         }
6010     }
6011 
6012     @Override
createInputConsumer(IBinder token, String name, int displayId, InputChannel inputChannel)6013     public void createInputConsumer(IBinder token, String name, int displayId,
6014             InputChannel inputChannel) {
6015         if (!mAtmInternal.isCallerRecents(Binder.getCallingUid())
6016                 && mContext.checkCallingOrSelfPermission(INPUT_CONSUMER) != PERMISSION_GRANTED) {
6017             throw new SecurityException("createInputConsumer requires INPUT_CONSUMER permission");
6018         }
6019 
6020         synchronized (mGlobalLock) {
6021             DisplayContent display = mRoot.getDisplayContent(displayId);
6022             if (display != null) {
6023                 display.getInputMonitor().createInputConsumer(token, name, inputChannel,
6024                         Binder.getCallingPid(), Binder.getCallingUserHandle());
6025             }
6026         }
6027     }
6028 
6029     @Override
destroyInputConsumer(String name, int displayId)6030     public boolean destroyInputConsumer(String name, int displayId) {
6031         if (!mAtmInternal.isCallerRecents(Binder.getCallingUid())
6032                 && mContext.checkCallingOrSelfPermission(INPUT_CONSUMER) != PERMISSION_GRANTED) {
6033             throw new SecurityException("destroyInputConsumer requires INPUT_CONSUMER permission");
6034         }
6035 
6036         synchronized (mGlobalLock) {
6037             DisplayContent display = mRoot.getDisplayContent(displayId);
6038             if (display != null) {
6039                 return display.getInputMonitor().destroyInputConsumer(name);
6040             }
6041             return false;
6042         }
6043     }
6044 
6045     @Override
getCurrentImeTouchRegion()6046     public Region getCurrentImeTouchRegion() {
6047         if (mContext.checkCallingOrSelfPermission(RESTRICTED_VR_ACCESS) != PERMISSION_GRANTED) {
6048             throw new SecurityException("getCurrentImeTouchRegion is restricted to VR services");
6049         }
6050         synchronized (mGlobalLock) {
6051             final Region r = new Region();
6052             // TODO(b/111080190): this method is only return the recent focused IME touch region,
6053             // For Multi-Session IME, will need to add API for given display Id to
6054             // get the right IME touch region.
6055             for (int i = mRoot.mChildren.size() - 1; i >= 0; --i) {
6056                 final DisplayContent displayContent = mRoot.mChildren.get(i);
6057                 if (displayContent.mInputMethodWindow != null) {
6058                     displayContent.mInputMethodWindow.getTouchableRegion(r);
6059                     return r;
6060                 }
6061             }
6062             return r;
6063         }
6064     }
6065 
6066     @Override
hasNavigationBar(int displayId)6067     public boolean hasNavigationBar(int displayId) {
6068         synchronized (mGlobalLock) {
6069             final DisplayContent dc = mRoot.getDisplayContent(displayId);
6070             if (dc == null) {
6071                 return false;
6072             }
6073             return dc.getDisplayPolicy().hasNavigationBar();
6074         }
6075     }
6076 
6077     @Override
lockNow(Bundle options)6078     public void lockNow(Bundle options) {
6079         mPolicy.lockNow(options);
6080     }
6081 
showRecentApps()6082     public void showRecentApps() {
6083         mPolicy.showRecentApps();
6084     }
6085 
6086     @Override
isSafeModeEnabled()6087     public boolean isSafeModeEnabled() {
6088         return mSafeMode;
6089     }
6090 
6091     @Override
clearWindowContentFrameStats(IBinder token)6092     public boolean clearWindowContentFrameStats(IBinder token) {
6093         if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
6094                 "clearWindowContentFrameStats()")) {
6095             throw new SecurityException("Requires FRAME_STATS permission");
6096         }
6097         synchronized (mGlobalLock) {
6098             WindowState windowState = mWindowMap.get(token);
6099             if (windowState == null) {
6100                 return false;
6101             }
6102             WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController;
6103             if (surfaceController == null) {
6104                 return false;
6105             }
6106             return surfaceController.clearWindowContentFrameStats();
6107         }
6108     }
6109 
6110     @Override
getWindowContentFrameStats(IBinder token)6111     public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
6112         if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
6113                 "getWindowContentFrameStats()")) {
6114             throw new SecurityException("Requires FRAME_STATS permission");
6115         }
6116         synchronized (mGlobalLock) {
6117             WindowState windowState = mWindowMap.get(token);
6118             if (windowState == null) {
6119                 return null;
6120             }
6121             WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController;
6122             if (surfaceController == null) {
6123                 return null;
6124             }
6125             if (mTempWindowRenderStats == null) {
6126                 mTempWindowRenderStats = new WindowContentFrameStats();
6127             }
6128             WindowContentFrameStats stats = mTempWindowRenderStats;
6129             if (!surfaceController.getWindowContentFrameStats(stats)) {
6130                 return null;
6131             }
6132             return stats;
6133         }
6134     }
6135 
dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll)6136     private void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
6137         pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
6138         mPolicy.dump("    ", pw, args);
6139     }
6140 
dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll)6141     private void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
6142         pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
6143         mAnimator.dumpLocked(pw, "    ", dumpAll);
6144     }
6145 
dumpTokensLocked(PrintWriter pw, boolean dumpAll)6146     private void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
6147         pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
6148         mRoot.dumpTokens(pw, dumpAll);
6149     }
6150 
6151 
dumpHighRefreshRateBlacklist(PrintWriter pw)6152     private void dumpHighRefreshRateBlacklist(PrintWriter pw) {
6153         pw.println("WINDOW MANAGER HIGH REFRESH RATE BLACKLIST (dumpsys window refresh)");
6154         mHighRefreshRateDenylist.dump(pw);
6155     }
6156 
dumpTraceStatus(PrintWriter pw)6157     private void dumpTraceStatus(PrintWriter pw) {
6158         pw.println("WINDOW MANAGER TRACE (dumpsys window trace)");
6159         pw.print(mWindowTracing.getStatus() + "\n");
6160     }
6161 
dumpLogStatus(PrintWriter pw)6162     private void dumpLogStatus(PrintWriter pw) {
6163         pw.println("WINDOW MANAGER LOGGING (dumpsys window logging)");
6164         pw.println(ProtoLogImpl.getSingleInstance().getStatus());
6165     }
6166 
dumpSessionsLocked(PrintWriter pw, boolean dumpAll)6167     private void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
6168         pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
6169         for (int i=0; i<mSessions.size(); i++) {
6170             Session s = mSessions.valueAt(i);
6171             pw.print("  Session "); pw.print(s); pw.println(':');
6172             s.dump(pw, "    ");
6173         }
6174     }
6175 
6176     /**
6177      * Write to a protocol buffer output stream. Protocol buffer message definition is at
6178      * {@link com.android.server.wm.WindowManagerServiceDumpProto}.
6179      *
6180      * @param proto     Stream to write the WindowContainer object to.
6181      * @param logLevel  Determines the amount of data to be written to the Protobuf.
6182      */
dumpDebugLocked(ProtoOutputStream proto, @WindowTraceLogLevel int logLevel)6183     void dumpDebugLocked(ProtoOutputStream proto, @WindowTraceLogLevel int logLevel) {
6184         mPolicy.dumpDebug(proto, POLICY);
6185         mRoot.dumpDebug(proto, ROOT_WINDOW_CONTAINER, logLevel);
6186         final DisplayContent topFocusedDisplayContent = mRoot.getTopFocusedDisplayContent();
6187         if (topFocusedDisplayContent.mCurrentFocus != null) {
6188             topFocusedDisplayContent.mCurrentFocus.writeIdentifierToProto(proto, FOCUSED_WINDOW);
6189         }
6190         if (topFocusedDisplayContent.mFocusedApp != null) {
6191             topFocusedDisplayContent.mFocusedApp.writeNameToProto(proto, FOCUSED_APP);
6192         }
6193         final WindowState imeWindow = mRoot.getCurrentInputMethodWindow();
6194         if (imeWindow != null) {
6195             imeWindow.writeIdentifierToProto(proto, INPUT_METHOD_WINDOW);
6196         }
6197         proto.write(DISPLAY_FROZEN, mDisplayFrozen);
6198         final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
6199         proto.write(FOCUSED_DISPLAY_ID, topFocusedDisplayContent.getDisplayId());
6200         proto.write(HARD_KEYBOARD_AVAILABLE, mHardKeyboardAvailable);
6201     }
6202 
dumpWindowsLocked(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows)6203     private void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
6204             ArrayList<WindowState> windows) {
6205         pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
6206         dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
6207     }
6208 
dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows)6209     private void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
6210             ArrayList<WindowState> windows) {
6211         mRoot.dumpWindowsNoHeader(pw, dumpAll, windows);
6212 
6213         if (!mHidingNonSystemOverlayWindows.isEmpty()) {
6214             pw.println();
6215             pw.println("  Hiding System Alert Windows:");
6216             for (int i = mHidingNonSystemOverlayWindows.size() - 1; i >= 0; i--) {
6217                 final WindowState w = mHidingNonSystemOverlayWindows.get(i);
6218                 pw.print("  #"); pw.print(i); pw.print(' ');
6219                 pw.print(w);
6220                 if (dumpAll) {
6221                     pw.println(":");
6222                     w.dump(pw, "    ", true);
6223                 } else {
6224                     pw.println();
6225                 }
6226             }
6227         }
6228         if (mPendingRemove.size() > 0) {
6229             pw.println();
6230             pw.println("  Remove pending for:");
6231             for (int i=mPendingRemove.size()-1; i>=0; i--) {
6232                 WindowState w = mPendingRemove.get(i);
6233                 if (windows == null || windows.contains(w)) {
6234                     pw.print("  Remove #"); pw.print(i); pw.print(' ');
6235                             pw.print(w);
6236                     if (dumpAll) {
6237                         pw.println(":");
6238                         w.dump(pw, "    ", true);
6239                     } else {
6240                         pw.println();
6241                     }
6242                 }
6243             }
6244         }
6245         if (mForceRemoves != null && mForceRemoves.size() > 0) {
6246             pw.println();
6247             pw.println("  Windows force removing:");
6248             for (int i=mForceRemoves.size()-1; i>=0; i--) {
6249                 WindowState w = mForceRemoves.get(i);
6250                 pw.print("  Removing #"); pw.print(i); pw.print(' ');
6251                         pw.print(w);
6252                 if (dumpAll) {
6253                     pw.println(":");
6254                     w.dump(pw, "    ", true);
6255                 } else {
6256                     pw.println();
6257                 }
6258             }
6259         }
6260         if (mDestroySurface.size() > 0) {
6261             pw.println();
6262             pw.println("  Windows waiting to destroy their surface:");
6263             for (int i=mDestroySurface.size()-1; i>=0; i--) {
6264                 WindowState w = mDestroySurface.get(i);
6265                 if (windows == null || windows.contains(w)) {
6266                     pw.print("  Destroy #"); pw.print(i); pw.print(' ');
6267                             pw.print(w);
6268                     if (dumpAll) {
6269                         pw.println(":");
6270                         w.dump(pw, "    ", true);
6271                     } else {
6272                         pw.println();
6273                     }
6274                 }
6275             }
6276         }
6277         if (mResizingWindows.size() > 0) {
6278             pw.println();
6279             pw.println("  Windows waiting to resize:");
6280             for (int i=mResizingWindows.size()-1; i>=0; i--) {
6281                 WindowState w = mResizingWindows.get(i);
6282                 if (windows == null || windows.contains(w)) {
6283                     pw.print("  Resizing #"); pw.print(i); pw.print(' ');
6284                             pw.print(w);
6285                     if (dumpAll) {
6286                         pw.println(":");
6287                         w.dump(pw, "    ", true);
6288                     } else {
6289                         pw.println();
6290                     }
6291                 }
6292             }
6293         }
6294         if (!mWaitingForDrawnCallbacks.isEmpty()) {
6295             pw.println();
6296             pw.println("  Clients waiting for these windows to be drawn:");
6297             mWaitingForDrawnCallbacks.forEach((wc, callback) -> {
6298                 pw.print("  WindowContainer ");
6299                 pw.println(wc.getName());
6300                 for (int i = wc.mWaitingForDrawn.size() - 1; i >= 0; i--) {
6301                     final WindowState win = (WindowState) wc.mWaitingForDrawn.get(i);
6302                     pw.print("  Waiting #"); pw.print(i); pw.print(' '); pw.print(win);
6303                 }
6304             });
6305 
6306         }
6307         pw.println();
6308         pw.print("  mGlobalConfiguration="); pw.println(mRoot.getConfiguration());
6309         pw.print("  mHasPermanentDpad="); pw.println(mHasPermanentDpad);
6310         mRoot.dumpTopFocusedDisplayId(pw);
6311         mRoot.forAllDisplays(dc -> {
6312             final int displayId = dc.getDisplayId();
6313             final InsetsControlTarget imeLayeringTarget = dc.getImeTarget(IME_TARGET_LAYERING);
6314             final InsetsControlTarget imeInputTarget = dc.getImeTarget(IME_TARGET_INPUT);
6315             final InsetsControlTarget imeControlTarget = dc.getImeTarget(IME_TARGET_CONTROL);
6316             if (imeLayeringTarget != null) {
6317                 pw.print("  imeLayeringTarget in display# "); pw.print(displayId);
6318                 pw.print(' '); pw.println(imeLayeringTarget);
6319             }
6320             if (imeInputTarget != null) {
6321                 pw.print("  imeInputTarget in display# "); pw.print(displayId);
6322                 pw.print(' '); pw.println(imeInputTarget);
6323             }
6324             if (imeControlTarget != null) {
6325                 pw.print("  imeControlTarget in display# "); pw.print(displayId);
6326                 pw.print(' '); pw.println(imeControlTarget);
6327             }
6328         });
6329         pw.print("  mInTouchMode="); pw.println(mInTouchMode);
6330         pw.print("  mBlurEnabled="); pw.println(mBlurController.getBlurEnabled());
6331         pw.print("  mLastDisplayFreezeDuration=");
6332                 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
6333                 if ( mLastFinishedFreezeSource != null) {
6334                     pw.print(" due to ");
6335                     pw.print(mLastFinishedFreezeSource);
6336                 }
6337                 pw.println();
6338         pw.print("  mLastWakeLockHoldingWindow=");pw.print(mLastWakeLockHoldingWindow);
6339                 pw.print(" mLastWakeLockObscuringWindow="); pw.print(mLastWakeLockObscuringWindow);
6340                 pw.println();
6341 
6342         mInputManagerCallback.dump(pw, "  ");
6343         mTaskSnapshotController.dump(pw, "  ");
6344         if (mAccessibilityController != null) {
6345             mAccessibilityController.dump(pw, "  ");
6346         }
6347 
6348         if (dumpAll) {
6349             final WindowState imeWindow = mRoot.getCurrentInputMethodWindow();
6350             if (imeWindow != null) {
6351                 pw.print("  mInputMethodWindow="); pw.println(imeWindow);
6352             }
6353             mWindowPlacerLocked.dump(pw, "  ");
6354             pw.print("  mSystemBooted="); pw.print(mSystemBooted);
6355                     pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
6356 
6357             mRoot.dumpLayoutNeededDisplayIds(pw);
6358 
6359             pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
6360             pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
6361                     pw.print(" windows="); pw.print(mWindowsFreezingScreen);
6362                     pw.print(" client="); pw.print(mClientFreezingScreen);
6363                     pw.print(" apps="); pw.print(mAppsFreezingScreen);
6364             final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
6365             pw.print("  mRotation="); pw.print(defaultDisplayContent.getRotation());
6366             pw.print("  mLastOrientation=");
6367                     pw.println(defaultDisplayContent.getLastOrientation());
6368             pw.print(" waitingForConfig=");
6369                     pw.println(defaultDisplayContent.mWaitingForConfig);
6370 
6371             pw.print("  Animation settings: disabled="); pw.print(mAnimationsDisabled);
6372                     pw.print(" window="); pw.print(mWindowAnimationScaleSetting);
6373                     pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting);
6374                     pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting);
6375             if (mRecentsAnimationController != null) {
6376                 pw.print("  mRecentsAnimationController="); pw.println(mRecentsAnimationController);
6377                 mRecentsAnimationController.dump(pw, "    ");
6378             }
6379         }
6380     }
6381 
dumpWindows(PrintWriter pw, String name, String[] args, int opti, boolean dumpAll)6382     private boolean dumpWindows(PrintWriter pw, String name, String[] args, int opti,
6383             boolean dumpAll) {
6384         final ArrayList<WindowState> windows = new ArrayList();
6385         if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) {
6386             final boolean appsOnly = name.contains("apps");
6387             final boolean visibleOnly = name.contains("visible");
6388             synchronized (mGlobalLock) {
6389                 if (appsOnly) {
6390                     mRoot.dumpDisplayContents(pw);
6391                 }
6392 
6393                 mRoot.forAllWindows((w) -> {
6394                     if ((!visibleOnly || w.isVisible())
6395                             && (!appsOnly || w.mActivityRecord != null)) {
6396                         windows.add(w);
6397                     }
6398                 }, true /* traverseTopToBottom */);
6399             }
6400         } else {
6401             synchronized (mGlobalLock) {
6402                 mRoot.getWindowsByName(windows, name);
6403             }
6404         }
6405 
6406         if (windows.size() <= 0) {
6407             return false;
6408         }
6409 
6410         synchronized (mGlobalLock) {
6411             dumpWindowsLocked(pw, dumpAll, windows);
6412         }
6413         return true;
6414     }
6415 
dumpLastANRLocked(PrintWriter pw)6416     private void dumpLastANRLocked(PrintWriter pw) {
6417         pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
6418         if (mLastANRState == null) {
6419             pw.println("  <no ANR has occurred since boot>");
6420         } else {
6421             pw.println(mLastANRState);
6422         }
6423     }
6424 
6425     /**
6426      * Saves information about the state of the window manager at
6427      * the time an ANR occurred before anything else in the system changes
6428      * in response.
6429      *
6430      * @param activity The application that ANR'd, may be null.
6431      * @param windowState The window that ANR'd, may be null.
6432      * @param reason The reason for the ANR, may be null.
6433      */
saveANRStateLocked(ActivityRecord activity, WindowState windowState, String reason)6434     void saveANRStateLocked(ActivityRecord activity, WindowState windowState, String reason) {
6435         StringWriter sw = new StringWriter();
6436         PrintWriter pw = new FastPrintWriter(sw, false, 1024);
6437         pw.println("  ANR time: " + DateFormat.getDateTimeInstance().format(new Date()));
6438         if (activity != null) {
6439             pw.println("  Application at fault: " + activity.stringName);
6440         }
6441         if (windowState != null) {
6442             pw.println("  Window at fault: " + windowState.mAttrs.getTitle());
6443         }
6444         if (reason != null) {
6445             pw.println("  Reason: " + reason);
6446         }
6447         for (int i = mRoot.getChildCount() - 1; i >= 0; i--) {
6448             final DisplayContent dc = mRoot.getChildAt(i);
6449             final int displayId = dc.getDisplayId();
6450             if (!dc.mWinAddedSinceNullFocus.isEmpty()) {
6451                 pw.println("  Windows added in display #" + displayId + " since null focus: "
6452                         + dc.mWinAddedSinceNullFocus);
6453             }
6454             if (!dc.mWinRemovedSinceNullFocus.isEmpty()) {
6455                 pw.println("  Windows removed in display #" + displayId + " since null focus: "
6456                         + dc.mWinRemovedSinceNullFocus);
6457             }
6458         }
6459         pw.println();
6460         dumpWindowsNoHeaderLocked(pw, true, null);
6461         pw.println();
6462         pw.println("Last ANR continued");
6463         mRoot.dumpDisplayContents(pw);
6464         pw.close();
6465         mLastANRState = sw.toString();
6466 
6467         mH.removeMessages(H.RESET_ANR_MESSAGE);
6468         mH.sendEmptyMessageDelayed(H.RESET_ANR_MESSAGE, LAST_ANR_LIFETIME_DURATION_MSECS);
6469     }
6470 
6471     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)6472     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
6473         PriorityDump.dump(mPriorityDumper, fd, pw, args);
6474     }
6475 
doDump(FileDescriptor fd, PrintWriter pw, String[] args, boolean useProto)6476     private void doDump(FileDescriptor fd, PrintWriter pw, String[] args, boolean useProto) {
6477         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
6478         boolean dumpAll = false;
6479 
6480         int opti = 0;
6481         while (opti < args.length) {
6482             String opt = args[opti];
6483             if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6484                 break;
6485             }
6486             opti++;
6487             if ("-a".equals(opt)) {
6488                 dumpAll = true;
6489             } else if ("-h".equals(opt)) {
6490                 pw.println("Window manager dump options:");
6491                 pw.println("  [-a] [-h] [cmd] ...");
6492                 pw.println("  cmd may be one of:");
6493                 pw.println("    l[astanr]: last ANR information");
6494                 pw.println("    p[policy]: policy state");
6495                 pw.println("    a[animator]: animator state");
6496                 pw.println("    s[essions]: active sessions");
6497                 pw.println("    surfaces: active surfaces (debugging enabled only)");
6498                 pw.println("    d[isplays]: active display contents");
6499                 pw.println("    t[okens]: token list");
6500                 pw.println("    w[indows]: window list");
6501                 pw.println("    trace: print trace status and write Winscope trace to file");
6502                 pw.println("  cmd may also be a NAME to dump windows.  NAME may");
6503                 pw.println("    be a partial substring in a window name, a");
6504                 pw.println("    Window hex object identifier, or");
6505                 pw.println("    \"all\" for all windows, or");
6506                 pw.println("    \"visible\" for the visible windows.");
6507                 pw.println("    \"visible-apps\" for the visible app windows.");
6508                 pw.println("  -a: include all available server state.");
6509                 pw.println("  --proto: output dump in protocol buffer format.");
6510                 return;
6511             } else {
6512                 pw.println("Unknown argument: " + opt + "; use -h for help");
6513             }
6514         }
6515 
6516         if (useProto) {
6517             final ProtoOutputStream proto = new ProtoOutputStream(fd);
6518             synchronized (mGlobalLock) {
6519                 dumpDebugLocked(proto, WindowTraceLogLevel.ALL);
6520             }
6521             proto.flush();
6522             return;
6523         }
6524         // Is the caller requesting to dump a particular piece of data?
6525         if (opti < args.length) {
6526             String cmd = args[opti];
6527             opti++;
6528             if ("lastanr".equals(cmd) || "l".equals(cmd)) {
6529                 synchronized (mGlobalLock) {
6530                     dumpLastANRLocked(pw);
6531                 }
6532                 return;
6533             } else if ("policy".equals(cmd) || "p".equals(cmd)) {
6534                 synchronized (mGlobalLock) {
6535                     dumpPolicyLocked(pw, args, true);
6536                 }
6537                 return;
6538             } else if ("animator".equals(cmd) || "a".equals(cmd)) {
6539                 synchronized (mGlobalLock) {
6540                     dumpAnimatorLocked(pw, args, true);
6541                 }
6542                 return;
6543             } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
6544                 synchronized (mGlobalLock) {
6545                     dumpSessionsLocked(pw, true);
6546                 }
6547                 return;
6548             } else if ("displays".equals(cmd) || "d".equals(cmd)) {
6549                 synchronized (mGlobalLock) {
6550                     mRoot.dumpDisplayContents(pw);
6551                 }
6552                 return;
6553             } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
6554                 synchronized (mGlobalLock) {
6555                     dumpTokensLocked(pw, true);
6556                 }
6557                 return;
6558             } else if ("windows".equals(cmd) || "w".equals(cmd)) {
6559                 synchronized (mGlobalLock) {
6560                     dumpWindowsLocked(pw, true, null);
6561                 }
6562                 return;
6563             } else if ("all".equals(cmd)) {
6564                 synchronized (mGlobalLock) {
6565                     dumpWindowsLocked(pw, true, null);
6566                 }
6567                 return;
6568             } else if ("containers".equals(cmd)) {
6569                 synchronized (mGlobalLock) {
6570                     mRoot.dumpChildrenNames(pw, " ");
6571                     pw.println(" ");
6572                     mRoot.forAllWindows(w -> {pw.println(w);}, true /* traverseTopToBottom */);
6573                 }
6574                 return;
6575             } else if ("trace".equals(cmd)) {
6576                 dumpTraceStatus(pw);
6577                 return;
6578             } else if ("logging".equals(cmd)) {
6579                 dumpLogStatus(pw);
6580                 return;
6581             } else if ("refresh".equals(cmd)) {
6582                 dumpHighRefreshRateBlacklist(pw);
6583                 return;
6584             } else if ("constants".equals(cmd)) {
6585                 mConstants.dump(pw);
6586                 return;
6587             } else {
6588                 // Dumping a single name?
6589                 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
6590                     pw.println("Bad window command, or no windows match: " + cmd);
6591                     pw.println("Use -h for help.");
6592                 }
6593                 return;
6594             }
6595         }
6596 
6597         synchronized (mGlobalLock) {
6598             pw.println();
6599             final String separator = "---------------------------------------------------------"
6600                     + "----------------------";
6601             if (dumpAll) {
6602                 pw.println(separator);
6603             }
6604             dumpLastANRLocked(pw);
6605             pw.println();
6606             if (dumpAll) {
6607                 pw.println(separator);
6608             }
6609             dumpPolicyLocked(pw, args, dumpAll);
6610             pw.println();
6611             if (dumpAll) {
6612                 pw.println(separator);
6613             }
6614             dumpAnimatorLocked(pw, args, dumpAll);
6615             pw.println();
6616             if (dumpAll) {
6617                 pw.println(separator);
6618             }
6619             dumpSessionsLocked(pw, dumpAll);
6620             pw.println();
6621             if (dumpAll) {
6622                 pw.println(separator);
6623             }
6624             if (dumpAll) {
6625                 pw.println(separator);
6626             }
6627             mRoot.dumpDisplayContents(pw);
6628             pw.println();
6629             if (dumpAll) {
6630                 pw.println(separator);
6631             }
6632             dumpTokensLocked(pw, dumpAll);
6633             pw.println();
6634             if (dumpAll) {
6635                 pw.println(separator);
6636             }
6637             dumpWindowsLocked(pw, dumpAll, null);
6638             if (dumpAll) {
6639                 pw.println(separator);
6640             }
6641             dumpTraceStatus(pw);
6642             if (dumpAll) {
6643                 pw.println(separator);
6644             }
6645             dumpLogStatus(pw);
6646             if (dumpAll) {
6647                 pw.println(separator);
6648             }
6649             dumpHighRefreshRateBlacklist(pw);
6650             if (dumpAll) {
6651                 pw.println(separator);
6652             }
6653             mConstants.dump(pw);
6654         }
6655     }
6656 
6657     // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
6658     @Override
monitor()6659     public void monitor() {
6660         synchronized (mGlobalLock) { }
6661     }
6662 
6663     // There is an inherent assumption that this will never return null.
6664     // TODO(multi-display): Inspect all the call-points of this method to see if they make sense to
6665     // support non-default display.
getDefaultDisplayContentLocked()6666     DisplayContent getDefaultDisplayContentLocked() {
6667         return mRoot.getDisplayContent(DEFAULT_DISPLAY);
6668     }
6669 
onOverlayChanged()6670     public void onOverlayChanged() {
6671         synchronized (mGlobalLock) {
6672             mRoot.forAllDisplays(displayContent -> {
6673                 displayContent.getDisplayPolicy().onOverlayChangedLw();
6674                 displayContent.updateDisplayInfo();
6675             });
6676             requestTraversal();
6677         }
6678     }
6679 
6680     @Override
getWindowManagerLock()6681     public Object getWindowManagerLock() {
6682         return mGlobalLock;
6683     }
6684 
6685     /**
6686      * Hint to a token that its activity will relaunch, which will trigger removal and addition of
6687      * a window.
6688      *
6689      * @param token Application token for which the activity will be relaunched.
6690      */
setWillReplaceWindow(IBinder token, boolean animate)6691     void setWillReplaceWindow(IBinder token, boolean animate) {
6692         final ActivityRecord activity = mRoot.getActivityRecord(token);
6693         if (activity == null) {
6694             ProtoLog.w(WM_ERROR, "Attempted to set replacing window on non-existing app token %s",
6695                     token);
6696             return;
6697         }
6698         if (!activity.hasContentToDisplay()) {
6699             ProtoLog.w(WM_ERROR,
6700                     "Attempted to set replacing window on app token with no content %s",
6701                     token);
6702             return;
6703         }
6704         activity.setWillReplaceWindows(animate);
6705     }
6706 
6707     /**
6708      * Hint to a token that its windows will be replaced across activity relaunch.
6709      * The windows would otherwise be removed  shortly following this as the
6710      * activity is torn down.
6711      * @param token Application token for which the activity will be relaunched.
6712      * @param childrenOnly Whether to mark only child windows for replacement
6713      *                     (for the case where main windows are being preserved/
6714      *                     reused rather than replaced).
6715      *
6716      */
6717     // TODO: The s at the end of the method name is the only difference with the name of the method
6718     // above. We should combine them or find better names.
setWillReplaceWindows(IBinder token, boolean childrenOnly)6719     void setWillReplaceWindows(IBinder token, boolean childrenOnly) {
6720         synchronized (mGlobalLock) {
6721             final ActivityRecord activity = mRoot.getActivityRecord(token);
6722             if (activity == null) {
6723                 ProtoLog.w(WM_ERROR,
6724                         "Attempted to set replacing window on non-existing app token %s",
6725                         token);
6726                 return;
6727             }
6728             if (!activity.hasContentToDisplay()) {
6729                 ProtoLog.w(WM_ERROR,
6730                         "Attempted to set replacing window on app token with no content %s",
6731                         token);
6732                 return;
6733             }
6734 
6735             if (childrenOnly) {
6736                 activity.setWillReplaceChildWindows();
6737             } else {
6738                 activity.setWillReplaceWindows(false /* animate */);
6739             }
6740 
6741             scheduleClearWillReplaceWindows(token, true /* replacing */);
6742         }
6743     }
6744 
6745     /**
6746      * If we're replacing the window, schedule a timer to clear the replaced window
6747      * after a timeout, in case the replacing window is not coming.
6748      *
6749      * If we're not replacing the window, clear the replace window settings of the app.
6750      *
6751      * @param token     Application token for the activity whose window might be replaced.
6752      * @param replacing Whether the window is being replaced or not.
6753      */
scheduleClearWillReplaceWindows(IBinder token, boolean replacing)6754     void scheduleClearWillReplaceWindows(IBinder token, boolean replacing) {
6755         final ActivityRecord activity = mRoot.getActivityRecord(token);
6756         if (activity == null) {
6757             ProtoLog.w(WM_ERROR, "Attempted to reset replacing window on non-existing app token %s",
6758                     token);
6759             return;
6760         }
6761         if (replacing) {
6762             scheduleWindowReplacementTimeouts(activity);
6763         } else {
6764             activity.clearWillReplaceWindows();
6765         }
6766     }
6767 
scheduleWindowReplacementTimeouts(ActivityRecord activity)6768     void scheduleWindowReplacementTimeouts(ActivityRecord activity) {
6769         if (!mWindowReplacementTimeouts.contains(activity)) {
6770             mWindowReplacementTimeouts.add(activity);
6771         }
6772         mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT);
6773         mH.sendEmptyMessageDelayed(
6774                 H.WINDOW_REPLACEMENT_TIMEOUT, WINDOW_REPLACEMENT_TIMEOUT_DURATION);
6775     }
6776 
6777     @Override
getDockedStackSide()6778     public int getDockedStackSide() {
6779         return 0;
6780     }
6781 
setDockedRootTaskResizing(boolean resizing)6782     void setDockedRootTaskResizing(boolean resizing) {
6783         getDefaultDisplayContentLocked().getDockedDividerController().setResizing(resizing);
6784         requestTraversal();
6785     }
6786 
6787     @Override
setDockedTaskDividerTouchRegion(Rect touchRegion)6788     public void setDockedTaskDividerTouchRegion(Rect touchRegion) {
6789         synchronized (mGlobalLock) {
6790             final DisplayContent dc = getDefaultDisplayContentLocked();
6791             dc.getDockedDividerController().setTouchRegion(touchRegion);
6792             dc.updateTouchExcludeRegion();
6793         }
6794     }
6795 
setForceDesktopModeOnExternalDisplays(boolean forceDesktopModeOnExternalDisplays)6796     void setForceDesktopModeOnExternalDisplays(boolean forceDesktopModeOnExternalDisplays) {
6797         synchronized (mGlobalLock) {
6798             mForceDesktopModeOnExternalDisplays = forceDesktopModeOnExternalDisplays;
6799         }
6800     }
6801 
6802     @VisibleForTesting
setIsPc(boolean isPc)6803     void setIsPc(boolean isPc) {
6804         synchronized (mGlobalLock) {
6805             mIsPc = isPc;
6806         }
6807     }
6808 
dipToPixel(int dip, DisplayMetrics displayMetrics)6809     static int dipToPixel(int dip, DisplayMetrics displayMetrics) {
6810         return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics);
6811     }
6812 
registerPinnedTaskListener(int displayId, IPinnedTaskListener listener)6813     public void registerPinnedTaskListener(int displayId, IPinnedTaskListener listener) {
6814         if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS,
6815                 "registerPinnedTaskListener()")) {
6816             return;
6817         }
6818         if (!mAtmService.mSupportsPictureInPicture) {
6819             return;
6820         }
6821         synchronized (mGlobalLock) {
6822             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
6823             displayContent.getPinnedTaskController().registerPinnedTaskListener(listener);
6824         }
6825     }
6826 
6827     @Override
requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId)6828     public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
6829         try {
6830             WindowState focusedWindow = getFocusedWindow();
6831             if (focusedWindow != null && focusedWindow.mClient != null) {
6832                 getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver, deviceId);
6833             }
6834         } catch (RemoteException e) {
6835         }
6836     }
6837 
6838     @Override
getStableInsets(int displayId, Rect outInsets)6839     public void getStableInsets(int displayId, Rect outInsets) throws RemoteException {
6840         synchronized (mGlobalLock) {
6841             getStableInsetsLocked(displayId, outInsets);
6842         }
6843     }
6844 
getStableInsetsLocked(int displayId, Rect outInsets)6845     void getStableInsetsLocked(int displayId, Rect outInsets) {
6846         outInsets.setEmpty();
6847         final DisplayContent dc = mRoot.getDisplayContent(displayId);
6848         if (dc != null) {
6849             final DisplayInfo di = dc.getDisplayInfo();
6850             dc.getDisplayPolicy().getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
6851                     di.displayCutout, outInsets);
6852         }
6853     }
6854 
6855     @Override
setForwardedInsets(int displayId, Insets insets)6856     public void setForwardedInsets(int displayId, Insets insets) throws RemoteException {
6857         synchronized (mGlobalLock) {
6858             final DisplayContent dc = mRoot.getDisplayContent(displayId);
6859             if (dc == null) {
6860                 return;
6861             }
6862             final int callingUid = Binder.getCallingUid();
6863             final int displayOwnerUid = dc.getDisplay().getOwnerUid();
6864             if (callingUid != displayOwnerUid) {
6865                 throw new SecurityException(
6866                         "Only owner of the display can set ForwardedInsets to it.");
6867             }
6868             dc.setForwardedInsets(insets);
6869         }
6870     }
6871 
intersectDisplayInsetBounds(Rect display, Rect insets, Rect inOutBounds)6872     void intersectDisplayInsetBounds(Rect display, Rect insets, Rect inOutBounds) {
6873         mTmpRect3.set(display);
6874         mTmpRect3.inset(insets);
6875         inOutBounds.intersect(mTmpRect3);
6876     }
6877 
6878     MousePositionTracker mMousePositionTracker = new MousePositionTracker();
6879 
6880     private static class MousePositionTracker implements PointerEventListener {
6881         private boolean mLatestEventWasMouse;
6882         private float mLatestMouseX;
6883         private float mLatestMouseY;
6884 
updatePosition(float x, float y)6885         void updatePosition(float x, float y) {
6886             synchronized (this) {
6887                 mLatestEventWasMouse = true;
6888                 mLatestMouseX = x;
6889                 mLatestMouseY = y;
6890             }
6891         }
6892 
6893         @Override
onPointerEvent(MotionEvent motionEvent)6894         public void onPointerEvent(MotionEvent motionEvent) {
6895             if (motionEvent.isFromSource(InputDevice.SOURCE_MOUSE)) {
6896                 updatePosition(motionEvent.getRawX(), motionEvent.getRawY());
6897             } else {
6898                 synchronized (this) {
6899                     mLatestEventWasMouse = false;
6900                 }
6901             }
6902         }
6903     };
6904 
updatePointerIcon(IWindow client)6905     void updatePointerIcon(IWindow client) {
6906         float mouseX, mouseY;
6907 
6908         synchronized(mMousePositionTracker) {
6909             if (!mMousePositionTracker.mLatestEventWasMouse) {
6910                 return;
6911             }
6912             mouseX = mMousePositionTracker.mLatestMouseX;
6913             mouseY = mMousePositionTracker.mLatestMouseY;
6914         }
6915 
6916         synchronized (mGlobalLock) {
6917             if (mDragDropController.dragDropActiveLocked()) {
6918                 // Drag cursor overrides the app cursor.
6919                 return;
6920             }
6921             WindowState callingWin = windowForClientLocked(null, client, false);
6922             if (callingWin == null) {
6923                 ProtoLog.w(WM_ERROR, "Bad requesting window %s", client);
6924                 return;
6925             }
6926             final DisplayContent displayContent = callingWin.getDisplayContent();
6927             if (displayContent == null) {
6928                 return;
6929             }
6930             WindowState windowUnderPointer =
6931                     displayContent.getTouchableWinAtPointLocked(mouseX, mouseY);
6932             if (windowUnderPointer != callingWin) {
6933                 return;
6934             }
6935             try {
6936                 windowUnderPointer.mClient.updatePointerIcon(
6937                         windowUnderPointer.translateToWindowX(mouseX),
6938                         windowUnderPointer.translateToWindowY(mouseY));
6939             } catch (RemoteException e) {
6940                 ProtoLog.w(WM_ERROR, "unable to update pointer icon");
6941             }
6942         }
6943     }
6944 
restorePointerIconLocked(DisplayContent displayContent, float latestX, float latestY)6945     void restorePointerIconLocked(DisplayContent displayContent, float latestX, float latestY) {
6946         // Mouse position tracker has not been getting updates while dragging, update it now.
6947         mMousePositionTracker.updatePosition(latestX, latestY);
6948 
6949         WindowState windowUnderPointer =
6950                 displayContent.getTouchableWinAtPointLocked(latestX, latestY);
6951         if (windowUnderPointer != null) {
6952             try {
6953                 windowUnderPointer.mClient.updatePointerIcon(
6954                         windowUnderPointer.translateToWindowX(latestX),
6955                         windowUnderPointer.translateToWindowY(latestY));
6956             } catch (RemoteException e) {
6957                 ProtoLog.w(WM_ERROR, "unable to restore pointer icon");
6958             }
6959         } else {
6960             InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_DEFAULT);
6961         }
6962     }
6963 
checkCallerOwnsDisplay(int displayId)6964     private void checkCallerOwnsDisplay(int displayId) {
6965         final Display display = mDisplayManager.getDisplay(displayId);
6966         if (display == null) {
6967             throw new IllegalArgumentException(
6968                     "Cannot find display for non-existent displayId: " + displayId);
6969         }
6970 
6971         final int callingUid = Binder.getCallingUid();
6972         final int displayOwnerUid = display.getOwnerUid();
6973         if (callingUid != displayOwnerUid) {
6974             throw new SecurityException("The caller doesn't own the display.");
6975         }
6976     }
6977 
6978     /** @see Session#updateDisplayContentLocation(IWindow, int, int, int)  */
updateDisplayContentLocation(IWindow client, int x, int y, int displayId)6979     void updateDisplayContentLocation(IWindow client, int x, int y, int displayId) {
6980         checkCallerOwnsDisplay(displayId);
6981 
6982         synchronized (mGlobalLock) {
6983             final long token = Binder.clearCallingIdentity();
6984             try {
6985                 final WindowState win = windowForClientLocked(null, client, false);
6986                 if (win == null) {
6987                     ProtoLog.w(WM_ERROR, "Bad requesting window %s", client);
6988                     return;
6989                 }
6990                 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
6991                 if (displayContent != null) {
6992                     displayContent.updateLocation(win, x, y);
6993                 }
6994             } finally {
6995                 Binder.restoreCallingIdentity(token);
6996             }
6997         }
6998     }
6999 
7000     /**
7001      * Update a tap exclude region in the window identified by the provided id. Touches down on this
7002      * region will not:
7003      * <ol>
7004      * <li>Switch focus to this window.</li>
7005      * <li>Move the display of this window to top.</li>
7006      * <li>Send the touch events to this window.</li>
7007      * </ol>
7008      * Passing an invalid region will remove the area from the exclude region of this window.
7009      */
updateTapExcludeRegion(IWindow client, Region region)7010     void updateTapExcludeRegion(IWindow client, Region region) {
7011         synchronized (mGlobalLock) {
7012             final WindowState callingWin = windowForClientLocked(null, client, false);
7013             if (callingWin == null) {
7014                 ProtoLog.w(WM_ERROR, "Bad requesting window %s", client);
7015                 return;
7016             }
7017             callingWin.updateTapExcludeRegion(region);
7018         }
7019     }
7020 
7021     /**
7022      * Forwards a scroll capture request to the appropriate window, if available.
7023      *
7024      * @param displayId the display for the request
7025      * @param behindClient token for a window, used to filter the search to windows behind it
7026      * @param taskId specifies the id of a task the result must belong to or -1 to match any task
7027      * @param listener to receive the response
7028      */
requestScrollCapture(int displayId, @Nullable IBinder behindClient, int taskId, IScrollCaptureResponseListener listener)7029     public void requestScrollCapture(int displayId, @Nullable IBinder behindClient, int taskId,
7030             IScrollCaptureResponseListener listener) {
7031         if (!checkCallingPermission(READ_FRAME_BUFFER, "requestScrollCapture()")) {
7032             throw new SecurityException("Requires READ_FRAME_BUFFER permission");
7033         }
7034         final long token = Binder.clearCallingIdentity();
7035         try {
7036             ScrollCaptureResponse.Builder responseBuilder = new ScrollCaptureResponse.Builder();
7037             synchronized (mGlobalLock) {
7038                 DisplayContent dc = mRoot.getDisplayContent(displayId);
7039                 if (dc == null) {
7040                     ProtoLog.e(WM_ERROR,
7041                             "Invalid displayId for requestScrollCapture: %d", displayId);
7042                     responseBuilder.setDescription(String.format("bad displayId: %d", displayId));
7043                     listener.onScrollCaptureResponse(responseBuilder.build());
7044                     return;
7045                 }
7046                 WindowState topWindow = null;
7047                 if (behindClient != null) {
7048                     topWindow = windowForClientLocked(null, behindClient, /* throwOnError*/ false);
7049                 }
7050                 WindowState targetWindow = dc.findScrollCaptureTargetWindow(topWindow, taskId);
7051                 if (targetWindow == null) {
7052                     responseBuilder.setDescription("findScrollCaptureTargetWindow returned null");
7053                     listener.onScrollCaptureResponse(responseBuilder.build());
7054                     return;
7055                 }
7056                 try {
7057                     // Forward to the window for handling, which will respond using the callback.
7058                     targetWindow.mClient.requestScrollCapture(listener);
7059                 } catch (RemoteException e) {
7060                     ProtoLog.w(WM_ERROR,
7061                             "requestScrollCapture: caught exception dispatching to window."
7062                                     + "token=%s", targetWindow.mClient.asBinder());
7063                     responseBuilder.setWindowTitle(targetWindow.getName());
7064                     responseBuilder.setDescription(String.format("caught exception: %s", e));
7065                     listener.onScrollCaptureResponse(responseBuilder.build());
7066                 }
7067             }
7068         } catch (RemoteException e) {
7069             ProtoLog.w(WM_ERROR,
7070                     "requestScrollCapture: caught exception dispatching callback: %s", e);
7071         } finally {
7072             Binder.restoreCallingIdentity(token);
7073         }
7074     }
7075 
7076     @Override
dontOverrideDisplayInfo(int displayId)7077     public void dontOverrideDisplayInfo(int displayId) {
7078         final long token = Binder.clearCallingIdentity();
7079         try {
7080             synchronized (mGlobalLock) {
7081                 final DisplayContent dc = getDisplayContentOrCreate(displayId, null /* token */);
7082                 if (dc == null) {
7083                     throw new IllegalArgumentException(
7084                             "Trying to configure a non existent display.");
7085                 }
7086                 // We usually set the override info in DisplayManager so that we get consistent
7087                 // values when displays are changing. However, we don't do this for displays that
7088                 // serve as containers for ActivityViews because we don't want letter-/pillar-boxing
7089                 // during resize.
7090                 dc.mShouldOverrideDisplayConfiguration = false;
7091                 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(displayId,
7092                         null /* info */);
7093             }
7094         } finally {
7095             Binder.restoreCallingIdentity(token);
7096         }
7097     }
7098 
7099     @Override
getWindowingMode(int displayId)7100     public int getWindowingMode(int displayId) {
7101         if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "getWindowingMode()")) {
7102             throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
7103         }
7104 
7105         synchronized (mGlobalLock) {
7106             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
7107             if (displayContent == null) {
7108                 ProtoLog.w(WM_ERROR,
7109                         "Attempted to get windowing mode of a display that does not exist: %d",
7110                         displayId);
7111                 return WindowConfiguration.WINDOWING_MODE_UNDEFINED;
7112             }
7113             return mDisplayWindowSettings.getWindowingModeLocked(displayContent);
7114         }
7115     }
7116 
7117     @Override
setWindowingMode(int displayId, int mode)7118     public void setWindowingMode(int displayId, int mode) {
7119         if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "setWindowingMode()")) {
7120             throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
7121         }
7122 
7123         final long origId = Binder.clearCallingIdentity();
7124         try {
7125             synchronized (mGlobalLock) {
7126                 final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null);
7127                 if (displayContent == null) {
7128                     ProtoLog.w(WM_ERROR,
7129                             "Attempted to set windowing mode to a display that does not exist: %d",
7130                             displayId);
7131                     return;
7132                 }
7133 
7134                 int lastWindowingMode = displayContent.getWindowingMode();
7135                 mDisplayWindowSettings.setWindowingModeLocked(displayContent, mode);
7136 
7137                 displayContent.reconfigureDisplayLocked();
7138 
7139                 if (lastWindowingMode != displayContent.getWindowingMode()) {
7140                     // reconfigure won't detect this change in isolation because the windowing mode
7141                     // is already set on the display, so fire off a new config now.
7142                     displayContent.sendNewConfiguration();
7143                     // Now that all configurations are updated, execute pending transitions.
7144                     displayContent.executeAppTransition();
7145                 }
7146             }
7147         } finally {
7148             Binder.restoreCallingIdentity(origId);
7149         }
7150     }
7151 
7152     @Override
getRemoveContentMode(int displayId)7153     public @RemoveContentMode int getRemoveContentMode(int displayId) {
7154         if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "getRemoveContentMode()")) {
7155             throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
7156         }
7157 
7158         synchronized (mGlobalLock) {
7159             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
7160             if (displayContent == null) {
7161                 ProtoLog.w(WM_ERROR,
7162                         "Attempted to get remove mode of a display that does not exist: %d",
7163                         displayId);
7164                 return REMOVE_CONTENT_MODE_UNDEFINED;
7165             }
7166             return mDisplayWindowSettings.getRemoveContentModeLocked(displayContent);
7167         }
7168     }
7169 
7170     @Override
setRemoveContentMode(int displayId, @RemoveContentMode int mode)7171     public void setRemoveContentMode(int displayId, @RemoveContentMode int mode) {
7172         if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "setRemoveContentMode()")) {
7173             throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
7174         }
7175 
7176         final long origId = Binder.clearCallingIdentity();
7177         try {
7178             synchronized (mGlobalLock) {
7179                 final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null);
7180                 if (displayContent == null) {
7181                     ProtoLog.w(WM_ERROR,
7182                             "Attempted to set remove mode to a display that does not exist: %d",
7183                             displayId);
7184                     return;
7185                 }
7186 
7187                 mDisplayWindowSettings.setRemoveContentModeLocked(displayContent, mode);
7188                 displayContent.reconfigureDisplayLocked();
7189             }
7190         } finally {
7191             Binder.restoreCallingIdentity(origId);
7192         }
7193     }
7194 
7195     @Override
shouldShowWithInsecureKeyguard(int displayId)7196     public boolean shouldShowWithInsecureKeyguard(int displayId) {
7197         if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "shouldShowWithInsecureKeyguard()")) {
7198             throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
7199         }
7200 
7201         synchronized (mGlobalLock) {
7202             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
7203             if (displayContent == null) {
7204                 ProtoLog.w(WM_ERROR, "Attempted to get flag of a display that does not exist: %d",
7205                         displayId);
7206                 return false;
7207             }
7208             return mDisplayWindowSettings.shouldShowWithInsecureKeyguardLocked(displayContent);
7209         }
7210     }
7211 
7212     @Override
setShouldShowWithInsecureKeyguard(int displayId, boolean shouldShow)7213     public void setShouldShowWithInsecureKeyguard(int displayId, boolean shouldShow) {
7214         if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW,
7215                 "setShouldShowWithInsecureKeyguard()")) {
7216             throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
7217         }
7218         final long origId = Binder.clearCallingIdentity();
7219         try {
7220             synchronized (mGlobalLock) {
7221                 final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null);
7222                 if (displayContent == null) {
7223                     ProtoLog.w(WM_ERROR, "Attempted to set flag to a display that does not exist: "
7224                             + "%d", displayId);
7225                     return;
7226                 }
7227 
7228                 mDisplayWindowSettings.setShouldShowWithInsecureKeyguardLocked(displayContent,
7229                         shouldShow);
7230 
7231                 displayContent.reconfigureDisplayLocked();
7232             }
7233         } finally {
7234             Binder.restoreCallingIdentity(origId);
7235         }
7236     }
7237 
7238     @Override
shouldShowSystemDecors(int displayId)7239     public boolean shouldShowSystemDecors(int displayId) {
7240         if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "shouldShowSystemDecors()")) {
7241             throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
7242         }
7243 
7244         synchronized (mGlobalLock) {
7245             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
7246             if (displayContent == null) {
7247                 ProtoLog.w(WM_ERROR, "Attempted to get system decors flag of a display that does "
7248                         + "not exist: %d", displayId);
7249                 return false;
7250             }
7251             return displayContent.supportsSystemDecorations();
7252         }
7253     }
7254 
7255     @Override
setShouldShowSystemDecors(int displayId, boolean shouldShow)7256     public void setShouldShowSystemDecors(int displayId, boolean shouldShow) {
7257         if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "setShouldShowSystemDecors()")) {
7258             throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
7259         }
7260         final long origId = Binder.clearCallingIdentity();
7261         try {
7262             synchronized (mGlobalLock) {
7263                 final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null);
7264                 if (displayContent == null) {
7265                     ProtoLog.w(WM_ERROR, "Attempted to set system decors flag to a display that "
7266                             + "does not exist: %d", displayId);
7267                     return;
7268                 }
7269                 if (!displayContent.isTrusted()) {
7270                     throw new SecurityException("Attempted to set system decors flag to an "
7271                             + "untrusted virtual display: " + displayId);
7272                 }
7273 
7274                 mDisplayWindowSettings.setShouldShowSystemDecorsLocked(displayContent, shouldShow);
7275 
7276                 displayContent.reconfigureDisplayLocked();
7277             }
7278         } finally {
7279             Binder.restoreCallingIdentity(origId);
7280         }
7281     }
7282 
7283     @Override
getDisplayImePolicy(int displayId)7284     public @DisplayImePolicy int getDisplayImePolicy(int displayId) {
7285         if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "getDisplayImePolicy()")) {
7286             throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
7287         }
7288         final DisplayContent dc = mRoot.getDisplayContent(displayId);
7289         if (dc == null) {
7290             ProtoLog.w(WM_ERROR,
7291                     "Attempted to get IME policy of a display that does not exist: %d",
7292                     displayId);
7293             return DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
7294         }
7295         synchronized (mGlobalLock) {
7296             return dc.getImePolicy();
7297         }
7298     }
7299 
7300     @Override
setDisplayImePolicy(int displayId, @DisplayImePolicy int imePolicy)7301     public void setDisplayImePolicy(int displayId, @DisplayImePolicy int imePolicy) {
7302         if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "setDisplayImePolicy()")) {
7303             throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
7304         }
7305         final long origId = Binder.clearCallingIdentity();
7306         try {
7307             synchronized (mGlobalLock) {
7308                 final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null);
7309                 if (displayContent == null) {
7310                     ProtoLog.w(WM_ERROR, "Attempted to set IME policy to a display"
7311                             + " that does not exist: %d", displayId);
7312                     return;
7313                 }
7314                 if (!displayContent.isTrusted()) {
7315                     throw new SecurityException("Attempted to set IME policy to an untrusted "
7316                             + "virtual display: " + displayId);
7317                 }
7318 
7319                 mDisplayWindowSettings.setDisplayImePolicy(displayContent, imePolicy);
7320 
7321                 displayContent.reconfigureDisplayLocked();
7322             }
7323         } finally {
7324             Binder.restoreCallingIdentity(origId);
7325         }
7326     }
7327 
7328     @Override
registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)7329     public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
7330             throws RemoteException {
7331         if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS, "registerShortcutKey")) {
7332             throw new SecurityException(
7333                     "Requires REGISTER_WINDOW_MANAGER_LISTENERS permission");
7334         }
7335         mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver);
7336     }
7337 
7338     private final class LocalService extends WindowManagerInternal {
7339 
7340         @Override
getAccessibilityController()7341         public AccessibilityControllerInternal getAccessibilityController() {
7342             return AccessibilityController.getAccessibilityControllerInternal(
7343                     WindowManagerService.this);
7344         }
7345 
7346         @Override
clearSnapshotCache()7347         public void clearSnapshotCache() {
7348             synchronized (mGlobalLock) {
7349                 mTaskSnapshotController.clearSnapshotCache();
7350             }
7351         }
7352 
7353         @Override
requestTraversalFromDisplayManager()7354         public void requestTraversalFromDisplayManager() {
7355             synchronized (mGlobalLock) {
7356                 requestTraversal();
7357             }
7358         }
7359 
7360         @Override
setMagnificationSpec(int displayId, MagnificationSpec spec)7361         public void setMagnificationSpec(int displayId, MagnificationSpec spec) {
7362             synchronized (mGlobalLock) {
7363                 if (mAccessibilityController != null) {
7364                     mAccessibilityController.setMagnificationSpec(displayId, spec);
7365                 } else {
7366                     throw new IllegalStateException("Magnification callbacks not set!");
7367                 }
7368             }
7369         }
7370 
7371         @Override
setForceShowMagnifiableBounds(int displayId, boolean show)7372         public void setForceShowMagnifiableBounds(int displayId, boolean show) {
7373             synchronized (mGlobalLock) {
7374                 if (mAccessibilityController != null) {
7375                     mAccessibilityController.setForceShowMagnifiableBounds(displayId, show);
7376                 } else {
7377                     throw new IllegalStateException("Magnification callbacks not set!");
7378                 }
7379             }
7380         }
7381 
7382         @Override
getMagnificationRegion(int displayId, @NonNull Region magnificationRegion)7383         public void getMagnificationRegion(int displayId, @NonNull Region magnificationRegion) {
7384             synchronized (mGlobalLock) {
7385                 if (mAccessibilityController != null) {
7386                     mAccessibilityController.getMagnificationRegion(displayId, magnificationRegion);
7387                 } else {
7388                     throw new IllegalStateException("Magnification callbacks not set!");
7389                 }
7390             }
7391         }
7392 
7393         @Override
getCompatibleMagnificationSpecForWindow(IBinder windowToken)7394         public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
7395             synchronized (mGlobalLock) {
7396                 WindowState windowState = mWindowMap.get(windowToken);
7397                 if (windowState == null) {
7398                     return null;
7399                 }
7400                 MagnificationSpec spec = null;
7401                 if (mAccessibilityController != null) {
7402                     spec = mAccessibilityController.getMagnificationSpecForWindow(windowState);
7403                 }
7404                 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
7405                     return null;
7406                 }
7407                 MagnificationSpec result = new MagnificationSpec();
7408                 if (spec != null) {
7409                     result.setTo(spec);
7410                 }
7411                 result.scale *= windowState.mGlobalScale;
7412                 return result;
7413             }
7414         }
7415 
7416         @Override
setMagnificationCallbacks(int displayId, @Nullable MagnificationCallbacks callbacks)7417         public boolean setMagnificationCallbacks(int displayId,
7418                 @Nullable MagnificationCallbacks callbacks) {
7419             synchronized (mGlobalLock) {
7420                 if (mAccessibilityController == null) {
7421                     mAccessibilityController = new AccessibilityController(
7422                             WindowManagerService.this);
7423                 }
7424                 boolean result = mAccessibilityController.setMagnificationCallbacks(
7425                         displayId, callbacks);
7426                 if (!mAccessibilityController.hasCallbacks()) {
7427                     mAccessibilityController = null;
7428                 }
7429                 return result;
7430             }
7431         }
7432 
7433         @Override
setWindowsForAccessibilityCallback(int displayId, WindowsForAccessibilityCallback callback)7434         public boolean setWindowsForAccessibilityCallback(int displayId,
7435                 WindowsForAccessibilityCallback callback) {
7436             synchronized (mGlobalLock) {
7437                 if (mAccessibilityController == null) {
7438                     mAccessibilityController = new AccessibilityController(
7439                             WindowManagerService.this);
7440                 }
7441                 final boolean result =
7442                         mAccessibilityController.setWindowsForAccessibilityCallback(
7443                         displayId, callback);
7444                 if (!mAccessibilityController.hasCallbacks()) {
7445                     mAccessibilityController = null;
7446                 }
7447                 return result;
7448             }
7449         }
7450 
7451         @Override
setInputFilter(IInputFilter filter)7452         public void setInputFilter(IInputFilter filter) {
7453             mInputManager.setInputFilter(filter);
7454         }
7455 
7456         @Override
getFocusedWindowToken()7457         public IBinder getFocusedWindowToken() {
7458             synchronized (mGlobalLock) {
7459                 WindowState windowState = getFocusedWindowLocked();
7460                 if (windowState != null) {
7461                     return windowState.mClient.asBinder();
7462                 }
7463                 return null;
7464             }
7465         }
7466 
7467         @Override
isKeyguardLocked()7468         public boolean isKeyguardLocked() {
7469             return WindowManagerService.this.isKeyguardLocked();
7470         }
7471 
7472         @Override
isKeyguardShowingAndNotOccluded()7473         public boolean isKeyguardShowingAndNotOccluded() {
7474             return WindowManagerService.this.isKeyguardShowingAndNotOccluded();
7475         }
7476 
7477         @Override
showGlobalActions()7478         public void showGlobalActions() {
7479             WindowManagerService.this.showGlobalActions();
7480         }
7481 
7482         @Override
getWindowFrame(IBinder token, Rect outBounds)7483         public void getWindowFrame(IBinder token, Rect outBounds) {
7484             synchronized (mGlobalLock) {
7485                 WindowState windowState = mWindowMap.get(token);
7486                 if (windowState != null) {
7487                     outBounds.set(windowState.getFrame());
7488                 } else {
7489                     outBounds.setEmpty();
7490                 }
7491             }
7492         }
7493 
7494         @Override
waitForAllWindowsDrawn(Runnable callback, long timeout, int displayId)7495         public void waitForAllWindowsDrawn(Runnable callback, long timeout, int displayId) {
7496             final WindowContainer container = displayId == INVALID_DISPLAY
7497                     ? mRoot : mRoot.getDisplayContent(displayId);
7498             if (container == null) {
7499                 // The waiting container doesn't exist, no need to wait to run the callback. Run and
7500                 // return;
7501                 callback.run();
7502                 return;
7503             }
7504             boolean allWindowsDrawn = false;
7505             synchronized (mGlobalLock) {
7506                 container.waitForAllWindowsDrawn();
7507                 mWindowPlacerLocked.requestTraversal();
7508                 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, container);
7509                 if (container.mWaitingForDrawn.isEmpty()) {
7510                     allWindowsDrawn = true;
7511                 } else {
7512                     mWaitingForDrawnCallbacks.put(container, callback);
7513                     mH.sendNewMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, container, timeout);
7514                     checkDrawnWindowsLocked();
7515                 }
7516             }
7517             if (allWindowsDrawn) {
7518                 callback.run();
7519             }
7520         }
7521 
7522         @Override
setForcedDisplaySize(int displayId, int width, int height)7523         public void setForcedDisplaySize(int displayId, int width, int height) {
7524             WindowManagerService.this.setForcedDisplaySize(displayId, width, height);
7525         }
7526 
7527         @Override
clearForcedDisplaySize(int displayId)7528         public void clearForcedDisplaySize(int displayId) {
7529             WindowManagerService.this.clearForcedDisplaySize(displayId);
7530         }
7531 
7532         @Override
addWindowToken(IBinder token, int type, int displayId, @Nullable Bundle options)7533         public void addWindowToken(IBinder token, int type, int displayId,
7534                 @Nullable Bundle options) {
7535             WindowManagerService.this.addWindowToken(token, type, displayId, options);
7536         }
7537 
7538         @Override
removeWindowToken(IBinder binder, boolean removeWindows, int displayId)7539         public void removeWindowToken(IBinder binder, boolean removeWindows, int displayId) {
7540             synchronized (mGlobalLock) {
7541                 if (removeWindows) {
7542                     final DisplayContent dc = mRoot.getDisplayContent(displayId);
7543                     if (dc == null) {
7544                         ProtoLog.w(WM_ERROR, "removeWindowToken: Attempted to remove token: %s"
7545                                 + " for non-exiting displayId=%d", binder, displayId);
7546                         return;
7547                     }
7548 
7549                     final WindowToken token = dc.removeWindowToken(binder);
7550                     if (token == null) {
7551                         ProtoLog.w(WM_ERROR,
7552                                 "removeWindowToken: Attempted to remove non-existing token: %s",
7553                                 binder);
7554                         return;
7555                     }
7556 
7557                     token.removeAllWindowsIfPossible();
7558                 }
7559                 WindowManagerService.this.removeWindowToken(binder, displayId);
7560             }
7561         }
7562 
7563         @Override
moveWindowTokenToDisplay(IBinder binder, int displayId)7564         public void moveWindowTokenToDisplay(IBinder binder, int displayId) {
7565             WindowManagerService.this.moveWindowTokenToDisplay(binder, displayId);
7566         }
7567 
7568         // TODO(multi-display): currently only used by PWM to notify keyguard transitions as well
7569         // forwarding it to SystemUI for synchronizing status and navigation bar animations.
7570         @Override
registerAppTransitionListener(AppTransitionListener listener)7571         public void registerAppTransitionListener(AppTransitionListener listener) {
7572             synchronized (mGlobalLock) {
7573                 getDefaultDisplayContentLocked().mAppTransition.registerListenerLocked(listener);
7574             }
7575         }
7576 
7577         @Override
registerKeyguardExitAnimationStartListener( KeyguardExitAnimationStartListener listener)7578         public void registerKeyguardExitAnimationStartListener(
7579                 KeyguardExitAnimationStartListener listener) {
7580             synchronized (mGlobalLock) {
7581                 getDefaultDisplayContentLocked().mAppTransition
7582                         .registerKeygaurdExitAnimationStartListener(listener);
7583             }
7584         }
7585 
7586         @Override
reportPasswordChanged(int userId)7587         public void reportPasswordChanged(int userId) {
7588             mKeyguardDisableHandler.updateKeyguardEnabled(userId);
7589         }
7590 
7591         @Override
getInputMethodWindowVisibleHeight(int displayId)7592         public int getInputMethodWindowVisibleHeight(int displayId) {
7593             synchronized (mGlobalLock) {
7594                 final DisplayContent dc = mRoot.getDisplayContent(displayId);
7595                 return dc.getInputMethodWindowVisibleHeight();
7596             }
7597         }
7598 
7599         @Override
setDismissImeOnBackKeyPressed(boolean dismissImeOnBackKeyPressed)7600         public void setDismissImeOnBackKeyPressed(boolean dismissImeOnBackKeyPressed) {
7601             mPolicy.setDismissImeOnBackKeyPressed(dismissImeOnBackKeyPressed);
7602         }
7603 
7604         @Override
updateInputMethodTargetWindow(@onNull IBinder imeToken, @NonNull IBinder imeTargetWindowToken)7605         public void updateInputMethodTargetWindow(@NonNull IBinder imeToken,
7606                 @NonNull IBinder imeTargetWindowToken) {
7607             // TODO (b/34628091): Use this method to address the window animation issue.
7608             if (DEBUG_INPUT_METHOD) {
7609                 Slog.w(TAG_WM, "updateInputMethodTargetWindow: imeToken=" + imeToken
7610                         + " imeTargetWindowToken=" + imeTargetWindowToken);
7611             }
7612             synchronized (mGlobalLock) {
7613                 final WindowState imeTarget = mWindowMap.get(imeTargetWindowToken);
7614                 if (imeTarget != null) {
7615                     imeTarget.getDisplayContent().updateImeInputAndControlTarget(imeTarget);
7616                 }
7617             }
7618         }
7619 
7620         @Override
isHardKeyboardAvailable()7621         public boolean isHardKeyboardAvailable() {
7622             synchronized (mGlobalLock) {
7623                 return mHardKeyboardAvailable;
7624             }
7625         }
7626 
7627         @Override
setOnHardKeyboardStatusChangeListener( OnHardKeyboardStatusChangeListener listener)7628         public void setOnHardKeyboardStatusChangeListener(
7629                 OnHardKeyboardStatusChangeListener listener) {
7630             synchronized (mGlobalLock) {
7631                 mHardKeyboardStatusChangeListener = listener;
7632             }
7633         }
7634 
7635         @Override
computeWindowsForAccessibility(int displayId)7636         public void computeWindowsForAccessibility(int displayId) {
7637             final AccessibilityController accessibilityController;
7638             synchronized (mGlobalLock) {
7639                 accessibilityController = mAccessibilityController;
7640             }
7641             if (accessibilityController != null) {
7642                 accessibilityController.performComputeChangedWindowsNot(displayId, true);
7643             }
7644         }
7645 
7646         @Override
setVr2dDisplayId(int vr2dDisplayId)7647         public void setVr2dDisplayId(int vr2dDisplayId) {
7648             if (DEBUG_DISPLAY) {
7649                 Slog.d(TAG, "setVr2dDisplayId called for: " + vr2dDisplayId);
7650             }
7651             synchronized (mGlobalLock) {
7652                 mVr2dDisplayId = vr2dDisplayId;
7653             }
7654         }
7655 
7656         @Override
registerDragDropControllerCallback(IDragDropCallback callback)7657         public void registerDragDropControllerCallback(IDragDropCallback callback) {
7658             mDragDropController.registerCallback(callback);
7659         }
7660 
7661         @Override
lockNow()7662         public void lockNow() {
7663             WindowManagerService.this.lockNow(null);
7664         }
7665 
7666         @Override
getWindowOwnerUserId(IBinder token)7667         public int getWindowOwnerUserId(IBinder token) {
7668             synchronized (mGlobalLock) {
7669                 WindowState window = mWindowMap.get(token);
7670                 if (window != null) {
7671                     return window.mShowUserId;
7672                 }
7673                 return UserHandle.USER_NULL;
7674             }
7675         }
7676 
7677         @Override
isUidFocused(int uid)7678         public boolean isUidFocused(int uid) {
7679             synchronized (mGlobalLock) {
7680                 for (int i = mRoot.getChildCount() - 1; i >= 0; i--) {
7681                     final DisplayContent displayContent = mRoot.getChildAt(i);
7682                     if (displayContent.mCurrentFocus != null
7683                             && uid == displayContent.mCurrentFocus.getOwningUid()) {
7684                         return true;
7685                     }
7686                 }
7687                 return false;
7688             }
7689         }
7690 
7691         @Override
isInputMethodClientFocus(int uid, int pid, int displayId)7692         public boolean isInputMethodClientFocus(int uid, int pid, int displayId) {
7693             if (displayId == Display.INVALID_DISPLAY) {
7694                 return false;
7695             }
7696             synchronized (mGlobalLock) {
7697                 final DisplayContent displayContent = mRoot.getTopFocusedDisplayContent();
7698                 if (displayContent == null
7699                         || displayContent.getDisplayId() != displayId
7700                         || !displayContent.hasAccess(uid)) {
7701                     return false;
7702                 }
7703                 if (displayContent.isInputMethodClientFocus(uid, pid)) {
7704                     return true;
7705                 }
7706                 // Okay, how about this...  what is the current focus?
7707                 // It seems in some cases we may not have moved the IM
7708                 // target window, such as when it was in a pop-up window,
7709                 // so let's also look at the current focus.  (An example:
7710                 // go to Gmail, start searching so the keyboard goes up,
7711                 // press home.  Sometimes the IME won't go down.)
7712                 // Would be nice to fix this more correctly, but it's
7713                 // way at the end of a release, and this should be good enough.
7714                 final WindowState currentFocus = displayContent.mCurrentFocus;
7715                 if (currentFocus != null && currentFocus.mSession.mUid == uid
7716                         && currentFocus.mSession.mPid == pid) {
7717                     return true;
7718                 }
7719             }
7720             return false;
7721         }
7722 
7723         @Override
showImePostLayout(IBinder imeTargetWindowToken)7724         public void showImePostLayout(IBinder imeTargetWindowToken) {
7725             synchronized (mGlobalLock) {
7726                 WindowState imeTarget = mWindowMap.get(imeTargetWindowToken);
7727                 if (imeTarget == null) {
7728                     return;
7729                 }
7730                 Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "WMS.showImePostLayout", 0);
7731                 final InsetsControlTarget controlTarget = imeTarget.getImeControlTarget();
7732                 imeTarget = controlTarget.getWindow();
7733                 // If InsetsControlTarget doesn't have a window, its using remoteControlTarget which
7734                 // is controlled by default display
7735                 final DisplayContent dc = imeTarget != null
7736                         ? imeTarget.getDisplayContent() : getDefaultDisplayContentLocked();
7737                 dc.getInsetsStateController().getImeSourceProvider()
7738                         .scheduleShowImePostLayout(controlTarget);
7739             }
7740         }
7741 
7742         @Override
hideIme(IBinder imeTargetWindowToken, int displayId)7743         public void hideIme(IBinder imeTargetWindowToken, int displayId) {
7744             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WMS.hideIme");
7745             synchronized (mGlobalLock) {
7746                 WindowState imeTarget = mWindowMap.get(imeTargetWindowToken);
7747                 ProtoLog.d(WM_DEBUG_IME, "hideIme target: %s ", imeTarget);
7748                 DisplayContent dc = mRoot.getDisplayContent(displayId);
7749                 if (imeTarget != null) {
7750                     imeTarget = imeTarget.getImeControlTarget().getWindow();
7751                     if (imeTarget != null) {
7752                         dc = imeTarget.getDisplayContent();
7753                     }
7754                     // If there was a pending IME show(), reset it as IME has been
7755                     // requested to be hidden.
7756                     dc.getInsetsStateController().getImeSourceProvider().abortShowImePostLayout();
7757                 }
7758                 if (dc != null && dc.getImeTarget(IME_TARGET_CONTROL) != null) {
7759                     ProtoLog.d(WM_DEBUG_IME, "hideIme Control target: %s ",
7760                             dc.getImeTarget(IME_TARGET_CONTROL));
7761                     dc.getImeTarget(IME_TARGET_CONTROL).hideInsets(
7762                             WindowInsets.Type.ime(), true /* fromIme */);
7763                 }
7764                 if (dc != null) {
7765                     dc.getInsetsStateController().getImeSourceProvider().setImeShowing(false);
7766                 }
7767             }
7768             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
7769         }
7770 
7771         @Override
isUidAllowedOnDisplay(int displayId, int uid)7772         public boolean isUidAllowedOnDisplay(int displayId, int uid) {
7773             if (displayId == Display.DEFAULT_DISPLAY) {
7774                 return true;
7775             }
7776             if (displayId == Display.INVALID_DISPLAY) {
7777                 return false;
7778             }
7779             synchronized (mGlobalLock) {
7780                 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
7781                 return displayContent != null && displayContent.hasAccess(uid);
7782             }
7783         }
7784 
7785         @Override
getDisplayIdForWindow(IBinder windowToken)7786         public int getDisplayIdForWindow(IBinder windowToken) {
7787             synchronized (mGlobalLock) {
7788                 final WindowState window = mWindowMap.get(windowToken);
7789                 if (window != null) {
7790                     return window.getDisplayContent().getDisplayId();
7791                 }
7792                 return Display.INVALID_DISPLAY;
7793             }
7794         }
7795 
7796         @Override
getTopFocusedDisplayId()7797         public int getTopFocusedDisplayId() {
7798             synchronized (mGlobalLock) {
7799                 return mRoot.getTopFocusedDisplayContent().getDisplayId();
7800             }
7801         }
7802 
7803         @Override
getTopFocusedDisplayUiContext()7804         public Context getTopFocusedDisplayUiContext() {
7805             synchronized (mGlobalLock) {
7806                 return mRoot.getTopFocusedDisplayContent().getDisplayUiContext();
7807             }
7808         }
7809 
7810         @Override
shouldShowSystemDecorOnDisplay(int displayId)7811         public boolean shouldShowSystemDecorOnDisplay(int displayId) {
7812             synchronized (mGlobalLock) {
7813                 return WindowManagerService.this.shouldShowSystemDecors(displayId);
7814             }
7815         }
7816 
7817         @Override
getDisplayImePolicy(int displayId)7818         public @DisplayImePolicy int getDisplayImePolicy(int displayId) {
7819             synchronized (mGlobalLock) {
7820                 return WindowManagerService.this.getDisplayImePolicy(displayId);
7821             }
7822         }
7823 
7824         @Override
addNonHighRefreshRatePackage(@onNull String packageName)7825         public void addNonHighRefreshRatePackage(@NonNull String packageName) {
7826             synchronized (mGlobalLock) {
7827                 mRoot.forAllDisplays(dc -> dc.getDisplayPolicy().getRefreshRatePolicy()
7828                         .addNonHighRefreshRatePackage(packageName));
7829             }
7830         }
7831 
7832         @Override
removeNonHighRefreshRatePackage(@onNull String packageName)7833         public void removeNonHighRefreshRatePackage(@NonNull String packageName) {
7834             synchronized (mGlobalLock) {
7835                 mRoot.forAllDisplays(dc -> dc.getDisplayPolicy().getRefreshRatePolicy()
7836                         .removeNonHighRefreshRatePackage(packageName));
7837             }
7838         }
7839 
7840         @Override
isTouchOrFaketouchDevice()7841         public boolean isTouchOrFaketouchDevice() {
7842             synchronized (mGlobalLock) {
7843                 // All touchable devices are also faketouchable.
7844                 return mIsFakeTouchDevice;
7845             }
7846         }
7847 
7848         @Override
getKeyInterceptionInfoFromToken(IBinder inputToken)7849         public @Nullable KeyInterceptionInfo getKeyInterceptionInfoFromToken(IBinder inputToken) {
7850             return mKeyInterceptionInfoForToken.get(inputToken);
7851         }
7852 
7853         @Override
setAccessibilityIdToSurfaceMetadata( IBinder windowToken, int accessibilityWindowId)7854         public void setAccessibilityIdToSurfaceMetadata(
7855                 IBinder windowToken, int accessibilityWindowId) {
7856             synchronized (mGlobalLock) {
7857                 final WindowState state = mWindowMap.get(windowToken);
7858                 if (state == null) {
7859                     Slog.w(TAG, "Cannot find window which accessibility connection is added to");
7860                     return;
7861                 }
7862                 mTransaction.setMetadata(state.mSurfaceControl,
7863                         SurfaceControl.METADATA_ACCESSIBILITY_ID, accessibilityWindowId).apply();
7864             }
7865         }
7866 
7867         @Override
getWindowName(@onNull IBinder binder)7868         public String getWindowName(@NonNull IBinder binder) {
7869             synchronized (mGlobalLock) {
7870                 final WindowState w = mWindowMap.get(binder);
7871                 return w != null ? w.getName() : null;
7872             }
7873         }
7874 
7875         @Override
getImeControlTargetNameForLogging(int displayId)7876         public String getImeControlTargetNameForLogging(int displayId) {
7877             synchronized (mGlobalLock) {
7878                 final DisplayContent dc = mRoot.getDisplayContent(displayId);
7879                 if (dc == null) {
7880                     return null;
7881                 }
7882                 final InsetsControlTarget target = dc.getImeTarget(IME_TARGET_CONTROL);
7883                 if (target == null) {
7884                     return null;
7885                 }
7886                 final WindowState win = target.getWindow();
7887                 return win != null ? win.getName() : target.toString();
7888             }
7889         }
7890 
7891         @Override
getImeTargetNameForLogging(int displayId)7892         public String getImeTargetNameForLogging(int displayId) {
7893             synchronized (mGlobalLock) {
7894                 final DisplayContent dc = mRoot.getDisplayContent(displayId);
7895                 if (dc == null || dc.getImeTarget(IME_TARGET_LAYERING) == null) {
7896                     return null;
7897                 }
7898                 return dc.getImeTarget(IME_TARGET_LAYERING).getWindow().getName();
7899             }
7900         }
7901 
7902         @Override
shouldRestoreImeVisibility(IBinder imeTargetWindowToken)7903         public boolean shouldRestoreImeVisibility(IBinder imeTargetWindowToken) {
7904             return WindowManagerService.this.shouldRestoreImeVisibility(imeTargetWindowToken);
7905         }
7906     }
7907 
registerAppFreezeListener(AppFreezeListener listener)7908     void registerAppFreezeListener(AppFreezeListener listener) {
7909         if (!mAppFreezeListeners.contains(listener)) {
7910             mAppFreezeListeners.add(listener);
7911         }
7912     }
7913 
unregisterAppFreezeListener(AppFreezeListener listener)7914     void unregisterAppFreezeListener(AppFreezeListener listener) {
7915         mAppFreezeListeners.remove(listener);
7916     }
7917 
7918     /**
7919      * WARNING: This interrupts surface updates, be careful! Don't
7920      * execute within the transaction for longer than you would
7921      * execute on an animation thread.
7922      * WARNING: This method contains locks known to the State of California
7923      * to cause Deadlocks and other conditions.
7924      *
7925      * Begins a surface transaction with which the AM can batch operations.
7926      * All Surface updates performed by the WindowManager following this
7927      * will not appear on screen until after the call to
7928      * closeSurfaceTransaction.
7929      *
7930      * ActivityManager can use this to ensure multiple 'commands' will all
7931      * be reflected in a single frame. For example when reparenting a window
7932      * which was previously hidden due to it's parent properties, we may
7933      * need to ensure it is hidden in the same frame that the properties
7934      * from the new parent are inherited, otherwise it could be revealed
7935      * mistakenly.
7936      *
7937      * TODO(b/36393204): We can investigate totally replacing #deferSurfaceLayout
7938      * with something like this but it seems that some existing cases of
7939      * deferSurfaceLayout may be a little too broad, in particular the total
7940      * enclosure of startActivityUnchecked which could run for quite some time.
7941      */
inSurfaceTransaction(Runnable exec)7942     void inSurfaceTransaction(Runnable exec) {
7943         SurfaceControl.openTransaction();
7944         try {
7945             exec.run();
7946         } finally {
7947             SurfaceControl.closeTransaction();
7948         }
7949     }
7950 
7951     /** Called to inform window manager if non-Vr UI shoul be disabled or not. */
disableNonVrUi(boolean disable)7952     public void disableNonVrUi(boolean disable) {
7953         synchronized (mGlobalLock) {
7954             // Allow alert window notifications to be shown if non-vr UI is enabled.
7955             final boolean showAlertWindowNotifications = !disable;
7956             if (showAlertWindowNotifications == mShowAlertWindowNotifications) {
7957                 return;
7958             }
7959             mShowAlertWindowNotifications = showAlertWindowNotifications;
7960 
7961             for (int i = mSessions.size() - 1; i >= 0; --i) {
7962                 final Session s = mSessions.valueAt(i);
7963                 s.setShowingAlertWindowNotificationAllowed(mShowAlertWindowNotifications);
7964             }
7965         }
7966     }
7967 
hasWideColorGamutSupport()7968     boolean hasWideColorGamutSupport() {
7969         return mHasWideColorGamutSupport &&
7970                 SystemProperties.getInt("persist.sys.sf.native_mode", 0) != 1;
7971     }
7972 
hasHdrSupport()7973     boolean hasHdrSupport() {
7974         return mHasHdrSupport && hasWideColorGamutSupport();
7975     }
7976 
updateNonSystemOverlayWindowsVisibilityIfNeeded(WindowState win, boolean surfaceShown)7977     void updateNonSystemOverlayWindowsVisibilityIfNeeded(WindowState win, boolean surfaceShown) {
7978         if (!win.hideNonSystemOverlayWindowsWhenVisible()
7979                 && !mHidingNonSystemOverlayWindows.contains(win)) {
7980             return;
7981         }
7982         final boolean systemAlertWindowsHidden = !mHidingNonSystemOverlayWindows.isEmpty();
7983         if (surfaceShown && win.hideNonSystemOverlayWindowsWhenVisible()) {
7984             if (!mHidingNonSystemOverlayWindows.contains(win)) {
7985                 mHidingNonSystemOverlayWindows.add(win);
7986             }
7987         } else {
7988             mHidingNonSystemOverlayWindows.remove(win);
7989         }
7990 
7991         final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty();
7992 
7993         if (systemAlertWindowsHidden == hideSystemAlertWindows) {
7994             return;
7995         }
7996 
7997         mRoot.forAllWindows((w) -> {
7998             w.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);
7999         }, false /* traverseTopToBottom */);
8000     }
8001 
8002     /** Called from Accessibility Controller to apply magnification spec */
applyMagnificationSpecLocked(int displayId, MagnificationSpec spec)8003     public void applyMagnificationSpecLocked(int displayId, MagnificationSpec spec) {
8004         final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
8005         if (displayContent != null) {
8006             displayContent.applyMagnificationSpec(spec);
8007         }
8008     }
8009 
makeSurfaceBuilder(SurfaceSession s)8010     SurfaceControl.Builder makeSurfaceBuilder(SurfaceSession s) {
8011         return mSurfaceControlFactory.apply(s);
8012     }
8013 
8014     /**
8015      * Called when the state of lock task mode changes. This should be used to disable immersive
8016      * mode confirmation.
8017      *
8018      * @param lockTaskState the new lock task mode state. One of
8019      *                      {@link ActivityManager#LOCK_TASK_MODE_NONE},
8020      *                      {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
8021      *                      {@link ActivityManager#LOCK_TASK_MODE_PINNED}.
8022      */
onLockTaskStateChanged(int lockTaskState)8023     void onLockTaskStateChanged(int lockTaskState) {
8024         // TODO: pass in displayId to determine which display the lock task state changed
8025         synchronized (mGlobalLock) {
8026             final PooledConsumer c = PooledLambda.obtainConsumer(
8027                     DisplayPolicy::onLockTaskStateChangedLw, PooledLambda.__(), lockTaskState);
8028             mRoot.forAllDisplayPolicies(c);
8029             c.recycle();
8030         }
8031     }
8032 
8033     @Override
injectInputAfterTransactionsApplied(InputEvent ev, int mode, boolean waitForAnimations)8034     public boolean injectInputAfterTransactionsApplied(InputEvent ev, int mode,
8035             boolean waitForAnimations) {
8036         boolean isDown;
8037         boolean isUp;
8038 
8039         if (ev instanceof KeyEvent) {
8040             KeyEvent keyEvent = (KeyEvent) ev;
8041             isDown = keyEvent.getAction() == KeyEvent.ACTION_DOWN;
8042             isUp = keyEvent.getAction() == KeyEvent.ACTION_UP;
8043         } else {
8044             MotionEvent motionEvent = (MotionEvent) ev;
8045             isDown = motionEvent.getAction() == MotionEvent.ACTION_DOWN;
8046             isUp = motionEvent.getAction() == MotionEvent.ACTION_UP;
8047         }
8048         final boolean isMouseEvent = ev.getSource() == InputDevice.SOURCE_MOUSE;
8049 
8050         // For ACTION_DOWN, syncInputTransactions before injecting input.
8051         // For all mouse events, also sync before injecting.
8052         // For ACTION_UP, sync after injecting.
8053         if (isDown || isMouseEvent) {
8054             syncInputTransactions(waitForAnimations);
8055         }
8056         final boolean result =
8057                 LocalServices.getService(InputManagerInternal.class).injectInputEvent(ev, mode);
8058         if (isUp) {
8059             syncInputTransactions(waitForAnimations);
8060         }
8061         return result;
8062     }
8063 
8064     @Override
syncInputTransactions(boolean waitForAnimations)8065     public void syncInputTransactions(boolean waitForAnimations) {
8066         final long token = Binder.clearCallingIdentity();
8067         try {
8068             if (waitForAnimations) {
8069                 waitForAnimationsToComplete();
8070             }
8071 
8072             // Collect all input transactions from all displays to make sure we could sync all input
8073             // windows at same time.
8074             final SurfaceControl.Transaction t = mTransactionFactory.get();
8075             synchronized (mGlobalLock) {
8076                 mWindowPlacerLocked.performSurfacePlacementIfScheduled();
8077                 mRoot.forAllDisplays(displayContent ->
8078                         displayContent.getInputMonitor().updateInputWindowsImmediately(t));
8079             }
8080 
8081             t.syncInputWindows().apply();
8082         } finally {
8083             Binder.restoreCallingIdentity(token);
8084         }
8085     }
8086 
8087     /**
8088      * Wait until all container animations and surface operations behalf of WindowManagerService
8089      * complete.
8090      */
waitForAnimationsToComplete()8091     private void waitForAnimationsToComplete() {
8092         synchronized (mGlobalLock) {
8093             long timeoutRemaining = ANIMATION_COMPLETED_TIMEOUT_MS;
8094             // This could prevent if there is no container animation, we still have to apply the
8095             // pending transaction and exit waiting.
8096             mAnimator.mNotifyWhenNoAnimation = true;
8097             while (timeoutRemaining > 0) {
8098                 boolean isAnimating = mAnimator.isAnimationScheduled()
8099                         || mRoot.isAnimating(TRANSITION | CHILDREN, ANIMATION_TYPE_ALL);
8100                 if (!isAnimating) {
8101                     break;
8102                 }
8103                 long startTime = System.currentTimeMillis();
8104                 try {
8105                     mGlobalLock.wait(timeoutRemaining);
8106                 } catch (InterruptedException e) {
8107                 }
8108                 timeoutRemaining -= (System.currentTimeMillis() - startTime);
8109             }
8110             mAnimator.mNotifyWhenNoAnimation = false;
8111 
8112             WindowContainer animatingContainer;
8113             animatingContainer = mRoot.getAnimatingContainer(TRANSITION | CHILDREN,
8114                     ANIMATION_TYPE_ALL);
8115             if (mAnimator.isAnimationScheduled() || animatingContainer != null) {
8116                 Slog.w(TAG, "Timed out waiting for animations to complete,"
8117                         + " animatingContainer=" + animatingContainer
8118                         + " animationType=" + SurfaceAnimator.animationTypeToString(
8119                         animatingContainer != null
8120                                 ? animatingContainer.mSurfaceAnimator.getAnimationType()
8121                                 : SurfaceAnimator.ANIMATION_TYPE_NONE));
8122             }
8123         }
8124     }
8125 
onAnimationFinished()8126     void onAnimationFinished() {
8127         synchronized (mGlobalLock) {
8128             mGlobalLock.notifyAll();
8129         }
8130     }
8131 
onPointerDownOutsideFocusLocked(IBinder touchedToken)8132     private void onPointerDownOutsideFocusLocked(IBinder touchedToken) {
8133         WindowState touchedWindow = mInputToWindowMap.get(touchedToken);
8134         if (touchedWindow == null) {
8135             // if a user taps outside the currently focused window onto an embedded window, treat
8136             // it as if the host window was tapped.
8137             touchedWindow = mEmbeddedWindowController.getHostWindow(touchedToken);
8138         }
8139 
8140         if (touchedWindow == null || !touchedWindow.canReceiveKeys(true /* fromUserTouch */)) {
8141             // If the window that received the input event cannot receive keys, don't move the
8142             // display it's on to the top since that window won't be able to get focus anyway.
8143             return;
8144         }
8145 
8146         if (mRecentsAnimationController != null
8147                 && mRecentsAnimationController.getTargetAppMainWindow() == touchedWindow) {
8148             // If there is an active recents animation and touched window is the target, then ignore
8149             // the touch. The target already handles touches using its own input monitor and we
8150             // don't want to trigger any lifecycle changes from focusing another window.
8151             // TODO(b/186770026): We should remove this once we support multiple resumed activities
8152             //                    while in overview
8153             return;
8154         }
8155 
8156         ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "onPointerDownOutsideFocusLocked called on %s",
8157                 touchedWindow);
8158         final DisplayContent displayContent = touchedWindow.getDisplayContent();
8159         if (!displayContent.isOnTop()) {
8160             displayContent.getParent().positionChildAt(WindowContainer.POSITION_TOP, displayContent,
8161                     true /* includingParents */);
8162         }
8163         handleTaskFocusChange(touchedWindow.getTask());
8164     }
8165 
8166     @VisibleForTesting
handleTaskFocusChange(Task task)8167     void handleTaskFocusChange(Task task) {
8168         if (task == null) {
8169             return;
8170         }
8171 
8172         // We ignore root home task since we don't want root home task to move to front when
8173         // touched. Specifically, in freeform we don't want tapping on home to cause the freeform
8174         // apps to go behind home. See b/117376413
8175         if (task.isActivityTypeHome()) {
8176             // Only ignore root home task if the requested focus home Task is in the same
8177             // TaskDisplayArea as the current focus Task.
8178             TaskDisplayArea homeTda = task.getDisplayArea();
8179             WindowState curFocusedWindow = getFocusedWindow();
8180             if (curFocusedWindow != null && homeTda != null
8181                     && curFocusedWindow.isDescendantOf(homeTda)) {
8182                 return;
8183             }
8184         }
8185 
8186         mAtmService.setFocusedTask(task.mTaskId);
8187     }
8188 
8189     /**
8190      * Assigns an InputChannel to a SurfaceControl and configures it to receive
8191      * touch input according to it's on-screen geometry.
8192      *
8193      * Used by WindowlessWindowManager to enable input on SurfaceControl embedded
8194      * views.
8195      */
grantInputChannel(Session session, int callingUid, int callingPid, int displayId, SurfaceControl surface, IWindow window, IBinder hostInputToken, int flags, int privateFlags, int type, InputChannel outInputChannel)8196     void grantInputChannel(Session session, int callingUid, int callingPid, int displayId,
8197                            SurfaceControl surface, IWindow window, IBinder hostInputToken,
8198                            int flags, int privateFlags, int type, InputChannel outInputChannel) {
8199         final InputApplicationHandle applicationHandle;
8200         final String name;
8201         final InputChannel clientChannel;
8202         synchronized (mGlobalLock) {
8203             EmbeddedWindowController.EmbeddedWindow win =
8204                     new EmbeddedWindowController.EmbeddedWindow(session, this, window,
8205                             mInputToWindowMap.get(hostInputToken), callingUid, callingPid, type,
8206                             displayId);
8207             clientChannel = win.openInputChannel();
8208             mEmbeddedWindowController.add(clientChannel.getToken(), win);
8209             applicationHandle = win.getApplicationHandle();
8210             name = win.getName();
8211         }
8212 
8213         updateInputChannel(clientChannel.getToken(), callingUid, callingPid, displayId, surface,
8214                 name, applicationHandle, flags, privateFlags, type, null /* region */);
8215 
8216         clientChannel.copyTo(outInputChannel);
8217     }
8218 
updateInputChannel(IBinder channelToken, int callingUid, int callingPid, int displayId, SurfaceControl surface, String name, InputApplicationHandle applicationHandle, int flags, int privateFlags, int type, Region region)8219     private void updateInputChannel(IBinder channelToken, int callingUid, int callingPid,
8220                                     int displayId, SurfaceControl surface, String name,
8221                                     InputApplicationHandle applicationHandle, int flags,
8222                                     int privateFlags, int type, Region region) {
8223         InputWindowHandle h = new InputWindowHandle(applicationHandle, displayId);
8224         h.token = channelToken;
8225         h.name = name;
8226 
8227         final int sanitizedFlags = flags & (LayoutParams.FLAG_NOT_TOUCHABLE
8228                 | LayoutParams.FLAG_SLIPPERY | LayoutParams.FLAG_NOT_FOCUSABLE);
8229         h.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | sanitizedFlags;
8230         h.layoutParamsType = type;
8231         h.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
8232         h.focusable = (flags & LayoutParams.FLAG_NOT_FOCUSABLE) == 0;
8233         h.hasWallpaper = false;
8234         h.paused = false;
8235 
8236         h.ownerUid = callingUid;
8237         h.ownerPid = callingPid;
8238 
8239         h.inputFeatures = 0;
8240 
8241         if (region == null) {
8242             h.replaceTouchableRegionWithCrop(null);
8243         } else {
8244             h.touchableRegion.set(region);
8245             h.replaceTouchableRegionWithCrop = false;
8246             h.setTouchableRegionCrop(surface);
8247         }
8248 
8249         //  Check private trusted overlay flag to set trustedOverlay field of input window handle.
8250         h.trustedOverlay = (privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0;
8251 
8252         SurfaceControl.Transaction t = mTransactionFactory.get();
8253         t.setInputWindowInfo(surface, h);
8254         t.apply();
8255         t.close();
8256         surface.release();
8257     }
8258 
8259     /**
8260      * Updates the flags on an existing surface's input channel. This assumes the surface provided
8261      * is the one associated with the provided input-channel. If this isn't the case, behavior
8262      * is undefined.
8263      */
updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface, int flags, int privateFlags, Region region)8264     void updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface,
8265             int flags, int privateFlags, Region region) {
8266         final InputApplicationHandle applicationHandle;
8267         final String name;
8268         final EmbeddedWindowController.EmbeddedWindow win;
8269         synchronized (mGlobalLock) {
8270             win = mEmbeddedWindowController.get(channelToken);
8271             if (win == null) {
8272                 Slog.e(TAG, "Couldn't find window for provided channelToken.");
8273                 return;
8274             }
8275             name = win.getName();
8276             applicationHandle = win.getApplicationHandle();
8277         }
8278 
8279         updateInputChannel(channelToken, win.mOwnerUid, win.mOwnerPid, displayId, surface, name,
8280                 applicationHandle, flags, privateFlags, win.mWindowType, region);
8281     }
8282 
8283     /** Return whether layer tracing is enabled */
isLayerTracing()8284     public boolean isLayerTracing() {
8285         if (!checkCallingPermission(
8286                 android.Manifest.permission.DUMP, "isLayerTracing()")) {
8287             throw new SecurityException("Requires DUMP permission");
8288         }
8289 
8290         final long token = Binder.clearCallingIdentity();
8291         try {
8292             Parcel data = null;
8293             Parcel reply = null;
8294             try {
8295                 IBinder sf = ServiceManager.getService("SurfaceFlinger");
8296                 if (sf != null) {
8297                     reply = Parcel.obtain();
8298                     data = Parcel.obtain();
8299                     data.writeInterfaceToken("android.ui.ISurfaceComposer");
8300                     sf.transact(/* LAYER_TRACE_STATUS_CODE */ 1026, data, reply, 0 /* flags */);
8301                     return reply.readBoolean();
8302                 }
8303             } catch (RemoteException e) {
8304                 Slog.e(TAG, "Failed to get layer tracing");
8305             } finally {
8306                 if (data != null) {
8307                     data.recycle();
8308                 }
8309                 if (reply != null) {
8310                     reply.recycle();
8311                 }
8312             }
8313         } finally {
8314             Binder.restoreCallingIdentity(token);
8315         }
8316         return false;
8317     }
8318 
8319     /** Enable or disable layer tracing */
setLayerTracing(boolean enabled)8320     public void setLayerTracing(boolean enabled) {
8321         if (!checkCallingPermission(
8322                 android.Manifest.permission.DUMP, "setLayerTracing()")) {
8323             throw new SecurityException("Requires DUMP permission");
8324         }
8325 
8326         final long token = Binder.clearCallingIdentity();
8327         try {
8328             Parcel data = null;
8329             try {
8330                 IBinder sf = ServiceManager.getService("SurfaceFlinger");
8331                 if (sf != null) {
8332                     data = Parcel.obtain();
8333                     data.writeInterfaceToken("android.ui.ISurfaceComposer");
8334                     data.writeInt(enabled ? 1 : 0);
8335                     sf.transact(/* LAYER_TRACE_CONTROL_CODE */ 1025, data, null, 0 /* flags */);
8336                 }
8337             } catch (RemoteException e) {
8338                 Slog.e(TAG, "Failed to set layer tracing");
8339             } finally {
8340                 if (data != null) {
8341                     data.recycle();
8342                 }
8343             }
8344         } finally {
8345             Binder.restoreCallingIdentity(token);
8346         }
8347     }
8348 
8349     /** Set layer tracing flags. */
setLayerTracingFlags(int flags)8350     public void setLayerTracingFlags(int flags) {
8351         if (!checkCallingPermission(
8352                 android.Manifest.permission.DUMP, "setLayerTracingFlags")) {
8353             throw new SecurityException("Requires DUMP permission");
8354         }
8355 
8356         final long token = Binder.clearCallingIdentity();
8357         try {
8358             Parcel data = null;
8359             try {
8360                 IBinder sf = ServiceManager.getService("SurfaceFlinger");
8361                 if (sf != null) {
8362                     data = Parcel.obtain();
8363                     data.writeInterfaceToken("android.ui.ISurfaceComposer");
8364                     data.writeInt(flags);
8365                     sf.transact(1033 /* LAYER_TRACE_FLAGS_CODE */, data, null, 0 /* flags */);
8366                 }
8367             } catch (RemoteException e) {
8368                 Slog.e(TAG, "Failed to set layer tracing flags");
8369             } finally {
8370                 if (data != null) {
8371                     data.recycle();
8372                 }
8373             }
8374         } finally {
8375             Binder.restoreCallingIdentity(token);
8376         }
8377     }
8378 
8379     @Override
mirrorDisplay(int displayId, SurfaceControl outSurfaceControl)8380     public boolean mirrorDisplay(int displayId, SurfaceControl outSurfaceControl) {
8381         if (!checkCallingPermission(READ_FRAME_BUFFER, "mirrorDisplay()")) {
8382             throw new SecurityException("Requires READ_FRAME_BUFFER permission");
8383         }
8384 
8385         final SurfaceControl displaySc;
8386         synchronized (mGlobalLock) {
8387             DisplayContent displayContent = mRoot.getDisplayContent(displayId);
8388             if (displayContent == null) {
8389                 Slog.e(TAG, "Invalid displayId " + displayId + " for mirrorDisplay");
8390                 return false;
8391             }
8392 
8393             displaySc = displayContent.getWindowingLayer();
8394         }
8395 
8396         final SurfaceControl mirror = SurfaceControl.mirrorSurface(displaySc);
8397         outSurfaceControl.copyFrom(mirror, "WMS.mirrorDisplay");
8398 
8399         return true;
8400     }
8401 
8402     @Override
getWindowInsets(WindowManager.LayoutParams attrs, int displayId, InsetsState outInsetsState)8403     public boolean getWindowInsets(WindowManager.LayoutParams attrs, int displayId,
8404             InsetsState outInsetsState) {
8405         final boolean fromLocal = Binder.getCallingPid() == myPid();
8406         final long origId = Binder.clearCallingIdentity();
8407         try {
8408             synchronized (mGlobalLock) {
8409                 final DisplayContent dc = getDisplayContentOrCreate(displayId, attrs.token);
8410                 if (dc == null) {
8411                     throw new WindowManager.InvalidDisplayException("Display#" + displayId
8412                             + "could not be found!");
8413                 }
8414                 final WindowToken windowToken = dc.getWindowToken(attrs.token);
8415                 return dc.getDisplayPolicy().getLayoutHint(attrs, windowToken, outInsetsState,
8416                         fromLocal);
8417             }
8418         } finally {
8419             Binder.restoreCallingIdentity(origId);
8420         }
8421     }
8422 
grantEmbeddedWindowFocus(Session session, IBinder inputToken, boolean grantFocus)8423     void grantEmbeddedWindowFocus(Session session, IBinder inputToken, boolean grantFocus) {
8424         synchronized (mGlobalLock) {
8425             final EmbeddedWindowController.EmbeddedWindow embeddedWindow =
8426                     mEmbeddedWindowController.get(inputToken);
8427             if (embeddedWindow == null) {
8428                 Slog.e(TAG, "Embedded window not found");
8429                 return;
8430             }
8431             if (embeddedWindow.mSession != session) {
8432                 Slog.e(TAG, "Window not in session:" + session);
8433                 return;
8434             }
8435             SurfaceControl.Transaction t = mTransactionFactory.get();
8436             final int displayId = embeddedWindow.mDisplayId;
8437             if (grantFocus) {
8438                 t.setFocusedWindow(inputToken, embeddedWindow.getName(), displayId).apply();
8439                 EventLog.writeEvent(LOGTAG_INPUT_FOCUS,
8440                         "Focus request " + embeddedWindow.getName(),
8441                         "reason=grantEmbeddedWindowFocus(true)");
8442             } else {
8443                 // Search for a new focus target
8444                 DisplayContent displayContent = mRoot.getDisplayContent(displayId);
8445                 WindowState newFocusTarget =  displayContent == null
8446                         ? null : displayContent.findFocusedWindow();
8447                 if (newFocusTarget == null) {
8448                     ProtoLog.v(WM_DEBUG_FOCUS, "grantEmbeddedWindowFocus remove request for "
8449                                     + "win=%s dropped since no candidate was found",
8450                             embeddedWindow.getName());
8451                     return;
8452                 }
8453                 t.requestFocusTransfer(newFocusTarget.mInputChannelToken, newFocusTarget.getName(),
8454                         inputToken, embeddedWindow.getName(),
8455                         displayId).apply();
8456                 EventLog.writeEvent(LOGTAG_INPUT_FOCUS,
8457                         "Transfer focus request " + newFocusTarget,
8458                         "reason=grantEmbeddedWindowFocus(false)");
8459             }
8460             ProtoLog.v(WM_DEBUG_FOCUS, "grantEmbeddedWindowFocus win=%s grantFocus=%s",
8461                     embeddedWindow.getName(), grantFocus);
8462         }
8463     }
8464 
grantEmbeddedWindowFocus(Session session, IWindow callingWindow, IBinder targetInputToken, boolean grantFocus)8465     void grantEmbeddedWindowFocus(Session session, IWindow callingWindow, IBinder targetInputToken,
8466                                   boolean grantFocus) {
8467         synchronized (mGlobalLock) {
8468             final WindowState hostWindow =
8469                     windowForClientLocked(session, callingWindow, false /* throwOnError*/);
8470             if (hostWindow == null) {
8471                 Slog.e(TAG, "Host window not found");
8472                 return;
8473             }
8474             if (hostWindow.mInputChannel == null) {
8475                 Slog.e(TAG, "Host window does not have an input channel");
8476                 return;
8477             }
8478             final EmbeddedWindowController.EmbeddedWindow embeddedWindow =
8479                     mEmbeddedWindowController.get(targetInputToken);
8480             if (embeddedWindow == null) {
8481                 Slog.e(TAG, "Embedded window not found");
8482                 return;
8483             }
8484             if (embeddedWindow.mHostWindowState != hostWindow) {
8485                 Slog.e(TAG, "Embedded window does not belong to the host");
8486                 return;
8487             }
8488             SurfaceControl.Transaction t = mTransactionFactory.get();
8489             if (grantFocus) {
8490                 t.requestFocusTransfer(targetInputToken, embeddedWindow.getName(),
8491                         hostWindow.mInputChannel.getToken(),
8492                         hostWindow.getName(),
8493                         hostWindow.getDisplayId()).apply();
8494                 EventLog.writeEvent(LOGTAG_INPUT_FOCUS,
8495                         "Transfer focus request " + embeddedWindow.getName(),
8496                         "reason=grantEmbeddedWindowFocus(true)");
8497             } else {
8498                 t.requestFocusTransfer(hostWindow.mInputChannel.getToken(), hostWindow.getName(),
8499                         targetInputToken,
8500                         embeddedWindow.getName(),
8501                         hostWindow.getDisplayId()).apply();
8502                 EventLog.writeEvent(LOGTAG_INPUT_FOCUS,
8503                         "Transfer focus request " + hostWindow,
8504                         "reason=grantEmbeddedWindowFocus(false)");
8505             }
8506             ProtoLog.v(WM_DEBUG_FOCUS, "grantEmbeddedWindowFocus win=%s grantFocus=%s",
8507                     embeddedWindow.getName(), grantFocus);
8508         }
8509     }
8510 
8511     @Override
holdLock(IBinder token, int durationMs)8512     public void holdLock(IBinder token, int durationMs) {
8513         mTestUtilityService.verifyHoldLockToken(token);
8514 
8515         synchronized (mGlobalLock) {
8516             SystemClock.sleep(durationMs);
8517         }
8518     }
8519 
8520     @Override
getSupportedDisplayHashAlgorithms()8521     public String[] getSupportedDisplayHashAlgorithms() {
8522         return mDisplayHashController.getSupportedHashAlgorithms();
8523     }
8524 
8525     @Override
verifyDisplayHash(DisplayHash displayHash)8526     public VerifiedDisplayHash verifyDisplayHash(DisplayHash displayHash) {
8527         return mDisplayHashController.verifyDisplayHash(displayHash);
8528     }
8529 
8530     @Override
setDisplayHashThrottlingEnabled(boolean enable)8531     public void setDisplayHashThrottlingEnabled(boolean enable) {
8532         if (!checkCallingPermission(READ_FRAME_BUFFER, "setDisplayHashThrottle()")) {
8533             throw new SecurityException("Requires READ_FRAME_BUFFER permission");
8534         }
8535         mDisplayHashController.setDisplayHashThrottlingEnabled(enable);
8536     }
8537 
8538     @Override
isTaskSnapshotSupported()8539     public boolean isTaskSnapshotSupported() {
8540         synchronized (mGlobalLock) {
8541             return !mTaskSnapshotController.shouldDisableSnapshots();
8542         }
8543     }
8544 
generateDisplayHash(Session session, IWindow window, Rect boundsInWindow, String hashAlgorithm, RemoteCallback callback)8545     void generateDisplayHash(Session session, IWindow window, Rect boundsInWindow,
8546             String hashAlgorithm, RemoteCallback callback) {
8547         final SurfaceControl displaySurfaceControl;
8548         final Rect boundsInDisplay = new Rect(boundsInWindow);
8549         synchronized (mGlobalLock) {
8550             final WindowState win = windowForClientLocked(session, window, false);
8551             if (win == null) {
8552                 Slog.w(TAG, "Failed to generate DisplayHash. Invalid window");
8553                 mDisplayHashController.sendDisplayHashError(callback,
8554                         DISPLAY_HASH_ERROR_MISSING_WINDOW);
8555                 return;
8556             }
8557 
8558             if (win.mActivityRecord == null || !win.mActivityRecord.isState(
8559                     Task.ActivityState.RESUMED)) {
8560                 mDisplayHashController.sendDisplayHashError(callback,
8561                         DISPLAY_HASH_ERROR_MISSING_WINDOW);
8562                 return;
8563             }
8564 
8565             DisplayContent displayContent = win.getDisplayContent();
8566             if (displayContent == null) {
8567                 Slog.w(TAG, "Failed to generate DisplayHash. Window is not on a display");
8568                 mDisplayHashController.sendDisplayHashError(callback,
8569                         DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN);
8570                 return;
8571             }
8572 
8573             displaySurfaceControl = displayContent.getSurfaceControl();
8574             mDisplayHashController.calculateDisplayHashBoundsLocked(win, boundsInWindow,
8575                     boundsInDisplay);
8576 
8577             if (boundsInDisplay.isEmpty()) {
8578                 Slog.w(TAG, "Failed to generate DisplayHash. Bounds are not on screen");
8579                 mDisplayHashController.sendDisplayHashError(callback,
8580                         DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN);
8581                 return;
8582             }
8583         }
8584 
8585         // A screenshot of the entire display is taken rather than just the window. This is
8586         // because if we take a screenshot of the window, it will not include content that might
8587         // be covering it with the same uid. We want to make sure we include content that's
8588         // covering to ensure we get as close as possible to what the user sees
8589         final int uid = session.mUid;
8590         SurfaceControl.LayerCaptureArgs.Builder args =
8591                 new SurfaceControl.LayerCaptureArgs.Builder(displaySurfaceControl)
8592                         .setUid(uid)
8593                         .setSourceCrop(boundsInDisplay);
8594 
8595         mDisplayHashController.generateDisplayHash(args, boundsInWindow, hashAlgorithm, uid,
8596                 callback);
8597     }
8598 
shouldRestoreImeVisibility(IBinder imeTargetWindowToken)8599     boolean shouldRestoreImeVisibility(IBinder imeTargetWindowToken) {
8600         synchronized (mGlobalLock) {
8601             final WindowState imeTargetWindow = mWindowMap.get(imeTargetWindowToken);
8602             if (imeTargetWindow == null) {
8603                 return false;
8604             }
8605             final Task imeTargetWindowTask = imeTargetWindow.getTask();
8606             if (imeTargetWindowTask == null) {
8607                 return false;
8608             }
8609             final TaskSnapshot snapshot = mAtmService.getTaskSnapshot(imeTargetWindowTask.mTaskId,
8610                     false /* isLowResolution */);
8611             return snapshot != null && snapshot.hasImeSurface();
8612         }
8613     }
8614 }
8615