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