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