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