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