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