OSDN Git Service

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