• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wm;
18 
19 import static android.Manifest.permission.MANAGE_APP_TOKENS;
20 import static android.Manifest.permission.READ_FRAME_BUFFER;
21 import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
22 import static android.Manifest.permission.RESTRICTED_VR_ACCESS;
23 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
24 import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
25 import static android.app.StatusBarManager.DISABLE_MASK;
26 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
27 import static android.content.Intent.ACTION_USER_REMOVED;
28 import static android.content.Intent.EXTRA_USER_HANDLE;
29 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
30 import static android.os.Process.ROOT_UID;
31 import static android.os.Process.SHELL_UID;
32 import static android.os.Process.SYSTEM_UID;
33 import static android.os.Process.myPid;
34 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
35 import static android.os.UserHandle.USER_NULL;
36 import static android.view.Display.DEFAULT_DISPLAY;
37 import static android.view.Display.INVALID_DISPLAY;
38 import static android.view.WindowManager.DOCKED_INVALID;
39 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
40 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
41 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
42 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
43 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
44 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
45 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
46 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
47 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
48 import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
49 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
50 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
51 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
52 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
53 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
54 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
55 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
56 import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
57 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
58 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
59 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
60 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
61 import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
62 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
63 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
64 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
65 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
66 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
67 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
68 import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY;
69 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
70 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
71 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
72 import static com.android.server.LockGuard.INDEX_WINDOW;
73 import static com.android.server.LockGuard.installLock;
74 import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
75 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END;
76 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START;
77 import static com.android.server.wm.KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED;
78 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
79 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
80 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
81 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
82 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
83 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
84 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
85 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
86 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
87 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
88 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
89 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
90 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
91 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
92 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
93 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
94 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
95 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
96 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
97 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
98 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
99 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
100 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
101 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
102 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
103 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_VERBOSE_TRANSACTIONS;
104 import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
105 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
106 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
107 
108 import android.Manifest;
109 import android.Manifest.permission;
110 import android.animation.AnimationHandler;
111 import android.animation.ValueAnimator;
112 import android.annotation.IntDef;
113 import android.annotation.NonNull;
114 import android.annotation.Nullable;
115 import android.app.ActivityManager;
116 import android.app.ActivityManager.TaskSnapshot;
117 import android.app.ActivityManagerInternal;
118 import android.app.ActivityThread;
119 import android.app.AppOpsManager;
120 import android.app.IActivityManager;
121 import android.content.BroadcastReceiver;
122 import android.content.ContentResolver;
123 import android.content.Context;
124 import android.content.Intent;
125 import android.content.IntentFilter;
126 import android.content.pm.ApplicationInfo;
127 import android.content.pm.PackageManager;
128 import android.content.res.Configuration;
129 import android.database.ContentObserver;
130 import android.graphics.Bitmap;
131 import android.graphics.GraphicBuffer;
132 import android.graphics.Matrix;
133 import android.graphics.PixelFormat;
134 import android.graphics.Point;
135 import android.graphics.Rect;
136 import android.graphics.RectF;
137 import android.graphics.Region;
138 import android.hardware.configstore.V1_0.ISurfaceFlingerConfigs;
139 import android.hardware.configstore.V1_0.OptionalBool;
140 import android.hardware.display.DisplayManager;
141 import android.hardware.display.DisplayManagerInternal;
142 import android.hardware.input.InputManager;
143 import android.net.Uri;
144 import android.os.Binder;
145 import android.os.Build;
146 import android.os.Bundle;
147 import android.os.Debug;
148 import android.os.Handler;
149 import android.os.IBinder;
150 import android.os.IRemoteCallback;
151 import android.os.Looper;
152 import android.os.Message;
153 import android.os.Parcel;
154 import android.os.ParcelFileDescriptor;
155 import android.os.PowerManager;
156 import android.os.PowerManagerInternal;
157 import android.os.PowerSaveState;
158 import android.os.RemoteException;
159 import android.os.ServiceManager;
160 import android.os.StrictMode;
161 import android.os.SystemClock;
162 import android.os.SystemProperties;
163 import android.os.SystemService;
164 import android.os.Trace;
165 import android.os.UserHandle;
166 import android.os.WorkSource;
167 import android.provider.Settings;
168 import android.text.format.DateUtils;
169 import android.util.ArraySet;
170 import android.util.DisplayMetrics;
171 import android.util.EventLog;
172 import android.util.Log;
173 import android.util.MergedConfiguration;
174 import android.util.Pair;
175 import android.util.Slog;
176 import android.util.SparseArray;
177 import android.util.SparseIntArray;
178 import android.util.TimeUtils;
179 import android.util.TypedValue;
180 import android.view.AppTransitionAnimationSpec;
181 import android.view.Display;
182 import android.view.DisplayInfo;
183 import android.view.Gravity;
184 import android.view.IAppTransitionAnimationSpecsFuture;
185 import android.view.IDockedStackListener;
186 import android.view.IInputFilter;
187 import android.view.IOnKeyguardExitResult;
188 import android.view.IPinnedStackListener;
189 import android.view.IRotationWatcher;
190 import android.view.IWallpaperVisibilityListener;
191 import android.view.IWindow;
192 import android.view.IWindowId;
193 import android.view.IWindowManager;
194 import android.view.IWindowSession;
195 import android.view.IWindowSessionCallback;
196 import android.view.InputChannel;
197 import android.view.InputDevice;
198 import android.view.InputEvent;
199 import android.view.InputEventReceiver;
200 import android.view.KeyEvent;
201 import android.view.MagnificationSpec;
202 import android.view.MotionEvent;
203 import android.view.PointerIcon;
204 import android.view.Surface;
205 import android.view.Surface.OutOfResourcesException;
206 import android.view.SurfaceControl;
207 import android.view.SurfaceSession;
208 import android.view.View;
209 import android.view.WindowContentFrameStats;
210 import android.view.WindowManager;
211 import android.view.WindowManager.LayoutParams;
212 import android.view.WindowManagerGlobal;
213 import android.view.WindowManagerInternal;
214 import android.view.WindowManagerPolicy;
215 import android.view.WindowManagerPolicy.PointerEventListener;
216 import android.view.WindowManagerPolicy.ScreenOffListener;
217 import android.view.animation.Animation;
218 import android.view.inputmethod.InputMethodManagerInternal;
219 
220 import com.android.internal.R;
221 import com.android.internal.app.IAssistScreenshotReceiver;
222 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
223 import com.android.internal.os.IResultReceiver;
224 import com.android.internal.policy.IKeyguardDismissCallback;
225 import com.android.internal.policy.IShortcutService;
226 import com.android.internal.util.DumpUtils;
227 import com.android.internal.util.FastPrintWriter;
228 import com.android.internal.view.IInputContext;
229 import com.android.internal.view.IInputMethodClient;
230 import com.android.internal.view.IInputMethodManager;
231 import com.android.internal.view.WindowManagerPolicyThread;
232 import com.android.server.AnimationThread;
233 import com.android.server.DisplayThread;
234 import com.android.server.EventLogTags;
235 import com.android.server.FgThread;
236 import com.android.server.LocalServices;
237 import com.android.server.UiThread;
238 import com.android.server.Watchdog;
239 import com.android.server.input.InputManagerService;
240 import com.android.server.power.BatterySaverPolicy.ServiceType;
241 import com.android.server.power.ShutdownThread;
242 
243 import java.io.BufferedWriter;
244 import java.io.DataInputStream;
245 import java.io.File;
246 import java.io.FileDescriptor;
247 import java.io.FileInputStream;
248 import java.io.FileNotFoundException;
249 import java.io.IOException;
250 import java.io.OutputStream;
251 import java.io.OutputStreamWriter;
252 import java.io.PrintWriter;
253 import java.io.StringWriter;
254 import java.lang.annotation.Retention;
255 import java.lang.annotation.RetentionPolicy;
256 import java.net.Socket;
257 import java.text.DateFormat;
258 import java.util.ArrayList;
259 import java.util.Date;
260 import java.util.List;
261 /** {@hide} */
262 public class WindowManagerService extends IWindowManager.Stub
263         implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
264     private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowManagerService" : TAG_WM;
265 
266     static final int LAYOUT_REPEAT_THRESHOLD = 4;
267 
268     static final boolean PROFILE_ORIENTATION = false;
269     static final boolean localLOGV = DEBUG;
270 
271     /** How much to multiply the policy's type layer, to reserve room
272      * for multiple windows of the same type and Z-ordering adjustment
273      * with TYPE_LAYER_OFFSET. */
274     static final int TYPE_LAYER_MULTIPLIER = 10000;
275 
276     /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
277      * or below others in the same layer. */
278     static final int TYPE_LAYER_OFFSET = 1000;
279 
280     /** How much to increment the layer for each window, to reserve room
281      * for effect surfaces between them.
282      */
283     static final int WINDOW_LAYER_MULTIPLIER = 5;
284 
285     /**
286      * Dim surface layer is immediately below target window.
287      */
288     static final int LAYER_OFFSET_DIM = 1;
289 
290     /**
291      * Animation thumbnail is as far as possible below the window above
292      * the thumbnail (or in other words as far as possible above the window
293      * below it).
294      */
295     static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER - 1;
296 
297     /** The maximum length we will accept for a loaded animation duration:
298      * this is 10 seconds.
299      */
300     static final int MAX_ANIMATION_DURATION = 10 * 1000;
301 
302     /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
303     static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000;
304 
305     /** Amount of time (in milliseconds) to delay before declaring a seamless rotation timeout. */
306     static final int SEAMLESS_ROTATION_TIMEOUT_DURATION = 2000;
307 
308     /** Amount of time (in milliseconds) to delay before declaring a window replacement timeout. */
309     static final int WINDOW_REPLACEMENT_TIMEOUT_DURATION = 2000;
310 
311     /** Amount of time to allow a last ANR message to exist before freeing the memory. */
312     static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours
313     /**
314      * If true, the window manager will do its own custom freezing and general
315      * management of the screen during rotation.
316      */
317     static final boolean CUSTOM_SCREEN_ROTATION = true;
318 
319     // Maximum number of milliseconds to wait for input devices to be enumerated before
320     // proceding with safe mode detection.
321     private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000;
322 
323     // Default input dispatching timeout in nanoseconds.
324     static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
325 
326     // Poll interval in milliseconds for watching boot animation finished.
327     private static final int BOOT_ANIMATION_POLL_INTERVAL = 200;
328 
329     // The name of the boot animation service in init.rc.
330     private static final String BOOT_ANIMATION_SERVICE = "bootanim";
331 
332     static final int UPDATE_FOCUS_NORMAL = 0;
333     static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
334     static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
335     static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
336 
337     private static final String SYSTEM_SECURE = "ro.secure";
338     private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
339 
340     private static final String DENSITY_OVERRIDE = "ro.config.density_override";
341     private static final String SIZE_OVERRIDE = "ro.config.size_override";
342 
343     private static final int MAX_SCREENSHOT_RETRIES = 3;
344 
345     private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
346 
347     // Used to indicate that if there is already a transition set, it should be preserved when
348     // trying to apply a new one.
349     private static final boolean ALWAYS_KEEP_CURRENT = true;
350 
351     private static final float DRAG_SHADOW_ALPHA_TRANSPARENT = .7071f;
352 
353     // Enums for animation scale update types.
354     @Retention(RetentionPolicy.SOURCE)
355     @IntDef({WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE, ANIMATION_DURATION_SCALE})
356     private @interface UpdateAnimationScaleMode {};
357     private static final int WINDOW_ANIMATION_SCALE = 0;
358     private static final int TRANSITION_ANIMATION_SCALE = 1;
359     private static final int ANIMATION_DURATION_SCALE = 2;
360 
361     final private KeyguardDisableHandler mKeyguardDisableHandler;
362     boolean mKeyguardGoingAway;
363     // VR Vr2d Display Id.
364     int mVr2dDisplayId = INVALID_DISPLAY;
365 
366     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
367         @Override
368         public void onReceive(Context context, Intent intent) {
369             switch (intent.getAction()) {
370                 case ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED:
371                     mKeyguardDisableHandler.sendEmptyMessage(KEYGUARD_POLICY_CHANGED);
372                     break;
373                 case ACTION_USER_REMOVED:
374                     final int userId = intent.getIntExtra(EXTRA_USER_HANDLE, USER_NULL);
375                     if (userId != USER_NULL) {
376                         synchronized (mWindowMap) {
377                             mScreenCaptureDisabled.remove(userId);
378                         }
379                     }
380                     break;
381             }
382         }
383     };
384     final WindowSurfacePlacer mWindowPlacerLocked;
385 
386     /**
387      * Current user when multi-user is enabled. Don't show windows of
388      * non-current user. Also see mCurrentProfileIds.
389      */
390     int mCurrentUserId;
391     /**
392      * Users that are profiles of the current user. These are also allowed to show windows
393      * on the current user.
394      */
395     int[] mCurrentProfileIds = new int[] {};
396 
397     final Context mContext;
398 
399     final boolean mHaveInputMethods;
400 
401     final boolean mHasPermanentDpad;
402     final long mDrawLockTimeoutMillis;
403     final boolean mAllowAnimationsInLowPowerMode;
404 
405     final boolean mAllowBootMessages;
406 
407     final boolean mLimitedAlphaCompositing;
408     final int mMaxUiWidth;
409 
410     final WindowManagerPolicy mPolicy;
411 
412     final IActivityManager mActivityManager;
413     final ActivityManagerInternal mAmInternal;
414 
415     final AppOpsManager mAppOps;
416 
417     final DisplaySettings mDisplaySettings;
418 
419     /** If the system should display notifications for apps displaying an alert window. */
420     boolean mShowAlertWindowNotifications = true;
421 
422     /**
423      * All currently active sessions with clients.
424      */
425     final ArraySet<Session> mSessions = new ArraySet<>();
426 
427     /**
428      * Mapping from an IWindow IBinder to the server's Window object.
429      * This is also used as the lock for all of our state.
430      * NOTE: Never call into methods that lock ActivityManagerService while holding this object.
431      */
432     final WindowHashMap mWindowMap = new WindowHashMap();
433 
434     /**
435      * List of window tokens that have finished starting their application,
436      * and now need to have the policy remove their windows.
437      */
438     final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<>();
439 
440     /**
441      * List of window tokens that have finished drawing their own windows and
442      * no longer need to show any saved surfaces. Windows that's still showing
443      * saved surfaces will be cleaned up after next animation pass.
444      */
445     final ArrayList<AppWindowToken> mFinishedEarlyAnim = new ArrayList<>();
446 
447     /**
448      * List of app window tokens that are waiting for replacing windows. If the
449      * replacement doesn't come in time the stale windows needs to be disposed of.
450      */
451     final ArrayList<AppWindowToken> mWindowReplacementTimeouts = new ArrayList<>();
452 
453     /**
454      * Windows that are being resized.  Used so we can tell the client about
455      * the resize after closing the transaction in which we resized the
456      * underlying surface.
457      */
458     final ArrayList<WindowState> mResizingWindows = new ArrayList<>();
459 
460     /**
461      * Windows whose animations have ended and now must be removed.
462      */
463     final ArrayList<WindowState> mPendingRemove = new ArrayList<>();
464 
465     /**
466      * Used when processing mPendingRemove to avoid working on the original array.
467      */
468     WindowState[] mPendingRemoveTmp = new WindowState[20];
469 
470     /**
471      * Windows whose surface should be destroyed.
472      */
473     final ArrayList<WindowState> mDestroySurface = new ArrayList<>();
474 
475     /**
476      * Windows with a preserved surface waiting to be destroyed. These windows
477      * are going through a surface change. We keep the old surface around until
478      * the first frame on the new surface finishes drawing.
479      */
480     final ArrayList<WindowState> mDestroyPreservedSurface = new ArrayList<>();
481 
482     /**
483      * Windows that have lost input focus and are waiting for the new
484      * focus window to be displayed before they are told about this.
485      */
486     ArrayList<WindowState> mLosingFocus = new ArrayList<>();
487 
488     /**
489      * This is set when we have run out of memory, and will either be an empty
490      * list or contain windows that need to be force removed.
491      */
492     final ArrayList<WindowState> mForceRemoves = new ArrayList<>();
493 
494     /**
495      * Windows that clients are waiting to have drawn.
496      */
497     ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>();
498     /**
499      * And the callback to make when they've all been drawn.
500      */
501     Runnable mWaitingForDrawnCallback;
502 
503     /** List of window currently causing non-system overlay windows to be hidden. */
504     private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<>();
505 
506     /**
507      * Stores for each user whether screencapture is disabled
508      * This array is essentially a cache for all userId for
509      * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled}
510      */
511     private SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<>();
512 
513     IInputMethodManager mInputMethodManager;
514 
515     AccessibilityController mAccessibilityController;
516 
517     final SurfaceSession mFxSession;
518     Watermark mWatermark;
519     StrictModeFlash mStrictModeFlash;
520     CircularDisplayMask mCircularDisplayMask;
521     EmulatorDisplayOverlay mEmulatorDisplayOverlay;
522 
523     final float[] mTmpFloats = new float[9];
524     final Rect mTmpRect = new Rect();
525     final Rect mTmpRect2 = new Rect();
526     final Rect mTmpRect3 = new Rect();
527     final RectF mTmpRectF = new RectF();
528 
529     final Matrix mTmpTransform = new Matrix();
530 
531     boolean mDisplayReady;
532     boolean mSafeMode;
533     boolean mDisplayEnabled = false;
534     boolean mSystemBooted = false;
535     boolean mForceDisplayEnabled = false;
536     boolean mShowingBootMessages = false;
537     boolean mBootAnimationStopped = false;
538 
539     // Following variables are for debugging screen wakelock only.
540     WindowState mLastWakeLockHoldingWindow = null;
541     WindowState mLastWakeLockObscuringWindow = null;
542 
543     /** Dump of the windows and app tokens at the time of the last ANR. Cleared after
544      * LAST_ANR_LIFETIME_DURATION_MSECS */
545     String mLastANRState;
546 
547     // The root of the device window hierarchy.
548     RootWindowContainer mRoot;
549 
550     int mDockedStackCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
551     Rect mDockedStackCreateBounds;
552 
553     private final SparseIntArray mTmpTaskIds = new SparseIntArray();
554 
555     boolean mForceResizableTasks = false;
556     boolean mSupportsPictureInPicture = false;
557 
getDragLayerLocked()558     int getDragLayerLocked() {
559         return mPolicy.getWindowLayerFromTypeLw(TYPE_DRAG) * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
560     }
561 
562     class RotationWatcher {
563         final IRotationWatcher mWatcher;
564         final IBinder.DeathRecipient mDeathRecipient;
565         final int mDisplayId;
RotationWatcher(IRotationWatcher watcher, IBinder.DeathRecipient deathRecipient, int displayId)566         RotationWatcher(IRotationWatcher watcher, IBinder.DeathRecipient deathRecipient,
567                 int displayId) {
568             mWatcher = watcher;
569             mDeathRecipient = deathRecipient;
570             mDisplayId = displayId;
571         }
572     }
573 
574     ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<>();
575     int mDeferredRotationPauseCount;
576     final WallpaperVisibilityListeners mWallpaperVisibilityListeners =
577             new WallpaperVisibilityListeners();
578 
579     int mSystemDecorLayer = 0;
580     final Rect mScreenRect = new Rect();
581 
582     boolean mDisplayFrozen = false;
583     long mDisplayFreezeTime = 0;
584     int mLastDisplayFreezeDuration = 0;
585     Object mLastFinishedFreezeSource = null;
586     boolean mWaitingForConfig = false;
587     boolean mSwitchingUser = false;
588 
589     final static int WINDOWS_FREEZING_SCREENS_NONE = 0;
590     final static int WINDOWS_FREEZING_SCREENS_ACTIVE = 1;
591     final static int WINDOWS_FREEZING_SCREENS_TIMEOUT = 2;
592     int mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
593 
594     boolean mClientFreezingScreen = false;
595     int mAppsFreezingScreen = 0;
596 
597     int mLayoutSeq = 0;
598 
599     // Last systemUiVisibility we received from status bar.
600     int mLastStatusBarVisibility = 0;
601     // Last systemUiVisibility we dispatched to windows.
602     int mLastDispatchedSystemUiVisibility = 0;
603 
604     // State while inside of layoutAndPlaceSurfacesLocked().
605     boolean mFocusMayChange;
606 
607     // This is held as long as we have the screen frozen, to give us time to
608     // perform a rotation animation when turning off shows the lock screen which
609     // changes the orientation.
610     private final PowerManager.WakeLock mScreenFrozenLock;
611 
612     final AppTransition mAppTransition;
613     boolean mSkipAppTransitionAnimation = false;
614 
615     final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<>();
616     final ArraySet<AppWindowToken> mClosingApps = new ArraySet<>();
617 
618     final UnknownAppVisibilityController mUnknownAppVisibilityController =
619             new UnknownAppVisibilityController(this);
620     final TaskSnapshotController mTaskSnapshotController;
621 
622     boolean mIsTouchDevice;
623 
624     final H mH = new H();
625 
626     /**
627      * Handler for things to run that have direct impact on an animation, i.e. animation tick,
628      * layout, starting window creation, whereas {@link H} runs things that are still important, but
629      * not as critical.
630      */
631     final Handler mAnimationHandler = new Handler(AnimationThread.getHandler().getLooper());
632 
633     WindowState mCurrentFocus = null;
634     WindowState mLastFocus = null;
635 
636     /** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
637     private final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>();
638     /** Windows removed since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
639     private final ArrayList<WindowState> mWinRemovedSinceNullFocus = new ArrayList<>();
640 
641     /** This just indicates the window the input method is on top of, not
642      * necessarily the window its input is going to. */
643     WindowState mInputMethodTarget = null;
644 
645     /** If true hold off on modifying the animation layer of mInputMethodTarget */
646     boolean mInputMethodTargetWaitingAnim;
647 
648     WindowState mInputMethodWindow = null;
649 
650     boolean mHardKeyboardAvailable;
651     WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
652     SettingsObserver mSettingsObserver;
653 
654     // A count of the windows which are 'seamlessly rotated', e.g. a surface
655     // at an old orientation is being transformed. We freeze orientation updates
656     // while any windows are seamlessly rotated, so we need to track when this
657     // hits zero so we can apply deferred orientation updates.
658     int mSeamlessRotationCount = 0;
659 
660     private final class SettingsObserver extends ContentObserver {
661         private final Uri mDisplayInversionEnabledUri =
662                 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
663         private final Uri mWindowAnimationScaleUri =
664                 Settings.Global.getUriFor(Settings.Global.WINDOW_ANIMATION_SCALE);
665         private final Uri mTransitionAnimationScaleUri =
666                 Settings.Global.getUriFor(Settings.Global.TRANSITION_ANIMATION_SCALE);
667         private final Uri mAnimationDurationScaleUri =
668                 Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE);
669 
SettingsObserver()670         public SettingsObserver() {
671             super(new Handler());
672             ContentResolver resolver = mContext.getContentResolver();
673             resolver.registerContentObserver(mDisplayInversionEnabledUri, false, this,
674                     UserHandle.USER_ALL);
675             resolver.registerContentObserver(mWindowAnimationScaleUri, false, this,
676                     UserHandle.USER_ALL);
677             resolver.registerContentObserver(mTransitionAnimationScaleUri, false, this,
678                     UserHandle.USER_ALL);
679             resolver.registerContentObserver(mAnimationDurationScaleUri, false, this,
680                     UserHandle.USER_ALL);
681         }
682 
683         @Override
onChange(boolean selfChange, Uri uri)684         public void onChange(boolean selfChange, Uri uri) {
685             if (uri == null) {
686                 return;
687             }
688 
689             if (mDisplayInversionEnabledUri.equals(uri)) {
690                 updateCircularDisplayMaskIfNeeded();
691             } else {
692                 @UpdateAnimationScaleMode
693                 final int mode;
694                 if (mWindowAnimationScaleUri.equals(uri)) {
695                     mode = WINDOW_ANIMATION_SCALE;
696                 } else if (mTransitionAnimationScaleUri.equals(uri)) {
697                     mode = TRANSITION_ANIMATION_SCALE;
698                 } else if (mAnimationDurationScaleUri.equals(uri)) {
699                     mode = ANIMATION_DURATION_SCALE;
700                 } else {
701                     // Ignoring unrecognized content changes
702                     return;
703                 }
704                 Message m = mH.obtainMessage(H.UPDATE_ANIMATION_SCALE, mode, 0);
705                 mH.sendMessage(m);
706             }
707         }
708     }
709 
710     boolean mAnimateWallpaperWithTarget;
711 
712     // TODO: Move to RootWindowContainer
713     AppWindowToken mFocusedApp = null;
714 
715     PowerManager mPowerManager;
716     PowerManagerInternal mPowerManagerInternal;
717 
718     private float mWindowAnimationScaleSetting = 1.0f;
719     private float mTransitionAnimationScaleSetting = 1.0f;
720     private float mAnimatorDurationScaleSetting = 1.0f;
721     private boolean mAnimationsDisabled = false;
722 
723     final InputManagerService mInputManager;
724     final DisplayManagerInternal mDisplayManagerInternal;
725     final DisplayManager mDisplayManager;
726     private final Display[] mDisplays;
727 
728     // Indicates whether this device supports wide color gamut rendering
729     private boolean mHasWideColorGamutSupport;
730 
731     // Who is holding the screen on.
732     private Session mHoldingScreenOn;
733     private PowerManager.WakeLock mHoldingScreenWakeLock;
734 
735     boolean mTurnOnScreen;
736 
737     // Whether or not a layout can cause a wake up when theater mode is enabled.
738     boolean mAllowTheaterModeWakeFromLayout;
739 
740     TaskPositioner mTaskPositioner;
741     DragState mDragState = null;
742 
743     // For frozen screen animations.
744     private int mExitAnimId, mEnterAnimId;
745 
746     // The display that the rotation animation is applying to.
747     private int mFrozenDisplayId;
748 
749     /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
750      * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
751     int mTransactionSequence;
752 
753     final WindowAnimator mAnimator;
754 
755     final BoundsAnimationController mBoundsAnimationController;
756 
757     private final PointerEventDispatcher mPointerEventDispatcher;
758 
759     private WindowContentFrameStats mTempWindowRenderStats;
760 
761     final class DragInputEventReceiver extends InputEventReceiver {
762         // Set, if stylus button was down at the start of the drag.
763         private boolean mStylusButtonDownAtStart;
764         // Indicates the first event to check for button state.
765         private boolean mIsStartEvent = true;
766         // Set to true to ignore input events after the drag gesture is complete but the drag events
767         // are still being dispatched.
768         private boolean mMuteInput = false;
769 
DragInputEventReceiver(InputChannel inputChannel, Looper looper)770         public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
771             super(inputChannel, looper);
772         }
773 
774         @Override
onInputEvent(InputEvent event, int displayId)775         public void onInputEvent(InputEvent event, int displayId) {
776             boolean handled = false;
777             try {
778                 if (mDragState == null) {
779                     // The drag has ended but the clean-up message has not been processed by
780                     // window manager. Drop events that occur after this until window manager
781                     // has a chance to clean-up the input handle.
782                     handled = true;
783                     return;
784                 }
785                 if (event instanceof MotionEvent
786                         && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0
787                         && !mMuteInput) {
788                     final MotionEvent motionEvent = (MotionEvent)event;
789                     boolean endDrag = false;
790                     final float newX = motionEvent.getRawX();
791                     final float newY = motionEvent.getRawY();
792                     final boolean isStylusButtonDown =
793                             (motionEvent.getButtonState() & MotionEvent.BUTTON_STYLUS_PRIMARY) != 0;
794 
795                     if (mIsStartEvent) {
796                         if (isStylusButtonDown) {
797                             // First event and the button was down, check for the button being
798                             // lifted in the future, if that happens we'll drop the item.
799                             mStylusButtonDownAtStart = true;
800                         }
801                         mIsStartEvent = false;
802                     }
803 
804                     switch (motionEvent.getAction()) {
805                     case MotionEvent.ACTION_DOWN: {
806                         if (DEBUG_DRAG) {
807                             Slog.w(TAG_WM, "Unexpected ACTION_DOWN in drag layer");
808                         }
809                     } break;
810 
811                     case MotionEvent.ACTION_MOVE: {
812                         if (mStylusButtonDownAtStart && !isStylusButtonDown) {
813                             if (DEBUG_DRAG) Slog.d(TAG_WM, "Button no longer pressed; dropping at "
814                                     + newX + "," + newY);
815                             mMuteInput = true;
816                             synchronized (mWindowMap) {
817                                 endDrag = mDragState.notifyDropLw(newX, newY);
818                             }
819                         } else {
820                             synchronized (mWindowMap) {
821                                 // move the surface and tell the involved window(s) where we are
822                                 mDragState.notifyMoveLw(newX, newY);
823                             }
824                         }
825                     } break;
826 
827                     case MotionEvent.ACTION_UP: {
828                         if (DEBUG_DRAG) Slog.d(TAG_WM, "Got UP on move channel; dropping at "
829                                 + newX + "," + newY);
830                         mMuteInput = true;
831                         synchronized (mWindowMap) {
832                             endDrag = mDragState.notifyDropLw(newX, newY);
833                         }
834                     } break;
835 
836                     case MotionEvent.ACTION_CANCEL: {
837                         if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag cancelled!");
838                         mMuteInput = true;
839                         endDrag = true;
840                     } break;
841                     }
842 
843                     if (endDrag) {
844                         if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ended; tearing down state");
845                         // tell all the windows that the drag has ended
846                         synchronized (mWindowMap) {
847                             // endDragLw will post back to looper to dispose the receiver
848                             // since we still need the receiver for the last finishInputEvent.
849                             mDragState.endDragLw();
850                         }
851                         mStylusButtonDownAtStart = false;
852                         mIsStartEvent = true;
853                     }
854 
855                     handled = true;
856                 }
857             } catch (Exception e) {
858                 Slog.e(TAG_WM, "Exception caught by drag handleMotion", e);
859             } finally {
860                 finishInputEvent(event, handled);
861             }
862         }
863     }
864 
865     /**
866      * Whether the UI is currently running in touch mode (not showing
867      * navigational focus because the user is directly pressing the screen).
868      */
869     boolean mInTouchMode;
870 
871     private ViewServer mViewServer;
872     final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>();
873     boolean mWindowsChanged = false;
874 
875     public interface WindowChangeListener {
windowsChanged()876         public void windowsChanged();
focusChanged()877         public void focusChanged();
878     }
879 
880     final Configuration mTempConfiguration = new Configuration();
881 
882     // If true, only the core apps and services are being launched because the device
883     // is in a special boot mode, such as being encrypted or waiting for a decryption password.
884     // For example, when this flag is true, there will be no wallpaper service.
885     final boolean mOnlyCore;
886 
887     // List of clients without a transtiton animation that we notify once we are done transitioning
888     // since they won't be notified through the app window animator.
889     final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>();
890 
891     static WindowManagerThreadPriorityBooster sThreadPriorityBooster =
892             new WindowManagerThreadPriorityBooster();
893 
boostPriorityForLockedSection()894     static void boostPriorityForLockedSection() {
895         sThreadPriorityBooster.boost();
896     }
897 
resetPriorityAfterLockedSection()898     static void resetPriorityAfterLockedSection() {
899         sThreadPriorityBooster.reset();
900     }
901 
openSurfaceTransaction()902     void openSurfaceTransaction() {
903         try {
904             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "openSurfaceTransaction");
905             synchronized (mWindowMap) {
906                 if (mRoot.mSurfaceTraceEnabled) {
907                     mRoot.mRemoteEventTrace.openSurfaceTransaction();
908                 }
909                 SurfaceControl.openTransaction();
910             }
911         } finally {
912             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
913         }
914     }
915 
916     /**
917      * Closes a surface transaction.
918      */
closeSurfaceTransaction()919     void closeSurfaceTransaction() {
920         try {
921             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "closeSurfaceTransaction");
922             synchronized (mWindowMap) {
923                 if (mRoot.mSurfaceTraceEnabled) {
924                     mRoot.mRemoteEventTrace.closeSurfaceTransaction();
925                 }
926                 SurfaceControl.closeTransaction();
927             }
928         } finally {
929             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
930         }
931     }
932 
933     /**
934      * Executes an empty animation transaction without holding the WM lock to simulate
935      * back-pressure. See {@link WindowAnimator#animate} why this is needed.
936      */
executeEmptyAnimationTransaction()937     void executeEmptyAnimationTransaction() {
938         try {
939             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "openSurfaceTransaction");
940             synchronized (mWindowMap) {
941                 if (mRoot.mSurfaceTraceEnabled) {
942                     mRoot.mRemoteEventTrace.openSurfaceTransaction();
943                 }
944                 SurfaceControl.openTransaction();
945                 SurfaceControl.setAnimationTransaction();
946                 if (mRoot.mSurfaceTraceEnabled) {
947                     mRoot.mRemoteEventTrace.closeSurfaceTransaction();
948                 }
949             }
950         } finally {
951             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
952         }
953         try {
954             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "closeSurfaceTransaction");
955             SurfaceControl.closeTransaction();
956         } finally {
957             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
958         }
959     }
960 
961     /** Listener to notify activity manager about app transitions. */
962     final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier
963             = new WindowManagerInternal.AppTransitionListener() {
964 
965         @Override
966         public void onAppTransitionCancelledLocked(int transit) {
967             mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_CANCELLED);
968         }
969 
970         @Override
971         public void onAppTransitionFinishedLocked(IBinder token) {
972             mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_FINISHED);
973             final AppWindowToken atoken = mRoot.getAppWindowToken(token);
974             if (atoken == null) {
975                 return;
976             }
977             if (atoken.mLaunchTaskBehind) {
978                 try {
979                     mActivityManager.notifyLaunchTaskBehindComplete(atoken.token);
980                 } catch (RemoteException e) {
981                 }
982                 atoken.mLaunchTaskBehind = false;
983             } else {
984                 atoken.updateReportedVisibilityLocked();
985                 if (atoken.mEnteringAnimation) {
986                     atoken.mEnteringAnimation = false;
987                     try {
988                         mActivityManager.notifyEnterAnimationComplete(atoken.token);
989                     } catch (RemoteException e) {
990                     }
991                 }
992             }
993         }
994     };
995 
996     final ArrayList<AppFreezeListener> mAppFreezeListeners = new ArrayList<>();
997 
998     interface AppFreezeListener {
onAppFreezeTimeout()999         void onAppFreezeTimeout();
1000     }
1001 
1002     private static WindowManagerService sInstance;
getInstance()1003     static WindowManagerService getInstance() {
1004         return sInstance;
1005     }
1006 
main(final Context context, final InputManagerService im, final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy)1007     public static WindowManagerService main(final Context context, final InputManagerService im,
1008             final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
1009             WindowManagerPolicy policy) {
1010         DisplayThread.getHandler().runWithScissors(() ->
1011                 sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
1012                         onlyCore, policy), 0);
1013         return sInstance;
1014     }
1015 
initPolicy()1016     private void initPolicy() {
1017         UiThread.getHandler().runWithScissors(new Runnable() {
1018             @Override
1019             public void run() {
1020                 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
1021 
1022                 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
1023             }
1024         }, 0);
1025     }
1026 
WindowManagerService(Context context, InputManagerService inputManager, boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy)1027     private WindowManagerService(Context context, InputManagerService inputManager,
1028             boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
1029             WindowManagerPolicy policy) {
1030         installLock(this, INDEX_WINDOW);
1031         mRoot = new RootWindowContainer(this);
1032         mContext = context;
1033         mHaveInputMethods = haveInputMethods;
1034         mAllowBootMessages = showBootMsgs;
1035         mOnlyCore = onlyCore;
1036         mLimitedAlphaCompositing = context.getResources().getBoolean(
1037                 com.android.internal.R.bool.config_sf_limitedAlpha);
1038         mHasPermanentDpad = context.getResources().getBoolean(
1039                 com.android.internal.R.bool.config_hasPermanentDpad);
1040         mInTouchMode = context.getResources().getBoolean(
1041                 com.android.internal.R.bool.config_defaultInTouchMode);
1042         mDrawLockTimeoutMillis = context.getResources().getInteger(
1043                 com.android.internal.R.integer.config_drawLockTimeoutMillis);
1044         mAllowAnimationsInLowPowerMode = context.getResources().getBoolean(
1045                 com.android.internal.R.bool.config_allowAnimationsInLowPowerMode);
1046         mMaxUiWidth = context.getResources().getInteger(
1047                 com.android.internal.R.integer.config_maxUiWidth);
1048         mInputManager = inputManager; // Must be before createDisplayContentLocked.
1049         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
1050         mDisplaySettings = new DisplaySettings();
1051         mDisplaySettings.readSettingsLocked();
1052 
1053         mWindowPlacerLocked = new WindowSurfacePlacer(this);
1054         mPolicy = policy;
1055         mTaskSnapshotController = new TaskSnapshotController(this);
1056 
1057         LocalServices.addService(WindowManagerPolicy.class, mPolicy);
1058 
1059         if(mInputManager != null) {
1060             final InputChannel inputChannel = mInputManager.monitorInput(TAG_WM);
1061             mPointerEventDispatcher = inputChannel != null
1062                     ? new PointerEventDispatcher(inputChannel) : null;
1063         } else {
1064             mPointerEventDispatcher = null;
1065         }
1066 
1067         mFxSession = new SurfaceSession();
1068         mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
1069         mDisplays = mDisplayManager.getDisplays();
1070         for (Display display : mDisplays) {
1071             createDisplayContentLocked(display);
1072         }
1073 
1074         mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
1075 
1076         mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1077         mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
1078 
1079         if (mPowerManagerInternal != null) {
1080             mPowerManagerInternal.registerLowPowerModeObserver(
1081                     new PowerManagerInternal.LowPowerModeListener() {
1082                 @Override
1083                 public int getServiceType() {
1084                     return ServiceType.ANIMATION;
1085                 }
1086 
1087                 @Override
1088                 public void onLowPowerModeChanged(PowerSaveState result) {
1089                     synchronized (mWindowMap) {
1090                         final boolean enabled = result.batterySaverEnabled;
1091                         if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
1092                             mAnimationsDisabled = enabled;
1093                             dispatchNewAnimatorScaleLocked(null);
1094                         }
1095                     }
1096                 }
1097             });
1098             mAnimationsDisabled = mPowerManagerInternal
1099                     .getLowPowerState(ServiceType.ANIMATION).batterySaverEnabled;
1100         }
1101         mScreenFrozenLock = mPowerManager.newWakeLock(
1102                 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
1103         mScreenFrozenLock.setReferenceCounted(false);
1104 
1105         mAppTransition = new AppTransition(context, this);
1106         mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier);
1107 
1108         final AnimationHandler animationHandler = new AnimationHandler();
1109         animationHandler.setProvider(new SfVsyncFrameCallbackProvider());
1110         mBoundsAnimationController = new BoundsAnimationController(context, mAppTransition,
1111                 AnimationThread.getHandler(), animationHandler);
1112 
1113         mActivityManager = ActivityManager.getService();
1114         mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
1115         mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
1116         AppOpsManager.OnOpChangedInternalListener opListener =
1117                 new AppOpsManager.OnOpChangedInternalListener() {
1118                     @Override public void onOpChanged(int op, String packageName) {
1119                         updateAppOpsState();
1120                     }
1121                 };
1122         mAppOps.startWatchingMode(OP_SYSTEM_ALERT_WINDOW, null, opListener);
1123         mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener);
1124 
1125         // Get persisted window scale setting
1126         mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
1127                 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
1128         mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
1129                 Settings.Global.TRANSITION_ANIMATION_SCALE,
1130                 context.getResources().getFloat(
1131                         R.dimen.config_appTransitionAnimationDurationScaleDefault));
1132 
1133         setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
1134                 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting));
1135 
1136         IntentFilter filter = new IntentFilter();
1137         // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
1138         filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
1139         // Listen to user removal broadcasts so that we can remove the user-specific data.
1140         filter.addAction(Intent.ACTION_USER_REMOVED);
1141         mContext.registerReceiver(mBroadcastReceiver, filter);
1142 
1143         mSettingsObserver = new SettingsObserver();
1144 
1145         mHoldingScreenWakeLock = mPowerManager.newWakeLock(
1146                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
1147         mHoldingScreenWakeLock.setReferenceCounted(false);
1148 
1149         mAnimator = new WindowAnimator(this);
1150 
1151         mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
1152                 com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
1153 
1154 
1155         LocalServices.addService(WindowManagerInternal.class, new LocalService());
1156         initPolicy();
1157 
1158         // Add ourself to the Watchdog monitors.
1159         Watchdog.getInstance().addMonitor(this);
1160 
1161         openSurfaceTransaction();
1162         try {
1163             createWatermarkInTransaction();
1164         } finally {
1165             closeSurfaceTransaction();
1166         }
1167 
1168         showEmulatorDisplayOverlayIfNeeded();
1169     }
1170 
getInputMonitor()1171     public InputMonitor getInputMonitor() {
1172         return mInputMonitor;
1173     }
1174 
1175     @Override
onTransact(int code, Parcel data, Parcel reply, int flags)1176     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1177             throws RemoteException {
1178         try {
1179             return super.onTransact(code, data, reply, flags);
1180         } catch (RuntimeException e) {
1181             // The window manager only throws security exceptions, so let's
1182             // log all others.
1183             if (!(e instanceof SecurityException)) {
1184                 Slog.wtf(TAG_WM, "Window Manager Crash", e);
1185             }
1186             throw e;
1187         }
1188     }
1189 
excludeWindowTypeFromTapOutTask(int windowType)1190     static boolean excludeWindowTypeFromTapOutTask(int windowType) {
1191         switch (windowType) {
1192             case TYPE_STATUS_BAR:
1193             case TYPE_NAVIGATION_BAR:
1194             case TYPE_INPUT_METHOD_DIALOG:
1195                 return true;
1196         }
1197         return false;
1198     }
1199 
addWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel)1200     public int addWindow(Session session, IWindow client, int seq,
1201             WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
1202             Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
1203             InputChannel outInputChannel) {
1204         int[] appOp = new int[1];
1205         int res = mPolicy.checkAddPermission(attrs, appOp);
1206         if (res != WindowManagerGlobal.ADD_OKAY) {
1207             return res;
1208         }
1209 
1210         boolean reportNewConfig = false;
1211         WindowState parentWindow = null;
1212         long origId;
1213         final int callingUid = Binder.getCallingUid();
1214         final int type = attrs.type;
1215 
1216         synchronized(mWindowMap) {
1217             if (!mDisplayReady) {
1218                 throw new IllegalStateException("Display has not been initialialized");
1219             }
1220 
1221             final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
1222             if (displayContent == null) {
1223                 Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: "
1224                         + displayId + ".  Aborting.");
1225                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
1226             }
1227             if (!displayContent.hasAccess(session.mUid)
1228                     && !mDisplayManagerInternal.isUidPresentOnDisplay(session.mUid, displayId)) {
1229                 Slog.w(TAG_WM, "Attempted to add window to a display for which the application "
1230                         + "does not have access: " + displayId + ".  Aborting.");
1231                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
1232             }
1233 
1234             if (mWindowMap.containsKey(client.asBinder())) {
1235                 Slog.w(TAG_WM, "Window " + client + " is already added");
1236                 return WindowManagerGlobal.ADD_DUPLICATE_ADD;
1237             }
1238 
1239             if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
1240                 parentWindow = windowForClientLocked(null, attrs.token, false);
1241                 if (parentWindow == null) {
1242                     Slog.w(TAG_WM, "Attempted to add window with token that is not a window: "
1243                           + attrs.token + ".  Aborting.");
1244                     return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
1245                 }
1246                 if (parentWindow.mAttrs.type >= FIRST_SUB_WINDOW
1247                         && parentWindow.mAttrs.type <= LAST_SUB_WINDOW) {
1248                     Slog.w(TAG_WM, "Attempted to add window with token that is a sub-window: "
1249                             + attrs.token + ".  Aborting.");
1250                     return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
1251                 }
1252             }
1253 
1254             if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) {
1255                 Slog.w(TAG_WM, "Attempted to add private presentation window to a non-private display.  Aborting.");
1256                 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
1257             }
1258 
1259             if (type == TYPE_PRESENTATION && !displayContent.getDisplay().isPublicPresentation()) {
1260                 Slog.w(TAG_WM,
1261                         "Attempted to add presentation window to a non-suitable display.  "
1262                                 + "Aborting.");
1263                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
1264             }
1265 
1266             AppWindowToken atoken = null;
1267             final boolean hasParent = parentWindow != null;
1268             // Use existing parent window token for child windows since they go in the same token
1269             // as there parent window so we can apply the same policy on them.
1270             WindowToken token = displayContent.getWindowToken(
1271                     hasParent ? parentWindow.mAttrs.token : attrs.token);
1272             // If this is a child window, we want to apply the same type checking rules as the
1273             // parent window type.
1274             final int rootType = hasParent ? parentWindow.mAttrs.type : type;
1275 
1276             boolean addToastWindowRequiresToken = false;
1277 
1278             if (token == null) {
1279                 if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
1280                     Slog.w(TAG_WM, "Attempted to add application window with unknown token "
1281                           + attrs.token + ".  Aborting.");
1282                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1283                 }
1284                 if (rootType == TYPE_INPUT_METHOD) {
1285                     Slog.w(TAG_WM, "Attempted to add input method window with unknown token "
1286                           + attrs.token + ".  Aborting.");
1287                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1288                 }
1289                 if (rootType == TYPE_VOICE_INTERACTION) {
1290                     Slog.w(TAG_WM, "Attempted to add voice interaction window with unknown token "
1291                           + attrs.token + ".  Aborting.");
1292                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1293                 }
1294                 if (rootType == TYPE_WALLPAPER) {
1295                     Slog.w(TAG_WM, "Attempted to add wallpaper window with unknown token "
1296                           + attrs.token + ".  Aborting.");
1297                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1298                 }
1299                 if (rootType == TYPE_DREAM) {
1300                     Slog.w(TAG_WM, "Attempted to add Dream window with unknown token "
1301                           + attrs.token + ".  Aborting.");
1302                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1303                 }
1304                 if (rootType == TYPE_QS_DIALOG) {
1305                     Slog.w(TAG_WM, "Attempted to add QS dialog window with unknown token "
1306                           + attrs.token + ".  Aborting.");
1307                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1308                 }
1309                 if (rootType == TYPE_ACCESSIBILITY_OVERLAY) {
1310                     Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with unknown token "
1311                             + attrs.token + ".  Aborting.");
1312                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1313                 }
1314                 if (type == TYPE_TOAST) {
1315                     // Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
1316                     if (doesAddToastWindowRequireToken(attrs.packageName, callingUid,
1317                             parentWindow)) {
1318                         Slog.w(TAG_WM, "Attempted to add a toast window with unknown token "
1319                                 + attrs.token + ".  Aborting.");
1320                         return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1321                     }
1322                 }
1323                 final IBinder binder = attrs.token != null ? attrs.token : client.asBinder();
1324                 token = new WindowToken(this, binder, type, false, displayContent,
1325                         session.mCanAddInternalSystemWindow);
1326             } else if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
1327                 atoken = token.asAppWindowToken();
1328                 if (atoken == null) {
1329                     Slog.w(TAG_WM, "Attempted to add window with non-application token "
1330                           + token + ".  Aborting.");
1331                     return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
1332                 } else if (atoken.removed) {
1333                     Slog.w(TAG_WM, "Attempted to add window with exiting application token "
1334                           + token + ".  Aborting.");
1335                     return WindowManagerGlobal.ADD_APP_EXITING;
1336                 }
1337             } else if (rootType == TYPE_INPUT_METHOD) {
1338                 if (token.windowType != TYPE_INPUT_METHOD) {
1339                     Slog.w(TAG_WM, "Attempted to add input method window with bad token "
1340                             + attrs.token + ".  Aborting.");
1341                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1342                 }
1343             } else if (rootType == TYPE_VOICE_INTERACTION) {
1344                 if (token.windowType != TYPE_VOICE_INTERACTION) {
1345                     Slog.w(TAG_WM, "Attempted to add voice interaction window with bad token "
1346                             + attrs.token + ".  Aborting.");
1347                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1348                 }
1349             } else if (rootType == TYPE_WALLPAPER) {
1350                 if (token.windowType != TYPE_WALLPAPER) {
1351                     Slog.w(TAG_WM, "Attempted to add wallpaper window with bad token "
1352                             + attrs.token + ".  Aborting.");
1353                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1354                 }
1355             } else if (rootType == TYPE_DREAM) {
1356                 if (token.windowType != TYPE_DREAM) {
1357                     Slog.w(TAG_WM, "Attempted to add Dream window with bad token "
1358                             + attrs.token + ".  Aborting.");
1359                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1360                 }
1361             } else if (rootType == TYPE_ACCESSIBILITY_OVERLAY) {
1362                 if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) {
1363                     Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with bad token "
1364                             + attrs.token + ".  Aborting.");
1365                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1366                 }
1367             } else if (type == TYPE_TOAST) {
1368                 // Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
1369                 addToastWindowRequiresToken = doesAddToastWindowRequireToken(attrs.packageName,
1370                         callingUid, parentWindow);
1371                 if (addToastWindowRequiresToken && token.windowType != TYPE_TOAST) {
1372                     Slog.w(TAG_WM, "Attempted to add a toast window with bad token "
1373                             + attrs.token + ".  Aborting.");
1374                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1375                 }
1376             } else if (type == TYPE_QS_DIALOG) {
1377                 if (token.windowType != TYPE_QS_DIALOG) {
1378                     Slog.w(TAG_WM, "Attempted to add QS dialog window with bad token "
1379                             + attrs.token + ".  Aborting.");
1380                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1381                 }
1382             } else if (token.asAppWindowToken() != null) {
1383                 Slog.w(TAG_WM, "Non-null appWindowToken for system window of rootType=" + rootType);
1384                 // It is not valid to use an app token with other system types; we will
1385                 // instead make a new token for it (as if null had been passed in for the token).
1386                 attrs.token = null;
1387                 token = new WindowToken(this, client.asBinder(), type, false, displayContent,
1388                         session.mCanAddInternalSystemWindow);
1389             }
1390 
1391             final WindowState win = new WindowState(this, session, client, token, parentWindow,
1392                     appOp[0], seq, attrs, viewVisibility, session.mUid,
1393                     session.mCanAddInternalSystemWindow);
1394             if (win.mDeathRecipient == null) {
1395                 // Client has apparently died, so there is no reason to
1396                 // continue.
1397                 Slog.w(TAG_WM, "Adding window client " + client.asBinder()
1398                         + " that is dead, aborting.");
1399                 return WindowManagerGlobal.ADD_APP_EXITING;
1400             }
1401 
1402             if (win.getDisplayContent() == null) {
1403                 Slog.w(TAG_WM, "Adding window to Display that has been removed.");
1404                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
1405             }
1406 
1407             mPolicy.adjustWindowParamsLw(win.mAttrs);
1408             win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
1409 
1410             res = mPolicy.prepareAddWindowLw(win, attrs);
1411             if (res != WindowManagerGlobal.ADD_OKAY) {
1412                 return res;
1413             }
1414 
1415             final boolean openInputChannels = (outInputChannel != null
1416                     && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
1417             if  (openInputChannels) {
1418                 win.openInputChannel(outInputChannel);
1419             }
1420 
1421             // If adding a toast requires a token for this app we always schedule hiding
1422             // toast windows to make sure they don't stick around longer then necessary.
1423             // We hide instead of remove such windows as apps aren't prepared to handle
1424             // windows being removed under them.
1425             //
1426             // If the app is older it can add toasts without a token and hence overlay
1427             // other apps. To be maximally compatible with these apps we will hide the
1428             // window after the toast timeout only if the focused window is from another
1429             // UID, otherwise we allow unlimited duration. When a UID looses focus we
1430             // schedule hiding all of its toast windows.
1431             if (type == TYPE_TOAST) {
1432                 if (!getDefaultDisplayContentLocked().canAddToastWindowForUid(callingUid)) {
1433                     Slog.w(TAG_WM, "Adding more than one toast window for UID at a time.");
1434                     return WindowManagerGlobal.ADD_DUPLICATE_ADD;
1435                 }
1436                 // Make sure this happens before we moved focus as one can make the
1437                 // toast focusable to force it not being hidden after the timeout.
1438                 // Focusable toasts are always timed out to prevent a focused app to
1439                 // show a focusable toasts while it has focus which will be kept on
1440                 // the screen after the activity goes away.
1441                 if (addToastWindowRequiresToken
1442                         || (attrs.flags & LayoutParams.FLAG_NOT_FOCUSABLE) == 0
1443                         || mCurrentFocus == null
1444                         || mCurrentFocus.mOwnerUid != callingUid) {
1445                     mH.sendMessageDelayed(
1446                             mH.obtainMessage(H.WINDOW_HIDE_TIMEOUT, win),
1447                             win.mAttrs.hideTimeoutMilliseconds);
1448                 }
1449             }
1450 
1451             // From now on, no exceptions or errors allowed!
1452 
1453             res = WindowManagerGlobal.ADD_OKAY;
1454             if (mCurrentFocus == null) {
1455                 mWinAddedSinceNullFocus.add(win);
1456             }
1457 
1458             if (excludeWindowTypeFromTapOutTask(type)) {
1459                 displayContent.mTapExcludedWindows.add(win);
1460             }
1461 
1462             origId = Binder.clearCallingIdentity();
1463 
1464             win.attach();
1465             mWindowMap.put(client.asBinder(), win);
1466             if (win.mAppOp != AppOpsManager.OP_NONE) {
1467                 int startOpResult = mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(),
1468                         win.getOwningPackage());
1469                 if ((startOpResult != AppOpsManager.MODE_ALLOWED) &&
1470                         (startOpResult != AppOpsManager.MODE_DEFAULT)) {
1471                     win.setAppOpVisibilityLw(false);
1472                 }
1473             }
1474 
1475             final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty();
1476             win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);
1477 
1478             final AppWindowToken aToken = token.asAppWindowToken();
1479             if (type == TYPE_APPLICATION_STARTING && aToken != null) {
1480                 aToken.startingWindow = win;
1481                 if (DEBUG_STARTING_WINDOW) Slog.v (TAG_WM, "addWindow: " + aToken
1482                         + " startingWindow=" + win);
1483             }
1484 
1485             boolean imMayMove = true;
1486 
1487             win.mToken.addWindow(win);
1488             if (type == TYPE_INPUT_METHOD) {
1489                 win.mGivenInsetsPending = true;
1490                 setInputMethodWindowLocked(win);
1491                 imMayMove = false;
1492             } else if (type == TYPE_INPUT_METHOD_DIALOG) {
1493                 displayContent.computeImeTarget(true /* updateImeTarget */);
1494                 imMayMove = false;
1495             } else {
1496                 if (type == TYPE_WALLPAPER) {
1497                     displayContent.mWallpaperController.clearLastWallpaperTimeoutTime();
1498                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1499                 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
1500                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1501                 } else if (displayContent.mWallpaperController.isBelowWallpaperTarget(win)) {
1502                     // If there is currently a wallpaper being shown, and
1503                     // the base layer of the new window is below the current
1504                     // layer of the target window, then adjust the wallpaper.
1505                     // This is to avoid a new window being placed between the
1506                     // wallpaper and its target.
1507                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1508                 }
1509             }
1510 
1511             // If the window is being added to a stack that's currently adjusted for IME,
1512             // make sure to apply the same adjust to this new window.
1513             win.applyAdjustForImeIfNeeded();
1514 
1515             if (type == TYPE_DOCK_DIVIDER) {
1516                 mRoot.getDisplayContent(displayId).getDockedDividerController().setWindow(win);
1517             }
1518 
1519             final WindowStateAnimator winAnimator = win.mWinAnimator;
1520             winAnimator.mEnterAnimationPending = true;
1521             winAnimator.mEnteringAnimation = true;
1522             // Check if we need to prepare a transition for replacing window first.
1523             if (atoken != null && atoken.isVisible()
1524                     && !prepareWindowReplacementTransition(atoken)) {
1525                 // If not, check if need to set up a dummy transition during display freeze
1526                 // so that the unfreeze wait for the apps to draw. This might be needed if
1527                 // the app is relaunching.
1528                 prepareNoneTransitionForRelaunching(atoken);
1529             }
1530 
1531             if (displayContent.isDefaultDisplay) {
1532                 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
1533                 final Rect taskBounds;
1534                 if (atoken != null && atoken.getTask() != null) {
1535                     taskBounds = mTmpRect;
1536                     atoken.getTask().getBounds(mTmpRect);
1537                 } else {
1538                     taskBounds = null;
1539                 }
1540                 if (mPolicy.getInsetHintLw(win.mAttrs, taskBounds, displayInfo.rotation,
1541                         displayInfo.logicalWidth, displayInfo.logicalHeight, outContentInsets,
1542                         outStableInsets, outOutsets)) {
1543                     res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR;
1544                 }
1545             } else {
1546                 outContentInsets.setEmpty();
1547                 outStableInsets.setEmpty();
1548             }
1549 
1550             if (mInTouchMode) {
1551                 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
1552             }
1553             if (win.mAppToken == null || !win.mAppToken.isClientHidden()) {
1554                 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
1555             }
1556 
1557             mInputMonitor.setUpdateInputWindowsNeededLw();
1558 
1559             boolean focusChanged = false;
1560             if (win.canReceiveKeys()) {
1561                 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
1562                         false /*updateInputWindows*/);
1563                 if (focusChanged) {
1564                     imMayMove = false;
1565                 }
1566             }
1567 
1568             if (imMayMove) {
1569                 displayContent.computeImeTarget(true /* updateImeTarget */);
1570             }
1571 
1572             // Don't do layout here, the window must call
1573             // relayout to be displayed, so we'll do it there.
1574             displayContent.assignWindowLayers(false /* setLayoutNeeded */);
1575 
1576             if (focusChanged) {
1577                 mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
1578             }
1579             mInputMonitor.updateInputWindowsLw(false /*force*/);
1580 
1581             if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addWindow: New client "
1582                     + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5));
1583 
1584             if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false, displayId)) {
1585                 reportNewConfig = true;
1586             }
1587         }
1588 
1589         if (reportNewConfig) {
1590             sendNewConfiguration(displayId);
1591         }
1592 
1593         Binder.restoreCallingIdentity(origId);
1594 
1595         return res;
1596     }
1597 
doesAddToastWindowRequireToken(String packageName, int callingUid, WindowState attachedWindow)1598     private boolean doesAddToastWindowRequireToken(String packageName, int callingUid,
1599             WindowState attachedWindow) {
1600         // Try using the target SDK of the root window
1601         if (attachedWindow != null) {
1602             return attachedWindow.mAppToken != null
1603                     && attachedWindow.mAppToken.mTargetSdk >= Build.VERSION_CODES.O;
1604         } else {
1605             // Otherwise, look at the package
1606             try {
1607                 ApplicationInfo appInfo = mContext.getPackageManager()
1608                         .getApplicationInfoAsUser(packageName, 0,
1609                                 UserHandle.getUserId(callingUid));
1610                 if (appInfo.uid != callingUid) {
1611                     throw new SecurityException("Package " + packageName + " not in UID "
1612                             + callingUid);
1613                 }
1614                 if (appInfo.targetSdkVersion >= Build.VERSION_CODES.O) {
1615                     return true;
1616                 }
1617             } catch (PackageManager.NameNotFoundException e) {
1618                 /* ignore */
1619             }
1620         }
1621         return false;
1622     }
1623 
1624     /**
1625      * Returns true if we're done setting up any transitions.
1626      */
prepareWindowReplacementTransition(AppWindowToken atoken)1627     private boolean prepareWindowReplacementTransition(AppWindowToken atoken) {
1628         atoken.clearAllDrawn();
1629         final WindowState replacedWindow = atoken.getReplacingWindow();
1630         if (replacedWindow == null) {
1631             // We expect to already receive a request to remove the old window. If it did not
1632             // happen, let's just simply add a window.
1633             return false;
1634         }
1635         // We use the visible frame, because we want the animation to morph the window from what
1636         // was visible to the user to the final destination of the new window.
1637         Rect frame = replacedWindow.mVisibleFrame;
1638         // We treat this as if this activity was opening, so we can trigger the app transition
1639         // animation and piggy-back on existing transition animation infrastructure.
1640         mOpeningApps.add(atoken);
1641         prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_RELAUNCH, ALWAYS_KEEP_CURRENT);
1642         mAppTransition.overridePendingAppTransitionClipReveal(frame.left, frame.top,
1643                 frame.width(), frame.height());
1644         executeAppTransition();
1645         return true;
1646     }
1647 
prepareNoneTransitionForRelaunching(AppWindowToken atoken)1648     private void prepareNoneTransitionForRelaunching(AppWindowToken atoken) {
1649         // Set up a none-transition and add the app to opening apps, so that the display
1650         // unfreeze wait for the apps to be drawn.
1651         // Note that if the display unfroze already because app unfreeze timed out,
1652         // we don't set up the transition anymore and just let it go.
1653         if (mDisplayFrozen && !mOpeningApps.contains(atoken) && atoken.isRelaunching()) {
1654             mOpeningApps.add(atoken);
1655             prepareAppTransition(AppTransition.TRANSIT_NONE, !ALWAYS_KEEP_CURRENT);
1656             executeAppTransition();
1657         }
1658     }
1659 
1660     /**
1661      * Returns whether screen capture is disabled for all windows of a specific user.
1662      */
isScreenCaptureDisabledLocked(int userId)1663     boolean isScreenCaptureDisabledLocked(int userId) {
1664         Boolean disabled = mScreenCaptureDisabled.get(userId);
1665         if (disabled == null) {
1666             return false;
1667         }
1668         return disabled;
1669     }
1670 
isSecureLocked(WindowState w)1671     boolean isSecureLocked(WindowState w) {
1672         if ((w.mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
1673             return true;
1674         }
1675         if (isScreenCaptureDisabledLocked(UserHandle.getUserId(w.mOwnerUid))) {
1676             return true;
1677         }
1678         return false;
1679     }
1680 
1681     @Override
enableSurfaceTrace(ParcelFileDescriptor pfd)1682     public void enableSurfaceTrace(ParcelFileDescriptor pfd) {
1683         final int callingUid = Binder.getCallingUid();
1684         if (callingUid != SHELL_UID && callingUid != ROOT_UID) {
1685             throw new SecurityException("Only shell can call enableSurfaceTrace");
1686         }
1687 
1688         synchronized (mWindowMap) {
1689             mRoot.enableSurfaceTrace(pfd);
1690         }
1691     }
1692 
1693     @Override
disableSurfaceTrace()1694     public void disableSurfaceTrace() {
1695         final int callingUid = Binder.getCallingUid();
1696         if (callingUid != SHELL_UID && callingUid != ROOT_UID &&
1697             callingUid != SYSTEM_UID) {
1698             throw new SecurityException("Only shell can call disableSurfaceTrace");
1699         }
1700         synchronized (mWindowMap) {
1701             mRoot.disableSurfaceTrace();
1702         }
1703     }
1704 
1705     /**
1706      * Set mScreenCaptureDisabled for specific user
1707      */
1708     @Override
setScreenCaptureDisabled(int userId, boolean disabled)1709     public void setScreenCaptureDisabled(int userId, boolean disabled) {
1710         int callingUid = Binder.getCallingUid();
1711         if (callingUid != SYSTEM_UID) {
1712             throw new SecurityException("Only system can call setScreenCaptureDisabled.");
1713         }
1714 
1715         synchronized(mWindowMap) {
1716             mScreenCaptureDisabled.put(userId, disabled);
1717             // Update secure surface for all windows belonging to this user.
1718             mRoot.setSecureSurfaceState(userId, disabled);
1719         }
1720     }
1721 
removeWindow(Session session, IWindow client)1722     void removeWindow(Session session, IWindow client) {
1723         synchronized(mWindowMap) {
1724             WindowState win = windowForClientLocked(session, client, false);
1725             if (win == null) {
1726                 return;
1727             }
1728             win.removeIfPossible();
1729         }
1730     }
1731 
1732     /**
1733      * Performs some centralized bookkeeping clean-up on the window that is being removed.
1734      * NOTE: Should only be called from {@link WindowState#removeImmediately()}
1735      * TODO: Maybe better handled with a method {@link WindowContainer#removeChild} if we can
1736      * figure-out a good way to have all parents of a WindowState doing the same thing without
1737      * forgetting to add the wiring when a new parent of WindowState is added.
1738      */
postWindowRemoveCleanupLocked(WindowState win)1739     void postWindowRemoveCleanupLocked(WindowState win) {
1740         if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "postWindowRemoveCleanupLocked: " + win);
1741         mWindowMap.remove(win.mClient.asBinder());
1742         if (win.mAppOp != AppOpsManager.OP_NONE) {
1743             mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage());
1744         }
1745 
1746         if (mCurrentFocus == null) {
1747             mWinRemovedSinceNullFocus.add(win);
1748         }
1749         mPendingRemove.remove(win);
1750         mResizingWindows.remove(win);
1751         updateNonSystemOverlayWindowsVisibilityIfNeeded(win, false /* surfaceShown */);
1752         mWindowsChanged = true;
1753         if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Final remove of window: " + win);
1754 
1755         if (mInputMethodWindow == win) {
1756             setInputMethodWindowLocked(null);
1757         }
1758 
1759         final WindowToken token = win.mToken;
1760         final AppWindowToken atoken = win.mAppToken;
1761         if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Removing " + win + " from " + token);
1762         // Window will already be removed from token before this post clean-up method is called.
1763         if (token.isEmpty()) {
1764             if (!token.mPersistOnEmpty) {
1765                 token.removeImmediately();
1766             } else if (atoken != null) {
1767                 // TODO: Should this be moved into AppWindowToken.removeWindow? Might go away after
1768                 // re-factor.
1769                 atoken.firstWindowDrawn = false;
1770                 atoken.clearAllDrawn();
1771                 final TaskStack stack = atoken.getStack();
1772                 if (stack != null) {
1773                     stack.mExitingAppTokens.remove(atoken);
1774                 }
1775             }
1776         }
1777 
1778         if (atoken != null) {
1779             atoken.postWindowRemoveStartingWindowCleanup(win);
1780         }
1781 
1782         final DisplayContent dc = win.getDisplayContent();
1783         if (win.mAttrs.type == TYPE_WALLPAPER) {
1784             dc.mWallpaperController.clearLastWallpaperTimeoutTime();
1785             dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1786         } else if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
1787             dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1788         }
1789 
1790         if (dc != null && !mWindowPlacerLocked.isInLayout()) {
1791             dc.assignWindowLayers(true /* setLayoutNeeded */);
1792             mWindowPlacerLocked.performSurfacePlacement();
1793             if (win.mAppToken != null) {
1794                 win.mAppToken.updateReportedVisibilityLocked();
1795             }
1796         }
1797 
1798         mInputMonitor.updateInputWindowsLw(true /*force*/);
1799     }
1800 
setInputMethodWindowLocked(WindowState win)1801     void setInputMethodWindowLocked(WindowState win) {
1802         mInputMethodWindow = win;
1803         final DisplayContent dc = win != null
1804                 ? win.getDisplayContent() : getDefaultDisplayContentLocked();
1805         dc.computeImeTarget(true /* updateImeTarget */);
1806     }
1807 
updateAppOpsState()1808     private void updateAppOpsState() {
1809         synchronized(mWindowMap) {
1810             mRoot.updateAppOpsState();
1811         }
1812     }
1813 
logSurface(WindowState w, String msg, boolean withStackTrace)1814     static void logSurface(WindowState w, String msg, boolean withStackTrace) {
1815         String str = "  SURFACE " + msg + ": " + w;
1816         if (withStackTrace) {
1817             logWithStack(TAG, str);
1818         } else {
1819             Slog.i(TAG_WM, str);
1820         }
1821     }
1822 
logSurface(SurfaceControl s, String title, String msg)1823     static void logSurface(SurfaceControl s, String title, String msg) {
1824         String str = "  SURFACE " + s + ": " + msg + " / " + title;
1825         Slog.i(TAG_WM, str);
1826     }
1827 
logWithStack(String tag, String s)1828     static void logWithStack(String tag, String s) {
1829         RuntimeException e = null;
1830         if (SHOW_STACK_CRAWLS) {
1831             e = new RuntimeException();
1832             e.fillInStackTrace();
1833         }
1834         Slog.i(tag, s, e);
1835     }
1836 
setTransparentRegionWindow(Session session, IWindow client, Region region)1837     void setTransparentRegionWindow(Session session, IWindow client, Region region) {
1838         long origId = Binder.clearCallingIdentity();
1839         try {
1840             synchronized (mWindowMap) {
1841                 WindowState w = windowForClientLocked(session, client, false);
1842                 if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
1843                         "transparentRegionHint=" + region, false);
1844 
1845                 if ((w != null) && w.mHasSurface) {
1846                     w.mWinAnimator.setTransparentRegionHintLocked(region);
1847                 }
1848             }
1849         } finally {
1850             Binder.restoreCallingIdentity(origId);
1851         }
1852     }
1853 
setInsetsWindow(Session session, IWindow client, int touchableInsets, Rect contentInsets, Rect visibleInsets, Region touchableRegion)1854     void setInsetsWindow(Session session, IWindow client, int touchableInsets, Rect contentInsets,
1855             Rect visibleInsets, Region touchableRegion) {
1856         long origId = Binder.clearCallingIdentity();
1857         try {
1858             synchronized (mWindowMap) {
1859                 WindowState w = windowForClientLocked(session, client, false);
1860                 if (DEBUG_LAYOUT) Slog.d(TAG, "setInsetsWindow " + w
1861                         + ", contentInsets=" + w.mGivenContentInsets + " -> " + contentInsets
1862                         + ", visibleInsets=" + w.mGivenVisibleInsets + " -> " + visibleInsets
1863                         + ", touchableRegion=" + w.mGivenTouchableRegion + " -> " + touchableRegion
1864                         + ", touchableInsets " + w.mTouchableInsets + " -> " + touchableInsets);
1865                 if (w != null) {
1866                     w.mGivenInsetsPending = false;
1867                     w.mGivenContentInsets.set(contentInsets);
1868                     w.mGivenVisibleInsets.set(visibleInsets);
1869                     w.mGivenTouchableRegion.set(touchableRegion);
1870                     w.mTouchableInsets = touchableInsets;
1871                     if (w.mGlobalScale != 1) {
1872                         w.mGivenContentInsets.scale(w.mGlobalScale);
1873                         w.mGivenVisibleInsets.scale(w.mGlobalScale);
1874                         w.mGivenTouchableRegion.scale(w.mGlobalScale);
1875                     }
1876                     w.setDisplayLayoutNeeded();
1877                     mWindowPlacerLocked.performSurfacePlacement();
1878                 }
1879             }
1880         } finally {
1881             Binder.restoreCallingIdentity(origId);
1882         }
1883     }
1884 
getWindowDisplayFrame(Session session, IWindow client, Rect outDisplayFrame)1885     public void getWindowDisplayFrame(Session session, IWindow client,
1886             Rect outDisplayFrame) {
1887         synchronized(mWindowMap) {
1888             WindowState win = windowForClientLocked(session, client, false);
1889             if (win == null) {
1890                 outDisplayFrame.setEmpty();
1891                 return;
1892             }
1893             outDisplayFrame.set(win.mDisplayFrame);
1894         }
1895     }
1896 
onRectangleOnScreenRequested(IBinder token, Rect rectangle)1897     public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
1898         synchronized (mWindowMap) {
1899             if (mAccessibilityController != null) {
1900                 WindowState window = mWindowMap.get(token);
1901                 //TODO (multidisplay): Magnification is supported only for the default display.
1902                 if (window != null && window.getDisplayId() == DEFAULT_DISPLAY) {
1903                     mAccessibilityController.onRectangleOnScreenRequestedLocked(rectangle);
1904                 }
1905             }
1906         }
1907     }
1908 
getWindowId(IBinder token)1909     public IWindowId getWindowId(IBinder token) {
1910         synchronized (mWindowMap) {
1911             WindowState window = mWindowMap.get(token);
1912             return window != null ? window.mWindowId : null;
1913         }
1914     }
1915 
pokeDrawLock(Session session, IBinder token)1916     public void pokeDrawLock(Session session, IBinder token) {
1917         synchronized (mWindowMap) {
1918             WindowState window = windowForClientLocked(session, token, false);
1919             if (window != null) {
1920                 window.pokeDrawLockLw(mDrawLockTimeoutMillis);
1921             }
1922         }
1923     }
1924 
relayoutWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame, MergedConfiguration mergedConfiguration, Surface outSurface)1925     public int relayoutWindow(Session session, IWindow client, int seq,
1926             WindowManager.LayoutParams attrs, int requestedWidth,
1927             int requestedHeight, int viewVisibility, int flags,
1928             Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
1929             Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
1930             MergedConfiguration mergedConfiguration, Surface outSurface) {
1931         int result = 0;
1932         boolean configChanged;
1933         boolean hasStatusBarPermission =
1934                 mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
1935                         == PackageManager.PERMISSION_GRANTED;
1936 
1937         long origId = Binder.clearCallingIdentity();
1938         final int displayId;
1939         synchronized(mWindowMap) {
1940             WindowState win = windowForClientLocked(session, client, false);
1941             if (win == null) {
1942                 return 0;
1943             }
1944             displayId = win.getDisplayId();
1945 
1946             WindowStateAnimator winAnimator = win.mWinAnimator;
1947             if (viewVisibility != View.GONE) {
1948                 win.setRequestedSize(requestedWidth, requestedHeight);
1949             }
1950 
1951             int attrChanges = 0;
1952             int flagChanges = 0;
1953             if (attrs != null) {
1954                 mPolicy.adjustWindowParamsLw(attrs);
1955                 // if they don't have the permission, mask out the status bar bits
1956                 if (seq == win.mSeq) {
1957                     int systemUiVisibility = attrs.systemUiVisibility
1958                             | attrs.subtreeSystemUiVisibility;
1959                     if ((systemUiVisibility & DISABLE_MASK) != 0) {
1960                         if (!hasStatusBarPermission) {
1961                             systemUiVisibility &= ~DISABLE_MASK;
1962                         }
1963                     }
1964                     win.mSystemUiVisibility = systemUiVisibility;
1965                 }
1966                 if (win.mAttrs.type != attrs.type) {
1967                     throw new IllegalArgumentException(
1968                             "Window type can not be changed after the window is added.");
1969                 }
1970 
1971                 // Odd choice but less odd than embedding in copyFrom()
1972                 if ((attrs.privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY)
1973                         != 0) {
1974                     attrs.x = win.mAttrs.x;
1975                     attrs.y = win.mAttrs.y;
1976                     attrs.width = win.mAttrs.width;
1977                     attrs.height = win.mAttrs.height;
1978                 }
1979 
1980                 flagChanges = win.mAttrs.flags ^= attrs.flags;
1981                 attrChanges = win.mAttrs.copyFrom(attrs);
1982                 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
1983                         | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
1984                     win.mLayoutNeeded = true;
1985                 }
1986                 if (win.mAppToken != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0
1987                         || (flagChanges & FLAG_DISMISS_KEYGUARD) != 0)) {
1988                     win.mAppToken.checkKeyguardFlagsChanged();
1989                 }
1990                 if (((attrChanges & LayoutParams.ACCESSIBILITY_TITLE_CHANGED) != 0)
1991                         && (mAccessibilityController != null)
1992                         && (win.getDisplayId() == DEFAULT_DISPLAY)) {
1993                     // No move or resize, but the controller checks for title changes as well
1994                     mAccessibilityController.onSomeWindowResizedOrMovedLocked();
1995                 }
1996 
1997                 if ((flagChanges & PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
1998                     updateNonSystemOverlayWindowsVisibilityIfNeeded(
1999                             win, win.mWinAnimator.getShown());
2000                 }
2001             }
2002 
2003             if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility
2004                     + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
2005             winAnimator.mSurfaceDestroyDeferred = (flags & RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
2006             win.mEnforceSizeCompat =
2007                     (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
2008             if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
2009                 winAnimator.mAlpha = attrs.alpha;
2010             }
2011             win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);
2012 
2013             if (win.mAttrs.surfaceInsets.left != 0
2014                     || win.mAttrs.surfaceInsets.top != 0
2015                     || win.mAttrs.surfaceInsets.right != 0
2016                     || win.mAttrs.surfaceInsets.bottom != 0) {
2017                 winAnimator.setOpaqueLocked(false);
2018             }
2019 
2020             boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0;
2021             final boolean isDefaultDisplay = win.isDefaultDisplay();
2022             boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility
2023                     || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
2024                     || (!win.mRelayoutCalled));
2025 
2026             boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
2027                     && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
2028             wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
2029             if ((flagChanges & FLAG_SECURE) != 0 && winAnimator.mSurfaceController != null) {
2030                 winAnimator.mSurfaceController.setSecure(isSecureLocked(win));
2031             }
2032 
2033             win.mRelayoutCalled = true;
2034             win.mInRelayout = true;
2035 
2036             final int oldVisibility = win.mViewVisibility;
2037             win.mViewVisibility = viewVisibility;
2038             if (DEBUG_SCREEN_ON) {
2039                 RuntimeException stack = new RuntimeException();
2040                 stack.fillInStackTrace();
2041                 Slog.i(TAG_WM, "Relayout " + win + ": oldVis=" + oldVisibility
2042                         + " newVis=" + viewVisibility, stack);
2043             }
2044 
2045             // We should only relayout if the view is visible, it is a starting window, or the
2046             // associated appToken is not hidden.
2047             final boolean shouldRelayout = viewVisibility == View.VISIBLE &&
2048                 (win.mAppToken == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
2049                     || !win.mAppToken.isClientHidden());
2050 
2051             if (shouldRelayout) {
2052                 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_1");
2053 
2054                 // We are about to create a surface, but we didn't run a layout yet. So better run
2055                 // a layout now that we already know the right size, as a resize call will make the
2056                 // surface transaction blocking until next vsync and slow us down.
2057                 // TODO: Ideally we'd create the surface after running layout a bit further down,
2058                 // but moving this seems to be too risky at this point in the release.
2059                 if (win.mLayoutSeq == -1) {
2060                     win.setDisplayLayoutNeeded();
2061                     mWindowPlacerLocked.performSurfacePlacement(true);
2062                 }
2063                 result = win.relayoutVisibleWindow(result, attrChanges, oldVisibility);
2064 
2065                 try {
2066                     result = createSurfaceControl(outSurface, result, win, winAnimator);
2067                 } catch (Exception e) {
2068                     mInputMonitor.updateInputWindowsLw(true /*force*/);
2069 
2070                     Slog.w(TAG_WM, "Exception thrown when creating surface for client "
2071                              + client + " (" + win.mAttrs.getTitle() + ")",
2072                              e);
2073                     Binder.restoreCallingIdentity(origId);
2074                     return 0;
2075                 }
2076                 if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
2077                     focusMayChange = isDefaultDisplay;
2078                 }
2079                 if (win.mAttrs.type == TYPE_INPUT_METHOD && mInputMethodWindow == null) {
2080                     setInputMethodWindowLocked(win);
2081                     imMayMove = true;
2082                 }
2083                 win.adjustStartingWindowFlags();
2084                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2085             } else {
2086                 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_2");
2087 
2088                 winAnimator.mEnterAnimationPending = false;
2089                 winAnimator.mEnteringAnimation = false;
2090                 final boolean usingSavedSurfaceBeforeVisible =
2091                         oldVisibility != View.VISIBLE && win.isAnimatingWithSavedSurface();
2092                 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
2093                     if (winAnimator.hasSurface() && !win.mAnimatingExit
2094                             && usingSavedSurfaceBeforeVisible) {
2095                         Slog.d(TAG, "Ignoring layout to invisible when using saved surface " + win);
2096                     }
2097                 }
2098 
2099                 if (winAnimator.hasSurface() && !win.mAnimatingExit
2100                         && !usingSavedSurfaceBeforeVisible) {
2101                     if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Relayout invis " + win
2102                             + ": mAnimatingExit=" + win.mAnimatingExit);
2103                     // If we are not currently running the exit animation, we
2104                     // need to see about starting one.
2105                     // We don't want to animate visibility of windows which are pending
2106                     // replacement. In the case of activity relaunch child windows
2107                     // could request visibility changes as they are detached from the main
2108                     // application window during the tear down process. If we satisfied
2109                     // these visibility changes though, we would cause a visual glitch
2110                     // hiding the window before it's replacement was available.
2111                     // So we just do nothing on our side.
2112                     if (!win.mWillReplaceWindow) {
2113                         focusMayChange = tryStartExitingAnimation(
2114                                 win, winAnimator, isDefaultDisplay, focusMayChange);
2115                     }
2116                     result |= RELAYOUT_RES_SURFACE_CHANGED;
2117                 }
2118                 if (viewVisibility == View.VISIBLE && winAnimator.hasSurface()) {
2119                     // We already told the client to go invisible, but the message may not be
2120                     // handled yet, or it might want to draw a last frame. If we already have a
2121                     // surface, let the client use that, but don't create new surface at this point.
2122                     Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: getSurface");
2123                     winAnimator.mSurfaceController.getSurface(outSurface);
2124                     Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2125                 } else {
2126                     if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win);
2127 
2128                     try {
2129                         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wmReleaseOutSurface_"
2130                                 + win.mAttrs.getTitle());
2131                         outSurface.release();
2132                     } finally {
2133                         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2134                     }
2135                 }
2136 
2137                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2138             }
2139 
2140             if (focusMayChange) {
2141                 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
2142                 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
2143                         false /*updateInputWindows*/)) {
2144                     imMayMove = false;
2145                 }
2146                 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
2147             }
2148 
2149             // updateFocusedWindowLocked() already assigned layers so we only need to
2150             // reassign them at this point if the IM window state gets shuffled
2151             boolean toBeDisplayed = (result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
2152             final DisplayContent dc = win.getDisplayContent();
2153             if (imMayMove) {
2154                 dc.computeImeTarget(true /* updateImeTarget */);
2155                 if (toBeDisplayed) {
2156                     // Little hack here -- we -should- be able to rely on the function to return
2157                     // true if the IME has moved and needs its layer recomputed. However, if the IME
2158                     // was hidden and isn't actually moved in the list, its layer may be out of data
2159                     // so we make sure to recompute it.
2160                     dc.assignWindowLayers(false /* setLayoutNeeded */);
2161                 }
2162             }
2163 
2164             if (wallpaperMayMove) {
2165                 win.getDisplayContent().pendingLayoutChanges |=
2166                         WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2167             }
2168 
2169             if (win.mAppToken != null) {
2170                 mUnknownAppVisibilityController.notifyRelayouted(win.mAppToken);
2171             }
2172 
2173             win.setDisplayLayoutNeeded();
2174             win.mGivenInsetsPending = (flags & WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
2175             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
2176                     "relayoutWindow: updateOrientationFromAppTokens");
2177             configChanged = updateOrientationFromAppTokensLocked(false, displayId);
2178             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2179 
2180             // We may be deferring layout passes at the moment, but since the client is interested
2181             // in the new out values right now we need to force a layout.
2182             mWindowPlacerLocked.performSurfacePlacement(true /* force */);
2183             if (toBeDisplayed && win.mIsWallpaper) {
2184                 DisplayInfo displayInfo = win.getDisplayContent().getDisplayInfo();
2185                 dc.mWallpaperController.updateWallpaperOffset(
2186                         win, displayInfo.logicalWidth, displayInfo.logicalHeight, false);
2187             }
2188             if (win.mAppToken != null) {
2189                 win.mAppToken.updateReportedVisibilityLocked();
2190             }
2191             if (winAnimator.mReportSurfaceResized) {
2192                 winAnimator.mReportSurfaceResized = false;
2193                 result |= WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED;
2194             }
2195             if (mPolicy.isNavBarForcedShownLw(win)) {
2196                 result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR;
2197             }
2198             if (!win.isGoneForLayoutLw()) {
2199                 win.mResizedWhileGone = false;
2200             }
2201 
2202             // We must always send the latest {@link MergedConfiguration}, regardless of whether we
2203             // have already reported it. The client might not have processed the previous value yet
2204             // and needs process it before handling the corresponding window frame. the variable
2205             // {@code mergedConfiguration} is an out parameter that will be passed back to the
2206             // client over IPC and checked there.
2207             // Note: in the cases where the window is tied to an activity, we should not send a
2208             // configuration update when the window has requested to be hidden. Doing so can lead
2209             // to the client erroneously accepting a configuration that would have otherwise caused
2210             // an activity restart. We instead hand back the last reported
2211             // {@link MergedConfiguration}.
2212             if (shouldRelayout) {
2213                 win.getMergedConfiguration(mergedConfiguration);
2214             } else {
2215                 win.getLastReportedMergedConfiguration(mergedConfiguration);
2216             }
2217 
2218             win.setLastReportedMergedConfiguration(mergedConfiguration);
2219 
2220             outFrame.set(win.mCompatFrame);
2221             outOverscanInsets.set(win.mOverscanInsets);
2222             outContentInsets.set(win.mContentInsets);
2223             win.mLastRelayoutContentInsets.set(win.mContentInsets);
2224             outVisibleInsets.set(win.mVisibleInsets);
2225             outStableInsets.set(win.mStableInsets);
2226             outOutsets.set(win.mOutsets);
2227             outBackdropFrame.set(win.getBackdropFrame(win.mFrame));
2228             if (localLOGV) Slog.v(
2229                 TAG_WM, "Relayout given client " + client.asBinder()
2230                 + ", requestedWidth=" + requestedWidth
2231                 + ", requestedHeight=" + requestedHeight
2232                 + ", viewVisibility=" + viewVisibility
2233                 + "\nRelayout returning frame=" + outFrame
2234                 + ", surface=" + outSurface);
2235 
2236             if (localLOGV || DEBUG_FOCUS) Slog.v(
2237                 TAG_WM, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
2238 
2239             result |= mInTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0;
2240 
2241             mInputMonitor.updateInputWindowsLw(true /*force*/);
2242 
2243             if (DEBUG_LAYOUT) {
2244                 Slog.v(TAG_WM, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
2245             }
2246             win.mInRelayout = false;
2247         }
2248 
2249         if (configChanged) {
2250             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: sendNewConfiguration");
2251             sendNewConfiguration(displayId);
2252             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2253         }
2254         Binder.restoreCallingIdentity(origId);
2255         return result;
2256     }
2257 
tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator, boolean isDefaultDisplay, boolean focusMayChange)2258     private boolean tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator,
2259             boolean isDefaultDisplay, boolean focusMayChange) {
2260         // Try starting an animation; if there isn't one, we
2261         // can destroy the surface right away.
2262         int transit = WindowManagerPolicy.TRANSIT_EXIT;
2263         if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
2264             transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2265         }
2266         if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) {
2267             focusMayChange = isDefaultDisplay;
2268             win.mAnimatingExit = true;
2269             win.mWinAnimator.mAnimating = true;
2270         } else if (win.mWinAnimator.isAnimationSet()) {
2271             // Currently in a hide animation... turn this into
2272             // an exit.
2273             win.mAnimatingExit = true;
2274             win.mWinAnimator.mAnimating = true;
2275         } else if (win.getDisplayContent().mWallpaperController.isWallpaperTarget(win)) {
2276             // If the wallpaper is currently behind this
2277             // window, we need to change both of them inside
2278             // of a transaction to avoid artifacts.
2279             win.mAnimatingExit = true;
2280             win.mWinAnimator.mAnimating = true;
2281         } else {
2282             if (mInputMethodWindow == win) {
2283                 setInputMethodWindowLocked(null);
2284             }
2285             boolean stopped = win.mAppToken != null ? win.mAppToken.mAppStopped : false;
2286             // We set mDestroying=true so AppWindowToken#notifyAppStopped in-to destroy surfaces
2287             // will later actually destroy the surface if we do not do so here. Normally we leave
2288             // this to the exit animation.
2289             win.mDestroying = true;
2290             win.destroySurface(false, stopped);
2291         }
2292         // TODO(multidisplay): Magnification is supported only for the default display.
2293         if (mAccessibilityController != null && win.getDisplayId() == DEFAULT_DISPLAY) {
2294             mAccessibilityController.onWindowTransitionLocked(win, transit);
2295         }
2296 
2297         // When we start the exit animation we take the Surface from the client
2298         // so it will stop perturbing it. We need to likewise takeaway the SurfaceFlinger
2299         // side child surfaces, so they will remain preserved in their current state
2300         // (rather than be cleaned up immediately by the app code).
2301         SurfaceControl.openTransaction();
2302         winAnimator.detachChildren();
2303         SurfaceControl.closeTransaction();
2304 
2305         return focusMayChange;
2306     }
2307 
createSurfaceControl(Surface outSurface, int result, WindowState win, WindowStateAnimator winAnimator)2308     private int createSurfaceControl(Surface outSurface, int result, WindowState win,
2309             WindowStateAnimator winAnimator) {
2310         if (!win.mHasSurface) {
2311             result |= RELAYOUT_RES_SURFACE_CHANGED;
2312         }
2313 
2314         WindowSurfaceController surfaceController;
2315         try {
2316             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl");
2317             surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
2318         } finally {
2319             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2320         }
2321         if (surfaceController != null) {
2322             surfaceController.getSurface(outSurface);
2323             if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, "  OUT SURFACE " + outSurface + ": copied");
2324         } else {
2325             // For some reason there isn't a surface.  Clear the
2326             // caller's object so they see the same state.
2327             Slog.w(TAG_WM, "Failed to create surface control for " + win);
2328             outSurface.release();
2329         }
2330 
2331         return result;
2332     }
2333 
outOfMemoryWindow(Session session, IWindow client)2334     public boolean outOfMemoryWindow(Session session, IWindow client) {
2335         final long origId = Binder.clearCallingIdentity();
2336 
2337         try {
2338             synchronized (mWindowMap) {
2339                 WindowState win = windowForClientLocked(session, client, false);
2340                 if (win == null) {
2341                     return false;
2342                 }
2343                 return mRoot.reclaimSomeSurfaceMemory(win.mWinAnimator, "from-client", false);
2344             }
2345         } finally {
2346             Binder.restoreCallingIdentity(origId);
2347         }
2348     }
2349 
finishDrawingWindow(Session session, IWindow client)2350     void finishDrawingWindow(Session session, IWindow client) {
2351         final long origId = Binder.clearCallingIdentity();
2352         try {
2353             synchronized (mWindowMap) {
2354                 WindowState win = windowForClientLocked(session, client, false);
2355                 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "finishDrawingWindow: " + win + " mDrawState="
2356                         + (win != null ? win.mWinAnimator.drawStateToString() : "null"));
2357                 if (win != null && win.mWinAnimator.finishDrawingLocked()) {
2358                     if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
2359                         win.getDisplayContent().pendingLayoutChanges |=
2360                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2361                     }
2362                     win.setDisplayLayoutNeeded();
2363                     mWindowPlacerLocked.requestTraversal();
2364                 }
2365             }
2366         } finally {
2367             Binder.restoreCallingIdentity(origId);
2368         }
2369     }
2370 
applyAnimationLocked(AppWindowToken atoken, WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction)2371     boolean applyAnimationLocked(AppWindowToken atoken, WindowManager.LayoutParams lp,
2372             int transit, boolean enter, boolean isVoiceInteraction) {
2373         // Only apply an animation if the display isn't frozen.  If it is
2374         // frozen, there is no reason to animate and it can cause strange
2375         // artifacts when we unfreeze the display if some different animation
2376         // is running.
2377         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WM#applyAnimationLocked");
2378         if (atoken.okToAnimate()) {
2379             final DisplayContent displayContent = atoken.getTask().getDisplayContent();
2380             final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2381             final int width = displayInfo.appWidth;
2382             final int height = displayInfo.appHeight;
2383             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
2384                     "applyAnimation: atoken=" + atoken);
2385 
2386             // Determine the visible rect to calculate the thumbnail clip
2387             final WindowState win = atoken.findMainWindow();
2388             final Rect frame = new Rect(0, 0, width, height);
2389             final Rect displayFrame = new Rect(0, 0,
2390                     displayInfo.logicalWidth, displayInfo.logicalHeight);
2391             final Rect insets = new Rect();
2392             final Rect stableInsets = new Rect();
2393             Rect surfaceInsets = null;
2394             final boolean freeform = win != null && win.inFreeformWorkspace();
2395             if (win != null) {
2396                 // Containing frame will usually cover the whole screen, including dialog windows.
2397                 // For freeform workspace windows it will not cover the whole screen and it also
2398                 // won't exactly match the final freeform window frame (e.g. when overlapping with
2399                 // the status bar). In that case we need to use the final frame.
2400                 if (freeform) {
2401                     frame.set(win.mFrame);
2402                 } else {
2403                     frame.set(win.mContainingFrame);
2404                 }
2405                 surfaceInsets = win.getAttrs().surfaceInsets;
2406                 insets.set(win.mContentInsets);
2407                 stableInsets.set(win.mStableInsets);
2408             }
2409 
2410             if (atoken.mLaunchTaskBehind) {
2411                 // Differentiate the two animations. This one which is briefly on the screen
2412                 // gets the !enter animation, and the other activity which remains on the
2413                 // screen gets the enter animation. Both appear in the mOpeningApps set.
2414                 enter = false;
2415             }
2416             if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
2417                     + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
2418                     + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
2419             final Configuration displayConfig = displayContent.getConfiguration();
2420             Animation a = mAppTransition.loadAnimation(lp, transit, enter, displayConfig.uiMode,
2421                     displayConfig.orientation, frame, displayFrame, insets, surfaceInsets,
2422                     stableInsets, isVoiceInteraction, freeform, atoken.getTask().mTaskId);
2423             if (a != null) {
2424                 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + atoken);
2425                 final int containingWidth = frame.width();
2426                 final int containingHeight = frame.height();
2427                 atoken.mAppAnimator.setAnimation(a, containingWidth, containingHeight, width,
2428                         height, mAppTransition.canSkipFirstFrame(),
2429                         mAppTransition.getAppStackClipMode(),
2430                         transit, mAppTransition.getTransitFlags());
2431             }
2432         } else {
2433             atoken.mAppAnimator.clearAnimation();
2434         }
2435         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2436 
2437         return atoken.mAppAnimator.animation != null;
2438     }
2439 
checkCallingPermission(String permission, String func)2440     boolean checkCallingPermission(String permission, String func) {
2441         // Quick check: if the calling permission is me, it's all okay.
2442         if (Binder.getCallingPid() == myPid()) {
2443             return true;
2444         }
2445 
2446         if (mContext.checkCallingPermission(permission)
2447                 == PackageManager.PERMISSION_GRANTED) {
2448             return true;
2449         }
2450         final String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid()
2451                 + ", uid=" + Binder.getCallingUid() + " requires " + permission;
2452         Slog.w(TAG_WM, msg);
2453         return false;
2454     }
2455 
2456     @Override
addWindowToken(IBinder binder, int type, int displayId)2457     public void addWindowToken(IBinder binder, int type, int displayId) {
2458         if (!checkCallingPermission(MANAGE_APP_TOKENS, "addWindowToken()")) {
2459             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2460         }
2461 
2462         synchronized(mWindowMap) {
2463             final DisplayContent dc = mRoot.getDisplayContentOrCreate(displayId);
2464             WindowToken token = dc.getWindowToken(binder);
2465             if (token != null) {
2466                 Slog.w(TAG_WM, "addWindowToken: Attempted to add binder token: " + binder
2467                         + " for already created window token: " + token
2468                         + " displayId=" + displayId);
2469                 return;
2470             }
2471             if (type == TYPE_WALLPAPER) {
2472                 new WallpaperWindowToken(this, binder, true, dc,
2473                         true /* ownerCanManageAppTokens */);
2474             } else {
2475                 new WindowToken(this, binder, type, true, dc, true /* ownerCanManageAppTokens */);
2476             }
2477         }
2478     }
2479 
2480     @Override
removeWindowToken(IBinder binder, int displayId)2481     public void removeWindowToken(IBinder binder, int displayId) {
2482         if (!checkCallingPermission(MANAGE_APP_TOKENS, "removeWindowToken()")) {
2483             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2484         }
2485 
2486         final long origId = Binder.clearCallingIdentity();
2487         try {
2488             synchronized (mWindowMap) {
2489                 final DisplayContent dc = mRoot.getDisplayContent(displayId);
2490                 if (dc == null) {
2491                     Slog.w(TAG_WM, "removeWindowToken: Attempted to remove token: " + binder
2492                             + " for non-exiting displayId=" + displayId);
2493                     return;
2494                 }
2495 
2496                 final WindowToken token = dc.removeWindowToken(binder);
2497                 if (token == null) {
2498                     Slog.w(TAG_WM,
2499                             "removeWindowToken: Attempted to remove non-existing token: " + binder);
2500                     return;
2501                 }
2502 
2503                 mInputMonitor.updateInputWindowsLw(true /*force*/);
2504             }
2505         } finally {
2506             Binder.restoreCallingIdentity(origId);
2507         }
2508     }
2509 
2510     @Override
updateOrientationFromAppTokens(Configuration currentConfig, IBinder freezeThisOneIfNeeded, int displayId)2511     public Configuration updateOrientationFromAppTokens(Configuration currentConfig,
2512             IBinder freezeThisOneIfNeeded, int displayId) {
2513         if (!checkCallingPermission(MANAGE_APP_TOKENS, "updateOrientationFromAppTokens()")) {
2514             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2515         }
2516 
2517         final Configuration config;
2518         final long ident = Binder.clearCallingIdentity();
2519         try {
2520             synchronized(mWindowMap) {
2521                 config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded,
2522                         displayId);
2523             }
2524         } finally {
2525             Binder.restoreCallingIdentity(ident);
2526         }
2527 
2528         return config;
2529     }
2530 
updateOrientationFromAppTokensLocked(Configuration currentConfig, IBinder freezeThisOneIfNeeded, int displayId)2531     private Configuration updateOrientationFromAppTokensLocked(Configuration currentConfig,
2532             IBinder freezeThisOneIfNeeded, int displayId) {
2533         if (!mDisplayReady) {
2534             return null;
2535         }
2536         Configuration config = null;
2537 
2538         if (updateOrientationFromAppTokensLocked(false, displayId)) {
2539             // If we changed the orientation but mOrientationChangeComplete is already true,
2540             // we used seamless rotation, and we don't need to freeze the screen.
2541             if (freezeThisOneIfNeeded != null && !mRoot.mOrientationChangeComplete) {
2542                 final AppWindowToken atoken = mRoot.getAppWindowToken(freezeThisOneIfNeeded);
2543                 if (atoken != null) {
2544                     atoken.startFreezingScreen();
2545                 }
2546             }
2547             config = computeNewConfigurationLocked(displayId);
2548 
2549         } else if (currentConfig != null) {
2550             // No obvious action we need to take, but if our current state mismatches the activity
2551             // manager's, update it, disregarding font scale, which should remain set to the value
2552             // of the previous configuration.
2553             // Here we're calling Configuration#unset() instead of setToDefaults() because we need
2554             // to keep override configs clear of non-empty values (e.g. fontSize).
2555             mTempConfiguration.unset();
2556             mTempConfiguration.updateFrom(currentConfig);
2557             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
2558             displayContent.computeScreenConfiguration(mTempConfiguration);
2559             if (currentConfig.diff(mTempConfiguration) != 0) {
2560                 mWaitingForConfig = true;
2561                 displayContent.setLayoutNeeded();
2562                 int anim[] = new int[2];
2563                 if (displayContent.isDimming()) {
2564                     anim[0] = anim[1] = 0;
2565                 } else {
2566                     mPolicy.selectRotationAnimationLw(anim);
2567                 }
2568                 startFreezingDisplayLocked(false, anim[0], anim[1], displayContent);
2569                 config = new Configuration(mTempConfiguration);
2570             }
2571         }
2572 
2573         return config;
2574     }
2575 
2576     /**
2577      * Determine the new desired orientation of the display, returning a non-null new Configuration
2578      * if it has changed from the current orientation.  IF TRUE IS RETURNED SOMEONE MUST CALL
2579      * {@link #setNewDisplayOverrideConfiguration(Configuration, int)} TO TELL THE WINDOW MANAGER IT
2580      * CAN UNFREEZE THE SCREEN.  This will typically be done for you if you call
2581      * {@link #sendNewConfiguration(int)}.
2582      *
2583      * The orientation is computed from non-application windows first. If none of the
2584      * non-application windows specify orientation, the orientation is computed from application
2585      * tokens.
2586      * @see android.view.IWindowManager#updateOrientationFromAppTokens(Configuration, IBinder, int)
2587      */
updateOrientationFromAppTokensLocked(boolean inTransaction, int displayId)2588     boolean updateOrientationFromAppTokensLocked(boolean inTransaction, int displayId) {
2589         long ident = Binder.clearCallingIdentity();
2590         try {
2591             final DisplayContent dc = mRoot.getDisplayContent(displayId);
2592             final int req = dc.getOrientation();
2593             if (req != dc.getLastOrientation()) {
2594                 dc.setLastOrientation(req);
2595                 //send a message to Policy indicating orientation change to take
2596                 //action like disabling/enabling sensors etc.,
2597                 // TODO(multi-display): Implement policy for secondary displays.
2598                 if (dc.isDefaultDisplay) {
2599                     mPolicy.setCurrentOrientationLw(req);
2600                 }
2601                 if (dc.updateRotationUnchecked(inTransaction)) {
2602                     // changed
2603                     return true;
2604                 }
2605             }
2606 
2607             return false;
2608         } finally {
2609             Binder.restoreCallingIdentity(ident);
2610         }
2611     }
2612 
2613     // If this is true we have updated our desired orientation, but not yet
2614     // changed the real orientation our applied our screen rotation animation.
2615     // For example, because a previous screen rotation was in progress.
rotationNeedsUpdateLocked()2616     boolean rotationNeedsUpdateLocked() {
2617         // TODO(multi-display): Check for updates on all displays. Need to have per-display policy
2618         // to implement WindowManagerPolicy#rotationForOrientationLw() correctly.
2619         final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
2620         final int lastOrientation = defaultDisplayContent.getLastOrientation();
2621         final int oldRotation = defaultDisplayContent.getRotation();
2622         final boolean oldAltOrientation = defaultDisplayContent.getAltOrientation();
2623 
2624         final int rotation = mPolicy.rotationForOrientationLw(lastOrientation,
2625                 oldRotation);
2626         boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
2627                 lastOrientation, rotation);
2628         if (oldRotation == rotation && oldAltOrientation == altOrientation) {
2629             return false;
2630         }
2631         return true;
2632     }
2633 
2634     @Override
setNewDisplayOverrideConfiguration(Configuration overrideConfig, int displayId)2635     public int[] setNewDisplayOverrideConfiguration(Configuration overrideConfig, int displayId) {
2636         if (!checkCallingPermission(MANAGE_APP_TOKENS, "setNewDisplayOverrideConfiguration()")) {
2637             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2638         }
2639 
2640         synchronized(mWindowMap) {
2641             if (mWaitingForConfig) {
2642                 mWaitingForConfig = false;
2643                 mLastFinishedFreezeSource = "new-config";
2644             }
2645             return mRoot.setDisplayOverrideConfigurationIfNeeded(overrideConfig, displayId);
2646         }
2647     }
2648 
setFocusTaskRegionLocked(AppWindowToken previousFocus)2649     void setFocusTaskRegionLocked(AppWindowToken previousFocus) {
2650         final Task focusedTask = mFocusedApp != null ? mFocusedApp.getTask() : null;
2651         final Task previousTask = previousFocus != null ? previousFocus.getTask() : null;
2652         final DisplayContent focusedDisplayContent =
2653                 focusedTask != null ? focusedTask.getDisplayContent() : null;
2654         final DisplayContent previousDisplayContent =
2655                 previousTask != null ? previousTask.getDisplayContent() : null;
2656         if (previousDisplayContent != null && previousDisplayContent != focusedDisplayContent) {
2657             previousDisplayContent.setTouchExcludeRegion(null);
2658         }
2659         if (focusedDisplayContent != null) {
2660             focusedDisplayContent.setTouchExcludeRegion(focusedTask);
2661         }
2662     }
2663 
2664     @Override
setFocusedApp(IBinder token, boolean moveFocusNow)2665     public void setFocusedApp(IBinder token, boolean moveFocusNow) {
2666         if (!checkCallingPermission(MANAGE_APP_TOKENS, "setFocusedApp()")) {
2667             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2668         }
2669 
2670         synchronized(mWindowMap) {
2671             final AppWindowToken newFocus;
2672             if (token == null) {
2673                 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Clearing focused app, was " + mFocusedApp);
2674                 newFocus = null;
2675             } else {
2676                 newFocus = mRoot.getAppWindowToken(token);
2677                 if (newFocus == null) {
2678                     Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token);
2679                 }
2680                 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Set focused app to: " + newFocus
2681                         + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow);
2682             }
2683 
2684             final boolean changed = mFocusedApp != newFocus;
2685             if (changed) {
2686                 AppWindowToken prev = mFocusedApp;
2687                 mFocusedApp = newFocus;
2688                 mInputMonitor.setFocusedAppLw(newFocus);
2689                 setFocusTaskRegionLocked(prev);
2690             }
2691 
2692             if (moveFocusNow && changed) {
2693                 final long origId = Binder.clearCallingIdentity();
2694                 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
2695                 Binder.restoreCallingIdentity(origId);
2696             }
2697         }
2698     }
2699 
2700     @Override
prepareAppTransition(int transit, boolean alwaysKeepCurrent)2701     public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
2702         prepareAppTransition(transit, alwaysKeepCurrent, 0 /* flags */, false /* forceOverride */);
2703     }
2704 
2705     /**
2706      * @param transit What kind of transition is happening. Use one of the constants
2707      *                AppTransition.TRANSIT_*.
2708      * @param alwaysKeepCurrent If true and a transition is already set, new transition will NOT
2709      *                          be set.
2710      * @param flags Additional flags for the app transition, Use a combination of the constants
2711      *              AppTransition.TRANSIT_FLAG_*.
2712      * @param forceOverride Always override the transit, not matter what was set previously.
2713      */
prepareAppTransition(int transit, boolean alwaysKeepCurrent, int flags, boolean forceOverride)2714     public void prepareAppTransition(int transit, boolean alwaysKeepCurrent, int flags,
2715             boolean forceOverride) {
2716         if (!checkCallingPermission(MANAGE_APP_TOKENS, "prepareAppTransition()")) {
2717             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2718         }
2719         synchronized(mWindowMap) {
2720             boolean prepared = mAppTransition.prepareAppTransitionLocked(transit, alwaysKeepCurrent,
2721                     flags, forceOverride);
2722             // TODO (multidisplay): associate app transitions with displays
2723             final DisplayContent dc = mRoot.getDisplayContent(DEFAULT_DISPLAY);
2724             if (prepared && dc != null && dc.okToAnimate()) {
2725                 mSkipAppTransitionAnimation = false;
2726             }
2727         }
2728     }
2729 
2730     @Override
getPendingAppTransition()2731     public int getPendingAppTransition() {
2732         return mAppTransition.getAppTransition();
2733     }
2734 
2735     @Override
overridePendingAppTransition(String packageName, int enterAnim, int exitAnim, IRemoteCallback startedCallback)2736     public void overridePendingAppTransition(String packageName,
2737             int enterAnim, int exitAnim, IRemoteCallback startedCallback) {
2738         synchronized(mWindowMap) {
2739             mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim,
2740                     startedCallback);
2741         }
2742     }
2743 
2744     @Override
overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, int startHeight)2745     public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
2746             int startHeight) {
2747         synchronized(mWindowMap) {
2748             mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth,
2749                     startHeight);
2750         }
2751     }
2752 
2753     @Override
overridePendingAppTransitionClipReveal(int startX, int startY, int startWidth, int startHeight)2754     public void overridePendingAppTransitionClipReveal(int startX, int startY,
2755             int startWidth, int startHeight) {
2756         synchronized(mWindowMap) {
2757             mAppTransition.overridePendingAppTransitionClipReveal(startX, startY, startWidth,
2758                     startHeight);
2759         }
2760     }
2761 
2762     @Override
overridePendingAppTransitionThumb(GraphicBuffer srcThumb, int startX, int startY, IRemoteCallback startedCallback, boolean scaleUp)2763     public void overridePendingAppTransitionThumb(GraphicBuffer srcThumb, int startX,
2764             int startY, IRemoteCallback startedCallback, boolean scaleUp) {
2765         synchronized(mWindowMap) {
2766             mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY,
2767                     startedCallback, scaleUp);
2768         }
2769     }
2770 
2771     @Override
overridePendingAppTransitionAspectScaledThumb(GraphicBuffer srcThumb, int startX, int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback, boolean scaleUp)2772     public void overridePendingAppTransitionAspectScaledThumb(GraphicBuffer srcThumb, int startX,
2773             int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
2774             boolean scaleUp) {
2775         synchronized(mWindowMap) {
2776             mAppTransition.overridePendingAppTransitionAspectScaledThumb(srcThumb, startX, startY,
2777                     targetWidth, targetHeight, startedCallback, scaleUp);
2778         }
2779     }
2780 
2781     @Override
overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs, IRemoteCallback onAnimationStartedCallback, IRemoteCallback onAnimationFinishedCallback, boolean scaleUp)2782     public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs,
2783             IRemoteCallback onAnimationStartedCallback, IRemoteCallback onAnimationFinishedCallback,
2784             boolean scaleUp) {
2785         synchronized (mWindowMap) {
2786             mAppTransition.overridePendingAppTransitionMultiThumb(specs, onAnimationStartedCallback,
2787                     onAnimationFinishedCallback, scaleUp);
2788             prolongAnimationsFromSpecs(specs, scaleUp);
2789 
2790         }
2791     }
2792 
prolongAnimationsFromSpecs(@onNull AppTransitionAnimationSpec[] specs, boolean scaleUp)2793     void prolongAnimationsFromSpecs(@NonNull AppTransitionAnimationSpec[] specs, boolean scaleUp) {
2794         // This is used by freeform <-> recents windows transition. We need to synchronize
2795         // the animation with the appearance of the content of recents, so we will make
2796         // animation stay on the first or last frame a little longer.
2797         mTmpTaskIds.clear();
2798         for (int i = specs.length - 1; i >= 0; i--) {
2799             mTmpTaskIds.put(specs[i].taskId, 0);
2800         }
2801         for (final WindowState win : mWindowMap.values()) {
2802             final Task task = win.getTask();
2803             if (task != null && mTmpTaskIds.get(task.mTaskId, -1) != -1
2804                     && task.inFreeformWorkspace()) {
2805                 final AppWindowToken appToken = win.mAppToken;
2806                 if (appToken != null && appToken.mAppAnimator != null) {
2807                     appToken.mAppAnimator.startProlongAnimation(scaleUp ?
2808                             PROLONG_ANIMATION_AT_START : PROLONG_ANIMATION_AT_END);
2809                 }
2810             }
2811         }
2812     }
2813 
2814     @Override
overridePendingAppTransitionInPlace(String packageName, int anim)2815     public void overridePendingAppTransitionInPlace(String packageName, int anim) {
2816         synchronized(mWindowMap) {
2817             mAppTransition.overrideInPlaceAppTransition(packageName, anim);
2818         }
2819     }
2820 
2821     @Override
overridePendingAppTransitionMultiThumbFuture( IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback, boolean scaleUp)2822     public void overridePendingAppTransitionMultiThumbFuture(
2823             IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback,
2824             boolean scaleUp) {
2825         synchronized(mWindowMap) {
2826             mAppTransition.overridePendingAppTransitionMultiThumbFuture(specsFuture, callback,
2827                     scaleUp);
2828         }
2829     }
2830 
2831     @Override
endProlongedAnimations()2832     public void endProlongedAnimations() {
2833         synchronized (mWindowMap) {
2834             for (final WindowState win : mWindowMap.values()) {
2835                 final AppWindowToken appToken = win.mAppToken;
2836                 if (appToken != null && appToken.mAppAnimator != null) {
2837                     appToken.mAppAnimator.endProlongedAnimation();
2838                 }
2839             }
2840             mAppTransition.notifyProlongedAnimationsEnded();
2841         }
2842     }
2843 
2844     @Override
executeAppTransition()2845     public void executeAppTransition() {
2846         if (!checkCallingPermission(MANAGE_APP_TOKENS, "executeAppTransition()")) {
2847             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2848         }
2849 
2850         synchronized(mWindowMap) {
2851             if (DEBUG_APP_TRANSITIONS) Slog.w(TAG_WM, "Execute app transition: " + mAppTransition
2852                     + " Callers=" + Debug.getCallers(5));
2853             if (mAppTransition.isTransitionSet()) {
2854                 mAppTransition.setReady();
2855                 final long origId = Binder.clearCallingIdentity();
2856                 try {
2857                     mWindowPlacerLocked.performSurfacePlacement();
2858                 } finally {
2859                     Binder.restoreCallingIdentity(origId);
2860                 }
2861             }
2862         }
2863     }
2864 
setAppFullscreen(IBinder token, boolean toOpaque)2865     public void setAppFullscreen(IBinder token, boolean toOpaque) {
2866         synchronized (mWindowMap) {
2867             final AppWindowToken atoken = mRoot.getAppWindowToken(token);
2868             if (atoken != null) {
2869                 atoken.setFillsParent(toOpaque);
2870                 setWindowOpaqueLocked(token, toOpaque);
2871                 mWindowPlacerLocked.requestTraversal();
2872             }
2873         }
2874     }
2875 
setWindowOpaque(IBinder token, boolean isOpaque)2876     public void setWindowOpaque(IBinder token, boolean isOpaque) {
2877         synchronized (mWindowMap) {
2878             setWindowOpaqueLocked(token, isOpaque);
2879         }
2880     }
2881 
setWindowOpaqueLocked(IBinder token, boolean isOpaque)2882     private void setWindowOpaqueLocked(IBinder token, boolean isOpaque) {
2883         final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
2884         if (wtoken != null) {
2885             final WindowState win = wtoken.findMainWindow();
2886             if (win != null) {
2887                 win.mWinAnimator.setOpaqueLocked(isOpaque);
2888             }
2889         }
2890     }
2891 
updateTokenInPlaceLocked(AppWindowToken wtoken, int transit)2892     void updateTokenInPlaceLocked(AppWindowToken wtoken, int transit) {
2893         if (transit != TRANSIT_UNSET) {
2894             if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
2895                 wtoken.mAppAnimator.setNullAnimation();
2896             }
2897             applyAnimationLocked(wtoken, null, transit, false, false);
2898         }
2899     }
2900 
setDockedStackCreateState(int mode, Rect bounds)2901     public void setDockedStackCreateState(int mode, Rect bounds) {
2902         synchronized (mWindowMap) {
2903             setDockedStackCreateStateLocked(mode, bounds);
2904         }
2905     }
2906 
setDockedStackCreateStateLocked(int mode, Rect bounds)2907     void setDockedStackCreateStateLocked(int mode, Rect bounds) {
2908         mDockedStackCreateMode = mode;
2909         mDockedStackCreateBounds = bounds;
2910     }
2911 
isValidPictureInPictureAspectRatio(int displayId, float aspectRatio)2912     public boolean isValidPictureInPictureAspectRatio(int displayId, float aspectRatio) {
2913         final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
2914         return displayContent.getPinnedStackController().isValidPictureInPictureAspectRatio(
2915                 aspectRatio);
2916     }
2917 
2918     @Override
getStackBounds(int stackId, Rect bounds)2919     public void getStackBounds(int stackId, Rect bounds) {
2920         synchronized (mWindowMap) {
2921             final TaskStack stack = mRoot.getStackById(stackId);
2922             if (stack != null) {
2923                 stack.getBounds(bounds);
2924                 return;
2925             }
2926             bounds.setEmpty();
2927         }
2928     }
2929 
2930     @Override
notifyShowingDreamChanged()2931     public void notifyShowingDreamChanged() {
2932         notifyKeyguardFlagsChanged(null /* callback */);
2933     }
2934 
2935     @Override
getInputMethodWindowLw()2936     public WindowManagerPolicy.WindowState getInputMethodWindowLw() {
2937         return mInputMethodWindow;
2938     }
2939 
2940     @Override
notifyKeyguardTrustedChanged()2941     public void notifyKeyguardTrustedChanged() {
2942         mH.sendEmptyMessage(H.NOTIFY_KEYGUARD_TRUSTED_CHANGED);
2943     }
2944 
2945     @Override
onKeyguardShowingAndNotOccludedChanged()2946     public void onKeyguardShowingAndNotOccludedChanged() {
2947         mH.sendEmptyMessage(H.RECOMPUTE_FOCUS);
2948     }
2949 
2950     @Override
screenTurningOff(ScreenOffListener listener)2951     public void screenTurningOff(ScreenOffListener listener) {
2952         mTaskSnapshotController.screenTurningOff(listener);
2953     }
2954 
2955     /**
2956      * Starts deferring layout passes. Useful when doing multiple changes but to optimize
2957      * performance, only one layout pass should be done. This can be called multiple times, and
2958      * layouting will be resumed once the last caller has called {@link #continueSurfaceLayout}
2959      */
deferSurfaceLayout()2960     public void deferSurfaceLayout() {
2961         synchronized (mWindowMap) {
2962             mWindowPlacerLocked.deferLayout();
2963         }
2964     }
2965 
2966     /**
2967      * Resumes layout passes after deferring them. See {@link #deferSurfaceLayout()}
2968      */
continueSurfaceLayout()2969     public void continueSurfaceLayout() {
2970         synchronized (mWindowMap) {
2971             mWindowPlacerLocked.continueLayout();
2972         }
2973     }
2974 
2975     /**
2976      * @return true if the activity contains windows that have
2977      *         {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set
2978      */
containsShowWhenLockedWindow(IBinder token)2979     public boolean containsShowWhenLockedWindow(IBinder token) {
2980         synchronized (mWindowMap) {
2981             final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
2982             return wtoken != null && wtoken.containsShowWhenLockedWindow();
2983         }
2984     }
2985 
2986     /**
2987      * @return true if the activity contains windows that have
2988      *         {@link LayoutParams#FLAG_DISMISS_KEYGUARD} set
2989      */
containsDismissKeyguardWindow(IBinder token)2990     public boolean containsDismissKeyguardWindow(IBinder token) {
2991         synchronized (mWindowMap) {
2992             final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
2993             return wtoken != null && wtoken.containsDismissKeyguardWindow();
2994         }
2995     }
2996 
2997     /**
2998      * Notifies activity manager that some Keyguard flags have changed and that it needs to
2999      * reevaluate the visibilities of the activities.
3000      * @param callback Runnable to be called when activity manager is done reevaluating visibilities
3001      */
notifyKeyguardFlagsChanged(@ullable Runnable callback)3002     void notifyKeyguardFlagsChanged(@Nullable Runnable callback) {
3003         final Runnable wrappedCallback = callback != null
3004                 ? () -> { synchronized (mWindowMap) { callback.run(); } }
3005                 : null;
3006         mH.obtainMessage(H.NOTIFY_KEYGUARD_FLAGS_CHANGED, wrappedCallback).sendToTarget();
3007     }
3008 
isKeyguardTrusted()3009     public boolean isKeyguardTrusted() {
3010         synchronized (mWindowMap) {
3011             return mPolicy.isKeyguardTrustedLw();
3012         }
3013     }
3014 
setKeyguardGoingAway(boolean keyguardGoingAway)3015     public void setKeyguardGoingAway(boolean keyguardGoingAway) {
3016         synchronized (mWindowMap) {
3017             mKeyguardGoingAway = keyguardGoingAway;
3018         }
3019     }
3020 
3021     // -------------------------------------------------------------
3022     // Misc IWindowSession methods
3023     // -------------------------------------------------------------
3024 
3025     @Override
startFreezingScreen(int exitAnim, int enterAnim)3026     public void startFreezingScreen(int exitAnim, int enterAnim) {
3027         if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
3028                 "startFreezingScreen()")) {
3029             throw new SecurityException("Requires FREEZE_SCREEN permission");
3030         }
3031 
3032         synchronized(mWindowMap) {
3033             if (!mClientFreezingScreen) {
3034                 mClientFreezingScreen = true;
3035                 final long origId = Binder.clearCallingIdentity();
3036                 try {
3037                     startFreezingDisplayLocked(false, exitAnim, enterAnim);
3038                     mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
3039                     mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
3040                 } finally {
3041                     Binder.restoreCallingIdentity(origId);
3042                 }
3043             }
3044         }
3045     }
3046 
3047     @Override
stopFreezingScreen()3048     public void stopFreezingScreen() {
3049         if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
3050                 "stopFreezingScreen()")) {
3051             throw new SecurityException("Requires FREEZE_SCREEN permission");
3052         }
3053 
3054         synchronized(mWindowMap) {
3055             if (mClientFreezingScreen) {
3056                 mClientFreezingScreen = false;
3057                 mLastFinishedFreezeSource = "client";
3058                 final long origId = Binder.clearCallingIdentity();
3059                 try {
3060                     stopFreezingDisplayLocked();
3061                 } finally {
3062                     Binder.restoreCallingIdentity(origId);
3063                 }
3064             }
3065         }
3066     }
3067 
3068     @Override
disableKeyguard(IBinder token, String tag)3069     public void disableKeyguard(IBinder token, String tag) {
3070         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
3071             != PackageManager.PERMISSION_GRANTED) {
3072             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
3073         }
3074         // If this isn't coming from the system then don't allow disabling the lockscreen
3075         // to bypass security.
3076         if (Binder.getCallingUid() != SYSTEM_UID && isKeyguardSecure()) {
3077             Log.d(TAG_WM, "current mode is SecurityMode, ignore disableKeyguard");
3078             return;
3079         }
3080 
3081         // If this isn't coming from the current profiles, ignore it.
3082         if (!isCurrentProfileLocked(UserHandle.getCallingUserId())) {
3083             Log.d(TAG_WM, "non-current profiles, ignore disableKeyguard");
3084             return;
3085         }
3086 
3087         if (token == null) {
3088             throw new IllegalArgumentException("token == null");
3089         }
3090 
3091         mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
3092                 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
3093     }
3094 
3095     @Override
reenableKeyguard(IBinder token)3096     public void reenableKeyguard(IBinder token) {
3097         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
3098             != PackageManager.PERMISSION_GRANTED) {
3099             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
3100         }
3101 
3102         if (token == null) {
3103             throw new IllegalArgumentException("token == null");
3104         }
3105 
3106         mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
3107                 KeyguardDisableHandler.KEYGUARD_REENABLE, token));
3108     }
3109 
3110     /**
3111      * @see android.app.KeyguardManager#exitKeyguardSecurely
3112      */
3113     @Override
exitKeyguardSecurely(final IOnKeyguardExitResult callback)3114     public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
3115         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
3116             != PackageManager.PERMISSION_GRANTED) {
3117             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
3118         }
3119 
3120         if (callback == null) {
3121             throw new IllegalArgumentException("callback == null");
3122         }
3123 
3124         mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
3125             @Override
3126             public void onKeyguardExitResult(boolean success) {
3127                 try {
3128                     callback.onKeyguardExitResult(success);
3129                 } catch (RemoteException e) {
3130                     // Client has died, we don't care.
3131                 }
3132             }
3133         });
3134     }
3135 
3136     @Override
inKeyguardRestrictedInputMode()3137     public boolean inKeyguardRestrictedInputMode() {
3138         return mPolicy.inKeyguardRestrictedKeyInputMode();
3139     }
3140 
3141     @Override
isKeyguardLocked()3142     public boolean isKeyguardLocked() {
3143         return mPolicy.isKeyguardLocked();
3144     }
3145 
isKeyguardShowingAndNotOccluded()3146     public boolean isKeyguardShowingAndNotOccluded() {
3147         return mPolicy.isKeyguardShowingAndNotOccluded();
3148     }
3149 
3150     @Override
isKeyguardSecure()3151     public boolean isKeyguardSecure() {
3152         int userId = UserHandle.getCallingUserId();
3153         long origId = Binder.clearCallingIdentity();
3154         try {
3155             return mPolicy.isKeyguardSecure(userId);
3156         } finally {
3157             Binder.restoreCallingIdentity(origId);
3158         }
3159     }
3160 
isShowingDream()3161     public boolean isShowingDream() {
3162         synchronized (mWindowMap) {
3163             return mPolicy.isShowingDreamLw();
3164         }
3165     }
3166 
3167     @Override
dismissKeyguard(IKeyguardDismissCallback callback)3168     public void dismissKeyguard(IKeyguardDismissCallback callback) {
3169         checkCallingPermission(permission.CONTROL_KEYGUARD, "dismissKeyguard");
3170         synchronized(mWindowMap) {
3171             mPolicy.dismissKeyguardLw(callback);
3172         }
3173     }
3174 
onKeyguardOccludedChanged(boolean occluded)3175     public void onKeyguardOccludedChanged(boolean occluded) {
3176         synchronized (mWindowMap) {
3177             mPolicy.onKeyguardOccludedChangedLw(occluded);
3178         }
3179     }
3180 
3181     @Override
setSwitchingUser(boolean switching)3182     public void setSwitchingUser(boolean switching) {
3183         if (!checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
3184                 "setSwitchingUser()")) {
3185             throw new SecurityException("Requires INTERACT_ACROSS_USERS_FULL permission");
3186         }
3187         mPolicy.setSwitchingUser(switching);
3188         synchronized (mWindowMap) {
3189             mSwitchingUser = switching;
3190         }
3191     }
3192 
showGlobalActions()3193     void showGlobalActions() {
3194         mPolicy.showGlobalActions();
3195     }
3196 
3197     @Override
closeSystemDialogs(String reason)3198     public void closeSystemDialogs(String reason) {
3199         synchronized(mWindowMap) {
3200             mRoot.closeSystemDialogs(reason);
3201         }
3202     }
3203 
fixScale(float scale)3204     static float fixScale(float scale) {
3205         if (scale < 0) scale = 0;
3206         else if (scale > 20) scale = 20;
3207         return Math.abs(scale);
3208     }
3209 
3210     @Override
setAnimationScale(int which, float scale)3211     public void setAnimationScale(int which, float scale) {
3212         if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
3213                 "setAnimationScale()")) {
3214             throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
3215         }
3216 
3217         scale = fixScale(scale);
3218         switch (which) {
3219             case 0: mWindowAnimationScaleSetting = scale; break;
3220             case 1: mTransitionAnimationScaleSetting = scale; break;
3221             case 2: mAnimatorDurationScaleSetting = scale; break;
3222         }
3223 
3224         // Persist setting
3225         mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
3226     }
3227 
3228     @Override
setAnimationScales(float[] scales)3229     public void setAnimationScales(float[] scales) {
3230         if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
3231                 "setAnimationScale()")) {
3232             throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
3233         }
3234 
3235         if (scales != null) {
3236             if (scales.length >= 1) {
3237                 mWindowAnimationScaleSetting = fixScale(scales[0]);
3238             }
3239             if (scales.length >= 2) {
3240                 mTransitionAnimationScaleSetting = fixScale(scales[1]);
3241             }
3242             if (scales.length >= 3) {
3243                 mAnimatorDurationScaleSetting = fixScale(scales[2]);
3244                 dispatchNewAnimatorScaleLocked(null);
3245             }
3246         }
3247 
3248         // Persist setting
3249         mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
3250     }
3251 
setAnimatorDurationScale(float scale)3252     private void setAnimatorDurationScale(float scale) {
3253         mAnimatorDurationScaleSetting = scale;
3254         ValueAnimator.setDurationScale(scale);
3255     }
3256 
getWindowAnimationScaleLocked()3257     public float getWindowAnimationScaleLocked() {
3258         return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting;
3259     }
3260 
getTransitionAnimationScaleLocked()3261     public float getTransitionAnimationScaleLocked() {
3262         return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting;
3263     }
3264 
3265     @Override
getAnimationScale(int which)3266     public float getAnimationScale(int which) {
3267         switch (which) {
3268             case 0: return mWindowAnimationScaleSetting;
3269             case 1: return mTransitionAnimationScaleSetting;
3270             case 2: return mAnimatorDurationScaleSetting;
3271         }
3272         return 0;
3273     }
3274 
3275     @Override
getAnimationScales()3276     public float[] getAnimationScales() {
3277         return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting,
3278                 mAnimatorDurationScaleSetting };
3279     }
3280 
3281     @Override
getCurrentAnimatorScale()3282     public float getCurrentAnimatorScale() {
3283         synchronized(mWindowMap) {
3284             return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting;
3285         }
3286     }
3287 
dispatchNewAnimatorScaleLocked(Session session)3288     void dispatchNewAnimatorScaleLocked(Session session) {
3289         mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget();
3290     }
3291 
3292     @Override
registerPointerEventListener(PointerEventListener listener)3293     public void registerPointerEventListener(PointerEventListener listener) {
3294         mPointerEventDispatcher.registerInputEventListener(listener);
3295     }
3296 
3297     @Override
unregisterPointerEventListener(PointerEventListener listener)3298     public void unregisterPointerEventListener(PointerEventListener listener) {
3299         mPointerEventDispatcher.unregisterInputEventListener(listener);
3300     }
3301 
3302     /** Check if the service is set to dispatch pointer events. */
canDispatchPointerEvents()3303     boolean canDispatchPointerEvents() {
3304         return mPointerEventDispatcher != null;
3305     }
3306 
3307     // Called by window manager policy. Not exposed externally.
3308     @Override
getLidState()3309     public int getLidState() {
3310         int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
3311                 InputManagerService.SW_LID);
3312         if (sw > 0) {
3313             // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
3314             return LID_CLOSED;
3315         } else if (sw == 0) {
3316             // Switch state: AKEY_STATE_UP.
3317             return LID_OPEN;
3318         } else {
3319             // Switch state: AKEY_STATE_UNKNOWN.
3320             return LID_ABSENT;
3321         }
3322     }
3323 
3324     // Called by window manager policy. Not exposed externally.
3325     @Override
lockDeviceNow()3326     public void lockDeviceNow() {
3327         lockNow(null);
3328     }
3329 
3330     // Called by window manager policy. Not exposed externally.
3331     @Override
getCameraLensCoverState()3332     public int getCameraLensCoverState() {
3333         int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
3334                 InputManagerService.SW_CAMERA_LENS_COVER);
3335         if (sw > 0) {
3336             // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
3337             return CAMERA_LENS_COVERED;
3338         } else if (sw == 0) {
3339             // Switch state: AKEY_STATE_UP.
3340             return CAMERA_LENS_UNCOVERED;
3341         } else {
3342             // Switch state: AKEY_STATE_UNKNOWN.
3343             return CAMERA_LENS_COVER_ABSENT;
3344         }
3345     }
3346 
3347     // Called by window manager policy.  Not exposed externally.
3348     @Override
switchInputMethod(boolean forwardDirection)3349     public void switchInputMethod(boolean forwardDirection) {
3350         final InputMethodManagerInternal inputMethodManagerInternal =
3351                 LocalServices.getService(InputMethodManagerInternal.class);
3352         if (inputMethodManagerInternal != null) {
3353             inputMethodManagerInternal.switchInputMethod(forwardDirection);
3354         }
3355     }
3356 
3357     // Called by window manager policy.  Not exposed externally.
3358     @Override
shutdown(boolean confirm)3359     public void shutdown(boolean confirm) {
3360         // Pass in the UI context, since ShutdownThread requires it (to show UI).
3361         ShutdownThread.shutdown(ActivityThread.currentActivityThread().getSystemUiContext(),
3362                 PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
3363     }
3364 
3365     // Called by window manager policy.  Not exposed externally.
3366     @Override
reboot(boolean confirm)3367     public void reboot(boolean confirm) {
3368         // Pass in the UI context, since ShutdownThread requires it (to show UI).
3369         ShutdownThread.reboot(ActivityThread.currentActivityThread().getSystemUiContext(),
3370                 PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
3371     }
3372 
3373     // Called by window manager policy.  Not exposed externally.
3374     @Override
rebootSafeMode(boolean confirm)3375     public void rebootSafeMode(boolean confirm) {
3376         // Pass in the UI context, since ShutdownThread requires it (to show UI).
3377         ShutdownThread.rebootSafeMode(ActivityThread.currentActivityThread().getSystemUiContext(),
3378                 confirm);
3379     }
3380 
setCurrentProfileIds(final int[] currentProfileIds)3381     public void setCurrentProfileIds(final int[] currentProfileIds) {
3382         synchronized (mWindowMap) {
3383             mCurrentProfileIds = currentProfileIds;
3384         }
3385     }
3386 
setCurrentUser(final int newUserId, final int[] currentProfileIds)3387     public void setCurrentUser(final int newUserId, final int[] currentProfileIds) {
3388         synchronized (mWindowMap) {
3389             mCurrentUserId = newUserId;
3390             mCurrentProfileIds = currentProfileIds;
3391             mAppTransition.setCurrentUser(newUserId);
3392             mPolicy.setCurrentUserLw(newUserId);
3393 
3394             // If keyguard was disabled, re-enable it
3395             // TODO: Keep track of keyguardEnabled state per user and use here...
3396             // e.g. enabled = mKeyguardDisableHandler.getEnabledStateForUser(newUserId);
3397             mPolicy.enableKeyguard(true);
3398 
3399             // Hide windows that should not be seen by the new user.
3400             mRoot.switchUser();
3401             mWindowPlacerLocked.performSurfacePlacement();
3402 
3403             // Notify whether the docked stack exists for the current user
3404             final DisplayContent displayContent = getDefaultDisplayContentLocked();
3405             final TaskStack stack = displayContent.getDockedStackIgnoringVisibility();
3406             displayContent.mDividerControllerLocked.notifyDockedStackExistsChanged(
3407                     stack != null && stack.hasTaskForUser(newUserId));
3408 
3409             // If the display is already prepared, update the density.
3410             // Otherwise, we'll update it when it's prepared.
3411             if (mDisplayReady) {
3412                 final int forcedDensity = getForcedDisplayDensityForUserLocked(newUserId);
3413                 final int targetDensity = forcedDensity != 0 ? forcedDensity
3414                         : displayContent.mInitialDisplayDensity;
3415                 setForcedDisplayDensityLocked(displayContent, targetDensity);
3416             }
3417         }
3418     }
3419 
3420     /* Called by WindowState */
isCurrentProfileLocked(int userId)3421     boolean isCurrentProfileLocked(int userId) {
3422         if (userId == mCurrentUserId) return true;
3423         for (int i = 0; i < mCurrentProfileIds.length; i++) {
3424             if (mCurrentProfileIds[i] == userId) return true;
3425         }
3426         return false;
3427     }
3428 
enableScreenAfterBoot()3429     public void enableScreenAfterBoot() {
3430         synchronized(mWindowMap) {
3431             if (DEBUG_BOOT) {
3432                 RuntimeException here = new RuntimeException("here");
3433                 here.fillInStackTrace();
3434                 Slog.i(TAG_WM, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
3435                         + " mForceDisplayEnabled=" + mForceDisplayEnabled
3436                         + " mShowingBootMessages=" + mShowingBootMessages
3437                         + " mSystemBooted=" + mSystemBooted, here);
3438             }
3439             if (mSystemBooted) {
3440                 return;
3441             }
3442             mSystemBooted = true;
3443             hideBootMessagesLocked();
3444             // If the screen still doesn't come up after 30 seconds, give
3445             // up and turn it on.
3446             mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30 * 1000);
3447         }
3448 
3449         mPolicy.systemBooted();
3450 
3451         performEnableScreen();
3452     }
3453 
3454     @Override
enableScreenIfNeeded()3455     public void enableScreenIfNeeded() {
3456         synchronized (mWindowMap) {
3457             enableScreenIfNeededLocked();
3458         }
3459     }
3460 
enableScreenIfNeededLocked()3461     void enableScreenIfNeededLocked() {
3462         if (DEBUG_BOOT) {
3463             RuntimeException here = new RuntimeException("here");
3464             here.fillInStackTrace();
3465             Slog.i(TAG_WM, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
3466                     + " mForceDisplayEnabled=" + mForceDisplayEnabled
3467                     + " mShowingBootMessages=" + mShowingBootMessages
3468                     + " mSystemBooted=" + mSystemBooted, here);
3469         }
3470         if (mDisplayEnabled) {
3471             return;
3472         }
3473         if (!mSystemBooted && !mShowingBootMessages) {
3474             return;
3475         }
3476         mH.sendEmptyMessage(H.ENABLE_SCREEN);
3477     }
3478 
performBootTimeout()3479     public void performBootTimeout() {
3480         synchronized(mWindowMap) {
3481             if (mDisplayEnabled) {
3482                 return;
3483             }
3484             Slog.w(TAG_WM, "***** BOOT TIMEOUT: forcing display enabled");
3485             mForceDisplayEnabled = true;
3486         }
3487         performEnableScreen();
3488     }
3489 
3490     /**
3491      * Called when System UI has been started.
3492      */
onSystemUiStarted()3493     public void onSystemUiStarted() {
3494         mPolicy.onSystemUiStarted();
3495     }
3496 
performEnableScreen()3497     private void performEnableScreen() {
3498         synchronized(mWindowMap) {
3499             if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
3500                     + " mForceDisplayEnabled=" + mForceDisplayEnabled
3501                     + " mShowingBootMessages=" + mShowingBootMessages
3502                     + " mSystemBooted=" + mSystemBooted
3503                     + " mOnlyCore=" + mOnlyCore,
3504                     new RuntimeException("here").fillInStackTrace());
3505             if (mDisplayEnabled) {
3506                 return;
3507             }
3508             if (!mSystemBooted && !mShowingBootMessages) {
3509                 return;
3510             }
3511 
3512             if (!mShowingBootMessages && !mPolicy.canDismissBootAnimation()) {
3513                 return;
3514             }
3515 
3516             // Don't enable the screen until all existing windows have been drawn.
3517             if (!mForceDisplayEnabled
3518                     // TODO(multidisplay): Expand to all displays?
3519                     && getDefaultDisplayContentLocked().checkWaitingForWindows()) {
3520                 return;
3521             }
3522 
3523             if (!mBootAnimationStopped) {
3524                 Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
3525                 // stop boot animation
3526                 // formerly we would just kill the process, but we now ask it to exit so it
3527                 // can choose where to stop the animation.
3528                 SystemProperties.set("service.bootanim.exit", "1");
3529                 mBootAnimationStopped = true;
3530             }
3531 
3532             if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {
3533                 if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: Waiting for anim complete");
3534                 return;
3535             }
3536 
3537             try {
3538                 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
3539                 if (surfaceFlinger != null) {
3540                     Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
3541                     Parcel data = Parcel.obtain();
3542                     data.writeInterfaceToken("android.ui.ISurfaceComposer");
3543                     surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
3544                             data, null, 0);
3545                     data.recycle();
3546                 }
3547             } catch (RemoteException ex) {
3548                 Slog.e(TAG_WM, "Boot completed: SurfaceFlinger is dead!");
3549             }
3550 
3551             EventLog.writeEvent(EventLogTags.WM_BOOT_ANIMATION_DONE, SystemClock.uptimeMillis());
3552             Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
3553             mDisplayEnabled = true;
3554             if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM, "******************** ENABLING SCREEN!");
3555 
3556             // Enable input dispatch.
3557             mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
3558         }
3559 
3560         try {
3561             mActivityManager.bootAnimationComplete();
3562         } catch (RemoteException e) {
3563         }
3564 
3565         mPolicy.enableScreenAfterBoot();
3566 
3567         // Make sure the last requested orientation has been applied.
3568         updateRotationUnchecked(false, false);
3569     }
3570 
checkBootAnimationCompleteLocked()3571     private boolean checkBootAnimationCompleteLocked() {
3572         if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) {
3573             mH.removeMessages(H.CHECK_IF_BOOT_ANIMATION_FINISHED);
3574             mH.sendEmptyMessageDelayed(H.CHECK_IF_BOOT_ANIMATION_FINISHED,
3575                     BOOT_ANIMATION_POLL_INTERVAL);
3576             if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Waiting for anim complete");
3577             return false;
3578         }
3579         if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Animation complete!");
3580         return true;
3581     }
3582 
showBootMessage(final CharSequence msg, final boolean always)3583     public void showBootMessage(final CharSequence msg, final boolean always) {
3584         boolean first = false;
3585         synchronized(mWindowMap) {
3586             if (DEBUG_BOOT) {
3587                 RuntimeException here = new RuntimeException("here");
3588                 here.fillInStackTrace();
3589                 Slog.i(TAG_WM, "showBootMessage: msg=" + msg + " always=" + always
3590                         + " mAllowBootMessages=" + mAllowBootMessages
3591                         + " mShowingBootMessages=" + mShowingBootMessages
3592                         + " mSystemBooted=" + mSystemBooted, here);
3593             }
3594             if (!mAllowBootMessages) {
3595                 return;
3596             }
3597             if (!mShowingBootMessages) {
3598                 if (!always) {
3599                     return;
3600                 }
3601                 first = true;
3602             }
3603             if (mSystemBooted) {
3604                 return;
3605             }
3606             mShowingBootMessages = true;
3607             mPolicy.showBootMessage(msg, always);
3608         }
3609         if (first) {
3610             performEnableScreen();
3611         }
3612     }
3613 
hideBootMessagesLocked()3614     public void hideBootMessagesLocked() {
3615         if (DEBUG_BOOT) {
3616             RuntimeException here = new RuntimeException("here");
3617             here.fillInStackTrace();
3618             Slog.i(TAG_WM, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
3619                     + " mForceDisplayEnabled=" + mForceDisplayEnabled
3620                     + " mShowingBootMessages=" + mShowingBootMessages
3621                     + " mSystemBooted=" + mSystemBooted, here);
3622         }
3623         if (mShowingBootMessages) {
3624             mShowingBootMessages = false;
3625             mPolicy.hideBootMessages();
3626         }
3627     }
3628 
3629     @Override
setInTouchMode(boolean mode)3630     public void setInTouchMode(boolean mode) {
3631         synchronized(mWindowMap) {
3632             mInTouchMode = mode;
3633         }
3634     }
3635 
updateCircularDisplayMaskIfNeeded()3636     private void updateCircularDisplayMaskIfNeeded() {
3637         if (mContext.getResources().getConfiguration().isScreenRound()
3638                 && mContext.getResources().getBoolean(
3639                 com.android.internal.R.bool.config_windowShowCircularMask)) {
3640             final int currentUserId;
3641             synchronized(mWindowMap) {
3642                 currentUserId = mCurrentUserId;
3643             }
3644             // Device configuration calls for a circular display mask, but we only enable the mask
3645             // if the accessibility color inversion feature is disabled, as the inverted mask
3646             // causes artifacts.
3647             int inversionState = Settings.Secure.getIntForUser(mContext.getContentResolver(),
3648                     Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, currentUserId);
3649             int showMask = (inversionState == 1) ? 0 : 1;
3650             Message m = mH.obtainMessage(H.SHOW_CIRCULAR_DISPLAY_MASK);
3651             m.arg1 = showMask;
3652             mH.sendMessage(m);
3653         }
3654     }
3655 
showEmulatorDisplayOverlayIfNeeded()3656     public void showEmulatorDisplayOverlayIfNeeded() {
3657         if (mContext.getResources().getBoolean(
3658                 com.android.internal.R.bool.config_windowEnableCircularEmulatorDisplayOverlay)
3659                 && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false)
3660                 && Build.IS_EMULATOR) {
3661             mH.sendMessage(mH.obtainMessage(H.SHOW_EMULATOR_DISPLAY_OVERLAY));
3662         }
3663     }
3664 
showCircularMask(boolean visible)3665     public void showCircularMask(boolean visible) {
3666         synchronized(mWindowMap) {
3667 
3668             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
3669                     ">>> OPEN TRANSACTION showCircularMask(visible=" + visible + ")");
3670             openSurfaceTransaction();
3671             try {
3672                 if (visible) {
3673                     // TODO(multi-display): support multiple displays
3674                     if (mCircularDisplayMask == null) {
3675                         int screenOffset = mContext.getResources().getInteger(
3676                                 com.android.internal.R.integer.config_windowOutsetBottom);
3677                         int maskThickness = mContext.getResources().getDimensionPixelSize(
3678                                 com.android.internal.R.dimen.circular_display_mask_thickness);
3679 
3680                         mCircularDisplayMask = new CircularDisplayMask(
3681                                 getDefaultDisplayContentLocked().getDisplay(),
3682                                 mFxSession,
3683                                 mPolicy.getWindowLayerFromTypeLw(
3684                                         WindowManager.LayoutParams.TYPE_POINTER)
3685                                         * TYPE_LAYER_MULTIPLIER + 10, screenOffset, maskThickness);
3686                     }
3687                     mCircularDisplayMask.setVisibility(true);
3688                 } else if (mCircularDisplayMask != null) {
3689                     mCircularDisplayMask.setVisibility(false);
3690                     mCircularDisplayMask = null;
3691                 }
3692             } finally {
3693                 closeSurfaceTransaction();
3694                 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
3695                         "<<< CLOSE TRANSACTION showCircularMask(visible=" + visible + ")");
3696             }
3697         }
3698     }
3699 
showEmulatorDisplayOverlay()3700     public void showEmulatorDisplayOverlay() {
3701         synchronized(mWindowMap) {
3702 
3703             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
3704                     ">>> OPEN TRANSACTION showEmulatorDisplayOverlay");
3705             openSurfaceTransaction();
3706             try {
3707                 if (mEmulatorDisplayOverlay == null) {
3708                     mEmulatorDisplayOverlay = new EmulatorDisplayOverlay(
3709                             mContext,
3710                             getDefaultDisplayContentLocked().getDisplay(),
3711                             mFxSession,
3712                             mPolicy.getWindowLayerFromTypeLw(
3713                                     WindowManager.LayoutParams.TYPE_POINTER)
3714                                     * TYPE_LAYER_MULTIPLIER + 10);
3715                 }
3716                 mEmulatorDisplayOverlay.setVisibility(true);
3717             } finally {
3718                 closeSurfaceTransaction();
3719                 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
3720                         "<<< CLOSE TRANSACTION showEmulatorDisplayOverlay");
3721             }
3722         }
3723     }
3724 
3725     // TODO: more accounting of which pid(s) turned it on, keep count,
3726     // only allow disables from pids which have count on, etc.
3727     @Override
showStrictModeViolation(boolean on)3728     public void showStrictModeViolation(boolean on) {
3729         final int pid = Binder.getCallingPid();
3730         if (on) {
3731             // Show the visualization, and enqueue a second message to tear it
3732             // down if we don't hear back from the app.
3733             mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 1, pid));
3734             mH.sendMessageDelayed(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 0, pid),
3735                     DateUtils.SECOND_IN_MILLIS);
3736         } else {
3737             mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 0, pid));
3738         }
3739     }
3740 
showStrictModeViolation(int arg, int pid)3741     private void showStrictModeViolation(int arg, int pid) {
3742         final boolean on = arg != 0;
3743         synchronized(mWindowMap) {
3744             // Ignoring requests to enable the red border from clients which aren't on screen.
3745             // (e.g. Broadcast Receivers in the background..)
3746             if (on && !mRoot.canShowStrictModeViolation(pid)) {
3747                 return;
3748             }
3749 
3750             if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
3751                     ">>> OPEN TRANSACTION showStrictModeViolation");
3752             // TODO: Modify this to use the surface trace once it is not going crazy.
3753             // b/31532461
3754             SurfaceControl.openTransaction();
3755             try {
3756                 // TODO(multi-display): support multiple displays
3757                 if (mStrictModeFlash == null) {
3758                     mStrictModeFlash = new StrictModeFlash(
3759                             getDefaultDisplayContentLocked().getDisplay(), mFxSession);
3760                 }
3761                 mStrictModeFlash.setVisibility(on);
3762             } finally {
3763                 SurfaceControl.closeTransaction();
3764                 if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
3765                         "<<< CLOSE TRANSACTION showStrictModeViolation");
3766             }
3767         }
3768     }
3769 
3770     @Override
setStrictModeVisualIndicatorPreference(String value)3771     public void setStrictModeVisualIndicatorPreference(String value) {
3772         SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
3773     }
3774 
3775     @Override
screenshotWallpaper()3776     public Bitmap screenshotWallpaper() {
3777         if (!checkCallingPermission(READ_FRAME_BUFFER,
3778                 "screenshotWallpaper()")) {
3779             throw new SecurityException("Requires READ_FRAME_BUFFER permission");
3780         }
3781         try {
3782             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "screenshotWallpaper");
3783             return screenshotApplications(null /* appToken */, DEFAULT_DISPLAY, -1 /* width */,
3784                     -1 /* height */, true /* includeFullDisplay */, 1f /* frameScale */,
3785                     Bitmap.Config.ARGB_8888, true /* wallpaperOnly */, false /* includeDecor */);
3786         } finally {
3787             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
3788         }
3789     }
3790 
3791     /**
3792      * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
3793      * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
3794      * of the target image.
3795      */
3796     @Override
requestAssistScreenshot(final IAssistScreenshotReceiver receiver)3797     public boolean requestAssistScreenshot(final IAssistScreenshotReceiver receiver) {
3798         if (!checkCallingPermission(READ_FRAME_BUFFER,
3799                 "requestAssistScreenshot()")) {
3800             throw new SecurityException("Requires READ_FRAME_BUFFER permission");
3801         }
3802 
3803         FgThread.getHandler().post(() -> {
3804             Bitmap bm = screenshotApplications(null /* appToken */, DEFAULT_DISPLAY,
3805                     -1 /* width */, -1 /* height */, true /* includeFullDisplay */,
3806                     1f /* frameScale */, Bitmap.Config.ARGB_8888, false /* wallpaperOnly */,
3807                     false /* includeDecor */);
3808             try {
3809                 receiver.send(bm);
3810             } catch (RemoteException e) {
3811             }
3812         });
3813 
3814         return true;
3815     }
3816 
getTaskSnapshot(int taskId, int userId, boolean reducedResolution)3817     public TaskSnapshot getTaskSnapshot(int taskId, int userId, boolean reducedResolution) {
3818         return mTaskSnapshotController.getSnapshot(taskId, userId, true /* restoreFromDisk */,
3819                 reducedResolution);
3820     }
3821 
3822     /**
3823      * In case a task write/delete operation was lost because the system crashed, this makes sure to
3824      * clean up the directory to remove obsolete files.
3825      *
3826      * @param persistentTaskIds A set of task ids that exist in our in-memory model.
3827      * @param runningUserIds The ids of the list of users that have tasks loaded in our in-memory
3828      *                       model.
3829      */
removeObsoleteTaskFiles(ArraySet<Integer> persistentTaskIds, int[] runningUserIds)3830     public void removeObsoleteTaskFiles(ArraySet<Integer> persistentTaskIds, int[] runningUserIds) {
3831         synchronized (mWindowMap) {
3832             mTaskSnapshotController.removeObsoleteTaskFiles(persistentTaskIds, runningUserIds);
3833         }
3834     }
3835 
3836     /**
3837      * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
3838      * In portrait mode, it grabs the full screenshot.
3839      *
3840      * @param displayId the Display to take a screenshot of.
3841      * @param width the width of the target bitmap
3842      * @param height the height of the target bitmap
3843      * @param includeFullDisplay true if the screen should not be cropped before capture
3844      * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
3845      * @param config of the output bitmap
3846      * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot
3847      * @param includeDecor whether to include window decors, like the status or navigation bar
3848      *                     background of the window
3849      */
screenshotApplications(IBinder appToken, int displayId, int width, int height, boolean includeFullDisplay, float frameScale, Bitmap.Config config, boolean wallpaperOnly, boolean includeDecor)3850     private Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
3851             int height, boolean includeFullDisplay, float frameScale, Bitmap.Config config,
3852             boolean wallpaperOnly, boolean includeDecor) {
3853         final DisplayContent displayContent;
3854         synchronized(mWindowMap) {
3855             displayContent = mRoot.getDisplayContentOrCreate(displayId);
3856             if (displayContent == null) {
3857                 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
3858                         + ": returning null. No Display for displayId=" + displayId);
3859                 return null;
3860             }
3861         }
3862         return displayContent.screenshotApplications(appToken, width, height,
3863                 includeFullDisplay, frameScale, config, wallpaperOnly, includeDecor);
3864     }
3865 
3866     /**
3867      * Freeze rotation changes.  (Enable "rotation lock".)
3868      * Persists across reboots.
3869      * @param rotation The desired rotation to freeze to, or -1 to use the
3870      * current rotation.
3871      */
3872     @Override
freezeRotation(int rotation)3873     public void freezeRotation(int rotation) {
3874         // TODO(multi-display): Track which display is rotated.
3875         if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
3876                 "freezeRotation()")) {
3877             throw new SecurityException("Requires SET_ORIENTATION permission");
3878         }
3879         if (rotation < -1 || rotation > Surface.ROTATION_270) {
3880             throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
3881                     + "rotation constant.");
3882         }
3883 
3884         final int defaultDisplayRotation = getDefaultDisplayRotation();
3885         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "freezeRotation: mRotation="
3886                 + defaultDisplayRotation);
3887 
3888         long origId = Binder.clearCallingIdentity();
3889         try {
3890             mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
3891                     rotation == -1 ? defaultDisplayRotation : rotation);
3892         } finally {
3893             Binder.restoreCallingIdentity(origId);
3894         }
3895 
3896         updateRotationUnchecked(false, false);
3897     }
3898 
3899     /**
3900      * Thaw rotation changes.  (Disable "rotation lock".)
3901      * Persists across reboots.
3902      */
3903     @Override
thawRotation()3904     public void thawRotation() {
3905         if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
3906                 "thawRotation()")) {
3907             throw new SecurityException("Requires SET_ORIENTATION permission");
3908         }
3909 
3910         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "thawRotation: mRotation="
3911                 + getDefaultDisplayRotation());
3912 
3913         long origId = Binder.clearCallingIdentity();
3914         try {
3915             mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
3916                     777); // rot not used
3917         } finally {
3918             Binder.restoreCallingIdentity(origId);
3919         }
3920 
3921         updateRotationUnchecked(false, false);
3922     }
3923 
3924     /**
3925      * Recalculate the current rotation.
3926      *
3927      * Called by the window manager policy whenever the state of the system changes
3928      * such that the current rotation might need to be updated, such as when the
3929      * device is docked or rotated into a new posture.
3930      */
3931     @Override
updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout)3932     public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
3933         updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
3934     }
3935 
3936     /**
3937      * Temporarily pauses rotation changes until resumed.
3938      *
3939      * This can be used to prevent rotation changes from occurring while the user is
3940      * performing certain operations, such as drag and drop.
3941      *
3942      * This call nests and must be matched by an equal number of calls to
3943      * {@link #resumeRotationLocked}.
3944      */
pauseRotationLocked()3945     void pauseRotationLocked() {
3946         mDeferredRotationPauseCount += 1;
3947     }
3948 
3949     /**
3950      * Resumes normal rotation changes after being paused.
3951      */
resumeRotationLocked()3952     void resumeRotationLocked() {
3953         if (mDeferredRotationPauseCount > 0) {
3954             mDeferredRotationPauseCount -= 1;
3955             if (mDeferredRotationPauseCount == 0) {
3956                 // TODO(multi-display): Update rotation for different displays separately.
3957                 final DisplayContent displayContent = getDefaultDisplayContentLocked();
3958                 final boolean changed = displayContent.updateRotationUnchecked(
3959                         false /* inTransaction */);
3960                 if (changed) {
3961                     mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
3962                             .sendToTarget();
3963                 }
3964             }
3965         }
3966     }
3967 
updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout)3968     private void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
3969         if(DEBUG_ORIENTATION) Slog.v(TAG_WM, "updateRotationUnchecked:"
3970                 + " alwaysSendConfiguration=" + alwaysSendConfiguration
3971                 + " forceRelayout=" + forceRelayout);
3972 
3973         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation");
3974 
3975         long origId = Binder.clearCallingIdentity();
3976 
3977         try {
3978             // TODO(multi-display): Update rotation for different displays separately.
3979             final boolean rotationChanged;
3980             final int displayId;
3981             synchronized (mWindowMap) {
3982                 final DisplayContent displayContent = getDefaultDisplayContentLocked();
3983                 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: display");
3984                 rotationChanged = displayContent.updateRotationUnchecked(
3985                         false /* inTransaction */);
3986                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
3987                 if (!rotationChanged || forceRelayout) {
3988                     displayContent.setLayoutNeeded();
3989                     Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
3990                             "updateRotation: performSurfacePlacement");
3991                     mWindowPlacerLocked.performSurfacePlacement();
3992                     Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
3993                 }
3994                 displayId = displayContent.getDisplayId();
3995             }
3996 
3997             if (rotationChanged || alwaysSendConfiguration) {
3998                 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: sendNewConfiguration");
3999                 sendNewConfiguration(displayId);
4000                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
4001             }
4002         } finally {
4003             Binder.restoreCallingIdentity(origId);
4004             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
4005         }
4006     }
4007 
4008     @Override
getDefaultDisplayRotation()4009     public int getDefaultDisplayRotation() {
4010         synchronized (mWindowMap) {
4011             return getDefaultDisplayContentLocked().getRotation();
4012         }
4013     }
4014 
4015     @Override
isRotationFrozen()4016     public boolean isRotationFrozen() {
4017         return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
4018     }
4019 
4020     @Override
watchRotation(IRotationWatcher watcher, int displayId)4021     public int watchRotation(IRotationWatcher watcher, int displayId) {
4022         final IBinder watcherBinder = watcher.asBinder();
4023         IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
4024             @Override
4025             public void binderDied() {
4026                 synchronized (mWindowMap) {
4027                     for (int i=0; i<mRotationWatchers.size(); i++) {
4028                         if (watcherBinder == mRotationWatchers.get(i).mWatcher.asBinder()) {
4029                             RotationWatcher removed = mRotationWatchers.remove(i);
4030                             IBinder binder = removed.mWatcher.asBinder();
4031                             if (binder != null) {
4032                                 binder.unlinkToDeath(this, 0);
4033                             }
4034                             i--;
4035                         }
4036                     }
4037                 }
4038             }
4039         };
4040 
4041         synchronized (mWindowMap) {
4042             try {
4043                 watcher.asBinder().linkToDeath(dr, 0);
4044                 mRotationWatchers.add(new RotationWatcher(watcher, dr, displayId));
4045             } catch (RemoteException e) {
4046                 // Client died, no cleanup needed.
4047             }
4048 
4049             return getDefaultDisplayRotation();
4050         }
4051     }
4052 
4053     @Override
removeRotationWatcher(IRotationWatcher watcher)4054     public void removeRotationWatcher(IRotationWatcher watcher) {
4055         final IBinder watcherBinder = watcher.asBinder();
4056         synchronized (mWindowMap) {
4057             for (int i=0; i<mRotationWatchers.size(); i++) {
4058                 RotationWatcher rotationWatcher = mRotationWatchers.get(i);
4059                 if (watcherBinder == rotationWatcher.mWatcher.asBinder()) {
4060                     RotationWatcher removed = mRotationWatchers.remove(i);
4061                     IBinder binder = removed.mWatcher.asBinder();
4062                     if (binder != null) {
4063                         binder.unlinkToDeath(removed.mDeathRecipient, 0);
4064                     }
4065                     i--;
4066                 }
4067             }
4068         }
4069     }
4070 
4071     @Override
registerWallpaperVisibilityListener(IWallpaperVisibilityListener listener, int displayId)4072     public boolean registerWallpaperVisibilityListener(IWallpaperVisibilityListener listener,
4073             int displayId) {
4074         synchronized (mWindowMap) {
4075             final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
4076             if (displayContent == null) {
4077                 throw new IllegalArgumentException("Trying to register visibility event "
4078                         + "for invalid display: " + displayId);
4079             }
4080             mWallpaperVisibilityListeners.registerWallpaperVisibilityListener(listener, displayId);
4081             return displayContent.mWallpaperController.isWallpaperVisible();
4082         }
4083     }
4084 
4085     @Override
unregisterWallpaperVisibilityListener(IWallpaperVisibilityListener listener, int displayId)4086     public void unregisterWallpaperVisibilityListener(IWallpaperVisibilityListener listener,
4087             int displayId) {
4088         synchronized (mWindowMap) {
4089             mWallpaperVisibilityListeners
4090                     .unregisterWallpaperVisibilityListener(listener, displayId);
4091         }
4092     }
4093 
4094     /**
4095      * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
4096      * theme attribute) on devices that feature a physical options menu key attempt to position
4097      * their menu panel window along the edge of the screen nearest the physical menu key.
4098      * This lowers the travel distance between invoking the menu panel and selecting
4099      * a menu option.
4100      *
4101      * This method helps control where that menu is placed. Its current implementation makes
4102      * assumptions about the menu key and its relationship to the screen based on whether
4103      * the device's natural orientation is portrait (width < height) or landscape.
4104      *
4105      * The menu key is assumed to be located along the bottom edge of natural-portrait
4106      * devices and along the right edge of natural-landscape devices. If these assumptions
4107      * do not hold for the target device, this method should be changed to reflect that.
4108      *
4109      * @return A {@link Gravity} value for placing the options menu window
4110      */
4111     @Override
getPreferredOptionsPanelGravity()4112     public int getPreferredOptionsPanelGravity() {
4113         synchronized (mWindowMap) {
4114             // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
4115             final DisplayContent displayContent = getDefaultDisplayContentLocked();
4116             final int rotation = displayContent.getRotation();
4117             if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
4118                 // On devices with a natural orientation of portrait
4119                 switch (rotation) {
4120                     default:
4121                     case Surface.ROTATION_0:
4122                         return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
4123                     case Surface.ROTATION_90:
4124                         return Gravity.RIGHT | Gravity.BOTTOM;
4125                     case Surface.ROTATION_180:
4126                         return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
4127                     case Surface.ROTATION_270:
4128                         return Gravity.START | Gravity.BOTTOM;
4129                 }
4130             }
4131 
4132             // On devices with a natural orientation of landscape
4133             switch (rotation) {
4134                 default:
4135                 case Surface.ROTATION_0:
4136                     return Gravity.RIGHT | Gravity.BOTTOM;
4137                 case Surface.ROTATION_90:
4138                     return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
4139                 case Surface.ROTATION_180:
4140                     return Gravity.START | Gravity.BOTTOM;
4141                 case Surface.ROTATION_270:
4142                     return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
4143             }
4144         }
4145     }
4146 
4147     /**
4148      * Starts the view server on the specified port.
4149      *
4150      * @param port The port to listener to.
4151      *
4152      * @return True if the server was successfully started, false otherwise.
4153      *
4154      * @see com.android.server.wm.ViewServer
4155      * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
4156      */
4157     @Override
startViewServer(int port)4158     public boolean startViewServer(int port) {
4159         if (isSystemSecure()) {
4160             return false;
4161         }
4162 
4163         if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
4164             return false;
4165         }
4166 
4167         if (port < 1024) {
4168             return false;
4169         }
4170 
4171         if (mViewServer != null) {
4172             if (!mViewServer.isRunning()) {
4173                 try {
4174                     return mViewServer.start();
4175                 } catch (IOException e) {
4176                     Slog.w(TAG_WM, "View server did not start");
4177                 }
4178             }
4179             return false;
4180         }
4181 
4182         try {
4183             mViewServer = new ViewServer(this, port);
4184             return mViewServer.start();
4185         } catch (IOException e) {
4186             Slog.w(TAG_WM, "View server did not start");
4187         }
4188         return false;
4189     }
4190 
isSystemSecure()4191     private boolean isSystemSecure() {
4192         return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
4193                 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
4194     }
4195 
4196     /**
4197      * Stops the view server if it exists.
4198      *
4199      * @return True if the server stopped, false if it wasn't started or
4200      *         couldn't be stopped.
4201      *
4202      * @see com.android.server.wm.ViewServer
4203      */
4204     @Override
stopViewServer()4205     public boolean stopViewServer() {
4206         if (isSystemSecure()) {
4207             return false;
4208         }
4209 
4210         if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
4211             return false;
4212         }
4213 
4214         if (mViewServer != null) {
4215             return mViewServer.stop();
4216         }
4217         return false;
4218     }
4219 
4220     /**
4221      * Indicates whether the view server is running.
4222      *
4223      * @return True if the server is running, false otherwise.
4224      *
4225      * @see com.android.server.wm.ViewServer
4226      */
4227     @Override
isViewServerRunning()4228     public boolean isViewServerRunning() {
4229         if (isSystemSecure()) {
4230             return false;
4231         }
4232 
4233         if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
4234             return false;
4235         }
4236 
4237         return mViewServer != null && mViewServer.isRunning();
4238     }
4239 
4240     /**
4241      * Lists all available windows in the system. The listing is written in the specified Socket's
4242      * output stream with the following syntax: windowHashCodeInHexadecimal windowName
4243      * Each line of the output represents a different window.
4244      *
4245      * @param client The remote client to send the listing to.
4246      * @return false if an error occurred, true otherwise.
4247      */
viewServerListWindows(Socket client)4248     boolean viewServerListWindows(Socket client) {
4249         if (isSystemSecure()) {
4250             return false;
4251         }
4252 
4253         boolean result = true;
4254 
4255         final ArrayList<WindowState> windows = new ArrayList();
4256         synchronized (mWindowMap) {
4257             mRoot.forAllWindows(w -> {
4258                 windows.add(w);
4259             }, false /* traverseTopToBottom */);
4260         }
4261 
4262         BufferedWriter out = null;
4263 
4264         // Any uncaught exception will crash the system process
4265         try {
4266             OutputStream clientStream = client.getOutputStream();
4267             out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
4268 
4269             final int count = windows.size();
4270             for (int i = 0; i < count; i++) {
4271                 final WindowState w = windows.get(i);
4272                 out.write(Integer.toHexString(System.identityHashCode(w)));
4273                 out.write(' ');
4274                 out.append(w.mAttrs.getTitle());
4275                 out.write('\n');
4276             }
4277 
4278             out.write("DONE.\n");
4279             out.flush();
4280         } catch (Exception e) {
4281             result = false;
4282         } finally {
4283             if (out != null) {
4284                 try {
4285                     out.close();
4286                 } catch (IOException e) {
4287                     result = false;
4288                 }
4289             }
4290         }
4291 
4292         return result;
4293     }
4294 
4295     // TODO(multidisplay): Extend to multiple displays.
4296     /**
4297      * Returns the focused window in the following format:
4298      * windowHashCodeInHexadecimal windowName
4299      *
4300      * @param client The remote client to send the listing to.
4301      * @return False if an error occurred, true otherwise.
4302      */
viewServerGetFocusedWindow(Socket client)4303     boolean viewServerGetFocusedWindow(Socket client) {
4304         if (isSystemSecure()) {
4305             return false;
4306         }
4307 
4308         boolean result = true;
4309 
4310         WindowState focusedWindow = getFocusedWindow();
4311 
4312         BufferedWriter out = null;
4313 
4314         // Any uncaught exception will crash the system process
4315         try {
4316             OutputStream clientStream = client.getOutputStream();
4317             out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
4318 
4319             if(focusedWindow != null) {
4320                 out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
4321                 out.write(' ');
4322                 out.append(focusedWindow.mAttrs.getTitle());
4323             }
4324             out.write('\n');
4325             out.flush();
4326         } catch (Exception e) {
4327             result = false;
4328         } finally {
4329             if (out != null) {
4330                 try {
4331                     out.close();
4332                 } catch (IOException e) {
4333                     result = false;
4334                 }
4335             }
4336         }
4337 
4338         return result;
4339     }
4340 
4341     /**
4342      * Sends a command to a target window. The result of the command, if any, will be
4343      * written in the output stream of the specified socket.
4344      *
4345      * The parameters must follow this syntax:
4346      * windowHashcode extra
4347      *
4348      * Where XX is the length in characeters of the windowTitle.
4349      *
4350      * The first parameter is the target window. The window with the specified hashcode
4351      * will be the target. If no target can be found, nothing happens. The extra parameters
4352      * will be delivered to the target window and as parameters to the command itself.
4353      *
4354      * @param client The remote client to sent the result, if any, to.
4355      * @param command The command to execute.
4356      * @param parameters The command parameters.
4357      *
4358      * @return True if the command was successfully delivered, false otherwise. This does
4359      *         not indicate whether the command itself was successful.
4360      */
viewServerWindowCommand(Socket client, String command, String parameters)4361     boolean viewServerWindowCommand(Socket client, String command, String parameters) {
4362         if (isSystemSecure()) {
4363             return false;
4364         }
4365 
4366         boolean success = true;
4367         Parcel data = null;
4368         Parcel reply = null;
4369 
4370         BufferedWriter out = null;
4371 
4372         // Any uncaught exception will crash the system process
4373         try {
4374             // Find the hashcode of the window
4375             int index = parameters.indexOf(' ');
4376             if (index == -1) {
4377                 index = parameters.length();
4378             }
4379             final String code = parameters.substring(0, index);
4380             int hashCode = (int) Long.parseLong(code, 16);
4381 
4382             // Extract the command's parameter after the window description
4383             if (index < parameters.length()) {
4384                 parameters = parameters.substring(index + 1);
4385             } else {
4386                 parameters = "";
4387             }
4388 
4389             final WindowState window = findWindow(hashCode);
4390             if (window == null) {
4391                 return false;
4392             }
4393 
4394             data = Parcel.obtain();
4395             data.writeInterfaceToken("android.view.IWindow");
4396             data.writeString(command);
4397             data.writeString(parameters);
4398             data.writeInt(1);
4399             ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
4400 
4401             reply = Parcel.obtain();
4402 
4403             final IBinder binder = window.mClient.asBinder();
4404             // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
4405             binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
4406 
4407             reply.readException();
4408 
4409             if (!client.isOutputShutdown()) {
4410                 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
4411                 out.write("DONE\n");
4412                 out.flush();
4413             }
4414 
4415         } catch (Exception e) {
4416             Slog.w(TAG_WM, "Could not send command " + command + " with parameters " + parameters, e);
4417             success = false;
4418         } finally {
4419             if (data != null) {
4420                 data.recycle();
4421             }
4422             if (reply != null) {
4423                 reply.recycle();
4424             }
4425             if (out != null) {
4426                 try {
4427                     out.close();
4428                 } catch (IOException e) {
4429 
4430                 }
4431             }
4432         }
4433 
4434         return success;
4435     }
4436 
addWindowChangeListener(WindowChangeListener listener)4437     public void addWindowChangeListener(WindowChangeListener listener) {
4438         synchronized(mWindowMap) {
4439             mWindowChangeListeners.add(listener);
4440         }
4441     }
4442 
removeWindowChangeListener(WindowChangeListener listener)4443     public void removeWindowChangeListener(WindowChangeListener listener) {
4444         synchronized(mWindowMap) {
4445             mWindowChangeListeners.remove(listener);
4446         }
4447     }
4448 
notifyWindowsChanged()4449     private void notifyWindowsChanged() {
4450         WindowChangeListener[] windowChangeListeners;
4451         synchronized(mWindowMap) {
4452             if(mWindowChangeListeners.isEmpty()) {
4453                 return;
4454             }
4455             windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
4456             windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
4457         }
4458         int N = windowChangeListeners.length;
4459         for(int i = 0; i < N; i++) {
4460             windowChangeListeners[i].windowsChanged();
4461         }
4462     }
4463 
notifyFocusChanged()4464     private void notifyFocusChanged() {
4465         WindowChangeListener[] windowChangeListeners;
4466         synchronized(mWindowMap) {
4467             if(mWindowChangeListeners.isEmpty()) {
4468                 return;
4469             }
4470             windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
4471             windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
4472         }
4473         int N = windowChangeListeners.length;
4474         for(int i = 0; i < N; i++) {
4475             windowChangeListeners[i].focusChanged();
4476         }
4477     }
4478 
findWindow(int hashCode)4479     private WindowState findWindow(int hashCode) {
4480         if (hashCode == -1) {
4481             // TODO(multidisplay): Extend to multiple displays.
4482             return getFocusedWindow();
4483         }
4484 
4485         synchronized (mWindowMap) {
4486             return mRoot.getWindow((w) -> System.identityHashCode(w) == hashCode);
4487         }
4488     }
4489 
4490     /**
4491      * Instruct the Activity Manager to fetch and update the current display's configuration and
4492      * broadcast them to config-changed listeners if appropriate.
4493      * NOTE: Can't be called with the window manager lock held since it call into activity manager.
4494      */
sendNewConfiguration(int displayId)4495     void sendNewConfiguration(int displayId) {
4496         try {
4497             final boolean configUpdated = mActivityManager.updateDisplayOverrideConfiguration(
4498                     null /* values */, displayId);
4499             if (!configUpdated) {
4500                 // Something changed (E.g. device rotation), but no configuration update is needed.
4501                 // E.g. changing device rotation by 180 degrees. Go ahead and perform surface
4502                 // placement to unfreeze the display since we froze it when the rotation was updated
4503                 // in DisplayContent#updateRotationUnchecked.
4504                 synchronized (mWindowMap) {
4505                     if (mWaitingForConfig) {
4506                         mWaitingForConfig = false;
4507                         mLastFinishedFreezeSource = "config-unchanged";
4508                         final DisplayContent dc = mRoot.getDisplayContent(displayId);
4509                         if (dc != null) {
4510                             dc.setLayoutNeeded();
4511                         }
4512                         mWindowPlacerLocked.performSurfacePlacement();
4513                     }
4514                 }
4515             }
4516         } catch (RemoteException e) {
4517         }
4518     }
4519 
computeNewConfiguration(int displayId)4520     public Configuration computeNewConfiguration(int displayId) {
4521         synchronized (mWindowMap) {
4522             return computeNewConfigurationLocked(displayId);
4523         }
4524     }
4525 
computeNewConfigurationLocked(int displayId)4526     private Configuration computeNewConfigurationLocked(int displayId) {
4527         if (!mDisplayReady) {
4528             return null;
4529         }
4530         final Configuration config = new Configuration();
4531         final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
4532         displayContent.computeScreenConfiguration(config);
4533         return config;
4534     }
4535 
notifyHardKeyboardStatusChange()4536     void notifyHardKeyboardStatusChange() {
4537         final boolean available;
4538         final WindowManagerInternal.OnHardKeyboardStatusChangeListener listener;
4539         synchronized (mWindowMap) {
4540             listener = mHardKeyboardStatusChangeListener;
4541             available = mHardKeyboardAvailable;
4542         }
4543         if (listener != null) {
4544             listener.onHardKeyboardStatusChange(available);
4545         }
4546     }
4547 
startMovingTask(IWindow window, float startX, float startY)4548     boolean startMovingTask(IWindow window, float startX, float startY) {
4549         WindowState win = null;
4550         synchronized (mWindowMap) {
4551             win = windowForClientLocked(null, window, false);
4552             // win shouldn't be null here, pass it down to startPositioningLocked
4553             // to get warning if it's null.
4554             if (!startPositioningLocked(
4555                         win, false /*resize*/, false /*preserveOrientation*/, startX, startY)) {
4556                 return false;
4557             }
4558         }
4559         try {
4560             mActivityManager.setFocusedTask(win.getTask().mTaskId);
4561         } catch(RemoteException e) {}
4562         return true;
4563     }
4564 
handleTapOutsideTask(DisplayContent displayContent, int x, int y)4565     private void handleTapOutsideTask(DisplayContent displayContent, int x, int y) {
4566         int taskId = -1;
4567         synchronized (mWindowMap) {
4568             final Task task = displayContent.findTaskForResizePoint(x, y);
4569             if (task != null) {
4570                 if (!startPositioningLocked(task.getTopVisibleAppMainWindow(), true /*resize*/,
4571                             task.preserveOrientationOnResize(), x, y)) {
4572                     return;
4573                 }
4574                 taskId = task.mTaskId;
4575             } else {
4576                 taskId = displayContent.taskIdFromPoint(x, y);
4577             }
4578         }
4579         if (taskId >= 0) {
4580             try {
4581                 mActivityManager.setFocusedTask(taskId);
4582             } catch(RemoteException e) {}
4583         }
4584     }
4585 
startPositioningLocked(WindowState win, boolean resize, boolean preserveOrientation, float startX, float startY)4586     private boolean startPositioningLocked(WindowState win, boolean resize,
4587             boolean preserveOrientation, float startX, float startY) {
4588         if (DEBUG_TASK_POSITIONING)
4589             Slog.d(TAG_WM, "startPositioningLocked: "
4590                             + "win=" + win + ", resize=" + resize + ", preserveOrientation="
4591                             + preserveOrientation + ", {" + startX + ", " + startY + "}");
4592 
4593         if (win == null || win.getAppToken() == null) {
4594             Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win);
4595             return false;
4596         }
4597         if (win.mInputChannel == null) {
4598             Slog.wtf(TAG_WM, "startPositioningLocked: " + win + " has no input channel, "
4599                     + " probably being removed");
4600             return false;
4601         }
4602 
4603         final DisplayContent displayContent = win.getDisplayContent();
4604         if (displayContent == null) {
4605             Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win);
4606             return false;
4607         }
4608 
4609         Display display = displayContent.getDisplay();
4610         mTaskPositioner = new TaskPositioner(this);
4611         mTaskPositioner.register(display);
4612         mInputMonitor.updateInputWindowsLw(true /*force*/);
4613 
4614         // We need to grab the touch focus so that the touch events during the
4615         // resizing/scrolling are not sent to the app. 'win' is the main window
4616         // of the app, it may not have focus since there might be other windows
4617         // on top (eg. a dialog window).
4618         WindowState transferFocusFromWin = win;
4619         if (mCurrentFocus != null && mCurrentFocus != win
4620                 && mCurrentFocus.mAppToken == win.mAppToken) {
4621             transferFocusFromWin = mCurrentFocus;
4622         }
4623         if (!mInputManager.transferTouchFocus(
4624                 transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) {
4625             Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus");
4626             mTaskPositioner.unregister();
4627             mTaskPositioner = null;
4628             mInputMonitor.updateInputWindowsLw(true /*force*/);
4629             return false;
4630         }
4631 
4632         mTaskPositioner.startDrag(win, resize, preserveOrientation, startX, startY);
4633         return true;
4634     }
4635 
finishPositioning()4636     private void finishPositioning() {
4637         if (DEBUG_TASK_POSITIONING) {
4638             Slog.d(TAG_WM, "finishPositioning");
4639         }
4640         synchronized (mWindowMap) {
4641             if (mTaskPositioner != null) {
4642                 mTaskPositioner.unregister();
4643                 mTaskPositioner = null;
4644                 mInputMonitor.updateInputWindowsLw(true /*force*/);
4645             }
4646         }
4647     }
4648 
4649     // -------------------------------------------------------------
4650     // Drag and drop
4651     // -------------------------------------------------------------
4652 
prepareDragSurface(IWindow window, SurfaceSession session, int flags, int width, int height, Surface outSurface)4653     IBinder prepareDragSurface(IWindow window, SurfaceSession session,
4654             int flags, int width, int height, Surface outSurface) {
4655         if (DEBUG_DRAG) {
4656             Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height
4657                     + " flags=" + Integer.toHexString(flags) + " win=" + window
4658                     + " asbinder=" + window.asBinder());
4659         }
4660 
4661         final int callerPid = Binder.getCallingPid();
4662         final int callerUid = Binder.getCallingUid();
4663         final long origId = Binder.clearCallingIdentity();
4664         IBinder token = null;
4665 
4666         try {
4667             synchronized (mWindowMap) {
4668                 try {
4669                     if (mDragState == null) {
4670                         // TODO(multi-display): support other displays
4671                         final DisplayContent displayContent = getDefaultDisplayContentLocked();
4672                         final Display display = displayContent.getDisplay();
4673 
4674                         SurfaceControl surface = new SurfaceControl(session, "drag surface",
4675                                 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
4676                         surface.setLayerStack(display.getLayerStack());
4677                         float alpha = 1;
4678                         if ((flags & View.DRAG_FLAG_OPAQUE) == 0) {
4679                             alpha = DRAG_SHADOW_ALPHA_TRANSPARENT;
4680                         }
4681                         surface.setAlpha(alpha);
4682 
4683                         if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, "  DRAG "
4684                                 + surface + ": CREATE");
4685                         outSurface.copyFrom(surface);
4686                         final IBinder winBinder = window.asBinder();
4687                         token = new Binder();
4688                         mDragState = new DragState(this, token, surface, flags, winBinder);
4689                         mDragState.mPid = callerPid;
4690                         mDragState.mUid = callerUid;
4691                         mDragState.mOriginalAlpha = alpha;
4692                         token = mDragState.mToken = new Binder();
4693 
4694                         // 5 second timeout for this window to actually begin the drag
4695                         mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
4696                         Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
4697                         mH.sendMessageDelayed(msg, 5000);
4698                     } else {
4699                         Slog.w(TAG_WM, "Drag already in progress");
4700                     }
4701                 } catch (OutOfResourcesException e) {
4702                     Slog.e(TAG_WM, "Can't allocate drag surface w=" + width + " h=" + height, e);
4703                     if (mDragState != null) {
4704                         mDragState.reset();
4705                         mDragState = null;
4706                     }
4707                 }
4708             }
4709         } finally {
4710             Binder.restoreCallingIdentity(origId);
4711         }
4712 
4713         return token;
4714     }
4715 
4716     // -------------------------------------------------------------
4717     // Input Events and Focus Management
4718     // -------------------------------------------------------------
4719 
4720     final InputMonitor mInputMonitor = new InputMonitor(this);
4721     private boolean mEventDispatchingEnabled;
4722 
4723     @Override
setEventDispatching(boolean enabled)4724     public void setEventDispatching(boolean enabled) {
4725         if (!checkCallingPermission(MANAGE_APP_TOKENS, "setEventDispatching()")) {
4726             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4727         }
4728 
4729         synchronized (mWindowMap) {
4730             mEventDispatchingEnabled = enabled;
4731             if (mDisplayEnabled) {
4732                 mInputMonitor.setEventDispatchingLw(enabled);
4733             }
4734         }
4735     }
4736 
getFocusedWindow()4737     private WindowState getFocusedWindow() {
4738         synchronized (mWindowMap) {
4739             return getFocusedWindowLocked();
4740         }
4741     }
4742 
getFocusedWindowLocked()4743     private WindowState getFocusedWindowLocked() {
4744         return mCurrentFocus;
4745     }
4746 
getImeFocusStackLocked()4747     TaskStack getImeFocusStackLocked() {
4748         // Don't use mCurrentFocus.getStack() because it returns home stack for system windows.
4749         // Also don't use mInputMethodTarget's stack, because some window with FLAG_NOT_FOCUSABLE
4750         // and FLAG_ALT_FOCUSABLE_IM flags both set might be set to IME target so they're moved
4751         // to make room for IME, but the window is not the focused window that's taking input.
4752         return (mFocusedApp != null && mFocusedApp.getTask() != null) ?
4753                 mFocusedApp.getTask().mStack : null;
4754     }
4755 
detectSafeMode()4756     public boolean detectSafeMode() {
4757         if (!mInputMonitor.waitForInputDevicesReady(
4758                 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
4759             Slog.w(TAG_WM, "Devices still not ready after waiting "
4760                    + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
4761                    + " milliseconds before attempting to detect safe mode.");
4762         }
4763 
4764         if (Settings.Global.getInt(
4765                 mContext.getContentResolver(), Settings.Global.SAFE_BOOT_DISALLOWED, 0) != 0) {
4766             return false;
4767         }
4768 
4769         int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
4770                 KeyEvent.KEYCODE_MENU);
4771         int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
4772         int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
4773                 KeyEvent.KEYCODE_DPAD_CENTER);
4774         int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
4775                 InputManagerService.BTN_MOUSE);
4776         int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
4777                 KeyEvent.KEYCODE_VOLUME_DOWN);
4778         mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
4779                 || volumeDownState > 0;
4780         try {
4781             if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0
4782                     || SystemProperties.getInt(ShutdownThread.RO_SAFEMODE_PROPERTY, 0) != 0) {
4783                 mSafeMode = true;
4784                 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
4785             }
4786         } catch (IllegalArgumentException e) {
4787         }
4788         if (mSafeMode) {
4789             Log.i(TAG_WM, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
4790                     + " dpad=" + dpadState + " trackball=" + trackballState + ")");
4791             SystemProperties.set(ShutdownThread.RO_SAFEMODE_PROPERTY, "1");
4792         } else {
4793             Log.i(TAG_WM, "SAFE MODE not enabled");
4794         }
4795         mPolicy.setSafeMode(mSafeMode);
4796         return mSafeMode;
4797     }
4798 
displayReady()4799     public void displayReady() {
4800         for (Display display : mDisplays) {
4801             displayReady(display.getDisplayId());
4802         }
4803 
4804         synchronized(mWindowMap) {
4805             final DisplayContent displayContent = getDefaultDisplayContentLocked();
4806             if (mMaxUiWidth > 0) {
4807                 displayContent.setMaxUiWidth(mMaxUiWidth);
4808             }
4809             readForcedDisplayPropertiesLocked(displayContent);
4810             mDisplayReady = true;
4811         }
4812 
4813         try {
4814             mActivityManager.updateConfiguration(null);
4815         } catch (RemoteException e) {
4816         }
4817 
4818         synchronized(mWindowMap) {
4819             mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
4820                     PackageManager.FEATURE_TOUCHSCREEN);
4821             configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
4822         }
4823 
4824         try {
4825             mActivityManager.updateConfiguration(null);
4826         } catch (RemoteException e) {
4827         }
4828 
4829         updateCircularDisplayMaskIfNeeded();
4830     }
4831 
displayReady(int displayId)4832     private void displayReady(int displayId) {
4833         synchronized(mWindowMap) {
4834             final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
4835             if (displayContent != null) {
4836                 mAnimator.addDisplayLocked(displayId);
4837                 displayContent.initializeDisplayBaseInfo();
4838             }
4839         }
4840     }
4841 
systemReady()4842     public void systemReady() {
4843         mPolicy.systemReady();
4844         mTaskSnapshotController.systemReady();
4845         mHasWideColorGamutSupport = queryWideColorGamutSupport();
4846     }
4847 
queryWideColorGamutSupport()4848     private static boolean queryWideColorGamutSupport() {
4849         try {
4850             ISurfaceFlingerConfigs surfaceFlinger = ISurfaceFlingerConfigs.getService();
4851             OptionalBool hasWideColor = surfaceFlinger.hasWideColorDisplay();
4852             if (hasWideColor != null) {
4853                 return hasWideColor.value;
4854             }
4855         } catch (RemoteException e) {
4856             // Ignore, we're in big trouble if we can't talk to SurfaceFlinger's config store
4857         }
4858         return false;
4859     }
4860 
4861     // -------------------------------------------------------------
4862     // Async Handler
4863     // -------------------------------------------------------------
4864 
4865     final class H extends android.os.Handler {
4866         public static final int REPORT_FOCUS_CHANGE = 2;
4867         public static final int REPORT_LOSING_FOCUS = 3;
4868         public static final int WINDOW_FREEZE_TIMEOUT = 11;
4869 
4870         public static final int APP_TRANSITION_TIMEOUT = 13;
4871         public static final int PERSIST_ANIMATION_SCALE = 14;
4872         public static final int FORCE_GC = 15;
4873         public static final int ENABLE_SCREEN = 16;
4874         public static final int APP_FREEZE_TIMEOUT = 17;
4875         public static final int SEND_NEW_CONFIGURATION = 18;
4876         public static final int REPORT_WINDOWS_CHANGE = 19;
4877         public static final int DRAG_START_TIMEOUT = 20;
4878         public static final int DRAG_END_TIMEOUT = 21;
4879         public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
4880         public static final int BOOT_TIMEOUT = 23;
4881         public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
4882         public static final int SHOW_STRICT_MODE_VIOLATION = 25;
4883         public static final int DO_ANIMATION_CALLBACK = 26;
4884 
4885         public static final int CLIENT_FREEZE_TIMEOUT = 30;
4886         public static final int TAP_OUTSIDE_TASK = 31;
4887         public static final int NOTIFY_ACTIVITY_DRAWN = 32;
4888 
4889         public static final int ALL_WINDOWS_DRAWN = 33;
4890 
4891         public static final int NEW_ANIMATOR_SCALE = 34;
4892 
4893         public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35;
4894         public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36;
4895 
4896         public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37;
4897         public static final int RESET_ANR_MESSAGE = 38;
4898         public static final int WALLPAPER_DRAW_PENDING_TIMEOUT = 39;
4899 
4900         public static final int FINISH_TASK_POSITIONING = 40;
4901 
4902         public static final int UPDATE_DOCKED_STACK_DIVIDER = 41;
4903 
4904         public static final int TEAR_DOWN_DRAG_AND_DROP_INPUT = 44;
4905 
4906         public static final int WINDOW_REPLACEMENT_TIMEOUT = 46;
4907 
4908         public static final int NOTIFY_APP_TRANSITION_STARTING = 47;
4909         public static final int NOTIFY_APP_TRANSITION_CANCELLED = 48;
4910         public static final int NOTIFY_APP_TRANSITION_FINISHED = 49;
4911         public static final int UPDATE_ANIMATION_SCALE = 51;
4912         public static final int WINDOW_HIDE_TIMEOUT = 52;
4913         public static final int NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED = 53;
4914         public static final int SEAMLESS_ROTATION_TIMEOUT = 54;
4915         public static final int RESTORE_POINTER_ICON = 55;
4916         public static final int NOTIFY_KEYGUARD_FLAGS_CHANGED = 56;
4917         public static final int NOTIFY_KEYGUARD_TRUSTED_CHANGED = 57;
4918         public static final int SET_HAS_OVERLAY_UI = 58;
4919         public static final int RECOMPUTE_FOCUS = 61;
4920 
4921         /**
4922          * Used to denote that an integer field in a message will not be used.
4923          */
4924         public static final int UNUSED = 0;
4925 
4926         @Override
handleMessage(Message msg)4927         public void handleMessage(Message msg) {
4928             if (DEBUG_WINDOW_TRACE) {
4929                 Slog.v(TAG_WM, "handleMessage: entry what=" + msg.what);
4930             }
4931             switch (msg.what) {
4932                 case REPORT_FOCUS_CHANGE: {
4933                     WindowState lastFocus;
4934                     WindowState newFocus;
4935 
4936                     AccessibilityController accessibilityController = null;
4937 
4938                     synchronized(mWindowMap) {
4939                         // TODO(multidisplay): Accessibility supported only of default desiplay.
4940                         if (mAccessibilityController != null && getDefaultDisplayContentLocked()
4941                                 .getDisplayId() == DEFAULT_DISPLAY) {
4942                             accessibilityController = mAccessibilityController;
4943                         }
4944 
4945                         lastFocus = mLastFocus;
4946                         newFocus = mCurrentFocus;
4947                         if (lastFocus == newFocus) {
4948                             // Focus is not changing, so nothing to do.
4949                             return;
4950                         }
4951                         mLastFocus = newFocus;
4952                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Focus moving from " + lastFocus +
4953                                 " to " + newFocus);
4954                         if (newFocus != null && lastFocus != null
4955                                 && !newFocus.isDisplayedLw()) {
4956                             //Slog.i(TAG_WM, "Delaying loss of focus...");
4957                             mLosingFocus.add(lastFocus);
4958                             lastFocus = null;
4959                         }
4960                     }
4961 
4962                     // First notify the accessibility manager for the change so it has
4963                     // the windows before the newly focused one starts firing eventgs.
4964                     if (accessibilityController != null) {
4965                         accessibilityController.onWindowFocusChangedNotLocked();
4966                     }
4967 
4968                     //System.out.println("Changing focus from " + lastFocus
4969                     //                   + " to " + newFocus);
4970                     if (newFocus != null) {
4971                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Gaining focus: " + newFocus);
4972                         newFocus.reportFocusChangedSerialized(true, mInTouchMode);
4973                         notifyFocusChanged();
4974                     }
4975 
4976                     if (lastFocus != null) {
4977                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing focus: " + lastFocus);
4978                         lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
4979                     }
4980                 } break;
4981 
4982                 case REPORT_LOSING_FOCUS: {
4983                     ArrayList<WindowState> losers;
4984 
4985                     synchronized(mWindowMap) {
4986                         losers = mLosingFocus;
4987                         mLosingFocus = new ArrayList<WindowState>();
4988                     }
4989 
4990                     final int N = losers.size();
4991                     for (int i=0; i<N; i++) {
4992                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing delayed focus: " +
4993                                 losers.get(i));
4994                         losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
4995                     }
4996                 } break;
4997 
4998                 case WINDOW_FREEZE_TIMEOUT: {
4999                     // TODO(multidisplay): Can non-default displays rotate?
5000                     synchronized (mWindowMap) {
5001                         getDefaultDisplayContentLocked().onWindowFreezeTimeout();
5002                     }
5003                     break;
5004                 }
5005 
5006                 case APP_TRANSITION_TIMEOUT: {
5007                     synchronized (mWindowMap) {
5008                         if (mAppTransition.isTransitionSet() || !mOpeningApps.isEmpty()
5009                                     || !mClosingApps.isEmpty()) {
5010                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "*** APP TRANSITION TIMEOUT."
5011                                     + " isTransitionSet()=" + mAppTransition.isTransitionSet()
5012                                     + " mOpeningApps.size()=" + mOpeningApps.size()
5013                                     + " mClosingApps.size()=" + mClosingApps.size());
5014                             mAppTransition.setTimeout();
5015                             mWindowPlacerLocked.performSurfacePlacement();
5016                         }
5017                     }
5018                     break;
5019                 }
5020 
5021                 case PERSIST_ANIMATION_SCALE: {
5022                     Settings.Global.putFloat(mContext.getContentResolver(),
5023                             Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
5024                     Settings.Global.putFloat(mContext.getContentResolver(),
5025                             Settings.Global.TRANSITION_ANIMATION_SCALE,
5026                             mTransitionAnimationScaleSetting);
5027                     Settings.Global.putFloat(mContext.getContentResolver(),
5028                             Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting);
5029                     break;
5030                 }
5031 
5032                 case UPDATE_ANIMATION_SCALE: {
5033                     @UpdateAnimationScaleMode
5034                     final int mode = msg.arg1;
5035                     switch (mode) {
5036                         case WINDOW_ANIMATION_SCALE: {
5037                             mWindowAnimationScaleSetting = Settings.Global.getFloat(
5038                                     mContext.getContentResolver(),
5039                                     Settings.Global.WINDOW_ANIMATION_SCALE,
5040                                     mWindowAnimationScaleSetting);
5041                             break;
5042                         }
5043                         case TRANSITION_ANIMATION_SCALE: {
5044                             mTransitionAnimationScaleSetting = Settings.Global.getFloat(
5045                                     mContext.getContentResolver(),
5046                                     Settings.Global.TRANSITION_ANIMATION_SCALE,
5047                                     mTransitionAnimationScaleSetting);
5048                             break;
5049                         }
5050                         case ANIMATION_DURATION_SCALE: {
5051                             mAnimatorDurationScaleSetting = Settings.Global.getFloat(
5052                                     mContext.getContentResolver(),
5053                                     Settings.Global.ANIMATOR_DURATION_SCALE,
5054                                     mAnimatorDurationScaleSetting);
5055                             dispatchNewAnimatorScaleLocked(null);
5056                             break;
5057                         }
5058                     }
5059                     break;
5060                 }
5061 
5062                 case FORCE_GC: {
5063                     synchronized (mWindowMap) {
5064                         // Since we're holding both mWindowMap and mAnimator we don't need to
5065                         // hold mAnimator.mLayoutToAnim.
5066                         if (mAnimator.isAnimating() || mAnimator.isAnimationScheduled()) {
5067                             // If we are animating, don't do the gc now but
5068                             // delay a bit so we don't interrupt the animation.
5069                             sendEmptyMessageDelayed(H.FORCE_GC, 2000);
5070                             return;
5071                         }
5072                         // If we are currently rotating the display, it will
5073                         // schedule a new message when done.
5074                         if (mDisplayFrozen) {
5075                             return;
5076                         }
5077                     }
5078                     Runtime.getRuntime().gc();
5079                     break;
5080                 }
5081 
5082                 case ENABLE_SCREEN: {
5083                     performEnableScreen();
5084                     break;
5085                 }
5086 
5087                 case APP_FREEZE_TIMEOUT: {
5088                     synchronized (mWindowMap) {
5089                         Slog.w(TAG_WM, "App freeze timeout expired.");
5090                         mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
5091                         for (int i = mAppFreezeListeners.size() - 1; i >=0 ; --i) {
5092                             mAppFreezeListeners.get(i).onAppFreezeTimeout();
5093                         }
5094                     }
5095                     break;
5096                 }
5097 
5098                 case CLIENT_FREEZE_TIMEOUT: {
5099                     synchronized (mWindowMap) {
5100                         if (mClientFreezingScreen) {
5101                             mClientFreezingScreen = false;
5102                             mLastFinishedFreezeSource = "client-timeout";
5103                             stopFreezingDisplayLocked();
5104                         }
5105                     }
5106                     break;
5107                 }
5108 
5109                 case SEND_NEW_CONFIGURATION: {
5110                     removeMessages(SEND_NEW_CONFIGURATION, msg.obj);
5111                     final int displayId = (Integer) msg.obj;
5112                     if (mRoot.getDisplayContent(displayId) != null) {
5113                         sendNewConfiguration(displayId);
5114                     } else {
5115                         // Message could come after display has already been removed.
5116                         if (DEBUG_CONFIGURATION) {
5117                             Slog.w(TAG, "Trying to send configuration to non-existing displayId="
5118                                     + displayId);
5119                         }
5120                     }
5121                     break;
5122                 }
5123 
5124                 case REPORT_WINDOWS_CHANGE: {
5125                     if (mWindowsChanged) {
5126                         synchronized (mWindowMap) {
5127                             mWindowsChanged = false;
5128                         }
5129                         notifyWindowsChanged();
5130                     }
5131                     break;
5132                 }
5133 
5134                 case DRAG_START_TIMEOUT: {
5135                     IBinder win = (IBinder)msg.obj;
5136                     if (DEBUG_DRAG) {
5137                         Slog.w(TAG_WM, "Timeout starting drag by win " + win);
5138                     }
5139                     synchronized (mWindowMap) {
5140                         // !!! TODO: ANR the app that has failed to start the drag in time
5141                         if (mDragState != null) {
5142                             mDragState.unregister();
5143                             mDragState.reset();
5144                             mDragState = null;
5145                         }
5146                     }
5147                     break;
5148                 }
5149 
5150                 case DRAG_END_TIMEOUT: {
5151                     IBinder win = (IBinder)msg.obj;
5152                     if (DEBUG_DRAG) {
5153                         Slog.w(TAG_WM, "Timeout ending drag to win " + win);
5154                     }
5155                     synchronized (mWindowMap) {
5156                         // !!! TODO: ANR the drag-receiving app
5157                         if (mDragState != null) {
5158                             mDragState.mDragResult = false;
5159                             mDragState.endDragLw();
5160                         }
5161                     }
5162                     break;
5163                 }
5164 
5165                 case TEAR_DOWN_DRAG_AND_DROP_INPUT: {
5166                     if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ending; tearing down input channel");
5167                     DragState.InputInterceptor interceptor = (DragState.InputInterceptor) msg.obj;
5168                     if (interceptor != null) {
5169                         synchronized (mWindowMap) {
5170                             interceptor.tearDown();
5171                         }
5172                     }
5173                 }
5174                 break;
5175 
5176                 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
5177                     notifyHardKeyboardStatusChange();
5178                     break;
5179                 }
5180 
5181                 case BOOT_TIMEOUT: {
5182                     performBootTimeout();
5183                     break;
5184                 }
5185 
5186                 case WAITING_FOR_DRAWN_TIMEOUT: {
5187                     Runnable callback = null;
5188                     synchronized (mWindowMap) {
5189                         Slog.w(TAG_WM, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);
5190                         mWaitingForDrawn.clear();
5191                         callback = mWaitingForDrawnCallback;
5192                         mWaitingForDrawnCallback = null;
5193                     }
5194                     if (callback != null) {
5195                         callback.run();
5196                     }
5197                     break;
5198                 }
5199 
5200                 case SHOW_STRICT_MODE_VIOLATION: {
5201                     showStrictModeViolation(msg.arg1, msg.arg2);
5202                     break;
5203                 }
5204 
5205                 case SHOW_CIRCULAR_DISPLAY_MASK: {
5206                     showCircularMask(msg.arg1 == 1);
5207                     break;
5208                 }
5209 
5210                 case SHOW_EMULATOR_DISPLAY_OVERLAY: {
5211                     showEmulatorDisplayOverlay();
5212                     break;
5213                 }
5214 
5215                 case DO_ANIMATION_CALLBACK: {
5216                     try {
5217                         ((IRemoteCallback)msg.obj).sendResult(null);
5218                     } catch (RemoteException e) {
5219                     }
5220                     break;
5221                 }
5222 
5223                 case TAP_OUTSIDE_TASK: {
5224                     handleTapOutsideTask((DisplayContent)msg.obj, msg.arg1, msg.arg2);
5225                 }
5226                 break;
5227 
5228                 case FINISH_TASK_POSITIONING: {
5229                     finishPositioning();
5230                 }
5231                 break;
5232 
5233                 case NOTIFY_ACTIVITY_DRAWN:
5234                     try {
5235                         mActivityManager.notifyActivityDrawn((IBinder) msg.obj);
5236                     } catch (RemoteException e) {
5237                     }
5238                     break;
5239                 case ALL_WINDOWS_DRAWN: {
5240                     Runnable callback;
5241                     synchronized (mWindowMap) {
5242                         callback = mWaitingForDrawnCallback;
5243                         mWaitingForDrawnCallback = null;
5244                     }
5245                     if (callback != null) {
5246                         callback.run();
5247                     }
5248                     break;
5249                 }
5250                 case NEW_ANIMATOR_SCALE: {
5251                     float scale = getCurrentAnimatorScale();
5252                     ValueAnimator.setDurationScale(scale);
5253                     Session session = (Session)msg.obj;
5254                     if (session != null) {
5255                         try {
5256                             session.mCallback.onAnimatorScaleChanged(scale);
5257                         } catch (RemoteException e) {
5258                         }
5259                     } else {
5260                         ArrayList<IWindowSessionCallback> callbacks
5261                                 = new ArrayList<IWindowSessionCallback>();
5262                         synchronized (mWindowMap) {
5263                             for (int i=0; i<mSessions.size(); i++) {
5264                                 callbacks.add(mSessions.valueAt(i).mCallback);
5265                             }
5266 
5267                         }
5268                         for (int i=0; i<callbacks.size(); i++) {
5269                             try {
5270                                 callbacks.get(i).onAnimatorScaleChanged(scale);
5271                             } catch (RemoteException e) {
5272                             }
5273                         }
5274                     }
5275                 }
5276                 break;
5277                 case CHECK_IF_BOOT_ANIMATION_FINISHED: {
5278                     final boolean bootAnimationComplete;
5279                     synchronized (mWindowMap) {
5280                         if (DEBUG_BOOT) Slog.i(TAG_WM, "CHECK_IF_BOOT_ANIMATION_FINISHED:");
5281                         bootAnimationComplete = checkBootAnimationCompleteLocked();
5282                     }
5283                     if (bootAnimationComplete) {
5284                         performEnableScreen();
5285                     }
5286                 }
5287                 break;
5288                 case RESET_ANR_MESSAGE: {
5289                     synchronized (mWindowMap) {
5290                         mLastANRState = null;
5291                     }
5292                     mAmInternal.clearSavedANRState();
5293                 }
5294                 break;
5295                 case WALLPAPER_DRAW_PENDING_TIMEOUT: {
5296                     synchronized (mWindowMap) {
5297                         if (mRoot.mWallpaperController.processWallpaperDrawPendingTimeout()) {
5298                             mWindowPlacerLocked.performSurfacePlacement();
5299                         }
5300                     }
5301                 }
5302                 break;
5303                 case UPDATE_DOCKED_STACK_DIVIDER: {
5304                     synchronized (mWindowMap) {
5305                         final DisplayContent displayContent = getDefaultDisplayContentLocked();
5306                         displayContent.getDockedDividerController().reevaluateVisibility(false);
5307                         displayContent.adjustForImeIfNeeded();
5308                     }
5309                 }
5310                 break;
5311                 case WINDOW_REPLACEMENT_TIMEOUT: {
5312                     synchronized (mWindowMap) {
5313                         for (int i = mWindowReplacementTimeouts.size() - 1; i >= 0; i--) {
5314                             final AppWindowToken token = mWindowReplacementTimeouts.get(i);
5315                             token.onWindowReplacementTimeout();
5316                         }
5317                         mWindowReplacementTimeouts.clear();
5318                     }
5319                 }
5320                 break;
5321                 case NOTIFY_APP_TRANSITION_STARTING: {
5322                     mAmInternal.notifyAppTransitionStarting((SparseIntArray) msg.obj,
5323                             msg.getWhen());
5324                 }
5325                 break;
5326                 case NOTIFY_APP_TRANSITION_CANCELLED: {
5327                     mAmInternal.notifyAppTransitionCancelled();
5328                 }
5329                 break;
5330                 case NOTIFY_APP_TRANSITION_FINISHED: {
5331                     mAmInternal.notifyAppTransitionFinished();
5332                 }
5333                 break;
5334                 case WINDOW_HIDE_TIMEOUT: {
5335                     final WindowState window = (WindowState) msg.obj;
5336                     synchronized(mWindowMap) {
5337                         // TODO: This is all about fixing b/21693547
5338                         // where partially initialized Toasts get stuck
5339                         // around and keep the screen on. We'd like
5340                         // to just remove the toast...but this can cause clients
5341                         // who miss the timeout due to normal circumstances (e.g.
5342                         // running under debugger) to crash (b/29105388). The windows will
5343                         // eventually be removed when the client process finishes.
5344                         // The best we can do for now is remove the FLAG_KEEP_SCREEN_ON
5345                         // and prevent the symptoms of b/21693547. Since apps don't
5346                         // support windows being removed under them we hide the window
5347                         // and it will be removed when the app dies.
5348                         window.mAttrs.flags &= ~FLAG_KEEP_SCREEN_ON;
5349                         window.hidePermanentlyLw();
5350                         window.setDisplayLayoutNeeded();
5351                         mWindowPlacerLocked.performSurfacePlacement();
5352                     }
5353                 }
5354                 break;
5355                 case NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED: {
5356                     mAmInternal.notifyDockedStackMinimizedChanged(msg.arg1 == 1);
5357                 }
5358                 break;
5359                 case RESTORE_POINTER_ICON: {
5360                     synchronized (mWindowMap) {
5361                         restorePointerIconLocked((DisplayContent)msg.obj, msg.arg1, msg.arg2);
5362                     }
5363                 }
5364                 break;
5365                 case SEAMLESS_ROTATION_TIMEOUT: {
5366                     // Rotation only supported on primary display.
5367                     // TODO(multi-display)
5368                     synchronized(mWindowMap) {
5369                         final DisplayContent dc = getDefaultDisplayContentLocked();
5370                         dc.onSeamlessRotationTimeout();
5371                     }
5372                 }
5373                 break;
5374                 case NOTIFY_KEYGUARD_FLAGS_CHANGED: {
5375                     mAmInternal.notifyKeyguardFlagsChanged((Runnable) msg.obj);
5376                 }
5377                 break;
5378                 case NOTIFY_KEYGUARD_TRUSTED_CHANGED: {
5379                     mAmInternal.notifyKeyguardTrustedChanged();
5380                 }
5381                 break;
5382                 case SET_HAS_OVERLAY_UI: {
5383                     mAmInternal.setHasOverlayUi(msg.arg1, msg.arg2 == 1);
5384                 }
5385                 break;
5386                 case RECOMPUTE_FOCUS: {
5387                     synchronized (mWindowMap) {
5388                         updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
5389                                 true /* updateInputWindows */);
5390                     }
5391                 }
5392                 break;
5393             }
5394             if (DEBUG_WINDOW_TRACE) {
5395                 Slog.v(TAG_WM, "handleMessage: exit");
5396             }
5397         }
5398     }
5399 
destroyPreservedSurfaceLocked()5400     void destroyPreservedSurfaceLocked() {
5401         for (int i = mDestroyPreservedSurface.size() - 1; i >= 0 ; i--) {
5402             final WindowState w = mDestroyPreservedSurface.get(i);
5403             w.mWinAnimator.destroyPreservedSurfaceLocked();
5404         }
5405         mDestroyPreservedSurface.clear();
5406     }
5407 
stopUsingSavedSurfaceLocked()5408     void stopUsingSavedSurfaceLocked() {
5409         for (int i = mFinishedEarlyAnim.size() - 1; i >= 0 ; i--) {
5410             final AppWindowToken wtoken = mFinishedEarlyAnim.get(i);
5411             wtoken.stopUsingSavedSurfaceLocked();
5412         }
5413         mFinishedEarlyAnim.clear();
5414     }
5415 
5416     // -------------------------------------------------------------
5417     // IWindowManager API
5418     // -------------------------------------------------------------
5419 
5420     @Override
openSession(IWindowSessionCallback callback, IInputMethodClient client, IInputContext inputContext)5421     public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
5422             IInputContext inputContext) {
5423         if (client == null) throw new IllegalArgumentException("null client");
5424         if (inputContext == null) throw new IllegalArgumentException("null inputContext");
5425         Session session = new Session(this, callback, client, inputContext);
5426         return session;
5427     }
5428 
5429     @Override
inputMethodClientHasFocus(IInputMethodClient client)5430     public boolean inputMethodClientHasFocus(IInputMethodClient client) {
5431         synchronized (mWindowMap) {
5432             // TODO: multi-display
5433             if (getDefaultDisplayContentLocked().inputMethodClientHasFocus(client)) {
5434                 return true;
5435             }
5436 
5437             // Okay, how about this...  what is the current focus?
5438             // It seems in some cases we may not have moved the IM
5439             // target window, such as when it was in a pop-up window,
5440             // so let's also look at the current focus.  (An example:
5441             // go to Gmail, start searching so the keyboard goes up,
5442             // press home.  Sometimes the IME won't go down.)
5443             // Would be nice to fix this more correctly, but it's
5444             // way at the end of a release, and this should be good enough.
5445             if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
5446                     && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
5447                 return true;
5448             }
5449         }
5450         return false;
5451     }
5452 
5453     @Override
getInitialDisplaySize(int displayId, Point size)5454     public void getInitialDisplaySize(int displayId, Point size) {
5455         synchronized (mWindowMap) {
5456             final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5457             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
5458                 size.x = displayContent.mInitialDisplayWidth;
5459                 size.y = displayContent.mInitialDisplayHeight;
5460             }
5461         }
5462     }
5463 
5464     @Override
getBaseDisplaySize(int displayId, Point size)5465     public void getBaseDisplaySize(int displayId, Point size) {
5466         synchronized (mWindowMap) {
5467             final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5468             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
5469                 size.x = displayContent.mBaseDisplayWidth;
5470                 size.y = displayContent.mBaseDisplayHeight;
5471             }
5472         }
5473     }
5474 
5475     @Override
setForcedDisplaySize(int displayId, int width, int height)5476     public void setForcedDisplaySize(int displayId, int width, int height) {
5477         if (mContext.checkCallingOrSelfPermission(
5478                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
5479                 PackageManager.PERMISSION_GRANTED) {
5480             throw new SecurityException("Must hold permission " +
5481                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
5482         }
5483         if (displayId != DEFAULT_DISPLAY) {
5484             throw new IllegalArgumentException("Can only set the default display");
5485         }
5486         final long ident = Binder.clearCallingIdentity();
5487         try {
5488             synchronized(mWindowMap) {
5489                 // Set some sort of reasonable bounds on the size of the display that we
5490                 // will try to emulate.
5491                 final int MIN_WIDTH = 200;
5492                 final int MIN_HEIGHT = 200;
5493                 final int MAX_SCALE = 2;
5494                 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5495                 if (displayContent != null) {
5496                     width = Math.min(Math.max(width, MIN_WIDTH),
5497                             displayContent.mInitialDisplayWidth * MAX_SCALE);
5498                     height = Math.min(Math.max(height, MIN_HEIGHT),
5499                             displayContent.mInitialDisplayHeight * MAX_SCALE);
5500                     setForcedDisplaySizeLocked(displayContent, width, height);
5501                     Settings.Global.putString(mContext.getContentResolver(),
5502                             Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
5503                 }
5504             }
5505         } finally {
5506             Binder.restoreCallingIdentity(ident);
5507         }
5508     }
5509 
5510     @Override
setForcedDisplayScalingMode(int displayId, int mode)5511     public void setForcedDisplayScalingMode(int displayId, int mode) {
5512         if (mContext.checkCallingOrSelfPermission(
5513                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
5514                 PackageManager.PERMISSION_GRANTED) {
5515             throw new SecurityException("Must hold permission " +
5516                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
5517         }
5518         if (displayId != DEFAULT_DISPLAY) {
5519             throw new IllegalArgumentException("Can only set the default display");
5520         }
5521         final long ident = Binder.clearCallingIdentity();
5522         try {
5523             synchronized(mWindowMap) {
5524                 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5525                 if (displayContent != null) {
5526                     if (mode < 0 || mode > 1) {
5527                         mode = 0;
5528                     }
5529                     setForcedDisplayScalingModeLocked(displayContent, mode);
5530                     Settings.Global.putInt(mContext.getContentResolver(),
5531                             Settings.Global.DISPLAY_SCALING_FORCE, mode);
5532                 }
5533             }
5534         } finally {
5535             Binder.restoreCallingIdentity(ident);
5536         }
5537     }
5538 
setForcedDisplayScalingModeLocked(DisplayContent displayContent, int mode)5539     private void setForcedDisplayScalingModeLocked(DisplayContent displayContent, int mode) {
5540         Slog.i(TAG_WM, "Using display scaling mode: " + (mode == 0 ? "auto" : "off"));
5541         displayContent.mDisplayScalingDisabled = (mode != 0);
5542         reconfigureDisplayLocked(displayContent);
5543     }
5544 
readForcedDisplayPropertiesLocked(final DisplayContent displayContent)5545     private void readForcedDisplayPropertiesLocked(final DisplayContent displayContent) {
5546         // Display size.
5547         String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
5548                 Settings.Global.DISPLAY_SIZE_FORCED);
5549         if (sizeStr == null || sizeStr.length() == 0) {
5550             sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
5551         }
5552         if (sizeStr != null && sizeStr.length() > 0) {
5553             final int pos = sizeStr.indexOf(',');
5554             if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
5555                 int width, height;
5556                 try {
5557                     width = Integer.parseInt(sizeStr.substring(0, pos));
5558                     height = Integer.parseInt(sizeStr.substring(pos+1));
5559                     if (displayContent.mBaseDisplayWidth != width
5560                             || displayContent.mBaseDisplayHeight != height) {
5561                         Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height);
5562                         displayContent.updateBaseDisplayMetrics(width, height,
5563                                 displayContent.mBaseDisplayDensity);
5564                     }
5565                 } catch (NumberFormatException ex) {
5566                 }
5567             }
5568         }
5569 
5570         // Display density.
5571         final int density = getForcedDisplayDensityForUserLocked(mCurrentUserId);
5572         if (density != 0) {
5573             displayContent.mBaseDisplayDensity = density;
5574         }
5575 
5576         // Display scaling mode.
5577         int mode = Settings.Global.getInt(mContext.getContentResolver(),
5578                 Settings.Global.DISPLAY_SCALING_FORCE, 0);
5579         if (mode != 0) {
5580             Slog.i(TAG_WM, "FORCED DISPLAY SCALING DISABLED");
5581             displayContent.mDisplayScalingDisabled = true;
5582         }
5583     }
5584 
5585     // displayContent must not be null
setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height)5586     private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
5587         Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
5588         displayContent.updateBaseDisplayMetrics(width, height, displayContent.mBaseDisplayDensity);
5589         reconfigureDisplayLocked(displayContent);
5590     }
5591 
5592     @Override
clearForcedDisplaySize(int displayId)5593     public void clearForcedDisplaySize(int displayId) {
5594         if (mContext.checkCallingOrSelfPermission(
5595                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
5596                 PackageManager.PERMISSION_GRANTED) {
5597             throw new SecurityException("Must hold permission " +
5598                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
5599         }
5600         if (displayId != DEFAULT_DISPLAY) {
5601             throw new IllegalArgumentException("Can only set the default display");
5602         }
5603         final long ident = Binder.clearCallingIdentity();
5604         try {
5605             synchronized(mWindowMap) {
5606                 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5607                 if (displayContent != null) {
5608                     setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
5609                             displayContent.mInitialDisplayHeight);
5610                     Settings.Global.putString(mContext.getContentResolver(),
5611                             Settings.Global.DISPLAY_SIZE_FORCED, "");
5612                 }
5613             }
5614         } finally {
5615             Binder.restoreCallingIdentity(ident);
5616         }
5617     }
5618 
5619     @Override
getInitialDisplayDensity(int displayId)5620     public int getInitialDisplayDensity(int displayId) {
5621         synchronized (mWindowMap) {
5622             final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5623             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
5624                 return displayContent.mInitialDisplayDensity;
5625             }
5626         }
5627         return -1;
5628     }
5629 
5630     @Override
getBaseDisplayDensity(int displayId)5631     public int getBaseDisplayDensity(int displayId) {
5632         synchronized (mWindowMap) {
5633             final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5634             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
5635                 return displayContent.mBaseDisplayDensity;
5636             }
5637         }
5638         return -1;
5639     }
5640 
5641     @Override
setForcedDisplayDensityForUser(int displayId, int density, int userId)5642     public void setForcedDisplayDensityForUser(int displayId, int density, int userId) {
5643         if (mContext.checkCallingOrSelfPermission(
5644                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
5645                 PackageManager.PERMISSION_GRANTED) {
5646             throw new SecurityException("Must hold permission " +
5647                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
5648         }
5649         if (displayId != DEFAULT_DISPLAY) {
5650             throw new IllegalArgumentException("Can only set the default display");
5651         }
5652 
5653         final int targetUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
5654                 Binder.getCallingUid(), userId, false, true, "setForcedDisplayDensityForUser",
5655                 null);
5656         final long ident = Binder.clearCallingIdentity();
5657         try {
5658             synchronized(mWindowMap) {
5659                 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5660                 if (displayContent != null && mCurrentUserId == targetUserId) {
5661                     setForcedDisplayDensityLocked(displayContent, density);
5662                 }
5663                 Settings.Secure.putStringForUser(mContext.getContentResolver(),
5664                         Settings.Secure.DISPLAY_DENSITY_FORCED,
5665                         Integer.toString(density), targetUserId);
5666             }
5667         } finally {
5668             Binder.restoreCallingIdentity(ident);
5669         }
5670     }
5671 
5672     @Override
clearForcedDisplayDensityForUser(int displayId, int userId)5673     public void clearForcedDisplayDensityForUser(int displayId, int userId) {
5674         if (mContext.checkCallingOrSelfPermission(
5675                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
5676                 PackageManager.PERMISSION_GRANTED) {
5677             throw new SecurityException("Must hold permission " +
5678                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
5679         }
5680         if (displayId != DEFAULT_DISPLAY) {
5681             throw new IllegalArgumentException("Can only set the default display");
5682         }
5683 
5684         final int callingUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
5685                 Binder.getCallingUid(), userId, false, true, "clearForcedDisplayDensityForUser",
5686                 null);
5687         final long ident = Binder.clearCallingIdentity();
5688         try {
5689             synchronized(mWindowMap) {
5690                 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5691                 if (displayContent != null && mCurrentUserId == callingUserId) {
5692                     setForcedDisplayDensityLocked(displayContent,
5693                             displayContent.mInitialDisplayDensity);
5694                 }
5695                 Settings.Secure.putStringForUser(mContext.getContentResolver(),
5696                         Settings.Secure.DISPLAY_DENSITY_FORCED, "", callingUserId);
5697             }
5698         } finally {
5699             Binder.restoreCallingIdentity(ident);
5700         }
5701     }
5702 
5703     /**
5704      * @param userId the ID of the user
5705      * @return the forced display density for the specified user, if set, or
5706      *         {@code 0} if not set
5707      */
getForcedDisplayDensityForUserLocked(int userId)5708     private int getForcedDisplayDensityForUserLocked(int userId) {
5709         String densityStr = Settings.Secure.getStringForUser(mContext.getContentResolver(),
5710                 Settings.Secure.DISPLAY_DENSITY_FORCED, userId);
5711         if (densityStr == null || densityStr.length() == 0) {
5712             densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
5713         }
5714         if (densityStr != null && densityStr.length() > 0) {
5715             try {
5716                 return Integer.parseInt(densityStr);
5717             } catch (NumberFormatException ex) {
5718             }
5719         }
5720         return 0;
5721     }
5722 
5723     /**
5724      * Forces the given display to the use the specified density.
5725      *
5726      * @param displayContent the display to modify
5727      * @param density the density in DPI to use
5728      */
setForcedDisplayDensityLocked(@onNull DisplayContent displayContent, int density)5729     private void setForcedDisplayDensityLocked(@NonNull DisplayContent displayContent,
5730             int density) {
5731         displayContent.mBaseDisplayDensity = density;
5732         reconfigureDisplayLocked(displayContent);
5733     }
5734 
reconfigureDisplayLocked(@onNull DisplayContent displayContent)5735     void reconfigureDisplayLocked(@NonNull DisplayContent displayContent) {
5736         if (!mDisplayReady) {
5737             return;
5738         }
5739         configureDisplayPolicyLocked(displayContent);
5740         displayContent.setLayoutNeeded();
5741 
5742         final int displayId = displayContent.getDisplayId();
5743         boolean configChanged = updateOrientationFromAppTokensLocked(false /* inTransaction */,
5744                 displayId);
5745         final Configuration currentDisplayConfig = displayContent.getConfiguration();
5746         mTempConfiguration.setTo(currentDisplayConfig);
5747         displayContent.computeScreenConfiguration(mTempConfiguration);
5748         configChanged |= currentDisplayConfig.diff(mTempConfiguration) != 0;
5749 
5750         if (configChanged) {
5751             mWaitingForConfig = true;
5752             startFreezingDisplayLocked(false /* inTransaction */, 0 /* exitAnim */,
5753                     0 /* enterAnim */, displayContent);
5754             mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget();
5755         }
5756 
5757         mWindowPlacerLocked.performSurfacePlacement();
5758     }
5759 
configureDisplayPolicyLocked(DisplayContent displayContent)5760     void configureDisplayPolicyLocked(DisplayContent displayContent) {
5761         mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
5762                 displayContent.mBaseDisplayWidth,
5763                 displayContent.mBaseDisplayHeight,
5764                 displayContent.mBaseDisplayDensity);
5765 
5766         DisplayInfo displayInfo = displayContent.getDisplayInfo();
5767         mPolicy.setDisplayOverscan(displayContent.getDisplay(),
5768                 displayInfo.overscanLeft, displayInfo.overscanTop,
5769                 displayInfo.overscanRight, displayInfo.overscanBottom);
5770     }
5771 
5772     /**
5773      * Get an array with display ids ordered by focus priority - last items should be given
5774      * focus first. Sparse array just maps position to displayId.
5775      */
5776     // TODO: Maintain display list in focus order in ActivityManager and remove this call.
getDisplaysInFocusOrder(SparseIntArray displaysInFocusOrder)5777     public void getDisplaysInFocusOrder(SparseIntArray displaysInFocusOrder) {
5778         synchronized(mWindowMap) {
5779             mRoot.getDisplaysInFocusOrder(displaysInFocusOrder);
5780         }
5781     }
5782 
5783     @Override
setOverscan(int displayId, int left, int top, int right, int bottom)5784     public void setOverscan(int displayId, int left, int top, int right, int bottom) {
5785         if (mContext.checkCallingOrSelfPermission(
5786                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
5787                 PackageManager.PERMISSION_GRANTED) {
5788             throw new SecurityException("Must hold permission " +
5789                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
5790         }
5791         final long ident = Binder.clearCallingIdentity();
5792         try {
5793             synchronized(mWindowMap) {
5794                 DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
5795                 if (displayContent != null) {
5796                     setOverscanLocked(displayContent, left, top, right, bottom);
5797                 }
5798             }
5799         } finally {
5800             Binder.restoreCallingIdentity(ident);
5801         }
5802     }
5803 
setOverscanLocked(DisplayContent displayContent, int left, int top, int right, int bottom)5804     private void setOverscanLocked(DisplayContent displayContent,
5805             int left, int top, int right, int bottom) {
5806         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5807         displayInfo.overscanLeft = left;
5808         displayInfo.overscanTop = top;
5809         displayInfo.overscanRight = right;
5810         displayInfo.overscanBottom = bottom;
5811 
5812         mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, displayInfo.name, left, top,
5813                 right, bottom);
5814         mDisplaySettings.writeSettingsLocked();
5815 
5816         reconfigureDisplayLocked(displayContent);
5817     }
5818 
5819     // -------------------------------------------------------------
5820     // Internals
5821     // -------------------------------------------------------------
5822 
windowForClientLocked(Session session, IWindow client, boolean throwOnError)5823     final WindowState windowForClientLocked(Session session, IWindow client, boolean throwOnError) {
5824         return windowForClientLocked(session, client.asBinder(), throwOnError);
5825     }
5826 
windowForClientLocked(Session session, IBinder client, boolean throwOnError)5827     final WindowState windowForClientLocked(Session session, IBinder client, boolean throwOnError) {
5828         WindowState win = mWindowMap.get(client);
5829         if (localLOGV) Slog.v(TAG_WM, "Looking up client " + client + ": " + win);
5830         if (win == null) {
5831             if (throwOnError) {
5832                 throw new IllegalArgumentException(
5833                         "Requested window " + client + " does not exist");
5834             }
5835             Slog.w(TAG_WM, "Failed looking up window callers=" + Debug.getCallers(3));
5836             return null;
5837         }
5838         if (session != null && win.mSession != session) {
5839             if (throwOnError) {
5840                 throw new IllegalArgumentException("Requested window " + client + " is in session "
5841                         + win.mSession + ", not " + session);
5842             }
5843             Slog.w(TAG_WM, "Failed looking up window callers=" + Debug.getCallers(3));
5844             return null;
5845         }
5846 
5847         return win;
5848     }
5849 
makeWindowFreezingScreenIfNeededLocked(WindowState w)5850     void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
5851         // If the screen is currently frozen or off, then keep
5852         // it frozen/off until this window draws at its new
5853         // orientation.
5854         if (!w.mToken.okToDisplay() && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
5855             if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Changing surface while display frozen: " + w);
5856             w.setOrientationChanging(true);
5857             w.mLastFreezeDuration = 0;
5858             mRoot.mOrientationChangeComplete = false;
5859             if (mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_NONE) {
5860                 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
5861                 // XXX should probably keep timeout from
5862                 // when we first froze the display.
5863                 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
5864                 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
5865                         WINDOW_FREEZE_TIMEOUT_DURATION);
5866             }
5867         }
5868     }
5869 
5870     /**
5871      * @return bitmap indicating if another pass through layout must be made.
5872      */
handleAnimatingStoppedAndTransitionLocked()5873     int handleAnimatingStoppedAndTransitionLocked() {
5874         int changes = 0;
5875 
5876         mAppTransition.setIdle();
5877 
5878         for (int i = mNoAnimationNotifyOnTransitionFinished.size() - 1; i >= 0; i--) {
5879             final IBinder token = mNoAnimationNotifyOnTransitionFinished.get(i);
5880             mAppTransition.notifyAppTransitionFinishedLocked(token);
5881         }
5882         mNoAnimationNotifyOnTransitionFinished.clear();
5883 
5884         // TODO: multi-display.
5885         final DisplayContent dc = getDefaultDisplayContentLocked();
5886 
5887         dc.mWallpaperController.hideDeferredWallpapersIfNeeded();
5888 
5889         dc.onAppTransitionDone();
5890 
5891         changes |= FINISH_LAYOUT_REDO_LAYOUT;
5892         if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG_WM,
5893                 "Wallpaper layer changed: assigning layers + relayout");
5894         dc.computeImeTarget(true /* updateImeTarget */);
5895         mRoot.mWallpaperMayChange = true;
5896         // Since the window list has been rebuilt, focus might have to be recomputed since the
5897         // actual order of windows might have changed again.
5898         mFocusMayChange = true;
5899 
5900         return changes;
5901     }
5902 
checkDrawnWindowsLocked()5903     void checkDrawnWindowsLocked() {
5904         if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
5905             return;
5906         }
5907         for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {
5908             WindowState win = mWaitingForDrawn.get(j);
5909             if (DEBUG_SCREEN_ON) Slog.i(TAG_WM, "Waiting for drawn " + win +
5910                     ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
5911                     " mHasSurface=" + win.mHasSurface +
5912                     " drawState=" + win.mWinAnimator.mDrawState);
5913             if (win.mRemoved || !win.mHasSurface || !win.mPolicyVisibility) {
5914                 // Window has been removed or hidden; no draw will now happen, so stop waiting.
5915                 if (DEBUG_SCREEN_ON) Slog.w(TAG_WM, "Aborted waiting for drawn: " + win);
5916                 mWaitingForDrawn.remove(win);
5917             } else if (win.hasDrawnLw()) {
5918                 // Window is now drawn (and shown).
5919                 if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "Window drawn win=" + win);
5920                 mWaitingForDrawn.remove(win);
5921             }
5922         }
5923         if (mWaitingForDrawn.isEmpty()) {
5924             if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "All windows drawn!");
5925             mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
5926             mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);
5927         }
5928     }
5929 
setHoldScreenLocked(final Session newHoldScreen)5930     void setHoldScreenLocked(final Session newHoldScreen) {
5931         final boolean hold = newHoldScreen != null;
5932 
5933         if (hold && mHoldingScreenOn != newHoldScreen) {
5934             mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
5935         }
5936         mHoldingScreenOn = newHoldScreen;
5937 
5938         final boolean state = mHoldingScreenWakeLock.isHeld();
5939         if (hold != state) {
5940             if (hold) {
5941                 if (DEBUG_KEEP_SCREEN_ON) {
5942                     Slog.d(TAG_KEEP_SCREEN_ON, "Acquiring screen wakelock due to "
5943                             + mRoot.mHoldScreenWindow);
5944                 }
5945                 mLastWakeLockHoldingWindow = mRoot.mHoldScreenWindow;
5946                 mLastWakeLockObscuringWindow = null;
5947                 mHoldingScreenWakeLock.acquire();
5948                 mPolicy.keepScreenOnStartedLw();
5949             } else {
5950                 if (DEBUG_KEEP_SCREEN_ON) {
5951                     Slog.d(TAG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by "
5952                             + mRoot.mObscuringWindow);
5953                 }
5954                 mLastWakeLockHoldingWindow = null;
5955                 mLastWakeLockObscuringWindow = mRoot.mObscuringWindow;
5956                 mPolicy.keepScreenOnStoppedLw();
5957                 mHoldingScreenWakeLock.release();
5958             }
5959         }
5960     }
5961 
requestTraversal()5962     void requestTraversal() {
5963         synchronized (mWindowMap) {
5964             mWindowPlacerLocked.requestTraversal();
5965         }
5966     }
5967 
5968     /** Note that Locked in this case is on mLayoutToAnim */
scheduleAnimationLocked()5969     void scheduleAnimationLocked() {
5970         mAnimator.scheduleAnimation();
5971     }
5972 
5973     // TODO: Move to DisplayContent
updateFocusedWindowLocked(int mode, boolean updateInputWindows)5974     boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
5975         WindowState newFocus = mRoot.computeFocusedWindow();
5976         if (mCurrentFocus != newFocus) {
5977             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
5978             // This check makes sure that we don't already have the focus
5979             // change message pending.
5980             mH.removeMessages(H.REPORT_FOCUS_CHANGE);
5981             mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
5982             // TODO(multidisplay): Focused windows on default display only.
5983             final DisplayContent displayContent = getDefaultDisplayContentLocked();
5984             boolean imWindowChanged = false;
5985             if (mInputMethodWindow != null) {
5986                 final WindowState prevTarget = mInputMethodTarget;
5987                 final WindowState newTarget =
5988                         displayContent.computeImeTarget(true /* updateImeTarget*/);
5989 
5990                 imWindowChanged = prevTarget != newTarget;
5991 
5992                 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
5993                         && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES) {
5994                     final int prevImeAnimLayer = mInputMethodWindow.mWinAnimator.mAnimLayer;
5995                     displayContent.assignWindowLayers(false /* setLayoutNeeded */);
5996                     imWindowChanged |=
5997                             prevImeAnimLayer != mInputMethodWindow.mWinAnimator.mAnimLayer;
5998                 }
5999             }
6000 
6001             if (imWindowChanged) {
6002                 mWindowsChanged = true;
6003                 displayContent.setLayoutNeeded();
6004                 newFocus = mRoot.computeFocusedWindow();
6005             }
6006 
6007             if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG_WM, "Changing focus from " +
6008                     mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4));
6009             final WindowState oldFocus = mCurrentFocus;
6010             mCurrentFocus = newFocus;
6011             mLosingFocus.remove(newFocus);
6012 
6013             if (mCurrentFocus != null) {
6014                 mWinAddedSinceNullFocus.clear();
6015                 mWinRemovedSinceNullFocus.clear();
6016             }
6017 
6018             int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
6019 
6020             if (imWindowChanged && oldFocus != mInputMethodWindow) {
6021                 // Focus of the input method window changed. Perform layout if needed.
6022                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
6023                     displayContent.performLayout(true /*initial*/,  updateInputWindows);
6024                     focusChanged &= ~FINISH_LAYOUT_REDO_LAYOUT;
6025                 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
6026                     // Client will do the layout, but we need to assign layers
6027                     // for handleNewWindowLocked() below.
6028                     displayContent.assignWindowLayers(false /* setLayoutNeeded */);
6029                 }
6030             }
6031 
6032             if ((focusChanged & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
6033                 // The change in focus caused us to need to do a layout.  Okay.
6034                 displayContent.setLayoutNeeded();
6035                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
6036                     displayContent.performLayout(true /*initial*/, updateInputWindows);
6037                 }
6038             }
6039 
6040             if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
6041                 // If we defer assigning layers, then the caller is responsible for
6042                 // doing this part.
6043                 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
6044             }
6045 
6046             displayContent.adjustForImeIfNeeded();
6047 
6048             // We may need to schedule some toast windows to be removed. The toasts for an app that
6049             // does not have input focus are removed within a timeout to prevent apps to redress
6050             // other apps' UI.
6051             displayContent.scheduleToastWindowsTimeoutIfNeededLocked(oldFocus, newFocus);
6052 
6053             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
6054             return true;
6055         }
6056         return false;
6057     }
6058 
startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim)6059     void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
6060         startFreezingDisplayLocked(inTransaction, exitAnim, enterAnim,
6061                 getDefaultDisplayContentLocked());
6062     }
6063 
startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim, DisplayContent displayContent)6064     void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim,
6065             DisplayContent displayContent) {
6066         if (mDisplayFrozen) {
6067             return;
6068         }
6069 
6070         if (!displayContent.isReady() || !mPolicy.isScreenOn() || !displayContent.okToAnimate()) {
6071             // No need to freeze the screen before the display is ready,  if the screen is off,
6072             // or we can't currently animate.
6073             return;
6074         }
6075 
6076         if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
6077                 "startFreezingDisplayLocked: inTransaction=" + inTransaction
6078                 + " exitAnim=" + exitAnim + " enterAnim=" + enterAnim
6079                 + " called by " + Debug.getCallers(8));
6080         mScreenFrozenLock.acquire();
6081 
6082         mDisplayFrozen = true;
6083         mDisplayFreezeTime = SystemClock.elapsedRealtime();
6084         mLastFinishedFreezeSource = null;
6085 
6086         // {@link mDisplayFrozen} prevents us from freezing on multiple displays at the same time.
6087         // As a result, we only track the display that has initially froze the screen.
6088         mFrozenDisplayId = displayContent.getDisplayId();
6089 
6090         mInputMonitor.freezeInputDispatchingLw();
6091 
6092         // Clear the last input window -- that is just used for
6093         // clean transitions between IMEs, and if we are freezing
6094         // the screen then the whole world is changing behind the scenes.
6095         mPolicy.setLastInputMethodWindowLw(null, null);
6096 
6097         if (mAppTransition.isTransitionSet()) {
6098             mAppTransition.freeze();
6099         }
6100 
6101         if (PROFILE_ORIENTATION) {
6102             File file = new File("/data/system/frozen");
6103             Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
6104         }
6105 
6106         // TODO(multidisplay): rotation on non-default displays
6107         if (CUSTOM_SCREEN_ROTATION && displayContent.isDefaultDisplay) {
6108             mExitAnimId = exitAnim;
6109             mEnterAnimId = enterAnim;
6110             ScreenRotationAnimation screenRotationAnimation =
6111                     mAnimator.getScreenRotationAnimationLocked(mFrozenDisplayId);
6112             if (screenRotationAnimation != null) {
6113                 screenRotationAnimation.kill();
6114             }
6115 
6116             // Check whether the current screen contains any secure content.
6117             boolean isSecure = displayContent.hasSecureWindowOnScreen();
6118 
6119             displayContent.updateDisplayInfo();
6120             screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
6121                     mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure,
6122                     this);
6123             mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId,
6124                     screenRotationAnimation);
6125         }
6126     }
6127 
stopFreezingDisplayLocked()6128     void stopFreezingDisplayLocked() {
6129         if (!mDisplayFrozen) {
6130             return;
6131         }
6132 
6133         if (mWaitingForConfig || mAppsFreezingScreen > 0
6134                 || mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_ACTIVE
6135                 || mClientFreezingScreen || !mOpeningApps.isEmpty()) {
6136             if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
6137                 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
6138                 + ", mAppsFreezingScreen=" + mAppsFreezingScreen
6139                 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
6140                 + ", mClientFreezingScreen=" + mClientFreezingScreen
6141                 + ", mOpeningApps.size()=" + mOpeningApps.size());
6142             return;
6143         }
6144 
6145         if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
6146                 "stopFreezingDisplayLocked: Unfreezing now");
6147 
6148         final DisplayContent displayContent = mRoot.getDisplayContent(mFrozenDisplayId);
6149 
6150         // We must make a local copy of the displayId as it can be potentially overwritten later on
6151         // in this method. For example, {@link startFreezingDisplayLocked} may be called as a result
6152         // of update rotation, but we reference the frozen display after that call in this method.
6153         final int displayId = mFrozenDisplayId;
6154         mFrozenDisplayId = INVALID_DISPLAY;
6155         mDisplayFrozen = false;
6156         mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
6157         StringBuilder sb = new StringBuilder(128);
6158         sb.append("Screen frozen for ");
6159         TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
6160         if (mLastFinishedFreezeSource != null) {
6161             sb.append(" due to ");
6162             sb.append(mLastFinishedFreezeSource);
6163         }
6164         Slog.i(TAG_WM, sb.toString());
6165         mH.removeMessages(H.APP_FREEZE_TIMEOUT);
6166         mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
6167         if (PROFILE_ORIENTATION) {
6168             Debug.stopMethodTracing();
6169         }
6170 
6171         boolean updateRotation = false;
6172 
6173         ScreenRotationAnimation screenRotationAnimation =
6174                 mAnimator.getScreenRotationAnimationLocked(displayId);
6175         if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
6176                 && screenRotationAnimation.hasScreenshot()) {
6177             if (DEBUG_ORIENTATION) Slog.i(TAG_WM, "**** Dismissing screen rotation animation");
6178             // TODO(multidisplay): rotation on main screen only.
6179             DisplayInfo displayInfo = displayContent.getDisplayInfo();
6180             // Get rotation animation again, with new top window
6181             boolean isDimming = displayContent.isDimming();
6182             if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
6183                 mExitAnimId = mEnterAnimId = 0;
6184             }
6185             if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
6186                     getTransitionAnimationScaleLocked(), displayInfo.logicalWidth,
6187                         displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
6188                 scheduleAnimationLocked();
6189             } else {
6190                 screenRotationAnimation.kill();
6191                 mAnimator.setScreenRotationAnimationLocked(displayId, null);
6192                 updateRotation = true;
6193             }
6194         } else {
6195             if (screenRotationAnimation != null) {
6196                 screenRotationAnimation.kill();
6197                 mAnimator.setScreenRotationAnimationLocked(displayId, null);
6198             }
6199             updateRotation = true;
6200         }
6201 
6202         mInputMonitor.thawInputDispatchingLw();
6203 
6204         boolean configChanged;
6205 
6206         // While the display is frozen we don't re-compute the orientation
6207         // to avoid inconsistent states.  However, something interesting
6208         // could have actually changed during that time so re-evaluate it
6209         // now to catch that.
6210         configChanged = updateOrientationFromAppTokensLocked(false, displayId);
6211 
6212         // A little kludge: a lot could have happened while the
6213         // display was frozen, so now that we are coming back we
6214         // do a gc so that any remote references the system
6215         // processes holds on others can be released if they are
6216         // no longer needed.
6217         mH.removeMessages(H.FORCE_GC);
6218         mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
6219 
6220         mScreenFrozenLock.release();
6221 
6222         if (updateRotation) {
6223             if (DEBUG_ORIENTATION) Slog.d(TAG_WM, "Performing post-rotate rotation");
6224             configChanged |= displayContent.updateRotationUnchecked(
6225                     false /* inTransaction */);
6226         }
6227 
6228         if (configChanged) {
6229             mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget();
6230         }
6231     }
6232 
getPropertyInt(String[] tokens, int index, int defUnits, int defDps, DisplayMetrics dm)6233     static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
6234             DisplayMetrics dm) {
6235         if (index < tokens.length) {
6236             String str = tokens[index];
6237             if (str != null && str.length() > 0) {
6238                 try {
6239                     int val = Integer.parseInt(str);
6240                     return val;
6241                 } catch (Exception e) {
6242                 }
6243             }
6244         }
6245         if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
6246             return defDps;
6247         }
6248         int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
6249         return val;
6250     }
6251 
createWatermarkInTransaction()6252     void createWatermarkInTransaction() {
6253         if (mWatermark != null) {
6254             return;
6255         }
6256 
6257         File file = new File("/system/etc/setup.conf");
6258         FileInputStream in = null;
6259         DataInputStream ind = null;
6260         try {
6261             in = new FileInputStream(file);
6262             ind = new DataInputStream(in);
6263             String line = ind.readLine();
6264             if (line != null) {
6265                 String[] toks = line.split("%");
6266                 if (toks != null && toks.length > 0) {
6267                     // TODO(multi-display): Show watermarks on secondary displays.
6268                     final DisplayContent displayContent = getDefaultDisplayContentLocked();
6269                     mWatermark = new Watermark(displayContent.getDisplay(),
6270                             displayContent.mRealDisplayMetrics, mFxSession, toks);
6271                 }
6272             }
6273         } catch (FileNotFoundException e) {
6274         } catch (IOException e) {
6275         } finally {
6276             if (ind != null) {
6277                 try {
6278                     ind.close();
6279                 } catch (IOException e) {
6280                 }
6281             } else if (in != null) {
6282                 try {
6283                     in.close();
6284                 } catch (IOException e) {
6285                 }
6286             }
6287         }
6288     }
6289 
6290     @Override
setRecentsVisibility(boolean visible)6291     public void setRecentsVisibility(boolean visible) {
6292         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
6293                 != PackageManager.PERMISSION_GRANTED) {
6294             throw new SecurityException("Caller does not hold permission "
6295                     + android.Manifest.permission.STATUS_BAR);
6296         }
6297 
6298         synchronized (mWindowMap) {
6299             mPolicy.setRecentsVisibilityLw(visible);
6300         }
6301     }
6302 
6303     @Override
setPipVisibility(boolean visible)6304     public void setPipVisibility(boolean visible) {
6305         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
6306                 != PackageManager.PERMISSION_GRANTED) {
6307             throw new SecurityException("Caller does not hold permission "
6308                     + android.Manifest.permission.STATUS_BAR);
6309         }
6310 
6311         synchronized (mWindowMap) {
6312             mPolicy.setPipVisibilityLw(visible);
6313         }
6314     }
6315 
6316     @Override
statusBarVisibilityChanged(int visibility)6317     public void statusBarVisibilityChanged(int visibility) {
6318         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
6319                 != PackageManager.PERMISSION_GRANTED) {
6320             throw new SecurityException("Caller does not hold permission "
6321                     + android.Manifest.permission.STATUS_BAR);
6322         }
6323 
6324         synchronized (mWindowMap) {
6325             mLastStatusBarVisibility = visibility;
6326             visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
6327             updateStatusBarVisibilityLocked(visibility);
6328         }
6329     }
6330 
6331     // TODO(multidisplay): StatusBar on multiple screens?
updateStatusBarVisibilityLocked(int visibility)6332     private boolean updateStatusBarVisibilityLocked(int visibility) {
6333         if (mLastDispatchedSystemUiVisibility == visibility) {
6334             return false;
6335         }
6336         final int globalDiff = (visibility ^ mLastDispatchedSystemUiVisibility)
6337                 // We are only interested in differences of one of the
6338                 // clearable flags...
6339                 & View.SYSTEM_UI_CLEARABLE_FLAGS
6340                 // ...if it has actually been cleared.
6341                 & ~visibility;
6342 
6343         mLastDispatchedSystemUiVisibility = visibility;
6344         mInputManager.setSystemUiVisibility(visibility);
6345         getDefaultDisplayContentLocked().updateSystemUiVisibility(visibility, globalDiff);
6346         return true;
6347     }
6348 
6349     @Override
reevaluateStatusBarVisibility()6350     public void reevaluateStatusBarVisibility() {
6351         synchronized (mWindowMap) {
6352             int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
6353             if (updateStatusBarVisibilityLocked(visibility)) {
6354                 mWindowPlacerLocked.requestTraversal();
6355             }
6356         }
6357     }
6358 
6359     /**
6360      * Used by ActivityManager to determine where to position an app with aspect ratio shorter then
6361      * the screen is.
6362      * @see WindowManagerPolicy#getNavBarPosition()
6363      */
getNavBarPosition()6364     public int getNavBarPosition() {
6365         synchronized (mWindowMap) {
6366             // Perform layout if it was scheduled before to make sure that we get correct nav bar
6367             // position when doing rotations.
6368             final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
6369             defaultDisplayContent.performLayout(false /* initial */,
6370                     false /* updateInputWindows */);
6371             return mPolicy.getNavBarPosition();
6372         }
6373     }
6374 
6375     @Override
createInputConsumer(Looper looper, String name, InputEventReceiver.Factory inputEventReceiverFactory)6376     public WindowManagerPolicy.InputConsumer createInputConsumer(Looper looper, String name,
6377             InputEventReceiver.Factory inputEventReceiverFactory) {
6378         synchronized (mWindowMap) {
6379             return mInputMonitor.createInputConsumer(looper, name, inputEventReceiverFactory);
6380         }
6381     }
6382 
6383     @Override
createInputConsumer(String name, InputChannel inputChannel)6384     public void createInputConsumer(String name, InputChannel inputChannel) {
6385         synchronized (mWindowMap) {
6386             mInputMonitor.createInputConsumer(name, inputChannel);
6387         }
6388     }
6389 
6390     @Override
destroyInputConsumer(String name)6391     public boolean destroyInputConsumer(String name) {
6392         synchronized (mWindowMap) {
6393             return mInputMonitor.destroyInputConsumer(name);
6394         }
6395     }
6396 
6397     @Override
getCurrentImeTouchRegion()6398     public Region getCurrentImeTouchRegion() {
6399         if (mContext.checkCallingOrSelfPermission(RESTRICTED_VR_ACCESS) != PERMISSION_GRANTED) {
6400             throw new SecurityException("getCurrentImeTouchRegion is restricted to VR services");
6401         }
6402         synchronized (mWindowMap) {
6403             final Region r = new Region();
6404             if (mInputMethodWindow != null) {
6405                 mInputMethodWindow.getTouchableRegion(r);
6406             }
6407             return r;
6408         }
6409     }
6410 
6411     @Override
hasNavigationBar()6412     public boolean hasNavigationBar() {
6413         return mPolicy.hasNavigationBar();
6414     }
6415 
6416     @Override
lockNow(Bundle options)6417     public void lockNow(Bundle options) {
6418         mPolicy.lockNow(options);
6419     }
6420 
showRecentApps(boolean fromHome)6421     public void showRecentApps(boolean fromHome) {
6422         mPolicy.showRecentApps(fromHome);
6423     }
6424 
6425     @Override
isSafeModeEnabled()6426     public boolean isSafeModeEnabled() {
6427         return mSafeMode;
6428     }
6429 
6430     @Override
clearWindowContentFrameStats(IBinder token)6431     public boolean clearWindowContentFrameStats(IBinder token) {
6432         if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
6433                 "clearWindowContentFrameStats()")) {
6434             throw new SecurityException("Requires FRAME_STATS permission");
6435         }
6436         synchronized (mWindowMap) {
6437             WindowState windowState = mWindowMap.get(token);
6438             if (windowState == null) {
6439                 return false;
6440             }
6441             WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController;
6442             if (surfaceController == null) {
6443                 return false;
6444             }
6445             return surfaceController.clearWindowContentFrameStats();
6446         }
6447     }
6448 
6449     @Override
getWindowContentFrameStats(IBinder token)6450     public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
6451         if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
6452                 "getWindowContentFrameStats()")) {
6453             throw new SecurityException("Requires FRAME_STATS permission");
6454         }
6455         synchronized (mWindowMap) {
6456             WindowState windowState = mWindowMap.get(token);
6457             if (windowState == null) {
6458                 return null;
6459             }
6460             WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController;
6461             if (surfaceController == null) {
6462                 return null;
6463             }
6464             if (mTempWindowRenderStats == null) {
6465                 mTempWindowRenderStats = new WindowContentFrameStats();
6466             }
6467             WindowContentFrameStats stats = mTempWindowRenderStats;
6468             if (!surfaceController.getWindowContentFrameStats(stats)) {
6469                 return null;
6470             }
6471             return stats;
6472         }
6473     }
6474 
notifyAppRelaunching(IBinder token)6475     public void notifyAppRelaunching(IBinder token) {
6476         synchronized (mWindowMap) {
6477             final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
6478             if (appWindow != null) {
6479                 appWindow.startRelaunching();
6480             }
6481         }
6482     }
6483 
notifyAppRelaunchingFinished(IBinder token)6484     public void notifyAppRelaunchingFinished(IBinder token) {
6485         synchronized (mWindowMap) {
6486             final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
6487             if (appWindow != null) {
6488                 appWindow.finishRelaunching();
6489             }
6490         }
6491     }
6492 
notifyAppRelaunchesCleared(IBinder token)6493     public void notifyAppRelaunchesCleared(IBinder token) {
6494         synchronized (mWindowMap) {
6495             final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
6496             if (appWindow != null) {
6497                 appWindow.clearRelaunching();
6498             }
6499         }
6500     }
6501 
notifyAppResumedFinished(IBinder token)6502     public void notifyAppResumedFinished(IBinder token) {
6503         synchronized (mWindowMap) {
6504             final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
6505             if (appWindow != null) {
6506                 mUnknownAppVisibilityController.notifyAppResumedFinished(appWindow);
6507             }
6508         }
6509     }
6510 
6511     /**
6512      * Called when a task has been removed from the recent tasks list.
6513      * <p>
6514      * Note: This doesn't go through {@link TaskWindowContainerController} yet as the window
6515      * container may not exist when this happens.
6516      */
notifyTaskRemovedFromRecents(int taskId, int userId)6517     public void notifyTaskRemovedFromRecents(int taskId, int userId) {
6518         synchronized (mWindowMap) {
6519             mTaskSnapshotController.notifyTaskRemovedFromRecents(taskId, userId);
6520         }
6521     }
6522 
6523     @Override
getDockedDividerInsetsLw()6524     public int getDockedDividerInsetsLw() {
6525         return getDefaultDisplayContentLocked().getDockedDividerController().getContentInsets();
6526     }
6527 
dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll)6528     private void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
6529         pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
6530         mPolicy.dump("    ", pw, args);
6531     }
6532 
dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll)6533     private void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
6534         pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
6535         mAnimator.dumpLocked(pw, "    ", dumpAll);
6536     }
6537 
dumpTokensLocked(PrintWriter pw, boolean dumpAll)6538     private void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
6539         pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
6540         mRoot.dumpTokens(pw, dumpAll);
6541         if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty()) {
6542             pw.println();
6543             if (mOpeningApps.size() > 0) {
6544                 pw.print("  mOpeningApps="); pw.println(mOpeningApps);
6545             }
6546             if (mClosingApps.size() > 0) {
6547                 pw.print("  mClosingApps="); pw.println(mClosingApps);
6548             }
6549         }
6550     }
6551 
dumpSessionsLocked(PrintWriter pw, boolean dumpAll)6552     private void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
6553         pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
6554         for (int i=0; i<mSessions.size(); i++) {
6555             Session s = mSessions.valueAt(i);
6556             pw.print("  Session "); pw.print(s); pw.println(':');
6557             s.dump(pw, "    ");
6558         }
6559     }
6560 
dumpWindowsLocked(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows)6561     private void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
6562             ArrayList<WindowState> windows) {
6563         pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
6564         dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
6565     }
6566 
dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows)6567     private void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
6568             ArrayList<WindowState> windows) {
6569         mRoot.dumpWindowsNoHeader(pw, dumpAll, windows);
6570 
6571         if (!mHidingNonSystemOverlayWindows.isEmpty()) {
6572             pw.println();
6573             pw.println("  Hiding System Alert Windows:");
6574             for (int i = mHidingNonSystemOverlayWindows.size() - 1; i >= 0; i--) {
6575                 final WindowState w = mHidingNonSystemOverlayWindows.get(i);
6576                 pw.print("  #"); pw.print(i); pw.print(' ');
6577                 pw.print(w);
6578                 if (dumpAll) {
6579                     pw.println(":");
6580                     w.dump(pw, "    ", true);
6581                 } else {
6582                     pw.println();
6583                 }
6584             }
6585         }
6586         if (mPendingRemove.size() > 0) {
6587             pw.println();
6588             pw.println("  Remove pending for:");
6589             for (int i=mPendingRemove.size()-1; i>=0; i--) {
6590                 WindowState w = mPendingRemove.get(i);
6591                 if (windows == null || windows.contains(w)) {
6592                     pw.print("  Remove #"); pw.print(i); pw.print(' ');
6593                             pw.print(w);
6594                     if (dumpAll) {
6595                         pw.println(":");
6596                         w.dump(pw, "    ", true);
6597                     } else {
6598                         pw.println();
6599                     }
6600                 }
6601             }
6602         }
6603         if (mForceRemoves != null && mForceRemoves.size() > 0) {
6604             pw.println();
6605             pw.println("  Windows force removing:");
6606             for (int i=mForceRemoves.size()-1; i>=0; i--) {
6607                 WindowState w = mForceRemoves.get(i);
6608                 pw.print("  Removing #"); pw.print(i); pw.print(' ');
6609                         pw.print(w);
6610                 if (dumpAll) {
6611                     pw.println(":");
6612                     w.dump(pw, "    ", true);
6613                 } else {
6614                     pw.println();
6615                 }
6616             }
6617         }
6618         if (mDestroySurface.size() > 0) {
6619             pw.println();
6620             pw.println("  Windows waiting to destroy their surface:");
6621             for (int i=mDestroySurface.size()-1; i>=0; i--) {
6622                 WindowState w = mDestroySurface.get(i);
6623                 if (windows == null || windows.contains(w)) {
6624                     pw.print("  Destroy #"); pw.print(i); pw.print(' ');
6625                             pw.print(w);
6626                     if (dumpAll) {
6627                         pw.println(":");
6628                         w.dump(pw, "    ", true);
6629                     } else {
6630                         pw.println();
6631                     }
6632                 }
6633             }
6634         }
6635         if (mLosingFocus.size() > 0) {
6636             pw.println();
6637             pw.println("  Windows losing focus:");
6638             for (int i=mLosingFocus.size()-1; i>=0; i--) {
6639                 WindowState w = mLosingFocus.get(i);
6640                 if (windows == null || windows.contains(w)) {
6641                     pw.print("  Losing #"); pw.print(i); pw.print(' ');
6642                             pw.print(w);
6643                     if (dumpAll) {
6644                         pw.println(":");
6645                         w.dump(pw, "    ", true);
6646                     } else {
6647                         pw.println();
6648                     }
6649                 }
6650             }
6651         }
6652         if (mResizingWindows.size() > 0) {
6653             pw.println();
6654             pw.println("  Windows waiting to resize:");
6655             for (int i=mResizingWindows.size()-1; i>=0; i--) {
6656                 WindowState w = mResizingWindows.get(i);
6657                 if (windows == null || windows.contains(w)) {
6658                     pw.print("  Resizing #"); pw.print(i); pw.print(' ');
6659                             pw.print(w);
6660                     if (dumpAll) {
6661                         pw.println(":");
6662                         w.dump(pw, "    ", true);
6663                     } else {
6664                         pw.println();
6665                     }
6666                 }
6667             }
6668         }
6669         if (mWaitingForDrawn.size() > 0) {
6670             pw.println();
6671             pw.println("  Clients waiting for these windows to be drawn:");
6672             for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
6673                 WindowState win = mWaitingForDrawn.get(i);
6674                 pw.print("  Waiting #"); pw.print(i); pw.print(' '); pw.print(win);
6675             }
6676         }
6677         pw.println();
6678         pw.print("  mGlobalConfiguration="); pw.println(mRoot.getConfiguration());
6679         pw.print("  mHasPermanentDpad="); pw.println(mHasPermanentDpad);
6680         pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
6681         if (mLastFocus != mCurrentFocus) {
6682             pw.print("  mLastFocus="); pw.println(mLastFocus);
6683         }
6684         pw.print("  mFocusedApp="); pw.println(mFocusedApp);
6685         if (mInputMethodTarget != null) {
6686             pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
6687         }
6688         pw.print("  mInTouchMode="); pw.print(mInTouchMode);
6689                 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
6690         pw.print("  mLastDisplayFreezeDuration=");
6691                 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
6692                 if ( mLastFinishedFreezeSource != null) {
6693                     pw.print(" due to ");
6694                     pw.print(mLastFinishedFreezeSource);
6695                 }
6696                 pw.println();
6697         pw.print("  mLastWakeLockHoldingWindow=");pw.print(mLastWakeLockHoldingWindow);
6698                 pw.print(" mLastWakeLockObscuringWindow="); pw.print(mLastWakeLockObscuringWindow);
6699                 pw.println();
6700 
6701         mInputMonitor.dump(pw, "  ");
6702         mUnknownAppVisibilityController.dump(pw, "  ");
6703         mTaskSnapshotController.dump(pw, "  ");
6704 
6705         if (dumpAll) {
6706             pw.print("  mSystemDecorLayer="); pw.print(mSystemDecorLayer);
6707                     pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
6708             if (mLastStatusBarVisibility != 0) {
6709                 pw.print("  mLastStatusBarVisibility=0x");
6710                         pw.println(Integer.toHexString(mLastStatusBarVisibility));
6711             }
6712             if (mInputMethodWindow != null) {
6713                 pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
6714             }
6715             mWindowPlacerLocked.dump(pw, "  ");
6716             mRoot.mWallpaperController.dump(pw, "  ");
6717             pw.print("  mSystemBooted="); pw.print(mSystemBooted);
6718                     pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
6719 
6720             mRoot.dumpLayoutNeededDisplayIds(pw);
6721 
6722             pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
6723             pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
6724                     pw.print(" windows="); pw.print(mWindowsFreezingScreen);
6725                     pw.print(" client="); pw.print(mClientFreezingScreen);
6726                     pw.print(" apps="); pw.print(mAppsFreezingScreen);
6727                     pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
6728             final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
6729             pw.print("  mRotation="); pw.print(defaultDisplayContent.getRotation());
6730                     pw.print(" mAltOrientation=");
6731                             pw.println(defaultDisplayContent.getAltOrientation());
6732             pw.print("  mLastWindowForcedOrientation=");
6733                     pw.print(defaultDisplayContent.getLastWindowForcedOrientation());
6734                     pw.print(" mLastOrientation=");
6735                             pw.println(defaultDisplayContent.getLastOrientation());
6736             pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
6737             pw.print("  Animation settings: disabled="); pw.print(mAnimationsDisabled);
6738                     pw.print(" window="); pw.print(mWindowAnimationScaleSetting);
6739                     pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting);
6740                     pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting);
6741             pw.print("  mSkipAppTransitionAnimation=");pw.println(mSkipAppTransitionAnimation);
6742             pw.println("  mLayoutToAnim:");
6743             mAppTransition.dump(pw, "    ");
6744         }
6745     }
6746 
dumpWindows(PrintWriter pw, String name, String[] args, int opti, boolean dumpAll)6747     private boolean dumpWindows(PrintWriter pw, String name, String[] args, int opti,
6748             boolean dumpAll) {
6749         final ArrayList<WindowState> windows = new ArrayList();
6750         if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) {
6751             final boolean appsOnly = name.contains("apps");
6752             final boolean visibleOnly = name.contains("visible");
6753             synchronized(mWindowMap) {
6754                 if (appsOnly) {
6755                     mRoot.dumpDisplayContents(pw);
6756                 }
6757 
6758                 mRoot.forAllWindows((w) -> {
6759                     if ((!visibleOnly || w.mWinAnimator.getShown())
6760                             && (!appsOnly || w.mAppToken != null)) {
6761                         windows.add(w);
6762                     }
6763                 }, true /* traverseTopToBottom */);
6764             }
6765         } else {
6766             synchronized(mWindowMap) {
6767                 mRoot.getWindowsByName(windows, name);
6768             }
6769         }
6770 
6771         if (windows.size() <= 0) {
6772             return false;
6773         }
6774 
6775         synchronized(mWindowMap) {
6776             dumpWindowsLocked(pw, dumpAll, windows);
6777         }
6778         return true;
6779     }
6780 
dumpLastANRLocked(PrintWriter pw)6781     private void dumpLastANRLocked(PrintWriter pw) {
6782         pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
6783         if (mLastANRState == null) {
6784             pw.println("  <no ANR has occurred since boot>");
6785         } else {
6786             pw.println(mLastANRState);
6787         }
6788     }
6789 
6790     /**
6791      * Saves information about the state of the window manager at
6792      * the time an ANR occurred before anything else in the system changes
6793      * in response.
6794      *
6795      * @param appWindowToken The application that ANR'd, may be null.
6796      * @param windowState The window that ANR'd, may be null.
6797      * @param reason The reason for the ANR, may be null.
6798      */
saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, String reason)6799     void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, String reason) {
6800         StringWriter sw = new StringWriter();
6801         PrintWriter pw = new FastPrintWriter(sw, false, 1024);
6802         pw.println("  ANR time: " + DateFormat.getDateTimeInstance().format(new Date()));
6803         if (appWindowToken != null) {
6804             pw.println("  Application at fault: " + appWindowToken.stringName);
6805         }
6806         if (windowState != null) {
6807             pw.println("  Window at fault: " + windowState.mAttrs.getTitle());
6808         }
6809         if (reason != null) {
6810             pw.println("  Reason: " + reason);
6811         }
6812         if (!mWinAddedSinceNullFocus.isEmpty()) {
6813             pw.println("  Windows added since null focus: " + mWinAddedSinceNullFocus);
6814         }
6815         if (!mWinRemovedSinceNullFocus.isEmpty()) {
6816             pw.println("  Windows removed since null focus: " + mWinRemovedSinceNullFocus);
6817         }
6818         pw.println();
6819         dumpWindowsNoHeaderLocked(pw, true, null);
6820         pw.println();
6821         pw.println("Last ANR continued");
6822         mRoot.dumpDisplayContents(pw);
6823         pw.close();
6824         mLastANRState = sw.toString();
6825 
6826         mH.removeMessages(H.RESET_ANR_MESSAGE);
6827         mH.sendEmptyMessageDelayed(H.RESET_ANR_MESSAGE, LAST_ANR_LIFETIME_DURATION_MSECS);
6828     }
6829 
6830     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)6831     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
6832         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
6833 
6834         boolean dumpAll = false;
6835 
6836         int opti = 0;
6837         while (opti < args.length) {
6838             String opt = args[opti];
6839             if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6840                 break;
6841             }
6842             opti++;
6843             if ("-a".equals(opt)) {
6844                 dumpAll = true;
6845             } else if ("-h".equals(opt)) {
6846                 pw.println("Window manager dump options:");
6847                 pw.println("  [-a] [-h] [cmd] ...");
6848                 pw.println("  cmd may be one of:");
6849                 pw.println("    l[astanr]: last ANR information");
6850                 pw.println("    p[policy]: policy state");
6851                 pw.println("    a[animator]: animator state");
6852                 pw.println("    s[essions]: active sessions");
6853                 pw.println("    surfaces: active surfaces (debugging enabled only)");
6854                 pw.println("    d[isplays]: active display contents");
6855                 pw.println("    t[okens]: token list");
6856                 pw.println("    w[indows]: window list");
6857                 pw.println("  cmd may also be a NAME to dump windows.  NAME may");
6858                 pw.println("    be a partial substring in a window name, a");
6859                 pw.println("    Window hex object identifier, or");
6860                 pw.println("    \"all\" for all windows, or");
6861                 pw.println("    \"visible\" for the visible windows.");
6862                 pw.println("    \"visible-apps\" for the visible app windows.");
6863                 pw.println("  -a: include all available server state.");
6864                 return;
6865             } else {
6866                 pw.println("Unknown argument: " + opt + "; use -h for help");
6867             }
6868         }
6869 
6870         // Is the caller requesting to dump a particular piece of data?
6871         if (opti < args.length) {
6872             String cmd = args[opti];
6873             opti++;
6874             if ("lastanr".equals(cmd) || "l".equals(cmd)) {
6875                 synchronized(mWindowMap) {
6876                     dumpLastANRLocked(pw);
6877                 }
6878                 return;
6879             } else if ("policy".equals(cmd) || "p".equals(cmd)) {
6880                 synchronized(mWindowMap) {
6881                     dumpPolicyLocked(pw, args, true);
6882                 }
6883                 return;
6884             } else if ("animator".equals(cmd) || "a".equals(cmd)) {
6885                 synchronized(mWindowMap) {
6886                     dumpAnimatorLocked(pw, args, true);
6887                 }
6888                 return;
6889             } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
6890                 synchronized(mWindowMap) {
6891                     dumpSessionsLocked(pw, true);
6892                 }
6893                 return;
6894             } else if ("surfaces".equals(cmd)) {
6895                 synchronized(mWindowMap) {
6896                     WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, null);
6897                 }
6898                 return;
6899             } else if ("displays".equals(cmd) || "d".equals(cmd)) {
6900                 synchronized(mWindowMap) {
6901                     mRoot.dumpDisplayContents(pw);
6902                 }
6903                 return;
6904             } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
6905                 synchronized(mWindowMap) {
6906                     dumpTokensLocked(pw, true);
6907                 }
6908                 return;
6909             } else if ("windows".equals(cmd) || "w".equals(cmd)) {
6910                 synchronized(mWindowMap) {
6911                     dumpWindowsLocked(pw, true, null);
6912                 }
6913                 return;
6914             } else if ("all".equals(cmd) || "a".equals(cmd)) {
6915                 synchronized(mWindowMap) {
6916                     dumpWindowsLocked(pw, true, null);
6917                 }
6918                 return;
6919             } else if ("containers".equals(cmd)) {
6920                 synchronized(mWindowMap) {
6921                     StringBuilder output = new StringBuilder();
6922                     mRoot.dumpChildrenNames(output, " ");
6923                     pw.println(output.toString());
6924                     pw.println(" ");
6925                     mRoot.forAllWindows(w -> {pw.println(w);}, true /* traverseTopToBottom */);
6926                 }
6927                 return;
6928             } else {
6929                 // Dumping a single name?
6930                 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
6931                     pw.println("Bad window command, or no windows match: " + cmd);
6932                     pw.println("Use -h for help.");
6933                 }
6934                 return;
6935             }
6936         }
6937 
6938         synchronized(mWindowMap) {
6939             pw.println();
6940             if (dumpAll) {
6941                 pw.println("-------------------------------------------------------------------------------");
6942             }
6943             dumpLastANRLocked(pw);
6944             pw.println();
6945             if (dumpAll) {
6946                 pw.println("-------------------------------------------------------------------------------");
6947             }
6948             dumpPolicyLocked(pw, args, dumpAll);
6949             pw.println();
6950             if (dumpAll) {
6951                 pw.println("-------------------------------------------------------------------------------");
6952             }
6953             dumpAnimatorLocked(pw, args, dumpAll);
6954             pw.println();
6955             if (dumpAll) {
6956                 pw.println("-------------------------------------------------------------------------------");
6957             }
6958             dumpSessionsLocked(pw, dumpAll);
6959             pw.println();
6960             if (dumpAll) {
6961                 pw.println("-------------------------------------------------------------------------------");
6962             }
6963             WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, dumpAll ?
6964                     "-------------------------------------------------------------------------------"
6965                     : null);
6966             pw.println();
6967             if (dumpAll) {
6968                 pw.println("-------------------------------------------------------------------------------");
6969             }
6970             mRoot.dumpDisplayContents(pw);
6971             pw.println();
6972             if (dumpAll) {
6973                 pw.println("-------------------------------------------------------------------------------");
6974             }
6975             dumpTokensLocked(pw, dumpAll);
6976             pw.println();
6977             if (dumpAll) {
6978                 pw.println("-------------------------------------------------------------------------------");
6979             }
6980             dumpWindowsLocked(pw, dumpAll, null);
6981         }
6982     }
6983 
6984     // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
6985     @Override
monitor()6986     public void monitor() {
6987         synchronized (mWindowMap) { }
6988     }
6989 
6990     // TODO: All the display method below should probably be moved into the RootWindowContainer...
createDisplayContentLocked(final Display display)6991     private void createDisplayContentLocked(final Display display) {
6992         if (display == null) {
6993             throw new IllegalArgumentException("getDisplayContent: display must not be null");
6994         }
6995         mRoot.getDisplayContentOrCreate(display.getDisplayId());
6996     }
6997 
6998     // There is an inherent assumption that this will never return null.
6999     // TODO(multi-display): Inspect all the call-points of this method to see if they make sense to
7000     // support non-default display.
getDefaultDisplayContentLocked()7001     DisplayContent getDefaultDisplayContentLocked() {
7002         return mRoot.getDisplayContentOrCreate(DEFAULT_DISPLAY);
7003     }
7004 
onDisplayAdded(int displayId)7005     public void onDisplayAdded(int displayId) {
7006         synchronized (mWindowMap) {
7007             final Display display = mDisplayManager.getDisplay(displayId);
7008             if (display != null) {
7009                 createDisplayContentLocked(display);
7010                 displayReady(displayId);
7011             }
7012             mWindowPlacerLocked.requestTraversal();
7013         }
7014     }
7015 
onDisplayRemoved(int displayId)7016     public void onDisplayRemoved(int displayId) {
7017         synchronized (mWindowMap) {
7018             final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
7019             if (displayContent != null) {
7020                 displayContent.removeIfPossible();
7021             }
7022             mAnimator.removeDisplayLocked(displayId);
7023             mWindowPlacerLocked.requestTraversal();
7024         }
7025     }
7026 
onDisplayChanged(int displayId)7027     public void onDisplayChanged(int displayId) {
7028         synchronized (mWindowMap) {
7029             final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
7030             if (displayContent != null) {
7031                 displayContent.updateDisplayInfo();
7032             }
7033             mWindowPlacerLocked.requestTraversal();
7034         }
7035     }
7036 
7037     @Override
getWindowManagerLock()7038     public Object getWindowManagerLock() {
7039         return mWindowMap;
7040     }
7041 
7042     /**
7043      * Hint to a token that its activity will relaunch, which will trigger removal and addition of
7044      * a window.
7045      * @param token Application token for which the activity will be relaunched.
7046      */
setWillReplaceWindow(IBinder token, boolean animate)7047     public void setWillReplaceWindow(IBinder token, boolean animate) {
7048         synchronized (mWindowMap) {
7049             final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
7050             if (appWindowToken == null || !appWindowToken.hasContentToDisplay()) {
7051                 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
7052                         + token);
7053                 return;
7054             }
7055             appWindowToken.setWillReplaceWindows(animate);
7056         }
7057     }
7058 
7059     /**
7060      * Hint to a token that its windows will be replaced across activity relaunch.
7061      * The windows would otherwise be removed  shortly following this as the
7062      * activity is torn down.
7063      * @param token Application token for which the activity will be relaunched.
7064      * @param childrenOnly Whether to mark only child windows for replacement
7065      *                     (for the case where main windows are being preserved/
7066      *                     reused rather than replaced).
7067      *
7068      */
7069     // TODO: The s at the end of the method name is the only difference with the name of the method
7070     // above. We should combine them or find better names.
setWillReplaceWindows(IBinder token, boolean childrenOnly)7071     void setWillReplaceWindows(IBinder token, boolean childrenOnly) {
7072         synchronized (mWindowMap) {
7073             final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
7074             if (appWindowToken == null || !appWindowToken.hasContentToDisplay()) {
7075                 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
7076                         + token);
7077                 return;
7078             }
7079 
7080             if (childrenOnly) {
7081                 appWindowToken.setWillReplaceChildWindows();
7082             } else {
7083                 appWindowToken.setWillReplaceWindows(false /* animate */);
7084             }
7085 
7086             scheduleClearWillReplaceWindows(token, true /* replacing */);
7087         }
7088     }
7089 
7090     /**
7091      * If we're replacing the window, schedule a timer to clear the replaced window
7092      * after a timeout, in case the replacing window is not coming.
7093      *
7094      * If we're not replacing the window, clear the replace window settings of the app.
7095      *
7096      * @param token Application token for the activity whose window might be replaced.
7097      * @param replacing Whether the window is being replaced or not.
7098      */
scheduleClearWillReplaceWindows(IBinder token, boolean replacing)7099     public void scheduleClearWillReplaceWindows(IBinder token, boolean replacing) {
7100         synchronized (mWindowMap) {
7101             final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
7102             if (appWindowToken == null) {
7103                 Slog.w(TAG_WM, "Attempted to reset replacing window on non-existing app token "
7104                         + token);
7105                 return;
7106             }
7107             if (replacing) {
7108                 scheduleWindowReplacementTimeouts(appWindowToken);
7109             } else {
7110                 appWindowToken.clearWillReplaceWindows();
7111             }
7112         }
7113     }
7114 
scheduleWindowReplacementTimeouts(AppWindowToken appWindowToken)7115     void scheduleWindowReplacementTimeouts(AppWindowToken appWindowToken) {
7116         if (!mWindowReplacementTimeouts.contains(appWindowToken)) {
7117             mWindowReplacementTimeouts.add(appWindowToken);
7118         }
7119         mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT);
7120         mH.sendEmptyMessageDelayed(
7121                 H.WINDOW_REPLACEMENT_TIMEOUT, WINDOW_REPLACEMENT_TIMEOUT_DURATION);
7122     }
7123 
7124     @Override
getDockedStackSide()7125     public int getDockedStackSide() {
7126         synchronized (mWindowMap) {
7127             final TaskStack dockedStack = getDefaultDisplayContentLocked()
7128                     .getDockedStackIgnoringVisibility();
7129             return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide();
7130         }
7131     }
7132 
7133     @Override
setDockedStackResizing(boolean resizing)7134     public void setDockedStackResizing(boolean resizing) {
7135         synchronized (mWindowMap) {
7136             getDefaultDisplayContentLocked().getDockedDividerController().setResizing(resizing);
7137             requestTraversal();
7138         }
7139     }
7140 
7141     @Override
setDockedStackDividerTouchRegion(Rect touchRegion)7142     public void setDockedStackDividerTouchRegion(Rect touchRegion) {
7143         synchronized (mWindowMap) {
7144             getDefaultDisplayContentLocked().getDockedDividerController()
7145                     .setTouchRegion(touchRegion);
7146             setFocusTaskRegionLocked(null);
7147         }
7148     }
7149 
7150     @Override
setResizeDimLayer(boolean visible, int targetStackId, float alpha)7151     public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
7152         synchronized (mWindowMap) {
7153             getDefaultDisplayContentLocked().getDockedDividerController().setResizeDimLayer(
7154                     visible, targetStackId, alpha);
7155         }
7156     }
7157 
setForceResizableTasks(boolean forceResizableTasks)7158     public void setForceResizableTasks(boolean forceResizableTasks) {
7159         synchronized (mWindowMap) {
7160             mForceResizableTasks = forceResizableTasks;
7161         }
7162     }
7163 
setSupportsPictureInPicture(boolean supportsPictureInPicture)7164     public void setSupportsPictureInPicture(boolean supportsPictureInPicture) {
7165         synchronized (mWindowMap) {
7166             mSupportsPictureInPicture = supportsPictureInPicture;
7167         }
7168     }
7169 
dipToPixel(int dip, DisplayMetrics displayMetrics)7170     static int dipToPixel(int dip, DisplayMetrics displayMetrics) {
7171         return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics);
7172     }
7173 
7174     @Override
registerDockedStackListener(IDockedStackListener listener)7175     public void registerDockedStackListener(IDockedStackListener listener) {
7176         if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS,
7177                 "registerDockedStackListener()")) {
7178             return;
7179         }
7180         synchronized (mWindowMap) {
7181             // TODO(multi-display): The listener is registered on the default display only.
7182             getDefaultDisplayContentLocked().mDividerControllerLocked.registerDockedStackListener(
7183                     listener);
7184         }
7185     }
7186 
7187     @Override
registerPinnedStackListener(int displayId, IPinnedStackListener listener)7188     public void registerPinnedStackListener(int displayId, IPinnedStackListener listener) {
7189         if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS,
7190                 "registerPinnedStackListener()")) {
7191             return;
7192         }
7193         if (!mSupportsPictureInPicture) {
7194             return;
7195         }
7196         synchronized (mWindowMap) {
7197             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
7198             displayContent.getPinnedStackController().registerPinnedStackListener(listener);
7199         }
7200     }
7201 
7202     @Override
requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId)7203     public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
7204         try {
7205             WindowState focusedWindow = getFocusedWindow();
7206             if (focusedWindow != null && focusedWindow.mClient != null) {
7207                 getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver, deviceId);
7208             }
7209         } catch (RemoteException e) {
7210         }
7211     }
7212 
7213     @Override
getStableInsets(int displayId, Rect outInsets)7214     public void getStableInsets(int displayId, Rect outInsets) throws RemoteException {
7215         synchronized (mWindowMap) {
7216             getStableInsetsLocked(displayId, outInsets);
7217         }
7218     }
7219 
getStableInsetsLocked(int displayId, Rect outInsets)7220     void getStableInsetsLocked(int displayId, Rect outInsets) {
7221         outInsets.setEmpty();
7222         final DisplayContent dc = mRoot.getDisplayContent(displayId);
7223         if (dc != null) {
7224             final DisplayInfo di = dc.getDisplayInfo();
7225             mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
7226         }
7227     }
7228 
intersectDisplayInsetBounds(Rect display, Rect insets, Rect inOutBounds)7229     void intersectDisplayInsetBounds(Rect display, Rect insets, Rect inOutBounds) {
7230         mTmpRect3.set(display);
7231         mTmpRect3.inset(insets);
7232         inOutBounds.intersect(mTmpRect3);
7233     }
7234 
7235     MousePositionTracker mMousePositionTracker = new MousePositionTracker();
7236 
7237     private static class MousePositionTracker implements PointerEventListener {
7238         private boolean mLatestEventWasMouse;
7239         private float mLatestMouseX;
7240         private float mLatestMouseY;
7241 
updatePosition(float x, float y)7242         void updatePosition(float x, float y) {
7243             synchronized (this) {
7244                 mLatestEventWasMouse = true;
7245                 mLatestMouseX = x;
7246                 mLatestMouseY = y;
7247             }
7248         }
7249 
7250         @Override
onPointerEvent(MotionEvent motionEvent)7251         public void onPointerEvent(MotionEvent motionEvent) {
7252             if (motionEvent.isFromSource(InputDevice.SOURCE_MOUSE)) {
7253                 updatePosition(motionEvent.getRawX(), motionEvent.getRawY());
7254             } else {
7255                 synchronized (this) {
7256                     mLatestEventWasMouse = false;
7257                 }
7258             }
7259         }
7260     };
7261 
updatePointerIcon(IWindow client)7262     void updatePointerIcon(IWindow client) {
7263         float mouseX, mouseY;
7264 
7265         synchronized(mMousePositionTracker) {
7266             if (!mMousePositionTracker.mLatestEventWasMouse) {
7267                 return;
7268             }
7269             mouseX = mMousePositionTracker.mLatestMouseX;
7270             mouseY = mMousePositionTracker.mLatestMouseY;
7271         }
7272 
7273         synchronized (mWindowMap) {
7274             if (mDragState != null) {
7275                 // Drag cursor overrides the app cursor.
7276                 return;
7277             }
7278             WindowState callingWin = windowForClientLocked(null, client, false);
7279             if (callingWin == null) {
7280                 Slog.w(TAG_WM, "Bad requesting window " + client);
7281                 return;
7282             }
7283             final DisplayContent displayContent = callingWin.getDisplayContent();
7284             if (displayContent == null) {
7285                 return;
7286             }
7287             WindowState windowUnderPointer =
7288                     displayContent.getTouchableWinAtPointLocked(mouseX, mouseY);
7289             if (windowUnderPointer != callingWin) {
7290                 return;
7291             }
7292             try {
7293                 windowUnderPointer.mClient.updatePointerIcon(
7294                         windowUnderPointer.translateToWindowX(mouseX),
7295                         windowUnderPointer.translateToWindowY(mouseY));
7296             } catch (RemoteException e) {
7297                 Slog.w(TAG_WM, "unable to update pointer icon");
7298             }
7299         }
7300     }
7301 
restorePointerIconLocked(DisplayContent displayContent, float latestX, float latestY)7302     void restorePointerIconLocked(DisplayContent displayContent, float latestX, float latestY) {
7303         // Mouse position tracker has not been getting updates while dragging, update it now.
7304         mMousePositionTracker.updatePosition(latestX, latestY);
7305 
7306         WindowState windowUnderPointer =
7307                 displayContent.getTouchableWinAtPointLocked(latestX, latestY);
7308         if (windowUnderPointer != null) {
7309             try {
7310                 windowUnderPointer.mClient.updatePointerIcon(
7311                         windowUnderPointer.translateToWindowX(latestX),
7312                         windowUnderPointer.translateToWindowY(latestY));
7313             } catch (RemoteException e) {
7314                 Slog.w(TAG_WM, "unable to restore pointer icon");
7315             }
7316         } else {
7317             InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_DEFAULT);
7318         }
7319     }
7320 
7321     @Override
registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)7322     public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
7323             throws RemoteException {
7324         if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS, "registerShortcutKey")) {
7325             throw new SecurityException(
7326                     "Requires REGISTER_WINDOW_MANAGER_LISTENERS permission");
7327         }
7328         mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver);
7329     }
7330 
markForSeamlessRotation(WindowState w, boolean seamlesslyRotated)7331     void markForSeamlessRotation(WindowState w, boolean seamlesslyRotated) {
7332         if (seamlesslyRotated == w.mSeamlesslyRotated) {
7333             return;
7334         }
7335         w.mSeamlesslyRotated = seamlesslyRotated;
7336         if (seamlesslyRotated) {
7337             mSeamlessRotationCount++;
7338         } else {
7339             mSeamlessRotationCount--;
7340         }
7341         if (mSeamlessRotationCount == 0) {
7342             if (DEBUG_ORIENTATION) {
7343                 Slog.i(TAG, "Performing post-rotate rotation after seamless rotation");
7344             }
7345             final DisplayContent displayContent = w.getDisplayContent();
7346             if (displayContent.updateRotationUnchecked(false /* inTransaction */)) {
7347                 mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
7348                         .sendToTarget();
7349             }
7350         }
7351     }
7352 
7353     private final class LocalService extends WindowManagerInternal {
7354         @Override
requestTraversalFromDisplayManager()7355         public void requestTraversalFromDisplayManager() {
7356             requestTraversal();
7357         }
7358 
7359         @Override
setMagnificationSpec(MagnificationSpec spec)7360         public void setMagnificationSpec(MagnificationSpec spec) {
7361             synchronized (mWindowMap) {
7362                 if (mAccessibilityController != null) {
7363                     mAccessibilityController.setMagnificationSpecLocked(spec);
7364                 } else {
7365                     throw new IllegalStateException("Magnification callbacks not set!");
7366                 }
7367             }
7368             if (Binder.getCallingPid() != myPid()) {
7369                 spec.recycle();
7370             }
7371         }
7372 
7373         @Override
setForceShowMagnifiableBounds(boolean show)7374         public void setForceShowMagnifiableBounds(boolean show) {
7375             synchronized (mWindowMap) {
7376                 if (mAccessibilityController != null) {
7377                     mAccessibilityController.setForceShowMagnifiableBoundsLocked(show);
7378                 } else {
7379                     throw new IllegalStateException("Magnification callbacks not set!");
7380                 }
7381             }
7382         }
7383 
7384         @Override
getMagnificationRegion(@onNull Region magnificationRegion)7385         public void getMagnificationRegion(@NonNull Region magnificationRegion) {
7386             synchronized (mWindowMap) {
7387                 if (mAccessibilityController != null) {
7388                     mAccessibilityController.getMagnificationRegionLocked(magnificationRegion);
7389                 } else {
7390                     throw new IllegalStateException("Magnification callbacks not set!");
7391                 }
7392             }
7393         }
7394 
7395         @Override
getCompatibleMagnificationSpecForWindow(IBinder windowToken)7396         public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
7397             synchronized (mWindowMap) {
7398                 WindowState windowState = mWindowMap.get(windowToken);
7399                 if (windowState == null) {
7400                     return null;
7401                 }
7402                 MagnificationSpec spec = null;
7403                 if (mAccessibilityController != null) {
7404                     spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState);
7405                 }
7406                 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
7407                     return null;
7408                 }
7409                 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec);
7410                 spec.scale *= windowState.mGlobalScale;
7411                 return spec;
7412             }
7413         }
7414 
7415         @Override
setMagnificationCallbacks(@ullable MagnificationCallbacks callbacks)7416         public void setMagnificationCallbacks(@Nullable MagnificationCallbacks callbacks) {
7417             synchronized (mWindowMap) {
7418                 if (mAccessibilityController == null) {
7419                     mAccessibilityController = new AccessibilityController(
7420                             WindowManagerService.this);
7421                 }
7422                 mAccessibilityController.setMagnificationCallbacksLocked(callbacks);
7423                 if (!mAccessibilityController.hasCallbacksLocked()) {
7424                     mAccessibilityController = null;
7425                 }
7426             }
7427         }
7428 
7429         @Override
setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback)7430         public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) {
7431             synchronized (mWindowMap) {
7432                 if (mAccessibilityController == null) {
7433                     mAccessibilityController = new AccessibilityController(
7434                             WindowManagerService.this);
7435                 }
7436                 mAccessibilityController.setWindowsForAccessibilityCallback(callback);
7437                 if (!mAccessibilityController.hasCallbacksLocked()) {
7438                     mAccessibilityController = null;
7439                 }
7440             }
7441         }
7442 
7443         @Override
setInputFilter(IInputFilter filter)7444         public void setInputFilter(IInputFilter filter) {
7445             mInputManager.setInputFilter(filter);
7446         }
7447 
7448         @Override
getFocusedWindowToken()7449         public IBinder getFocusedWindowToken() {
7450             synchronized (mWindowMap) {
7451                 WindowState windowState = getFocusedWindowLocked();
7452                 if (windowState != null) {
7453                     return windowState.mClient.asBinder();
7454                 }
7455                 return null;
7456             }
7457         }
7458 
7459         @Override
isKeyguardLocked()7460         public boolean isKeyguardLocked() {
7461             return WindowManagerService.this.isKeyguardLocked();
7462         }
7463 
7464         @Override
isKeyguardShowingAndNotOccluded()7465         public boolean isKeyguardShowingAndNotOccluded() {
7466             return WindowManagerService.this.isKeyguardShowingAndNotOccluded();
7467         }
7468 
7469         @Override
showGlobalActions()7470         public void showGlobalActions() {
7471             WindowManagerService.this.showGlobalActions();
7472         }
7473 
7474         @Override
getWindowFrame(IBinder token, Rect outBounds)7475         public void getWindowFrame(IBinder token, Rect outBounds) {
7476             synchronized (mWindowMap) {
7477                 WindowState windowState = mWindowMap.get(token);
7478                 if (windowState != null) {
7479                     outBounds.set(windowState.mFrame);
7480                 } else {
7481                     outBounds.setEmpty();
7482                 }
7483             }
7484         }
7485 
7486         @Override
waitForAllWindowsDrawn(Runnable callback, long timeout)7487         public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
7488             boolean allWindowsDrawn = false;
7489             synchronized (mWindowMap) {
7490                 mWaitingForDrawnCallback = callback;
7491                 getDefaultDisplayContentLocked().waitForAllWindowsDrawn();
7492                 mWindowPlacerLocked.requestTraversal();
7493                 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
7494                 if (mWaitingForDrawn.isEmpty()) {
7495                     allWindowsDrawn = true;
7496                 } else {
7497                     mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
7498                     checkDrawnWindowsLocked();
7499                 }
7500             }
7501             if (allWindowsDrawn) {
7502                 callback.run();
7503             }
7504         }
7505 
7506         @Override
addWindowToken(IBinder token, int type, int displayId)7507         public void addWindowToken(IBinder token, int type, int displayId) {
7508             WindowManagerService.this.addWindowToken(token, type, displayId);
7509         }
7510 
7511         @Override
removeWindowToken(IBinder binder, boolean removeWindows, int displayId)7512         public void removeWindowToken(IBinder binder, boolean removeWindows, int displayId) {
7513             synchronized(mWindowMap) {
7514                 if (removeWindows) {
7515                     final DisplayContent dc = mRoot.getDisplayContent(displayId);
7516                     if (dc == null) {
7517                         Slog.w(TAG_WM, "removeWindowToken: Attempted to remove token: " + binder
7518                                 + " for non-exiting displayId=" + displayId);
7519                         return;
7520                     }
7521 
7522                     final WindowToken token = dc.removeWindowToken(binder);
7523                     if (token == null) {
7524                         Slog.w(TAG_WM, "removeWindowToken: Attempted to remove non-existing token: "
7525                                 + binder);
7526                         return;
7527                     }
7528 
7529                     token.removeAllWindowsIfPossible();
7530                 }
7531                 WindowManagerService.this.removeWindowToken(binder, displayId);
7532             }
7533         }
7534 
7535         @Override
registerAppTransitionListener(AppTransitionListener listener)7536         public void registerAppTransitionListener(AppTransitionListener listener) {
7537             synchronized (mWindowMap) {
7538                 mAppTransition.registerListenerLocked(listener);
7539             }
7540         }
7541 
7542         @Override
getInputMethodWindowVisibleHeight()7543         public int getInputMethodWindowVisibleHeight() {
7544             synchronized (mWindowMap) {
7545                 return mPolicy.getInputMethodWindowVisibleHeightLw();
7546             }
7547         }
7548 
7549         @Override
saveLastInputMethodWindowForTransition()7550         public void saveLastInputMethodWindowForTransition() {
7551             synchronized (mWindowMap) {
7552                 if (mInputMethodWindow != null) {
7553                     mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
7554                 }
7555             }
7556         }
7557 
7558         @Override
clearLastInputMethodWindowForTransition()7559         public void clearLastInputMethodWindowForTransition() {
7560             synchronized (mWindowMap) {
7561                 mPolicy.setLastInputMethodWindowLw(null, null);
7562             }
7563         }
7564 
7565         @Override
updateInputMethodWindowStatus(@onNull IBinder imeToken, boolean imeWindowVisible, boolean dismissImeOnBackKeyPressed, @Nullable IBinder targetWindowToken)7566         public void updateInputMethodWindowStatus(@NonNull IBinder imeToken,
7567                 boolean imeWindowVisible, boolean dismissImeOnBackKeyPressed,
7568                 @Nullable IBinder targetWindowToken) {
7569             // TODO (b/34628091): Use this method to address the window animation issue.
7570             if (DEBUG_INPUT_METHOD) {
7571                 Slog.w(TAG_WM, "updateInputMethodWindowStatus: imeToken=" + imeToken
7572                         + " dismissImeOnBackKeyPressed=" + dismissImeOnBackKeyPressed
7573                         + " imeWindowVisible=" + imeWindowVisible
7574                         + " targetWindowToken=" + targetWindowToken);
7575             }
7576             mPolicy.setDismissImeOnBackKeyPressed(dismissImeOnBackKeyPressed);
7577         }
7578 
7579         @Override
isHardKeyboardAvailable()7580         public boolean isHardKeyboardAvailable() {
7581             synchronized (mWindowMap) {
7582                 return mHardKeyboardAvailable;
7583             }
7584         }
7585 
7586         @Override
setOnHardKeyboardStatusChangeListener( OnHardKeyboardStatusChangeListener listener)7587         public void setOnHardKeyboardStatusChangeListener(
7588                 OnHardKeyboardStatusChangeListener listener) {
7589             synchronized (mWindowMap) {
7590                 mHardKeyboardStatusChangeListener = listener;
7591             }
7592         }
7593 
7594         @Override
isStackVisible(int stackId)7595         public boolean isStackVisible(int stackId) {
7596             synchronized (mWindowMap) {
7597                 final DisplayContent dc = getDefaultDisplayContentLocked();
7598                 return dc.isStackVisible(stackId);
7599             }
7600         }
7601 
7602         @Override
isDockedDividerResizing()7603         public boolean isDockedDividerResizing() {
7604             synchronized (mWindowMap) {
7605                 return getDefaultDisplayContentLocked().getDockedDividerController().isResizing();
7606             }
7607         }
7608 
7609         @Override
computeWindowsForAccessibility()7610         public void computeWindowsForAccessibility() {
7611             final AccessibilityController accessibilityController;
7612             synchronized (mWindowMap) {
7613                 accessibilityController = mAccessibilityController;
7614             }
7615             if (accessibilityController != null) {
7616                 accessibilityController.performComputeChangedWindowsNotLocked();
7617             }
7618         }
7619 
7620         @Override
setVr2dDisplayId(int vr2dDisplayId)7621         public void setVr2dDisplayId(int vr2dDisplayId) {
7622             if (DEBUG_DISPLAY) {
7623                 Slog.d(TAG, "setVr2dDisplayId called for: " + vr2dDisplayId);
7624             }
7625             synchronized (WindowManagerService.this) {
7626                 mVr2dDisplayId = vr2dDisplayId;
7627             }
7628         }
7629     }
7630 
registerAppFreezeListener(AppFreezeListener listener)7631     void registerAppFreezeListener(AppFreezeListener listener) {
7632         if (!mAppFreezeListeners.contains(listener)) {
7633             mAppFreezeListeners.add(listener);
7634         }
7635     }
7636 
unregisterAppFreezeListener(AppFreezeListener listener)7637     void unregisterAppFreezeListener(AppFreezeListener listener) {
7638         mAppFreezeListeners.remove(listener);
7639     }
7640 
7641     /**
7642      * WARNING: This interrupts surface updates, be careful! Don't
7643      * execute within the transaction for longer than you would
7644      * execute on an animation thread.
7645      * WARNING: This holds the WindowManager lock, so if exec will acquire
7646      * the ActivityManager lock, you should hold it BEFORE calling this
7647      * otherwise there is a risk of deadlock if another thread holding the AM
7648      * lock waits on the WM lock.
7649      * WARNING: This method contains locks known to the State of California
7650      * to cause Deadlocks and other conditions.
7651      *
7652      * Begins a surface transaction with which the AM can batch operations.
7653      * All Surface updates performed by the WindowManager following this
7654      * will not appear on screen until after the call to
7655      * closeSurfaceTransaction.
7656      *
7657      * ActivityManager can use this to ensure multiple 'commands' will all
7658      * be reflected in a single frame. For example when reparenting a window
7659      * which was previously hidden due to it's parent properties, we may
7660      * need to ensure it is hidden in the same frame that the properties
7661      * from the new parent are inherited, otherwise it could be revealed
7662      * mistakenly.
7663      *
7664      * TODO(b/36393204): We can investigate totally replacing #deferSurfaceLayout
7665      * with something like this but it seems that some existing cases of
7666      * deferSurfaceLayout may be a little too broad, in particular the total
7667      * enclosure of startActivityUnchecked which could run for quite some time.
7668      */
inSurfaceTransaction(Runnable exec)7669     public void inSurfaceTransaction(Runnable exec) {
7670         // We hold the WindowManger lock to ensure relayoutWindow
7671         // does not return while a Surface transaction is opening.
7672         // The client depends on us to have resized the surface
7673         // by that point (b/36462635)
7674 
7675         synchronized (mWindowMap) {
7676             SurfaceControl.openTransaction();
7677             try {
7678                 exec.run();
7679             } finally {
7680                 SurfaceControl.closeTransaction();
7681             }
7682         }
7683     }
7684 
7685     /** Called to inform window manager if non-Vr UI shoul be disabled or not. */
disableNonVrUi(boolean disable)7686     public void disableNonVrUi(boolean disable) {
7687         synchronized (mWindowMap) {
7688             // Allow alert window notifications to be shown if non-vr UI is enabled.
7689             final boolean showAlertWindowNotifications = !disable;
7690             if (showAlertWindowNotifications == mShowAlertWindowNotifications) {
7691                 return;
7692             }
7693             mShowAlertWindowNotifications = showAlertWindowNotifications;
7694 
7695             for (int i = mSessions.size() - 1; i >= 0; --i) {
7696                 final Session s = mSessions.valueAt(i);
7697                 s.setShowingAlertWindowNotificationAllowed(mShowAlertWindowNotifications);
7698             }
7699         }
7700     }
7701 
hasWideColorGamutSupport()7702     boolean hasWideColorGamutSupport() {
7703         return mHasWideColorGamutSupport &&
7704                 !SystemProperties.getBoolean("persist.sys.sf.native_mode", false);
7705     }
7706 
updateNonSystemOverlayWindowsVisibilityIfNeeded(WindowState win, boolean surfaceShown)7707     void updateNonSystemOverlayWindowsVisibilityIfNeeded(WindowState win, boolean surfaceShown) {
7708         if (!win.hideNonSystemOverlayWindowsWhenVisible()
7709                 && !mHidingNonSystemOverlayWindows.contains(win)) {
7710             return;
7711         }
7712         final boolean systemAlertWindowsHidden = !mHidingNonSystemOverlayWindows.isEmpty();
7713         if (surfaceShown) {
7714             if (!mHidingNonSystemOverlayWindows.contains(win)) {
7715                 mHidingNonSystemOverlayWindows.add(win);
7716             }
7717         } else {
7718             mHidingNonSystemOverlayWindows.remove(win);
7719         }
7720 
7721         final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty();
7722 
7723         if (systemAlertWindowsHidden == hideSystemAlertWindows) {
7724             return;
7725         }
7726 
7727         mRoot.forAllWindows((w) -> {
7728             w.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);
7729         }, false /* traverseTopToBottom */);
7730     }
7731 }
7732