OSDN Git Service

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