PhoneWindowManager.java revision 0390fff82c37c705670a6c8937c11b52e2af4cb6
1/*
2 * Copyright (C) 2006 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.policy;
18
19import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
20import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
21import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
22import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
23import static android.app.ActivityManager.StackId.HOME_STACK_ID;
24import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
25import static android.app.AppOpsManager.OP_TOAST_WINDOW;
26import static android.content.Context.CONTEXT_RESTRICTED;
27import static android.content.Context.DISPLAY_SERVICE;
28import static android.content.Context.WINDOW_SERVICE;
29import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
30import static android.content.pm.PackageManager.FEATURE_LEANBACK;
31import static android.content.pm.PackageManager.FEATURE_WATCH;
32import static android.content.pm.PackageManager.PERMISSION_GRANTED;
33import static android.content.res.Configuration.EMPTY;
34import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
35import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
36import static android.os.Build.VERSION_CODES.M;
37import static android.os.Build.VERSION_CODES.O;
38import static android.view.WindowManager.DOCKED_LEFT;
39import static android.view.WindowManager.DOCKED_RIGHT;
40import static android.view.WindowManager.DOCKED_TOP;
41import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
42import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
43import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
44import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
45import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
46import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
47import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
48import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
49import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR;
50import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
51import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN;
52import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
53import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
54import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
55import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
56import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
57import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
58import static android.view.WindowManager.LayoutParams.LAST_SYSTEM_WINDOW;
59import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
60import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
61import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
62import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
63import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
64import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
65import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
66import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
67import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
68import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
69import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
70import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
71import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
72import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
73import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
74import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
75import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
76import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
77import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
78import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
79import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
80import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
81import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
82import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
83import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
84import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
85import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
86import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
87import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
88import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
89import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
90import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
91import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
92import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR;
93import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
94import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
95import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
96import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
97import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
98import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
99import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
100import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
101import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
102import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
103import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING;
104import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
105import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
106import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
107import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
108import static android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION;
109import static android.view.WindowManagerGlobal.ADD_OKAY;
110import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED;
111import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
112import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
113import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
114import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
115import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
116import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
117
118import android.annotation.Nullable;
119import android.app.ActivityManager;
120import android.app.ActivityManager.StackId;
121import android.app.ActivityManagerInternal;
122import android.app.ActivityManagerInternal.SleepToken;
123import android.app.AppOpsManager;
124import android.app.IUiModeManager;
125import android.app.ProgressDialog;
126import android.app.SearchManager;
127import android.app.StatusBarManager;
128import android.app.UiModeManager;
129import android.content.ActivityNotFoundException;
130import android.content.BroadcastReceiver;
131import android.content.ComponentName;
132import android.content.ContentResolver;
133import android.content.Context;
134import android.content.Intent;
135import android.content.IntentFilter;
136import android.content.ServiceConnection;
137import android.content.pm.ActivityInfo;
138import android.content.pm.ApplicationInfo;
139import android.content.pm.PackageManager;
140import android.content.pm.ResolveInfo;
141import android.content.res.CompatibilityInfo;
142import android.content.res.Configuration;
143import android.content.res.Resources;
144import android.content.res.TypedArray;
145import android.database.ContentObserver;
146import android.graphics.PixelFormat;
147import android.graphics.Rect;
148import android.graphics.drawable.Drawable;
149import android.hardware.display.DisplayManager;
150import android.hardware.hdmi.HdmiControlManager;
151import android.hardware.hdmi.HdmiPlaybackClient;
152import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback;
153import android.hardware.input.InputManager;
154import android.hardware.input.InputManagerInternal;
155import android.hardware.power.V1_0.PowerHint;
156import android.media.AudioAttributes;
157import android.media.AudioManager;
158import android.media.AudioSystem;
159import android.media.IAudioService;
160import android.media.session.MediaSessionLegacyHelper;
161import android.os.Binder;
162import android.os.Build;
163import android.os.Bundle;
164import android.os.FactoryTest;
165import android.os.Handler;
166import android.os.IBinder;
167import android.os.IDeviceIdleController;
168import android.os.Looper;
169import android.os.Message;
170import android.os.Messenger;
171import android.os.PowerManager;
172import android.os.PowerManagerInternal;
173import android.os.Process;
174import android.os.RemoteException;
175import android.os.ServiceManager;
176import android.os.SystemClock;
177import android.os.SystemProperties;
178import android.os.UEventObserver;
179import android.os.UserHandle;
180import android.os.Vibrator;
181import android.os.VibrationEffect;
182import android.provider.MediaStore;
183import android.provider.Settings;
184import android.service.dreams.DreamManagerInternal;
185import android.service.dreams.DreamService;
186import android.service.dreams.IDreamManager;
187import android.service.vr.IPersistentVrStateCallbacks;
188import android.speech.RecognizerIntent;
189import android.telecom.TelecomManager;
190import android.util.DisplayMetrics;
191import android.util.EventLog;
192import android.util.Log;
193import android.util.LongSparseArray;
194import android.util.MutableBoolean;
195import android.util.Slog;
196import android.util.SparseArray;
197import android.view.Display;
198import android.view.Gravity;
199import android.view.HapticFeedbackConstants;
200import android.view.IApplicationToken;
201import android.view.IWindowManager;
202import android.view.InputChannel;
203import android.view.InputDevice;
204import android.view.InputEvent;
205import android.view.InputEventReceiver;
206import android.view.KeyCharacterMap;
207import android.view.KeyCharacterMap.FallbackAction;
208import android.view.KeyEvent;
209import android.view.MotionEvent;
210import android.view.PointerIcon;
211import android.view.Surface;
212import android.view.View;
213import android.view.ViewConfiguration;
214import android.view.WindowManager;
215import android.view.WindowManager.LayoutParams;
216import android.view.WindowManagerGlobal;
217import android.view.WindowManagerInternal;
218import android.view.WindowManagerInternal.AppTransitionListener;
219import android.view.WindowManagerPolicy;
220import android.view.accessibility.AccessibilityEvent;
221import android.view.accessibility.AccessibilityManager;
222import android.view.animation.Animation;
223import android.view.animation.AnimationSet;
224import android.view.animation.AnimationUtils;
225import android.view.autofill.AutofillManagerInternal;
226import android.view.inputmethod.InputMethodManagerInternal;
227
228import com.android.internal.R;
229import com.android.internal.logging.MetricsLogger;
230import com.android.internal.policy.IKeyguardDismissCallback;
231import com.android.internal.policy.IShortcutService;
232import com.android.internal.policy.PhoneWindow;
233import com.android.internal.statusbar.IStatusBarService;
234import com.android.internal.util.ScreenShapeHelper;
235import com.android.internal.widget.PointerLocationView;
236import com.android.server.GestureLauncherService;
237import com.android.server.LocalServices;
238import com.android.server.SystemServiceManager;
239import com.android.server.policy.keyguard.KeyguardServiceDelegate;
240import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener;
241import com.android.server.policy.keyguard.KeyguardStateMonitor.StateCallback;
242import com.android.server.statusbar.StatusBarManagerInternal;
243import com.android.server.wm.AppTransition;
244import com.android.server.vr.VrManagerInternal;
245
246import java.io.File;
247import java.io.FileReader;
248import java.io.IOException;
249import java.io.PrintWriter;
250import java.util.List;
251
252/**
253 * WindowManagerPolicy implementation for the Android phone UI.  This
254 * introduces a new method suffix, Lp, for an internal lock of the
255 * PhoneWindowManager.  This is used to protect some internal state, and
256 * can be acquired with either the Lw and Li lock held, so has the restrictions
257 * of both of those when held.
258 */
259public class PhoneWindowManager implements WindowManagerPolicy {
260    static final String TAG = "WindowManager";
261    static final boolean DEBUG = false;
262    static final boolean localLOGV = false;
263    static final boolean DEBUG_INPUT = false;
264    static final boolean DEBUG_KEYGUARD = false;
265    static final boolean DEBUG_LAYOUT = false;
266    static final boolean DEBUG_SPLASH_SCREEN = false;
267    static final boolean DEBUG_WAKEUP = false;
268    static final boolean SHOW_SPLASH_SCREENS = true;
269
270    // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
271    // No longer recommended for desk docks;
272    static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
273
274    // Whether to allow devices placed in vr headset viewers to have an alternative Home intent.
275    static final boolean ENABLE_VR_HEADSET_HOME_CAPTURE = true;
276
277    static final boolean ALTERNATE_CAR_MODE_NAV_SIZE = false;
278
279    static final int SHORT_PRESS_POWER_NOTHING = 0;
280    static final int SHORT_PRESS_POWER_GO_TO_SLEEP = 1;
281    static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2;
282    static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3;
283    static final int SHORT_PRESS_POWER_GO_HOME = 4;
284    static final int SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME = 5;
285
286    static final int LONG_PRESS_POWER_NOTHING = 0;
287    static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
288    static final int LONG_PRESS_POWER_SHUT_OFF = 2;
289    static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
290
291    static final int LONG_PRESS_BACK_NOTHING = 0;
292    static final int LONG_PRESS_BACK_GO_TO_VOICE_ASSIST = 1;
293
294    static final int MULTI_PRESS_POWER_NOTHING = 0;
295    static final int MULTI_PRESS_POWER_THEATER_MODE = 1;
296    static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2;
297
298    // Number of presses needed before we induce panic press behavior on the back button
299    static final int PANIC_PRESS_BACK_COUNT = 4;
300    static final int PANIC_PRESS_BACK_NOTHING = 0;
301    static final int PANIC_PRESS_BACK_HOME = 1;
302
303    // These need to match the documentation/constant in
304    // core/res/res/values/config.xml
305    static final int LONG_PRESS_HOME_NOTHING = 0;
306    static final int LONG_PRESS_HOME_ALL_APPS = 1;
307    static final int LONG_PRESS_HOME_ASSIST = 2;
308    static final int LAST_LONG_PRESS_HOME_BEHAVIOR = LONG_PRESS_HOME_ASSIST;
309
310    static final int DOUBLE_TAP_HOME_NOTHING = 0;
311    static final int DOUBLE_TAP_HOME_RECENT_SYSTEM_UI = 1;
312
313    static final int SHORT_PRESS_WINDOW_NOTHING = 0;
314    static final int SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE = 1;
315
316    static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP = 0;
317    static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME = 1;
318
319    static final int PENDING_KEY_NULL = -1;
320
321    // Controls navigation bar opacity depending on which workspace stacks are currently
322    // visible.
323    // Nav bar is always opaque when either the freeform stack or docked stack is visible.
324    static final int NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED = 0;
325    // Nav bar is always translucent when the freeform stack is visible, otherwise always opaque.
326    static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1;
327
328    static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
329    static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
330    static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
331    static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
332    static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";
333
334    /**
335     * These are the system UI flags that, when changing, can cause the layout
336     * of the screen to change.
337     */
338    static final int SYSTEM_UI_CHANGING_LAYOUT =
339              View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
340            | View.SYSTEM_UI_FLAG_FULLSCREEN
341            | View.STATUS_BAR_TRANSLUCENT
342            | View.NAVIGATION_BAR_TRANSLUCENT
343            | View.STATUS_BAR_TRANSPARENT
344            | View.NAVIGATION_BAR_TRANSPARENT;
345
346    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
347            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
348            .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
349            .build();
350
351    // The panic gesture may become active only after the keyguard is dismissed and the immersive
352    // app shows again. If that doesn't happen for 30s we drop the gesture.
353    private static final long PANIC_GESTURE_EXPIRATION = 30000;
354
355    private static final String SYSUI_PACKAGE = "com.android.systemui";
356    private static final String SYSUI_SCREENSHOT_SERVICE =
357            "com.android.systemui.screenshot.TakeScreenshotService";
358    private static final String SYSUI_SCREENSHOT_ERROR_RECEIVER =
359            "com.android.systemui.screenshot.ScreenshotServiceErrorReceiver";
360
361    private static final int NAV_BAR_BOTTOM = 0;
362    private static final int NAV_BAR_RIGHT = 1;
363    private static final int NAV_BAR_LEFT = 2;
364
365    /**
366     * Keyguard stuff
367     */
368    private boolean mKeyguardDrawnOnce;
369
370    /* Table of Application Launch keys.  Maps from key codes to intent categories.
371     *
372     * These are special keys that are used to launch particular kinds of applications,
373     * such as a web browser.  HID defines nearly a hundred of them in the Consumer (0x0C)
374     * usage page.  We don't support quite that many yet...
375     */
376    static SparseArray<String> sApplicationLaunchKeyCategories;
377    static {
378        sApplicationLaunchKeyCategories = new SparseArray<String>();
379        sApplicationLaunchKeyCategories.append(
380                KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER);
381        sApplicationLaunchKeyCategories.append(
382                KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL);
383        sApplicationLaunchKeyCategories.append(
384                KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS);
385        sApplicationLaunchKeyCategories.append(
386                KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR);
387        sApplicationLaunchKeyCategories.append(
388                KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC);
389        sApplicationLaunchKeyCategories.append(
390                KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
391    }
392
393    /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
394    static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;
395
396    /** Amount of time (in milliseconds) a toast window can be shown. */
397    public static final int TOAST_WINDOW_TIMEOUT = 3500; // 3.5 seconds
398
399    /**
400     * Lock protecting internal state.  Must not call out into window
401     * manager with lock held.  (This lock will be acquired in places
402     * where the window manager is calling in with its own lock held.)
403     */
404    private final Object mLock = new Object();
405
406    Context mContext;
407    IWindowManager mWindowManager;
408    WindowManagerFuncs mWindowManagerFuncs;
409    WindowManagerInternal mWindowManagerInternal;
410    PowerManager mPowerManager;
411    ActivityManagerInternal mActivityManagerInternal;
412    AutofillManagerInternal mAutofillManagerInternal;
413    InputManagerInternal mInputManagerInternal;
414    InputMethodManagerInternal mInputMethodManagerInternal;
415    DreamManagerInternal mDreamManagerInternal;
416    PowerManagerInternal mPowerManagerInternal;
417    IStatusBarService mStatusBarService;
418    StatusBarManagerInternal mStatusBarManagerInternal;
419    boolean mPreloadedRecentApps;
420    final Object mServiceAquireLock = new Object();
421    Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
422    SearchManager mSearchManager;
423    AccessibilityManager mAccessibilityManager;
424    BurnInProtectionHelper mBurnInProtectionHelper;
425    AppOpsManager mAppOpsManager;
426    private boolean mHasFeatureWatch;
427    private boolean mHasFeatureLeanback;
428
429    // Assigned on main thread, accessed on UI thread
430    volatile VrManagerInternal mVrManagerInternal;
431
432    // Vibrator pattern for haptic feedback of a long press.
433    long[] mLongPressVibePattern;
434
435    // Vibrator pattern for haptic feedback of virtual key press.
436    long[] mVirtualKeyVibePattern;
437
438    // Vibrator pattern for a short vibration.
439    long[] mKeyboardTapVibePattern;
440
441    // Vibrator pattern for a short vibration when tapping on an hour/minute tick of a Clock.
442    long[] mClockTickVibePattern;
443
444    // Vibrator pattern for a short vibration when tapping on a day/month/year date of a Calendar.
445    long[] mCalendarDateVibePattern;
446
447    // Vibrator pattern for haptic feedback during boot when safe mode is disabled.
448    long[] mSafeModeDisabledVibePattern;
449
450    // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
451    long[] mSafeModeEnabledVibePattern;
452
453    // Vibrator pattern for haptic feedback of a context click.
454    long[] mContextClickVibePattern;
455
456    /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
457    boolean mEnableShiftMenuBugReports = false;
458
459    /** Controller that supports enabling an AccessibilityService by holding down the volume keys */
460    private AccessibilityShortcutController mAccessibilityShortcutController;
461
462    boolean mSafeMode;
463    WindowState mStatusBar = null;
464    int mStatusBarHeight;
465    WindowState mNavigationBar = null;
466    boolean mHasNavigationBar = false;
467    boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?
468    int mNavigationBarPosition = NAV_BAR_BOTTOM;
469    int[] mNavigationBarHeightForRotationDefault = new int[4];
470    int[] mNavigationBarWidthForRotationDefault = new int[4];
471    int[] mNavigationBarHeightForRotationInCarMode = new int[4];
472    int[] mNavigationBarWidthForRotationInCarMode = new int[4];
473
474    private LongSparseArray<IShortcutService> mShortcutKeyServices = new LongSparseArray<>();
475
476    // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
477    // This is for car dock and this is updated from resource.
478    private boolean mEnableCarDockHomeCapture = true;
479
480    boolean mBootMessageNeedsHiding;
481    KeyguardServiceDelegate mKeyguardDelegate;
482    private boolean mKeyguardBound;
483    final Runnable mWindowManagerDrawCallback = new Runnable() {
484        @Override
485        public void run() {
486            if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!");
487            mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);
488        }
489    };
490    final DrawnListener mKeyguardDrawnCallback = new DrawnListener() {
491        @Override
492        public void onDrawn() {
493            if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn.");
494            mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
495        }
496    };
497
498    GlobalActions mGlobalActions;
499    Handler mHandler;
500    WindowState mLastInputMethodWindow = null;
501    WindowState mLastInputMethodTargetWindow = null;
502
503    // FIXME This state is shared between the input reader and handler thread.
504    // Technically it's broken and buggy but it has been like this for many years
505    // and we have not yet seen any problems.  Someday we'll rewrite this logic
506    // so that only one thread is involved in handling input policy.  Unfortunately
507    // it's on a critical path for power management so we can't just post the work to the
508    // handler thread.  We'll need to resolve this someday by teaching the input dispatcher
509    // to hold wakelocks during dispatch and eliminating the critical path.
510    volatile boolean mPowerKeyHandled;
511    volatile boolean mBackKeyHandled;
512    volatile boolean mBeganFromNonInteractive;
513    volatile int mPowerKeyPressCounter;
514    volatile int mBackKeyPressCounter;
515    volatile boolean mEndCallKeyHandled;
516    volatile boolean mCameraGestureTriggeredDuringGoingToSleep;
517    volatile boolean mGoingToSleep;
518    volatile boolean mRecentsVisible;
519    volatile boolean mPictureInPictureVisible;
520    // Written by vr manager thread, only read in this class.
521    volatile private boolean mPersistentVrModeEnabled;
522    volatile private boolean mDismissImeOnBackKeyPressed;
523
524    // Used to hold the last user key used to wake the device.  This helps us prevent up events
525    // from being passed to the foregrounded app without a corresponding down event
526    volatile int mPendingWakeKey = PENDING_KEY_NULL;
527
528    int mRecentAppsHeldModifiers;
529    boolean mLanguageSwitchKeyPressed;
530
531    int mLidState = LID_ABSENT;
532    int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT;
533    boolean mHaveBuiltInKeyboard;
534
535    boolean mSystemReady;
536    boolean mSystemBooted;
537    boolean mHdmiPlugged;
538    HdmiControl mHdmiControl;
539    IUiModeManager mUiModeManager;
540    int mUiMode;
541    int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
542    int mLidOpenRotation;
543    int mCarDockRotation;
544    int mDeskDockRotation;
545    int mUndockedHdmiRotation;
546    int mDemoHdmiRotation;
547    boolean mDemoHdmiRotationLock;
548    int mDemoRotation;
549    boolean mDemoRotationLock;
550
551    boolean mWakeGestureEnabledSetting;
552    MyWakeGestureListener mWakeGestureListener;
553
554    // Default display does not rotate, apps that require non-default orientation will have to
555    // have the orientation emulated.
556    private boolean mForceDefaultOrientation = false;
557
558    int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
559    int mUserRotation = Surface.ROTATION_0;
560    boolean mAccelerometerDefault;
561
562    boolean mSupportAutoRotation;
563    int mAllowAllRotations = -1;
564    boolean mCarDockEnablesAccelerometer;
565    boolean mDeskDockEnablesAccelerometer;
566    int mLidKeyboardAccessibility;
567    int mLidNavigationAccessibility;
568    boolean mLidControlsScreenLock;
569    boolean mLidControlsSleep;
570    int mShortPressOnPowerBehavior;
571    int mLongPressOnPowerBehavior;
572    int mDoublePressOnPowerBehavior;
573    int mTriplePressOnPowerBehavior;
574    int mLongPressOnBackBehavior;
575    int mPanicPressOnBackBehavior;
576    int mShortPressOnSleepBehavior;
577    int mShortPressWindowBehavior;
578    boolean mAwake;
579    boolean mScreenOnEarly;
580    boolean mScreenOnFully;
581    ScreenOnListener mScreenOnListener;
582    boolean mKeyguardDrawComplete;
583    boolean mWindowManagerDrawComplete;
584    boolean mOrientationSensorEnabled = false;
585    int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
586    boolean mHasSoftInput = false;
587    boolean mTranslucentDecorEnabled = true;
588    boolean mUseTvRouting;
589
590    private boolean mHandleVolumeKeysInWM;
591
592    int mPointerLocationMode = 0; // guarded by mLock
593
594    // The last window we were told about in focusChanged.
595    WindowState mFocusedWindow;
596    IApplicationToken mFocusedApp;
597
598    PointerLocationView mPointerLocationView;
599
600    // The current size of the screen; really; extends into the overscan area of
601    // the screen and doesn't account for any system elements like the status bar.
602    int mOverscanScreenLeft, mOverscanScreenTop;
603    int mOverscanScreenWidth, mOverscanScreenHeight;
604    // The current visible size of the screen; really; (ir)regardless of whether the status
605    // bar can be hidden but not extending into the overscan area.
606    int mUnrestrictedScreenLeft, mUnrestrictedScreenTop;
607    int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight;
608    // Like mOverscanScreen*, but allowed to move into the overscan region where appropriate.
609    int mRestrictedOverscanScreenLeft, mRestrictedOverscanScreenTop;
610    int mRestrictedOverscanScreenWidth, mRestrictedOverscanScreenHeight;
611    // The current size of the screen; these may be different than (0,0)-(dw,dh)
612    // if the status bar can't be hidden; in that case it effectively carves out
613    // that area of the display from all other windows.
614    int mRestrictedScreenLeft, mRestrictedScreenTop;
615    int mRestrictedScreenWidth, mRestrictedScreenHeight;
616    // During layout, the current screen borders accounting for any currently
617    // visible system UI elements.
618    int mSystemLeft, mSystemTop, mSystemRight, mSystemBottom;
619    // For applications requesting stable content insets, these are them.
620    int mStableLeft, mStableTop, mStableRight, mStableBottom;
621    // For applications requesting stable content insets but have also set the
622    // fullscreen window flag, these are the stable dimensions without the status bar.
623    int mStableFullscreenLeft, mStableFullscreenTop;
624    int mStableFullscreenRight, mStableFullscreenBottom;
625    // During layout, the current screen borders with all outer decoration
626    // (status bar, input method dock) accounted for.
627    int mCurLeft, mCurTop, mCurRight, mCurBottom;
628    // During layout, the frame in which content should be displayed
629    // to the user, accounting for all screen decoration except for any
630    // space they deem as available for other content.  This is usually
631    // the same as mCur*, but may be larger if the screen decor has supplied
632    // content insets.
633    int mContentLeft, mContentTop, mContentRight, mContentBottom;
634    // During layout, the frame in which voice content should be displayed
635    // to the user, accounting for all screen decoration except for any
636    // space they deem as available for other content.
637    int mVoiceContentLeft, mVoiceContentTop, mVoiceContentRight, mVoiceContentBottom;
638    // During layout, the current screen borders along which input method
639    // windows are placed.
640    int mDockLeft, mDockTop, mDockRight, mDockBottom;
641    // During layout, the layer at which the doc window is placed.
642    int mDockLayer;
643    // During layout, this is the layer of the status bar.
644    int mStatusBarLayer;
645    int mLastSystemUiFlags;
646    // Bits that we are in the process of clearing, so we want to prevent
647    // them from being set by applications until everything has been updated
648    // to have them clear.
649    int mResettingSystemUiFlags = 0;
650    // Bits that we are currently always keeping cleared.
651    int mForceClearedSystemUiFlags = 0;
652    int mLastFullscreenStackSysUiFlags;
653    int mLastDockedStackSysUiFlags;
654    final Rect mNonDockedStackBounds = new Rect();
655    final Rect mDockedStackBounds = new Rect();
656    final Rect mLastNonDockedStackBounds = new Rect();
657    final Rect mLastDockedStackBounds = new Rect();
658
659    // What we last reported to system UI about whether the compatibility
660    // menu needs to be displayed.
661    boolean mLastFocusNeedsMenu = false;
662    // If nonzero, a panic gesture was performed at that time in uptime millis and is still pending.
663    private long mPendingPanicGestureUptime;
664
665    InputConsumer mInputConsumer = null;
666
667    static final Rect mTmpParentFrame = new Rect();
668    static final Rect mTmpDisplayFrame = new Rect();
669    static final Rect mTmpOverscanFrame = new Rect();
670    static final Rect mTmpContentFrame = new Rect();
671    static final Rect mTmpVisibleFrame = new Rect();
672    static final Rect mTmpDecorFrame = new Rect();
673    static final Rect mTmpStableFrame = new Rect();
674    static final Rect mTmpNavigationFrame = new Rect();
675    static final Rect mTmpOutsetFrame = new Rect();
676    private static final Rect mTmpRect = new Rect();
677
678    WindowState mTopFullscreenOpaqueWindowState;
679    WindowState mTopFullscreenOpaqueOrDimmingWindowState;
680    WindowState mTopDockedOpaqueWindowState;
681    WindowState mTopDockedOpaqueOrDimmingWindowState;
682    boolean mTopIsFullscreen;
683    boolean mForceStatusBar;
684    boolean mForceStatusBarFromKeyguard;
685    private boolean mForceStatusBarTransparent;
686    int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
687    boolean mForcingShowNavBar;
688    int mForcingShowNavBarLayer;
689
690    private boolean mPendingKeyguardOccluded;
691    private boolean mKeyguardOccludedChanged;
692
693    boolean mShowingDream;
694    private boolean mLastShowingDream;
695    boolean mDreamingLockscreen;
696    boolean mDreamingSleepTokenNeeded;
697    SleepToken mDreamingSleepToken;
698    SleepToken mScreenOffSleepToken;
699    volatile boolean mKeyguardOccluded;
700    boolean mHomePressed;
701    boolean mHomeConsumed;
702    boolean mHomeDoubleTapPending;
703    Intent mHomeIntent;
704    Intent mCarDockIntent;
705    Intent mDeskDockIntent;
706    Intent mVrHeadsetHomeIntent;
707    boolean mSearchKeyShortcutPending;
708    boolean mConsumeSearchKeyUp;
709    boolean mAssistKeyLongPressed;
710    boolean mPendingMetaAction;
711    boolean mPendingCapsLockToggle;
712    int mMetaState;
713    int mInitialMetaState;
714    boolean mForceShowSystemBars;
715
716    // support for activating the lock screen while the screen is on
717    boolean mAllowLockscreenWhenOn;
718    int mLockScreenTimeout;
719    boolean mLockScreenTimerActive;
720
721    // Behavior of ENDCALL Button.  (See Settings.System.END_BUTTON_BEHAVIOR.)
722    int mEndcallBehavior;
723
724    // Behavior of POWER button while in-call and screen on.
725    // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
726    int mIncallPowerBehavior;
727
728    // Behavior of Back button while in-call and screen on
729    int mIncallBackBehavior;
730
731    Display mDisplay;
732
733    private int mDisplayRotation;
734
735    int mLandscapeRotation = 0;  // default landscape rotation
736    int mSeascapeRotation = 0;   // "other" landscape rotation, 180 degrees from mLandscapeRotation
737    int mPortraitRotation = 0;   // default portrait rotation
738    int mUpsideDownRotation = 0; // "other" portrait rotation
739
740    int mOverscanLeft = 0;
741    int mOverscanTop = 0;
742    int mOverscanRight = 0;
743    int mOverscanBottom = 0;
744
745    // What we do when the user long presses on home
746    private int mLongPressOnHomeBehavior;
747
748    // What we do when the user double-taps on home
749    private int mDoubleTapOnHomeBehavior;
750
751    // Allowed theater mode wake actions
752    private boolean mAllowTheaterModeWakeFromKey;
753    private boolean mAllowTheaterModeWakeFromPowerKey;
754    private boolean mAllowTheaterModeWakeFromMotion;
755    private boolean mAllowTheaterModeWakeFromMotionWhenNotDreaming;
756    private boolean mAllowTheaterModeWakeFromCameraLens;
757    private boolean mAllowTheaterModeWakeFromLidSwitch;
758    private boolean mAllowTheaterModeWakeFromWakeGesture;
759
760    // Whether to support long press from power button in non-interactive mode
761    private boolean mSupportLongPressPowerWhenNonInteractive;
762
763    // Whether to go to sleep entering theater mode from power button
764    private boolean mGoToSleepOnButtonPressTheaterMode;
765
766    // Screenshot trigger states
767    // Time to volume and power must be pressed within this interval of each other.
768    private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
769    // Increase the chord delay when taking a screenshot from the keyguard
770    private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f;
771    private boolean mScreenshotChordEnabled;
772    private boolean mScreenshotChordVolumeDownKeyTriggered;
773    private long mScreenshotChordVolumeDownKeyTime;
774    private boolean mScreenshotChordVolumeDownKeyConsumed;
775    private boolean mA11yShortcutChordVolumeUpKeyTriggered;
776    private long mA11yShortcutChordVolumeUpKeyTime;
777    private boolean mA11yShortcutChordVolumeUpKeyConsumed;
778
779    private boolean mScreenshotChordPowerKeyTriggered;
780    private long mScreenshotChordPowerKeyTime;
781
782    private static final long BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS = 1000;
783
784    private boolean mBugreportTvKey1Pressed;
785    private boolean mBugreportTvKey2Pressed;
786    private boolean mBugreportTvScheduled;
787
788    private boolean mAccessibilityTvKey1Pressed;
789    private boolean mAccessibilityTvKey2Pressed;
790    private boolean mAccessibilityTvScheduled;
791
792    /* The number of steps between min and max brightness */
793    private static final int BRIGHTNESS_STEPS = 10;
794
795    SettingsObserver mSettingsObserver;
796    ShortcutManager mShortcutManager;
797    PowerManager.WakeLock mBroadcastWakeLock;
798    PowerManager.WakeLock mPowerKeyWakeLock;
799    boolean mHavePendingMediaKeyRepeatWithWakeLock;
800
801    private int mCurrentUserId;
802
803    // Maps global key codes to the components that will handle them.
804    private GlobalKeyManager mGlobalKeyManager;
805
806    // Fallback actions by key code.
807    private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions =
808            new SparseArray<KeyCharacterMap.FallbackAction>();
809
810    private final LogDecelerateInterpolator mLogDecelerateInterpolator
811            = new LogDecelerateInterpolator(100, 0);
812
813    private final MutableBoolean mTmpBoolean = new MutableBoolean(false);
814
815    private static final int MSG_ENABLE_POINTER_LOCATION = 1;
816    private static final int MSG_DISABLE_POINTER_LOCATION = 2;
817    private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
818    private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
819    private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
820    private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6;
821    private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7;
822    private static final int MSG_DISPATCH_SHOW_RECENTS = 9;
823    private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10;
824    private static final int MSG_HIDE_BOOT_MESSAGE = 11;
825    private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12;
826    private static final int MSG_POWER_DELAYED_PRESS = 13;
827    private static final int MSG_POWER_LONG_PRESS = 14;
828    private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 15;
829    private static final int MSG_REQUEST_TRANSIENT_BARS = 16;
830    private static final int MSG_SHOW_PICTURE_IN_PICTURE_MENU = 17;
831    private static final int MSG_BACK_LONG_PRESS = 18;
832    private static final int MSG_DISPOSE_INPUT_CONSUMER = 19;
833    private static final int MSG_BACK_DELAYED_PRESS = 20;
834    private static final int MSG_ACCESSIBILITY_SHORTCUT = 21;
835    private static final int MSG_BUGREPORT_TV = 22;
836    private static final int MSG_ACCESSIBILITY_TV = 23;
837    private static final int MSG_DISPATCH_BACK_KEY_TO_AUTOFILL = 24;
838
839    private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
840    private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
841
842    private class PolicyHandler extends Handler {
843        @Override
844        public void handleMessage(Message msg) {
845            switch (msg.what) {
846                case MSG_ENABLE_POINTER_LOCATION:
847                    enablePointerLocation();
848                    break;
849                case MSG_DISABLE_POINTER_LOCATION:
850                    disablePointerLocation();
851                    break;
852                case MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK:
853                    dispatchMediaKeyWithWakeLock((KeyEvent)msg.obj);
854                    break;
855                case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK:
856                    dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj);
857                    break;
858                case MSG_DISPATCH_SHOW_RECENTS:
859                    showRecentApps(false, msg.arg1 != 0);
860                    break;
861                case MSG_DISPATCH_SHOW_GLOBAL_ACTIONS:
862                    showGlobalActionsInternal();
863                    break;
864                case MSG_KEYGUARD_DRAWN_COMPLETE:
865                    if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete");
866                    finishKeyguardDrawn();
867                    break;
868                case MSG_KEYGUARD_DRAWN_TIMEOUT:
869                    Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete");
870                    finishKeyguardDrawn();
871                    break;
872                case MSG_WINDOW_MANAGER_DRAWN_COMPLETE:
873                    if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete");
874                    finishWindowsDrawn();
875                    break;
876                case MSG_HIDE_BOOT_MESSAGE:
877                    handleHideBootMessage();
878                    break;
879                case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK:
880                    launchVoiceAssistWithWakeLock(msg.arg1 != 0);
881                    break;
882                case MSG_POWER_DELAYED_PRESS:
883                    powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2);
884                    finishPowerKeyPress();
885                    break;
886                case MSG_POWER_LONG_PRESS:
887                    powerLongPress();
888                    break;
889                case MSG_UPDATE_DREAMING_SLEEP_TOKEN:
890                    updateDreamingSleepToken(msg.arg1 != 0);
891                    break;
892                case MSG_REQUEST_TRANSIENT_BARS:
893                    WindowState targetBar = (msg.arg1 == MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS) ?
894                            mStatusBar : mNavigationBar;
895                    if (targetBar != null) {
896                        requestTransientBars(targetBar);
897                    }
898                    break;
899                case MSG_SHOW_PICTURE_IN_PICTURE_MENU:
900                    showPictureInPictureMenuInternal();
901                    break;
902                case MSG_BACK_LONG_PRESS:
903                    backLongPress();
904                    finishBackKeyPress();
905                    break;
906                case MSG_DISPOSE_INPUT_CONSUMER:
907                    disposeInputConsumer((InputConsumer) msg.obj);
908                    break;
909                case MSG_BACK_DELAYED_PRESS:
910                    backMultiPressAction((Long) msg.obj, msg.arg1);
911                    finishBackKeyPress();
912                    break;
913                case MSG_ACCESSIBILITY_SHORTCUT:
914                    accessibilityShortcutActivated();
915                    break;
916                case MSG_BUGREPORT_TV:
917                    takeBugreport();
918                    break;
919                case MSG_ACCESSIBILITY_TV:
920                    if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(false)) {
921                        accessibilityShortcutActivated();
922                    }
923                    break;
924                case MSG_DISPATCH_BACK_KEY_TO_AUTOFILL:
925                    mAutofillManagerInternal.onBackKeyPressed();
926                    break;
927            }
928        }
929    }
930
931    private UEventObserver mHDMIObserver = new UEventObserver() {
932        @Override
933        public void onUEvent(UEventObserver.UEvent event) {
934            setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
935        }
936    };
937
938    class SettingsObserver extends ContentObserver {
939        SettingsObserver(Handler handler) {
940            super(handler);
941        }
942
943        void observe() {
944            // Observe all users' changes
945            ContentResolver resolver = mContext.getContentResolver();
946            resolver.registerContentObserver(Settings.System.getUriFor(
947                    Settings.System.END_BUTTON_BEHAVIOR), false, this,
948                    UserHandle.USER_ALL);
949            resolver.registerContentObserver(Settings.Secure.getUriFor(
950                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this,
951                    UserHandle.USER_ALL);
952            resolver.registerContentObserver(Settings.Secure.getUriFor(
953                    Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR), false, this,
954                    UserHandle.USER_ALL);
955            resolver.registerContentObserver(Settings.Secure.getUriFor(
956                    Settings.Secure.WAKE_GESTURE_ENABLED), false, this,
957                    UserHandle.USER_ALL);
958            resolver.registerContentObserver(Settings.System.getUriFor(
959                    Settings.System.ACCELEROMETER_ROTATION), false, this,
960                    UserHandle.USER_ALL);
961            resolver.registerContentObserver(Settings.System.getUriFor(
962                    Settings.System.USER_ROTATION), false, this,
963                    UserHandle.USER_ALL);
964            resolver.registerContentObserver(Settings.System.getUriFor(
965                    Settings.System.SCREEN_OFF_TIMEOUT), false, this,
966                    UserHandle.USER_ALL);
967            resolver.registerContentObserver(Settings.System.getUriFor(
968                    Settings.System.POINTER_LOCATION), false, this,
969                    UserHandle.USER_ALL);
970            resolver.registerContentObserver(Settings.Secure.getUriFor(
971                    Settings.Secure.DEFAULT_INPUT_METHOD), false, this,
972                    UserHandle.USER_ALL);
973            resolver.registerContentObserver(Settings.Secure.getUriFor(
974                    Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this,
975                    UserHandle.USER_ALL);
976            resolver.registerContentObserver(Settings.Global.getUriFor(
977                    Settings.Global.POLICY_CONTROL), false, this,
978                    UserHandle.USER_ALL);
979            updateSettings();
980        }
981
982        @Override public void onChange(boolean selfChange) {
983            updateSettings();
984            updateRotation(false);
985        }
986    }
987
988    class MyWakeGestureListener extends WakeGestureListener {
989        MyWakeGestureListener(Context context, Handler handler) {
990            super(context, handler);
991        }
992
993        @Override
994        public void onWakeUp() {
995            synchronized (mLock) {
996                if (shouldEnableWakeGestureLp()) {
997                    performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
998                    wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture,
999                            "android.policy:GESTURE");
1000                }
1001            }
1002        }
1003    }
1004
1005    class MyOrientationListener extends WindowOrientationListener {
1006        private final Runnable mUpdateRotationRunnable = new Runnable() {
1007            @Override
1008            public void run() {
1009                // send interaction hint to improve redraw performance
1010                mPowerManagerInternal.powerHint(PowerHint.INTERACTION, 0);
1011                updateRotation(false);
1012            }
1013        };
1014
1015        MyOrientationListener(Context context, Handler handler) {
1016            super(context, handler);
1017        }
1018
1019        @Override
1020        public void onProposedRotationChanged(int rotation) {
1021            if (localLOGV) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
1022            mHandler.post(mUpdateRotationRunnable);
1023        }
1024    }
1025    MyOrientationListener mOrientationListener;
1026
1027    final IPersistentVrStateCallbacks mPersistentVrModeListener =
1028            new IPersistentVrStateCallbacks.Stub() {
1029        @Override
1030        public void onPersistentVrStateChanged(boolean enabled) {
1031            mPersistentVrModeEnabled = enabled;
1032        }
1033    };
1034
1035    private final StatusBarController mStatusBarController = new StatusBarController();
1036
1037    private final BarController mNavigationBarController = new BarController("NavigationBar",
1038            View.NAVIGATION_BAR_TRANSIENT,
1039            View.NAVIGATION_BAR_UNHIDE,
1040            View.NAVIGATION_BAR_TRANSLUCENT,
1041            StatusBarManager.WINDOW_NAVIGATION_BAR,
1042            WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
1043            View.NAVIGATION_BAR_TRANSPARENT);
1044
1045    private final BarController.OnBarVisibilityChangedListener mNavBarVisibilityListener =
1046            new BarController.OnBarVisibilityChangedListener() {
1047        @Override
1048        public void onBarVisibilityChanged(boolean visible) {
1049            mAccessibilityManager.notifyAccessibilityButtonVisibilityChanged(visible);
1050        }
1051    };
1052
1053    private ImmersiveModeConfirmation mImmersiveModeConfirmation;
1054
1055    private SystemGesturesPointerEventListener mSystemGestures;
1056
1057    IStatusBarService getStatusBarService() {
1058        synchronized (mServiceAquireLock) {
1059            if (mStatusBarService == null) {
1060                mStatusBarService = IStatusBarService.Stub.asInterface(
1061                        ServiceManager.getService("statusbar"));
1062            }
1063            return mStatusBarService;
1064        }
1065    }
1066
1067    StatusBarManagerInternal getStatusBarManagerInternal() {
1068        synchronized (mServiceAquireLock) {
1069            if (mStatusBarManagerInternal == null) {
1070                mStatusBarManagerInternal =
1071                        LocalServices.getService(StatusBarManagerInternal.class);
1072            }
1073            return mStatusBarManagerInternal;
1074        }
1075    }
1076
1077    /*
1078     * We always let the sensor be switched on by default except when
1079     * the user has explicitly disabled sensor based rotation or when the
1080     * screen is switched off.
1081     */
1082    boolean needSensorRunningLp() {
1083        if (mSupportAutoRotation) {
1084            if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
1085                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
1086                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
1087                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
1088                // If the application has explicitly requested to follow the
1089                // orientation, then we need to turn the sensor on.
1090                return true;
1091            }
1092        }
1093        if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
1094                (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
1095                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
1096                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
1097            // enable accelerometer if we are docked in a dock that enables accelerometer
1098            // orientation management,
1099            return true;
1100        }
1101        if (mUserRotationMode == USER_ROTATION_LOCKED) {
1102            // If the setting for using the sensor by default is enabled, then
1103            // we will always leave it on.  Note that the user could go to
1104            // a window that forces an orientation that does not use the
1105            // sensor and in theory we could turn it off... however, when next
1106            // turning it on we won't have a good value for the current
1107            // orientation for a little bit, which can cause orientation
1108            // changes to lag, so we'd like to keep it always on.  (It will
1109            // still be turned off when the screen is off.)
1110            return false;
1111        }
1112        return mSupportAutoRotation;
1113    }
1114
1115    /*
1116     * Various use cases for invoking this function
1117     * screen turning off, should always disable listeners if already enabled
1118     * screen turned on and current app has sensor based orientation, enable listeners
1119     * if not already enabled
1120     * screen turned on and current app does not have sensor orientation, disable listeners if
1121     * already enabled
1122     * screen turning on and current app has sensor based orientation, enable listeners if needed
1123     * screen turning on and current app has nosensor based orientation, do nothing
1124     */
1125    void updateOrientationListenerLp() {
1126        if (!mOrientationListener.canDetectOrientation()) {
1127            // If sensor is turned off or nonexistent for some reason
1128            return;
1129        }
1130        // Could have been invoked due to screen turning on or off or
1131        // change of the currently visible window's orientation.
1132        if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly
1133                + ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation
1134                + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled
1135                + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
1136                + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
1137        final boolean keyguardGoingAway = mWindowManagerInternal.isKeyguardGoingAway();
1138
1139        boolean disable = true;
1140        // Note: We postpone the rotating of the screen until the keyguard as well as the
1141        // window manager have reported a draw complete or the keyguard is going away in dismiss
1142        // mode.
1143        if (mScreenOnEarly && mAwake && ((mKeyguardDrawComplete && mWindowManagerDrawComplete)
1144                || keyguardGoingAway)) {
1145            if (needSensorRunningLp()) {
1146                disable = false;
1147                //enable listener if not already enabled
1148                if (!mOrientationSensorEnabled) {
1149                    // Don't clear the current sensor orientation if the keyguard is going away in
1150                    // dismiss mode. This allows window manager to use the last sensor reading to
1151                    // determine the orientation vs. falling back to the last known orientation if
1152                    // the sensor reading was cleared which can cause it to relaunch the app that
1153                    // will show in the wrong orientation first before correcting leading to app
1154                    // launch delays.
1155                    mOrientationListener.enable(!keyguardGoingAway /* clearCurrentRotation */);
1156                    if(localLOGV) Slog.v(TAG, "Enabling listeners");
1157                    mOrientationSensorEnabled = true;
1158                }
1159            }
1160        }
1161        //check if sensors need to be disabled
1162        if (disable && mOrientationSensorEnabled) {
1163            mOrientationListener.disable();
1164            if(localLOGV) Slog.v(TAG, "Disabling listeners");
1165            mOrientationSensorEnabled = false;
1166        }
1167    }
1168
1169    private void interceptBackKeyDown() {
1170        MetricsLogger.count(mContext, "key_back_down", 1);
1171        // Reset back key state for long press
1172        mBackKeyHandled = false;
1173
1174        // Cancel multi-press detection timeout.
1175        if (hasPanicPressOnBackBehavior()) {
1176            if (mBackKeyPressCounter != 0
1177                    && mBackKeyPressCounter < PANIC_PRESS_BACK_COUNT) {
1178                mHandler.removeMessages(MSG_BACK_DELAYED_PRESS);
1179            }
1180        }
1181
1182        if (hasLongPressOnBackBehavior()) {
1183            Message msg = mHandler.obtainMessage(MSG_BACK_LONG_PRESS);
1184            msg.setAsynchronous(true);
1185            mHandler.sendMessageDelayed(msg,
1186                    ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1187        }
1188    }
1189
1190    // returns true if the key was handled and should not be passed to the user
1191    private boolean interceptBackKeyUp(KeyEvent event) {
1192        // Cache handled state
1193        boolean handled = mBackKeyHandled;
1194
1195        if (hasPanicPressOnBackBehavior()) {
1196            // Check for back key panic press
1197            ++mBackKeyPressCounter;
1198
1199            final long eventTime = event.getDownTime();
1200
1201            if (mBackKeyPressCounter <= PANIC_PRESS_BACK_COUNT) {
1202                // This could be a multi-press.  Wait a little bit longer to confirm.
1203                Message msg = mHandler.obtainMessage(MSG_BACK_DELAYED_PRESS,
1204                    mBackKeyPressCounter, 0, eventTime);
1205                msg.setAsynchronous(true);
1206                mHandler.sendMessageDelayed(msg, ViewConfiguration.getMultiPressTimeout());
1207            }
1208        }
1209
1210        // Reset back long press state
1211        cancelPendingBackKeyAction();
1212
1213        if (mHasFeatureWatch) {
1214            TelecomManager telecomManager = getTelecommService();
1215
1216            if (telecomManager != null) {
1217                if (telecomManager.isRinging()) {
1218                    // Pressing back while there's a ringing incoming
1219                    // call should silence the ringer.
1220                    telecomManager.silenceRinger();
1221
1222                    // It should not prevent navigating away
1223                    return false;
1224                } else if (
1225                    (mIncallBackBehavior & Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_HANGUP) != 0
1226                        && telecomManager.isInCall()) {
1227                    // Otherwise, if "Back button ends call" is enabled,
1228                    // the Back button will hang up any current active call.
1229                    return telecomManager.endCall();
1230                }
1231            }
1232        }
1233
1234        if (mAutofillManagerInternal != null && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
1235            mHandler.sendMessage(mHandler.obtainMessage(MSG_DISPATCH_BACK_KEY_TO_AUTOFILL));
1236        }
1237
1238        return handled;
1239    }
1240
1241    private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
1242        // Hold a wake lock until the power key is released.
1243        if (!mPowerKeyWakeLock.isHeld()) {
1244            mPowerKeyWakeLock.acquire();
1245        }
1246
1247        // Cancel multi-press detection timeout.
1248        if (mPowerKeyPressCounter != 0) {
1249            mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);
1250        }
1251
1252        // Detect user pressing the power button in panic when an application has
1253        // taken over the whole screen.
1254        boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
1255                SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags),
1256                isNavBarEmpty(mLastSystemUiFlags));
1257        if (panic) {
1258            mHandler.post(mHiddenNavPanic);
1259        }
1260
1261        // Latch power key state to detect screenshot chord.
1262        if (interactive && !mScreenshotChordPowerKeyTriggered
1263                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
1264            mScreenshotChordPowerKeyTriggered = true;
1265            mScreenshotChordPowerKeyTime = event.getDownTime();
1266            interceptScreenshotChord();
1267        }
1268
1269        // Stop ringing or end call if configured to do so when power is pressed.
1270        TelecomManager telecomManager = getTelecommService();
1271        boolean hungUp = false;
1272        if (telecomManager != null) {
1273            if (telecomManager.isRinging()) {
1274                // Pressing Power while there's a ringing incoming
1275                // call should silence the ringer.
1276                telecomManager.silenceRinger();
1277            } else if ((mIncallPowerBehavior
1278                    & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
1279                    && telecomManager.isInCall() && interactive) {
1280                // Otherwise, if "Power button ends call" is enabled,
1281                // the Power button will hang up any current active call.
1282                hungUp = telecomManager.endCall();
1283            }
1284        }
1285
1286        GestureLauncherService gestureService = LocalServices.getService(
1287                GestureLauncherService.class);
1288        boolean gesturedServiceIntercepted = false;
1289        if (gestureService != null) {
1290            gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive,
1291                    mTmpBoolean);
1292            if (mTmpBoolean.value && mGoingToSleep) {
1293                mCameraGestureTriggeredDuringGoingToSleep = true;
1294            }
1295        }
1296
1297        // If the power key has still not yet been handled, then detect short
1298        // press, long press, or multi press and decide what to do.
1299        mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
1300                || mA11yShortcutChordVolumeUpKeyTriggered || gesturedServiceIntercepted;
1301        if (!mPowerKeyHandled) {
1302            if (interactive) {
1303                // When interactive, we're already awake.
1304                // Wait for a long press or for the button to be released to decide what to do.
1305                if (hasLongPressOnPowerBehavior()) {
1306                    Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
1307                    msg.setAsynchronous(true);
1308                    mHandler.sendMessageDelayed(msg,
1309                            ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1310                }
1311            } else {
1312                wakeUpFromPowerKey(event.getDownTime());
1313
1314                if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
1315                    Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
1316                    msg.setAsynchronous(true);
1317                    mHandler.sendMessageDelayed(msg,
1318                            ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1319                    mBeganFromNonInteractive = true;
1320                } else {
1321                    final int maxCount = getMaxMultiPressPowerCount();
1322
1323                    if (maxCount <= 1) {
1324                        mPowerKeyHandled = true;
1325                    } else {
1326                        mBeganFromNonInteractive = true;
1327                    }
1328                }
1329            }
1330        }
1331    }
1332
1333    private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
1334        final boolean handled = canceled || mPowerKeyHandled;
1335        mScreenshotChordPowerKeyTriggered = false;
1336        cancelPendingScreenshotChordAction();
1337        cancelPendingPowerKeyAction();
1338
1339        if (!handled) {
1340            // Figure out how to handle the key now that it has been released.
1341            mPowerKeyPressCounter += 1;
1342
1343            final int maxCount = getMaxMultiPressPowerCount();
1344            final long eventTime = event.getDownTime();
1345            if (mPowerKeyPressCounter < maxCount) {
1346                // This could be a multi-press.  Wait a little bit longer to confirm.
1347                // Continue holding the wake lock.
1348                Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
1349                        interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
1350                msg.setAsynchronous(true);
1351                mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
1352                return;
1353            }
1354
1355            // No other actions.  Handle it immediately.
1356            powerPress(eventTime, interactive, mPowerKeyPressCounter);
1357        }
1358
1359        // Done.  Reset our state.
1360        finishPowerKeyPress();
1361    }
1362
1363    private void finishPowerKeyPress() {
1364        mBeganFromNonInteractive = false;
1365        mPowerKeyPressCounter = 0;
1366        if (mPowerKeyWakeLock.isHeld()) {
1367            mPowerKeyWakeLock.release();
1368        }
1369    }
1370
1371    private void finishBackKeyPress() {
1372        mBackKeyPressCounter = 0;
1373    }
1374
1375    private void cancelPendingPowerKeyAction() {
1376        if (!mPowerKeyHandled) {
1377            mPowerKeyHandled = true;
1378            mHandler.removeMessages(MSG_POWER_LONG_PRESS);
1379        }
1380    }
1381
1382    private void cancelPendingBackKeyAction() {
1383        if (!mBackKeyHandled) {
1384            mBackKeyHandled = true;
1385            mHandler.removeMessages(MSG_BACK_LONG_PRESS);
1386        }
1387    }
1388
1389    private void backMultiPressAction(long eventTime, int count) {
1390        if (count >= PANIC_PRESS_BACK_COUNT) {
1391            switch (mPanicPressOnBackBehavior) {
1392                case PANIC_PRESS_BACK_NOTHING:
1393                    break;
1394                case PANIC_PRESS_BACK_HOME:
1395                    launchHomeFromHotKey();
1396                    break;
1397            }
1398        }
1399    }
1400
1401    private void powerPress(long eventTime, boolean interactive, int count) {
1402        if (mScreenOnEarly && !mScreenOnFully) {
1403            Slog.i(TAG, "Suppressed redundant power key press while "
1404                    + "already in the process of turning the screen on.");
1405            return;
1406        }
1407
1408        if (count == 2) {
1409            powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
1410        } else if (count == 3) {
1411            powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
1412        } else if (interactive && !mBeganFromNonInteractive) {
1413            switch (mShortPressOnPowerBehavior) {
1414                case SHORT_PRESS_POWER_NOTHING:
1415                    break;
1416                case SHORT_PRESS_POWER_GO_TO_SLEEP:
1417                    mPowerManager.goToSleep(eventTime,
1418                            PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
1419                    break;
1420                case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
1421                    mPowerManager.goToSleep(eventTime,
1422                            PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
1423                            PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
1424                    break;
1425                case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
1426                    mPowerManager.goToSleep(eventTime,
1427                            PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
1428                            PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
1429                    launchHomeFromHotKey();
1430                    break;
1431                case SHORT_PRESS_POWER_GO_HOME:
1432                    shortPressPowerGoHome();
1433                    break;
1434                case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME: {
1435                    if (mDismissImeOnBackKeyPressed) {
1436                        if (mInputMethodManagerInternal == null) {
1437                            mInputMethodManagerInternal =
1438                                    LocalServices.getService(InputMethodManagerInternal.class);
1439                        }
1440                        if (mInputMethodManagerInternal != null) {
1441                            mInputMethodManagerInternal.hideCurrentInputMethod();
1442                        }
1443                    } else {
1444                        shortPressPowerGoHome();
1445                    }
1446                    break;
1447                }
1448            }
1449        }
1450    }
1451
1452    private void shortPressPowerGoHome() {
1453        launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
1454        if (isKeyguardShowingAndNotOccluded()) {
1455            // Notify keyguard so it can do any special handling for the power button since the
1456            // device will not power off and only launch home.
1457            mKeyguardDelegate.onShortPowerPressedGoHome();
1458        }
1459    }
1460
1461    private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) {
1462        switch (behavior) {
1463            case MULTI_PRESS_POWER_NOTHING:
1464                break;
1465            case MULTI_PRESS_POWER_THEATER_MODE:
1466                if (!isUserSetupComplete()) {
1467                    Slog.i(TAG, "Ignoring toggling theater mode - device not setup.");
1468                    break;
1469                }
1470
1471                if (isTheaterModeEnabled()) {
1472                    Slog.i(TAG, "Toggling theater mode off.");
1473                    Settings.Global.putInt(mContext.getContentResolver(),
1474                            Settings.Global.THEATER_MODE_ON, 0);
1475                    if (!interactive) {
1476                        wakeUpFromPowerKey(eventTime);
1477                    }
1478                } else {
1479                    Slog.i(TAG, "Toggling theater mode on.");
1480                    Settings.Global.putInt(mContext.getContentResolver(),
1481                            Settings.Global.THEATER_MODE_ON, 1);
1482
1483                    if (mGoToSleepOnButtonPressTheaterMode && interactive) {
1484                        mPowerManager.goToSleep(eventTime,
1485                                PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
1486                    }
1487                }
1488                break;
1489            case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
1490                Slog.i(TAG, "Starting brightness boost.");
1491                if (!interactive) {
1492                    wakeUpFromPowerKey(eventTime);
1493                }
1494                mPowerManager.boostScreenBrightness(eventTime);
1495                break;
1496        }
1497    }
1498
1499    private int getMaxMultiPressPowerCount() {
1500        if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
1501            return 3;
1502        }
1503        if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
1504            return 2;
1505        }
1506        return 1;
1507    }
1508
1509    private void powerLongPress() {
1510        final int behavior = getResolvedLongPressOnPowerBehavior();
1511        switch (behavior) {
1512        case LONG_PRESS_POWER_NOTHING:
1513            break;
1514        case LONG_PRESS_POWER_GLOBAL_ACTIONS:
1515            mPowerKeyHandled = true;
1516            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1517            showGlobalActionsInternal();
1518            break;
1519        case LONG_PRESS_POWER_SHUT_OFF:
1520        case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
1521            mPowerKeyHandled = true;
1522            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1523            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
1524            mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
1525            break;
1526        }
1527    }
1528
1529    private void backLongPress() {
1530        mBackKeyHandled = true;
1531
1532        switch (mLongPressOnBackBehavior) {
1533            case LONG_PRESS_BACK_NOTHING:
1534                break;
1535            case LONG_PRESS_BACK_GO_TO_VOICE_ASSIST:
1536                final boolean keyguardActive = mKeyguardDelegate == null
1537                        ? false
1538                        : mKeyguardDelegate.isShowing();
1539                if (!keyguardActive) {
1540                    Intent intent = new Intent(Intent.ACTION_VOICE_ASSIST);
1541                    startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
1542                }
1543                break;
1544        }
1545    }
1546
1547    private void accessibilityShortcutActivated() {
1548        mAccessibilityShortcutController.performAccessibilityShortcut();
1549    }
1550
1551    private void disposeInputConsumer(InputConsumer inputConsumer) {
1552        if (inputConsumer != null) {
1553            inputConsumer.dismiss();
1554        }
1555    }
1556
1557    private void sleepPress(long eventTime) {
1558        if (mShortPressOnSleepBehavior == SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME) {
1559            launchHomeFromHotKey(false /* awakenDreams */, true /*respectKeyguard*/);
1560        }
1561    }
1562
1563    private void sleepRelease(long eventTime) {
1564        switch (mShortPressOnSleepBehavior) {
1565            case SHORT_PRESS_SLEEP_GO_TO_SLEEP:
1566            case SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME:
1567                Slog.i(TAG, "sleepRelease() calling goToSleep(GO_TO_SLEEP_REASON_SLEEP_BUTTON)");
1568                mPowerManager.goToSleep(eventTime,
1569                       PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON, 0);
1570                break;
1571        }
1572    }
1573
1574    private int getResolvedLongPressOnPowerBehavior() {
1575        if (FactoryTest.isLongPressOnPowerOffEnabled()) {
1576            return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
1577        }
1578        return mLongPressOnPowerBehavior;
1579    }
1580
1581    private boolean hasLongPressOnPowerBehavior() {
1582        return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;
1583    }
1584
1585    private boolean hasLongPressOnBackBehavior() {
1586        return mLongPressOnBackBehavior != LONG_PRESS_BACK_NOTHING;
1587    }
1588
1589    private boolean hasPanicPressOnBackBehavior() {
1590        return mPanicPressOnBackBehavior != PANIC_PRESS_BACK_NOTHING;
1591    }
1592
1593    private void interceptScreenshotChord() {
1594        if (mScreenshotChordEnabled
1595                && mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered
1596                && !mA11yShortcutChordVolumeUpKeyTriggered) {
1597            final long now = SystemClock.uptimeMillis();
1598            if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
1599                    && now <= mScreenshotChordPowerKeyTime
1600                            + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
1601                mScreenshotChordVolumeDownKeyConsumed = true;
1602                cancelPendingPowerKeyAction();
1603                mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
1604                mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
1605            }
1606        }
1607    }
1608
1609    private void interceptAccessibilityShortcutChord() {
1610        if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(isKeyguardLocked())
1611                && mScreenshotChordVolumeDownKeyTriggered && mA11yShortcutChordVolumeUpKeyTriggered
1612                && !mScreenshotChordPowerKeyTriggered) {
1613            final long now = SystemClock.uptimeMillis();
1614            if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
1615                    && now <= mA11yShortcutChordVolumeUpKeyTime
1616                    + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
1617                mScreenshotChordVolumeDownKeyConsumed = true;
1618                mA11yShortcutChordVolumeUpKeyConsumed = true;
1619                mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_ACCESSIBILITY_SHORTCUT),
1620                        ViewConfiguration.get(mContext).getAccessibilityShortcutKeyTimeout());
1621            }
1622        }
1623    }
1624
1625    private long getScreenshotChordLongPressDelay() {
1626        if (mKeyguardDelegate.isShowing()) {
1627            // Double the time it takes to take a screenshot from the keyguard
1628            return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER *
1629                    ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
1630        }
1631        return ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout();
1632    }
1633
1634    private void cancelPendingScreenshotChordAction() {
1635        mHandler.removeCallbacks(mScreenshotRunnable);
1636    }
1637
1638    private void cancelPendingAccessibilityShortcutAction() {
1639        mHandler.removeMessages(MSG_ACCESSIBILITY_SHORTCUT);
1640    }
1641
1642    private final Runnable mEndCallLongPress = new Runnable() {
1643        @Override
1644        public void run() {
1645            mEndCallKeyHandled = true;
1646            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1647            showGlobalActionsInternal();
1648        }
1649    };
1650
1651    private class ScreenshotRunnable implements Runnable {
1652        private int mScreenshotType = TAKE_SCREENSHOT_FULLSCREEN;
1653
1654        public void setScreenshotType(int screenshotType) {
1655            mScreenshotType = screenshotType;
1656        }
1657
1658        @Override
1659        public void run() {
1660            takeScreenshot(mScreenshotType);
1661        }
1662    }
1663
1664    private final ScreenshotRunnable mScreenshotRunnable = new ScreenshotRunnable();
1665
1666    @Override
1667    public void showGlobalActions() {
1668        mHandler.removeMessages(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
1669        mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);
1670    }
1671
1672    void showGlobalActionsInternal() {
1673        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
1674        if (mGlobalActions == null) {
1675            mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
1676        }
1677        final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();
1678        mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
1679        if (keyguardShowing) {
1680            // since it took two seconds of long press to bring this up,
1681            // poke the wake lock so they have some time to see the dialog.
1682            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
1683        }
1684    }
1685
1686    boolean isDeviceProvisioned() {
1687        return Settings.Global.getInt(
1688                mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
1689    }
1690
1691    boolean isUserSetupComplete() {
1692        boolean isSetupComplete = Settings.Secure.getIntForUser(mContext.getContentResolver(),
1693                Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
1694        if (mHasFeatureLeanback) {
1695            isSetupComplete &= isTvUserSetupComplete();
1696        }
1697        return isSetupComplete;
1698    }
1699
1700    private boolean isTvUserSetupComplete() {
1701        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
1702                Settings.Secure.TV_USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
1703    }
1704
1705    private void handleShortPressOnHome() {
1706        // Turn on the connected TV and switch HDMI input if we're a HDMI playback device.
1707        final HdmiControl hdmiControl = getHdmiControl();
1708        if (hdmiControl != null) {
1709            hdmiControl.turnOnTv();
1710        }
1711
1712        // If there's a dream running then use home to escape the dream
1713        // but don't actually go home.
1714        if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) {
1715            mDreamManagerInternal.stopDream(false /*immediate*/);
1716            return;
1717        }
1718
1719        // Go home!
1720        launchHomeFromHotKey();
1721    }
1722
1723    /**
1724     * Creates an accessor to HDMI control service that performs the operation of
1725     * turning on TV (optional) and switching input to us. If HDMI control service
1726     * is not available or we're not a HDMI playback device, the operation is no-op.
1727     * @return {@link HdmiControl} instance if available, null otherwise.
1728     */
1729    private HdmiControl getHdmiControl() {
1730        if (null == mHdmiControl) {
1731            if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
1732                return null;
1733            }
1734            HdmiControlManager manager = (HdmiControlManager) mContext.getSystemService(
1735                        Context.HDMI_CONTROL_SERVICE);
1736            HdmiPlaybackClient client = null;
1737            if (manager != null) {
1738                client = manager.getPlaybackClient();
1739            }
1740            mHdmiControl = new HdmiControl(client);
1741        }
1742        return mHdmiControl;
1743    }
1744
1745    private static class HdmiControl {
1746        private final HdmiPlaybackClient mClient;
1747
1748        private HdmiControl(HdmiPlaybackClient client) {
1749            mClient = client;
1750        }
1751
1752        public void turnOnTv() {
1753            if (mClient == null) {
1754                return;
1755            }
1756            mClient.oneTouchPlay(new OneTouchPlayCallback() {
1757                @Override
1758                public void onComplete(int result) {
1759                    if (result != HdmiControlManager.RESULT_SUCCESS) {
1760                        Log.w(TAG, "One touch play failed: " + result);
1761                    }
1762                }
1763            });
1764        }
1765    }
1766
1767    private void handleLongPressOnHome(int deviceId) {
1768        if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_NOTHING) {
1769            return;
1770        }
1771        mHomeConsumed = true;
1772        performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
1773        switch (mLongPressOnHomeBehavior) {
1774            case LONG_PRESS_HOME_ALL_APPS:
1775                launchAllAppsAction();
1776                break;
1777            case LONG_PRESS_HOME_ASSIST:
1778                launchAssistAction(null, deviceId);
1779                break;
1780            default:
1781                Log.w(TAG, "Undefined home long press behavior: " + mLongPressOnHomeBehavior);
1782                break;
1783        }
1784    }
1785
1786    private void launchAllAppsAction() {
1787        Intent intent = new Intent(Intent.ACTION_ALL_APPS);
1788        startActivityAsUser(intent, UserHandle.CURRENT);
1789    }
1790
1791    private void handleDoubleTapOnHome() {
1792        if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
1793            mHomeConsumed = true;
1794            toggleRecentApps();
1795        }
1796    }
1797
1798    private void showPictureInPictureMenu(KeyEvent event) {
1799        if (DEBUG_INPUT) Log.d(TAG, "showPictureInPictureMenu event=" + event);
1800        mHandler.removeMessages(MSG_SHOW_PICTURE_IN_PICTURE_MENU);
1801        Message msg = mHandler.obtainMessage(MSG_SHOW_PICTURE_IN_PICTURE_MENU);
1802        msg.setAsynchronous(true);
1803        msg.sendToTarget();
1804    }
1805
1806    private void showPictureInPictureMenuInternal() {
1807        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
1808        if (statusbar != null) {
1809            statusbar.showPictureInPictureMenu();
1810        }
1811    }
1812
1813    private final Runnable mHomeDoubleTapTimeoutRunnable = new Runnable() {
1814        @Override
1815        public void run() {
1816            if (mHomeDoubleTapPending) {
1817                mHomeDoubleTapPending = false;
1818                handleShortPressOnHome();
1819            }
1820        }
1821    };
1822
1823    private boolean isRoundWindow() {
1824        return mContext.getResources().getConfiguration().isScreenRound();
1825    }
1826
1827    /** {@inheritDoc} */
1828    @Override
1829    public void init(Context context, IWindowManager windowManager,
1830            WindowManagerFuncs windowManagerFuncs) {
1831        mContext = context;
1832        mWindowManager = windowManager;
1833        mWindowManagerFuncs = windowManagerFuncs;
1834        mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
1835        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
1836        mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
1837        mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
1838        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
1839        mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
1840        mHasFeatureWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH);
1841        mHasFeatureLeanback = mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK);
1842        mAccessibilityShortcutController =
1843                new AccessibilityShortcutController(mContext, new Handler(), mCurrentUserId);
1844        // Init display burn-in protection
1845        boolean burnInProtectionEnabled = context.getResources().getBoolean(
1846                com.android.internal.R.bool.config_enableBurnInProtection);
1847        // Allow a system property to override this. Used by developer settings.
1848        boolean burnInProtectionDevMode =
1849                SystemProperties.getBoolean("persist.debug.force_burn_in", false);
1850        if (burnInProtectionEnabled || burnInProtectionDevMode) {
1851            final int minHorizontal;
1852            final int maxHorizontal;
1853            final int minVertical;
1854            final int maxVertical;
1855            final int maxRadius;
1856            if (burnInProtectionDevMode) {
1857                minHorizontal = -8;
1858                maxHorizontal = 8;
1859                minVertical = -8;
1860                maxVertical = -4;
1861                maxRadius = (isRoundWindow()) ? 6 : -1;
1862            } else {
1863                Resources resources = context.getResources();
1864                minHorizontal = resources.getInteger(
1865                        com.android.internal.R.integer.config_burnInProtectionMinHorizontalOffset);
1866                maxHorizontal = resources.getInteger(
1867                        com.android.internal.R.integer.config_burnInProtectionMaxHorizontalOffset);
1868                minVertical = resources.getInteger(
1869                        com.android.internal.R.integer.config_burnInProtectionMinVerticalOffset);
1870                maxVertical = resources.getInteger(
1871                        com.android.internal.R.integer.config_burnInProtectionMaxVerticalOffset);
1872                maxRadius = resources.getInteger(
1873                        com.android.internal.R.integer.config_burnInProtectionMaxRadius);
1874            }
1875            mBurnInProtectionHelper = new BurnInProtectionHelper(
1876                    context, minHorizontal, maxHorizontal, minVertical, maxVertical, maxRadius);
1877        }
1878
1879        mHandler = new PolicyHandler();
1880        mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
1881        mOrientationListener = new MyOrientationListener(mContext, mHandler);
1882        try {
1883            mOrientationListener.setCurrentRotation(windowManager.getDefaultDisplayRotation());
1884        } catch (RemoteException ex) { }
1885        mSettingsObserver = new SettingsObserver(mHandler);
1886        mSettingsObserver.observe();
1887        mShortcutManager = new ShortcutManager(context);
1888        mUiMode = context.getResources().getInteger(
1889                com.android.internal.R.integer.config_defaultUiModeType);
1890        mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
1891        mHomeIntent.addCategory(Intent.CATEGORY_HOME);
1892        mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1893                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1894        mEnableCarDockHomeCapture = context.getResources().getBoolean(
1895                com.android.internal.R.bool.config_enableCarDockHomeLaunch);
1896        mCarDockIntent =  new Intent(Intent.ACTION_MAIN, null);
1897        mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
1898        mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1899                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1900        mDeskDockIntent =  new Intent(Intent.ACTION_MAIN, null);
1901        mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
1902        mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1903                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1904        mVrHeadsetHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
1905        mVrHeadsetHomeIntent.addCategory(Intent.CATEGORY_VR_HOME);
1906        mVrHeadsetHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1907                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1908
1909        mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1910        mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1911                "PhoneWindowManager.mBroadcastWakeLock");
1912        mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1913                "PhoneWindowManager.mPowerKeyWakeLock");
1914        mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
1915        mSupportAutoRotation = mContext.getResources().getBoolean(
1916                com.android.internal.R.bool.config_supportAutoRotation);
1917        mLidOpenRotation = readRotation(
1918                com.android.internal.R.integer.config_lidOpenRotation);
1919        mCarDockRotation = readRotation(
1920                com.android.internal.R.integer.config_carDockRotation);
1921        mDeskDockRotation = readRotation(
1922                com.android.internal.R.integer.config_deskDockRotation);
1923        mUndockedHdmiRotation = readRotation(
1924                com.android.internal.R.integer.config_undockedHdmiRotation);
1925        mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
1926                com.android.internal.R.bool.config_carDockEnablesAccelerometer);
1927        mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
1928                com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
1929        mLidKeyboardAccessibility = mContext.getResources().getInteger(
1930                com.android.internal.R.integer.config_lidKeyboardAccessibility);
1931        mLidNavigationAccessibility = mContext.getResources().getInteger(
1932                com.android.internal.R.integer.config_lidNavigationAccessibility);
1933        mLidControlsScreenLock = mContext.getResources().getBoolean(
1934                com.android.internal.R.bool.config_lidControlsScreenLock);
1935        mLidControlsSleep = mContext.getResources().getBoolean(
1936                com.android.internal.R.bool.config_lidControlsSleep);
1937        mTranslucentDecorEnabled = mContext.getResources().getBoolean(
1938                com.android.internal.R.bool.config_enableTranslucentDecor);
1939
1940        mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
1941                com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
1942        mAllowTheaterModeWakeFromPowerKey = mAllowTheaterModeWakeFromKey
1943                || mContext.getResources().getBoolean(
1944                    com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey);
1945        mAllowTheaterModeWakeFromMotion = mContext.getResources().getBoolean(
1946                com.android.internal.R.bool.config_allowTheaterModeWakeFromMotion);
1947        mAllowTheaterModeWakeFromMotionWhenNotDreaming = mContext.getResources().getBoolean(
1948                com.android.internal.R.bool.config_allowTheaterModeWakeFromMotionWhenNotDreaming);
1949        mAllowTheaterModeWakeFromCameraLens = mContext.getResources().getBoolean(
1950                com.android.internal.R.bool.config_allowTheaterModeWakeFromCameraLens);
1951        mAllowTheaterModeWakeFromLidSwitch = mContext.getResources().getBoolean(
1952                com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch);
1953        mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean(
1954                com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture);
1955
1956        mGoToSleepOnButtonPressTheaterMode = mContext.getResources().getBoolean(
1957                com.android.internal.R.bool.config_goToSleepOnButtonPressTheaterMode);
1958
1959        mSupportLongPressPowerWhenNonInteractive = mContext.getResources().getBoolean(
1960                com.android.internal.R.bool.config_supportLongPressPowerWhenNonInteractive);
1961
1962        mLongPressOnBackBehavior = mContext.getResources().getInteger(
1963                com.android.internal.R.integer.config_longPressOnBackBehavior);
1964        mPanicPressOnBackBehavior = mContext.getResources().getInteger(
1965                com.android.internal.R.integer.config_backPanicBehavior);
1966
1967        mShortPressOnPowerBehavior = mContext.getResources().getInteger(
1968                com.android.internal.R.integer.config_shortPressOnPowerBehavior);
1969        mLongPressOnPowerBehavior = mContext.getResources().getInteger(
1970                com.android.internal.R.integer.config_longPressOnPowerBehavior);
1971        mDoublePressOnPowerBehavior = mContext.getResources().getInteger(
1972                com.android.internal.R.integer.config_doublePressOnPowerBehavior);
1973        mTriplePressOnPowerBehavior = mContext.getResources().getInteger(
1974                com.android.internal.R.integer.config_triplePressOnPowerBehavior);
1975        mShortPressOnSleepBehavior = mContext.getResources().getInteger(
1976                com.android.internal.R.integer.config_shortPressOnSleepBehavior);
1977
1978        mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION;
1979
1980        mHandleVolumeKeysInWM = mContext.getResources().getBoolean(
1981                com.android.internal.R.bool.config_handleVolumeKeysInWindowManager);
1982
1983        readConfigurationDependentBehaviors();
1984
1985        mAccessibilityManager = (AccessibilityManager) context.getSystemService(
1986                Context.ACCESSIBILITY_SERVICE);
1987
1988        // register for dock events
1989        IntentFilter filter = new IntentFilter();
1990        filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
1991        filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
1992        filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
1993        filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
1994        filter.addAction(Intent.ACTION_DOCK_EVENT);
1995        Intent intent = context.registerReceiver(mDockReceiver, filter);
1996        if (intent != null) {
1997            // Retrieve current sticky dock event broadcast.
1998            mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
1999                    Intent.EXTRA_DOCK_STATE_UNDOCKED);
2000        }
2001
2002        // register for dream-related broadcasts
2003        filter = new IntentFilter();
2004        filter.addAction(Intent.ACTION_DREAMING_STARTED);
2005        filter.addAction(Intent.ACTION_DREAMING_STOPPED);
2006        context.registerReceiver(mDreamReceiver, filter);
2007
2008        // register for multiuser-relevant broadcasts
2009        filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
2010        context.registerReceiver(mMultiuserReceiver, filter);
2011
2012        // monitor for system gestures
2013        mSystemGestures = new SystemGesturesPointerEventListener(context,
2014                new SystemGesturesPointerEventListener.Callbacks() {
2015                    @Override
2016                    public void onSwipeFromTop() {
2017                        if (mStatusBar != null) {
2018                            requestTransientBars(mStatusBar);
2019                        }
2020                    }
2021                    @Override
2022                    public void onSwipeFromBottom() {
2023                        if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_BOTTOM) {
2024                            requestTransientBars(mNavigationBar);
2025                        }
2026                    }
2027                    @Override
2028                    public void onSwipeFromRight() {
2029                        if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_RIGHT) {
2030                            requestTransientBars(mNavigationBar);
2031                        }
2032                    }
2033                    @Override
2034                    public void onSwipeFromLeft() {
2035                        if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_LEFT) {
2036                            requestTransientBars(mNavigationBar);
2037                        }
2038                    }
2039                    @Override
2040                    public void onFling(int duration) {
2041                        if (mPowerManagerInternal != null) {
2042                            mPowerManagerInternal.powerHint(
2043                                    PowerHint.INTERACTION, duration);
2044                        }
2045                    }
2046                    @Override
2047                    public void onDebug() {
2048                        // no-op
2049                    }
2050                    @Override
2051                    public void onDown() {
2052                        mOrientationListener.onTouchStart();
2053                    }
2054                    @Override
2055                    public void onUpOrCancel() {
2056                        mOrientationListener.onTouchEnd();
2057                    }
2058                    @Override
2059                    public void onMouseHoverAtTop() {
2060                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
2061                        Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
2062                        msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
2063                        mHandler.sendMessageDelayed(msg, 500);
2064                    }
2065                    @Override
2066                    public void onMouseHoverAtBottom() {
2067                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
2068                        Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
2069                        msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
2070                        mHandler.sendMessageDelayed(msg, 500);
2071                    }
2072                    @Override
2073                    public void onMouseLeaveFromEdge() {
2074                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
2075                    }
2076                });
2077        mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext);
2078        mWindowManagerFuncs.registerPointerEventListener(mSystemGestures);
2079
2080        mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
2081        mLongPressVibePattern = getLongIntArray(mContext.getResources(),
2082                com.android.internal.R.array.config_longPressVibePattern);
2083        mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(),
2084                com.android.internal.R.array.config_virtualKeyVibePattern);
2085        mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(),
2086                com.android.internal.R.array.config_keyboardTapVibePattern);
2087        mClockTickVibePattern = getLongIntArray(mContext.getResources(),
2088                com.android.internal.R.array.config_clockTickVibePattern);
2089        mCalendarDateVibePattern = getLongIntArray(mContext.getResources(),
2090                com.android.internal.R.array.config_calendarDateVibePattern);
2091        mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
2092                com.android.internal.R.array.config_safeModeDisabledVibePattern);
2093        mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
2094                com.android.internal.R.array.config_safeModeEnabledVibePattern);
2095        mContextClickVibePattern = getLongIntArray(mContext.getResources(),
2096                com.android.internal.R.array.config_contextClickVibePattern);
2097
2098        mScreenshotChordEnabled = mContext.getResources().getBoolean(
2099                com.android.internal.R.bool.config_enableScreenshotChord);
2100
2101        mGlobalKeyManager = new GlobalKeyManager(mContext);
2102
2103        // Controls rotation and the like.
2104        initializeHdmiState();
2105
2106        // Match current screen state.
2107        if (!mPowerManager.isInteractive()) {
2108            startedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
2109            finishedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
2110        }
2111
2112        mWindowManagerInternal.registerAppTransitionListener(
2113                mStatusBarController.getAppTransitionListener());
2114        mWindowManagerInternal.registerAppTransitionListener(new AppTransitionListener() {
2115            @Override
2116            public int onAppTransitionStartingLocked(int transit, IBinder openToken,
2117                    IBinder closeToken,
2118                    Animation openAnimation, Animation closeAnimation) {
2119                return handleStartTransitionForKeyguardLw(transit, openAnimation);
2120            }
2121
2122            @Override
2123            public void onAppTransitionCancelledLocked(int transit) {
2124                handleStartTransitionForKeyguardLw(transit, null /* transit */);
2125            }
2126        });
2127        mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
2128                new StateCallback() {
2129                    @Override
2130                    public void onTrustedChanged() {
2131                        mWindowManagerFuncs.notifyKeyguardTrustedChanged();
2132                    }
2133                });
2134    }
2135
2136    /**
2137     * Read values from config.xml that may be overridden depending on
2138     * the configuration of the device.
2139     * eg. Disable long press on home goes to recents on sw600dp.
2140     */
2141    private void readConfigurationDependentBehaviors() {
2142        final Resources res = mContext.getResources();
2143
2144        mLongPressOnHomeBehavior = res.getInteger(
2145                com.android.internal.R.integer.config_longPressOnHomeBehavior);
2146        if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||
2147                mLongPressOnHomeBehavior > LAST_LONG_PRESS_HOME_BEHAVIOR) {
2148            mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
2149        }
2150
2151        mDoubleTapOnHomeBehavior = res.getInteger(
2152                com.android.internal.R.integer.config_doubleTapOnHomeBehavior);
2153        if (mDoubleTapOnHomeBehavior < DOUBLE_TAP_HOME_NOTHING ||
2154                mDoubleTapOnHomeBehavior > DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
2155            mDoubleTapOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
2156        }
2157
2158        mShortPressWindowBehavior = SHORT_PRESS_WINDOW_NOTHING;
2159        if (mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
2160            mShortPressWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE;
2161        }
2162
2163        mNavBarOpacityMode = res.getInteger(
2164                com.android.internal.R.integer.config_navBarOpacityMode);
2165    }
2166
2167    @Override
2168    public void setInitialDisplaySize(Display display, int width, int height, int density) {
2169        // This method might be called before the policy has been fully initialized
2170        // or for other displays we don't care about.
2171        // TODO(multi-display): Define policy for secondary displays.
2172        if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) {
2173            return;
2174        }
2175        mDisplay = display;
2176
2177        final Resources res = mContext.getResources();
2178        int shortSize, longSize;
2179        if (width > height) {
2180            shortSize = height;
2181            longSize = width;
2182            mLandscapeRotation = Surface.ROTATION_0;
2183            mSeascapeRotation = Surface.ROTATION_180;
2184            if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
2185                mPortraitRotation = Surface.ROTATION_90;
2186                mUpsideDownRotation = Surface.ROTATION_270;
2187            } else {
2188                mPortraitRotation = Surface.ROTATION_270;
2189                mUpsideDownRotation = Surface.ROTATION_90;
2190            }
2191        } else {
2192            shortSize = width;
2193            longSize = height;
2194            mPortraitRotation = Surface.ROTATION_0;
2195            mUpsideDownRotation = Surface.ROTATION_180;
2196            if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
2197                mLandscapeRotation = Surface.ROTATION_270;
2198                mSeascapeRotation = Surface.ROTATION_90;
2199            } else {
2200                mLandscapeRotation = Surface.ROTATION_90;
2201                mSeascapeRotation = Surface.ROTATION_270;
2202            }
2203        }
2204
2205        // SystemUI (status bar) layout policy
2206        int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
2207        int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
2208
2209        // Allow the navigation bar to move on non-square small devices (phones).
2210        mNavigationBarCanMove = width != height && shortSizeDp < 600;
2211
2212        mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
2213
2214        // Allow a system property to override this. Used by the emulator.
2215        // See also hasNavigationBar().
2216        String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
2217        if ("1".equals(navBarOverride)) {
2218            mHasNavigationBar = false;
2219        } else if ("0".equals(navBarOverride)) {
2220            mHasNavigationBar = true;
2221        }
2222
2223        // For demo purposes, allow the rotation of the HDMI display to be controlled.
2224        // By default, HDMI locks rotation to landscape.
2225        if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
2226            mDemoHdmiRotation = mPortraitRotation;
2227        } else {
2228            mDemoHdmiRotation = mLandscapeRotation;
2229        }
2230        mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
2231
2232        // For demo purposes, allow the rotation of the remote display to be controlled.
2233        // By default, remote display locks rotation to landscape.
2234        if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
2235            mDemoRotation = mPortraitRotation;
2236        } else {
2237            mDemoRotation = mLandscapeRotation;
2238        }
2239        mDemoRotationLock = SystemProperties.getBoolean(
2240                "persist.demo.rotationlock", false);
2241
2242        // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
2243        // http://developer.android.com/guide/practices/screens_support.html#range
2244        mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 &&
2245                res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
2246                // For debug purposes the next line turns this feature off with:
2247                // $ adb shell setprop config.override_forced_orient true
2248                // $ adb shell wm size reset
2249                !"true".equals(SystemProperties.get("config.override_forced_orient"));
2250    }
2251
2252    /**
2253     * @return whether the navigation bar can be hidden, e.g. the device has a
2254     *         navigation bar and touch exploration is not enabled
2255     */
2256    private boolean canHideNavigationBar() {
2257        return mHasNavigationBar;
2258    }
2259
2260    @Override
2261    public boolean isDefaultOrientationForced() {
2262        return mForceDefaultOrientation;
2263    }
2264
2265    @Override
2266    public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) {
2267        // TODO(multi-display): Define policy for secondary displays.
2268        if (display.getDisplayId() == Display.DEFAULT_DISPLAY) {
2269            mOverscanLeft = left;
2270            mOverscanTop = top;
2271            mOverscanRight = right;
2272            mOverscanBottom = bottom;
2273        }
2274    }
2275
2276    public void updateSettings() {
2277        ContentResolver resolver = mContext.getContentResolver();
2278        boolean updateRotation = false;
2279        synchronized (mLock) {
2280            mEndcallBehavior = Settings.System.getIntForUser(resolver,
2281                    Settings.System.END_BUTTON_BEHAVIOR,
2282                    Settings.System.END_BUTTON_BEHAVIOR_DEFAULT,
2283                    UserHandle.USER_CURRENT);
2284            mIncallPowerBehavior = Settings.Secure.getIntForUser(resolver,
2285                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
2286                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT,
2287                    UserHandle.USER_CURRENT);
2288            mIncallBackBehavior = Settings.Secure.getIntForUser(resolver,
2289                    Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR,
2290                    Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_DEFAULT,
2291                    UserHandle.USER_CURRENT);
2292
2293            // Configure wake gesture.
2294            boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver,
2295                    Settings.Secure.WAKE_GESTURE_ENABLED, 0,
2296                    UserHandle.USER_CURRENT) != 0;
2297            if (mWakeGestureEnabledSetting != wakeGestureEnabledSetting) {
2298                mWakeGestureEnabledSetting = wakeGestureEnabledSetting;
2299                updateWakeGestureListenerLp();
2300            }
2301
2302            // Configure rotation lock.
2303            int userRotation = Settings.System.getIntForUser(resolver,
2304                    Settings.System.USER_ROTATION, Surface.ROTATION_0,
2305                    UserHandle.USER_CURRENT);
2306            if (mUserRotation != userRotation) {
2307                mUserRotation = userRotation;
2308                updateRotation = true;
2309            }
2310            int userRotationMode = Settings.System.getIntForUser(resolver,
2311                    Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
2312                            WindowManagerPolicy.USER_ROTATION_FREE :
2313                                    WindowManagerPolicy.USER_ROTATION_LOCKED;
2314            if (mUserRotationMode != userRotationMode) {
2315                mUserRotationMode = userRotationMode;
2316                updateRotation = true;
2317                updateOrientationListenerLp();
2318            }
2319
2320            if (mSystemReady) {
2321                int pointerLocation = Settings.System.getIntForUser(resolver,
2322                        Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT);
2323                if (mPointerLocationMode != pointerLocation) {
2324                    mPointerLocationMode = pointerLocation;
2325                    mHandler.sendEmptyMessage(pointerLocation != 0 ?
2326                            MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
2327                }
2328            }
2329            // use screen off timeout setting as the timeout for the lockscreen
2330            mLockScreenTimeout = Settings.System.getIntForUser(resolver,
2331                    Settings.System.SCREEN_OFF_TIMEOUT, 0, UserHandle.USER_CURRENT);
2332            String imId = Settings.Secure.getStringForUser(resolver,
2333                    Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.USER_CURRENT);
2334            boolean hasSoftInput = imId != null && imId.length() > 0;
2335            if (mHasSoftInput != hasSoftInput) {
2336                mHasSoftInput = hasSoftInput;
2337                updateRotation = true;
2338            }
2339            if (mImmersiveModeConfirmation != null) {
2340                mImmersiveModeConfirmation.loadSetting(mCurrentUserId);
2341            }
2342        }
2343        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
2344            PolicyControl.reloadFromSetting(mContext);
2345        }
2346        if (updateRotation) {
2347            updateRotation(true);
2348        }
2349    }
2350
2351    private void updateWakeGestureListenerLp() {
2352        if (shouldEnableWakeGestureLp()) {
2353            mWakeGestureListener.requestWakeUpTrigger();
2354        } else {
2355            mWakeGestureListener.cancelWakeUpTrigger();
2356        }
2357    }
2358
2359    private boolean shouldEnableWakeGestureLp() {
2360        return mWakeGestureEnabledSetting && !mAwake
2361                && (!mLidControlsSleep || mLidState != LID_CLOSED)
2362                && mWakeGestureListener.isSupported();
2363    }
2364
2365    private void enablePointerLocation() {
2366        if (mPointerLocationView == null) {
2367            mPointerLocationView = new PointerLocationView(mContext);
2368            mPointerLocationView.setPrintCoords(false);
2369            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
2370                    WindowManager.LayoutParams.MATCH_PARENT,
2371                    WindowManager.LayoutParams.MATCH_PARENT);
2372            lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
2373            lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
2374                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
2375                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2376                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
2377            if (ActivityManager.isHighEndGfx()) {
2378                lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
2379                lp.privateFlags |=
2380                        WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
2381            }
2382            lp.format = PixelFormat.TRANSLUCENT;
2383            lp.setTitle("PointerLocation");
2384            WindowManager wm = (WindowManager) mContext.getSystemService(WINDOW_SERVICE);
2385            lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
2386            wm.addView(mPointerLocationView, lp);
2387            mWindowManagerFuncs.registerPointerEventListener(mPointerLocationView);
2388        }
2389    }
2390
2391    private void disablePointerLocation() {
2392        if (mPointerLocationView != null) {
2393            mWindowManagerFuncs.unregisterPointerEventListener(mPointerLocationView);
2394            WindowManager wm = (WindowManager) mContext.getSystemService(WINDOW_SERVICE);
2395            wm.removeView(mPointerLocationView);
2396            mPointerLocationView = null;
2397        }
2398    }
2399
2400    private int readRotation(int resID) {
2401        try {
2402            int rotation = mContext.getResources().getInteger(resID);
2403            switch (rotation) {
2404                case 0:
2405                    return Surface.ROTATION_0;
2406                case 90:
2407                    return Surface.ROTATION_90;
2408                case 180:
2409                    return Surface.ROTATION_180;
2410                case 270:
2411                    return Surface.ROTATION_270;
2412            }
2413        } catch (Resources.NotFoundException e) {
2414            // fall through
2415        }
2416        return -1;
2417    }
2418
2419    /** {@inheritDoc} */
2420    @Override
2421    public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) {
2422        int type = attrs.type;
2423
2424        outAppOp[0] = AppOpsManager.OP_NONE;
2425
2426        if (!((type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW)
2427                || (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW)
2428                || (type >= FIRST_SYSTEM_WINDOW && type <= LAST_SYSTEM_WINDOW))) {
2429            return WindowManagerGlobal.ADD_INVALID_TYPE;
2430        }
2431
2432        if (type < FIRST_SYSTEM_WINDOW || type > LAST_SYSTEM_WINDOW) {
2433            // Window manager will make sure these are okay.
2434            return ADD_OKAY;
2435        }
2436
2437        if (!isSystemAlertWindowType(type)) {
2438            switch (type) {
2439                case TYPE_TOAST:
2440                    // Only apps that target older than O SDK can add window without a token, after
2441                    // that we require a token so apps cannot add toasts directly as the token is
2442                    // added by the notification system.
2443                    // Window manager does the checking for this.
2444                    outAppOp[0] = OP_TOAST_WINDOW;
2445                    return ADD_OKAY;
2446                case TYPE_DREAM:
2447                case TYPE_INPUT_METHOD:
2448                case TYPE_WALLPAPER:
2449                case TYPE_PRESENTATION:
2450                case TYPE_PRIVATE_PRESENTATION:
2451                case TYPE_VOICE_INTERACTION:
2452                case TYPE_ACCESSIBILITY_OVERLAY:
2453                case TYPE_QS_DIALOG:
2454                    // The window manager will check these.
2455                    return ADD_OKAY;
2456            }
2457            return mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
2458                    == PERMISSION_GRANTED ? ADD_OKAY : ADD_PERMISSION_DENIED;
2459        }
2460
2461        // Things get a little more interesting for alert windows...
2462        outAppOp[0] = OP_SYSTEM_ALERT_WINDOW;
2463
2464        final int callingUid = Binder.getCallingUid();
2465        // system processes will be automatically granted privilege to draw
2466        if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
2467            return ADD_OKAY;
2468        }
2469
2470        ApplicationInfo appInfo;
2471        try {
2472            appInfo = mContext.getPackageManager().getApplicationInfoAsUser(
2473                            attrs.packageName,
2474                            0 /* flags */,
2475                            UserHandle.getUserId(callingUid));
2476        } catch (PackageManager.NameNotFoundException e) {
2477            appInfo = null;
2478        }
2479
2480        if (appInfo == null || (type != TYPE_APPLICATION_OVERLAY && appInfo.targetSdkVersion >= O)) {
2481            /**
2482             * Apps targeting >= {@link Build.VERSION_CODES#O} are required to hold
2483             * {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW} (system signature apps)
2484             * permission to add alert windows that aren't
2485             * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY}.
2486             */
2487            return (mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
2488                    == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
2489        }
2490
2491        // check if user has enabled this operation. SecurityException will be thrown if this app
2492        // has not been allowed by the user
2493        final int mode = mAppOpsManager.checkOpNoThrow(outAppOp[0], callingUid, attrs.packageName);
2494        switch (mode) {
2495            case AppOpsManager.MODE_ALLOWED:
2496            case AppOpsManager.MODE_IGNORED:
2497                // although we return ADD_OKAY for MODE_IGNORED, the added window will
2498                // actually be hidden in WindowManagerService
2499                return ADD_OKAY;
2500            case AppOpsManager.MODE_ERRORED:
2501                // Don't crash legacy apps
2502                if (appInfo.targetSdkVersion < M) {
2503                    return ADD_OKAY;
2504                }
2505                return ADD_PERMISSION_DENIED;
2506            default:
2507                // in the default mode, we will make a decision here based on
2508                // checkCallingPermission()
2509                return (mContext.checkCallingOrSelfPermission(SYSTEM_ALERT_WINDOW)
2510                        == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
2511        }
2512    }
2513
2514    @Override
2515    public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) {
2516
2517        // If this switch statement is modified, modify the comment in the declarations of
2518        // the type in {@link WindowManager.LayoutParams} as well.
2519        switch (attrs.type) {
2520            default:
2521                // These are the windows that by default are shown only to the user that created
2522                // them. If this needs to be overridden, set
2523                // {@link WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS} in
2524                // {@link WindowManager.LayoutParams}. Note that permission
2525                // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well.
2526                if ((attrs.privateFlags & PRIVATE_FLAG_SHOW_FOR_ALL_USERS) == 0) {
2527                    return true;
2528                }
2529                break;
2530
2531            // These are the windows that by default are shown to all users. However, to
2532            // protect against spoofing, check permissions below.
2533            case TYPE_APPLICATION_STARTING:
2534            case TYPE_BOOT_PROGRESS:
2535            case TYPE_DISPLAY_OVERLAY:
2536            case TYPE_INPUT_CONSUMER:
2537            case TYPE_KEYGUARD_DIALOG:
2538            case TYPE_MAGNIFICATION_OVERLAY:
2539            case TYPE_NAVIGATION_BAR:
2540            case TYPE_NAVIGATION_BAR_PANEL:
2541            case TYPE_PHONE:
2542            case TYPE_POINTER:
2543            case TYPE_PRIORITY_PHONE:
2544            case TYPE_SEARCH_BAR:
2545            case TYPE_STATUS_BAR:
2546            case TYPE_STATUS_BAR_PANEL:
2547            case TYPE_STATUS_BAR_SUB_PANEL:
2548            case TYPE_SYSTEM_DIALOG:
2549            case TYPE_VOLUME_OVERLAY:
2550            case TYPE_PRESENTATION:
2551            case TYPE_PRIVATE_PRESENTATION:
2552            case TYPE_DOCK_DIVIDER:
2553                break;
2554        }
2555
2556        // Check if third party app has set window to system window type.
2557        return mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW) != PERMISSION_GRANTED;
2558    }
2559
2560    @Override
2561    public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
2562        switch (attrs.type) {
2563            case TYPE_SYSTEM_OVERLAY:
2564            case TYPE_SECURE_SYSTEM_OVERLAY:
2565                // These types of windows can't receive input events.
2566                attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2567                        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
2568                attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
2569                break;
2570            case TYPE_STATUS_BAR:
2571
2572                // If the Keyguard is in a hidden state (occluded by another window), we force to
2573                // remove the wallpaper and keyguard flag so that any change in-flight after setting
2574                // the keyguard as occluded wouldn't set these flags again.
2575                // See {@link #processKeyguardSetHiddenResultLw}.
2576                if (mKeyguardOccluded) {
2577                    attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
2578                    attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2579                }
2580                break;
2581
2582            case TYPE_SCREENSHOT:
2583                attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
2584                break;
2585
2586            case TYPE_TOAST:
2587                // While apps should use the dedicated toast APIs to add such windows
2588                // it possible legacy apps to add the window directly. Therefore, we
2589                // make windows added directly by the app behave as a toast as much
2590                // as possible in terms of timeout and animation.
2591                if (attrs.hideTimeoutMilliseconds < 0
2592                        || attrs.hideTimeoutMilliseconds > TOAST_WINDOW_TIMEOUT) {
2593                    attrs.hideTimeoutMilliseconds = TOAST_WINDOW_TIMEOUT;
2594                }
2595                attrs.windowAnimations = com.android.internal.R.style.Animation_Toast;
2596                break;
2597        }
2598
2599        if (attrs.type != TYPE_STATUS_BAR) {
2600            // The status bar is the only window allowed to exhibit keyguard behavior.
2601            attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2602        }
2603
2604        if (ActivityManager.isHighEndGfx()) {
2605            if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
2606                attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
2607            }
2608            final boolean forceWindowDrawsStatusBarBackground =
2609                    (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND)
2610                            != 0;
2611            if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
2612                    || forceWindowDrawsStatusBarBackground
2613                            && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) {
2614                attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2615            }
2616        }
2617    }
2618
2619    void readLidState() {
2620        mLidState = mWindowManagerFuncs.getLidState();
2621    }
2622
2623    private void readCameraLensCoverState() {
2624        mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState();
2625    }
2626
2627    private boolean isHidden(int accessibilityMode) {
2628        switch (accessibilityMode) {
2629            case 1:
2630                return mLidState == LID_CLOSED;
2631            case 2:
2632                return mLidState == LID_OPEN;
2633            default:
2634                return false;
2635        }
2636    }
2637
2638    /** {@inheritDoc} */
2639    @Override
2640    public void adjustConfigurationLw(Configuration config, int keyboardPresence,
2641            int navigationPresence) {
2642        mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0;
2643
2644        readConfigurationDependentBehaviors();
2645        readLidState();
2646
2647        if (config.keyboard == Configuration.KEYBOARD_NOKEYS
2648                || (keyboardPresence == PRESENCE_INTERNAL
2649                        && isHidden(mLidKeyboardAccessibility))) {
2650            config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
2651            if (!mHasSoftInput) {
2652                config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
2653            }
2654        }
2655
2656        if (config.navigation == Configuration.NAVIGATION_NONAV
2657                || (navigationPresence == PRESENCE_INTERNAL
2658                        && isHidden(mLidNavigationAccessibility))) {
2659            config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
2660        }
2661    }
2662
2663    @Override
2664    public void onConfigurationChanged() {
2665        // TODO(multi-display): Define policy for secondary displays.
2666        final Resources res = mContext.getResources();
2667
2668        mStatusBarHeight =
2669                res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
2670
2671        // Height of the navigation bar when presented horizontally at bottom
2672        mNavigationBarHeightForRotationDefault[mPortraitRotation] =
2673        mNavigationBarHeightForRotationDefault[mUpsideDownRotation] =
2674                res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
2675        mNavigationBarHeightForRotationDefault[mLandscapeRotation] =
2676        mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize(
2677                com.android.internal.R.dimen.navigation_bar_height_landscape);
2678
2679        // Width of the navigation bar when presented vertically along one side
2680        mNavigationBarWidthForRotationDefault[mPortraitRotation] =
2681        mNavigationBarWidthForRotationDefault[mUpsideDownRotation] =
2682        mNavigationBarWidthForRotationDefault[mLandscapeRotation] =
2683        mNavigationBarWidthForRotationDefault[mSeascapeRotation] =
2684                res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
2685
2686        if (ALTERNATE_CAR_MODE_NAV_SIZE) {
2687            // Height of the navigation bar when presented horizontally at bottom
2688            mNavigationBarHeightForRotationInCarMode[mPortraitRotation] =
2689            mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] =
2690                    res.getDimensionPixelSize(
2691                            com.android.internal.R.dimen.navigation_bar_height_car_mode);
2692            mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] =
2693            mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize(
2694                    com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode);
2695
2696            // Width of the navigation bar when presented vertically along one side
2697            mNavigationBarWidthForRotationInCarMode[mPortraitRotation] =
2698            mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] =
2699            mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] =
2700            mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] =
2701                    res.getDimensionPixelSize(
2702                            com.android.internal.R.dimen.navigation_bar_width_car_mode);
2703        }
2704    }
2705
2706    @Override
2707    public int getMaxWallpaperLayer() {
2708        return getWindowLayerFromTypeLw(TYPE_STATUS_BAR);
2709    }
2710
2711    private int getNavigationBarWidth(int rotation, int uiMode) {
2712        if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2713            return mNavigationBarWidthForRotationInCarMode[rotation];
2714        } else {
2715            return mNavigationBarWidthForRotationDefault[rotation];
2716        }
2717    }
2718
2719    @Override
2720    public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
2721            int displayId) {
2722        // TODO(multi-display): Support navigation bar on secondary displays.
2723        if (displayId == Display.DEFAULT_DISPLAY && mHasNavigationBar) {
2724            // For a basic navigation bar, when we are in landscape mode we place
2725            // the navigation bar to the side.
2726            if (mNavigationBarCanMove && fullWidth > fullHeight) {
2727                return fullWidth - getNavigationBarWidth(rotation, uiMode);
2728            }
2729        }
2730        return fullWidth;
2731    }
2732
2733    private int getNavigationBarHeight(int rotation, int uiMode) {
2734        if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2735            return mNavigationBarHeightForRotationInCarMode[rotation];
2736        } else {
2737            return mNavigationBarHeightForRotationDefault[rotation];
2738        }
2739    }
2740
2741    @Override
2742    public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
2743            int displayId) {
2744        // TODO(multi-display): Support navigation bar on secondary displays.
2745        if (displayId == Display.DEFAULT_DISPLAY && mHasNavigationBar) {
2746            // For a basic navigation bar, when we are in portrait mode we place
2747            // the navigation bar to the bottom.
2748            if (!mNavigationBarCanMove || fullWidth < fullHeight) {
2749                return fullHeight - getNavigationBarHeight(rotation, uiMode);
2750            }
2751        }
2752        return fullHeight;
2753    }
2754
2755    @Override
2756    public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
2757            int displayId) {
2758        return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode, displayId);
2759    }
2760
2761    @Override
2762    public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
2763            int displayId) {
2764        // There is a separate status bar at the top of the display.  We don't count that as part
2765        // of the fixed decor, since it can hide; however, for purposes of configurations,
2766        // we do want to exclude it since applications can't generally use that part
2767        // of the screen.
2768        // TODO(multi-display): Support status bars on secondary displays.
2769        if (displayId == Display.DEFAULT_DISPLAY) {
2770            return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayId)
2771                    - mStatusBarHeight;
2772        }
2773        return fullHeight;
2774    }
2775
2776    @Override
2777    public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) {
2778        return attrs.type == TYPE_STATUS_BAR;
2779    }
2780
2781    @Override
2782    public boolean canBeHiddenByKeyguardLw(WindowState win) {
2783        switch (win.getAttrs().type) {
2784            case TYPE_STATUS_BAR:
2785            case TYPE_NAVIGATION_BAR:
2786            case TYPE_WALLPAPER:
2787            case TYPE_DREAM:
2788                return false;
2789            default:
2790                // Hide only windows below the keyguard host window.
2791                return getWindowLayerLw(win) < getWindowLayerFromTypeLw(TYPE_STATUS_BAR);
2792        }
2793    }
2794
2795    private boolean shouldBeHiddenByKeyguard(WindowState win, WindowState imeTarget) {
2796
2797        // Keyguard visibility of window from activities are determined over activity visibility.
2798        if (win.getAppToken() != null) {
2799            return false;
2800        }
2801
2802        final LayoutParams attrs = win.getAttrs();
2803        final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleLw() &&
2804                ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0
2805                        || !canBeHiddenByKeyguardLw(imeTarget));
2806
2807        // Show IME over the keyguard if the target allows it
2808        boolean allowWhenLocked = (win.isInputMethodWindow() || imeTarget == this)
2809                && showImeOverKeyguard;;
2810
2811        if (isKeyguardLocked() && isKeyguardOccluded()) {
2812            // Show SHOW_WHEN_LOCKED windows if Keyguard is occluded.
2813            allowWhenLocked |= (attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
2814                    // Show error dialogs over apps that are shown on lockscreen
2815                    || (attrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
2816        }
2817
2818        boolean keyguardLocked = isKeyguardLocked();
2819        boolean hideDockDivider = attrs.type == TYPE_DOCK_DIVIDER
2820                && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
2821        return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == Display.DEFAULT_DISPLAY)
2822                || hideDockDivider;
2823    }
2824
2825    /** {@inheritDoc} */
2826    @Override
2827    public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme,
2828            CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon,
2829            int logo, int windowFlags, Configuration overrideConfig, int displayId) {
2830        if (!SHOW_SPLASH_SCREENS) {
2831            return null;
2832        }
2833        if (packageName == null) {
2834            return null;
2835        }
2836
2837        WindowManager wm = null;
2838        View view = null;
2839
2840        try {
2841            Context context = mContext;
2842            if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen " + packageName
2843                    + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
2844                    + Integer.toHexString(theme));
2845
2846            // Obtain proper context to launch on the right display.
2847            final Context displayContext = getDisplayContext(context, displayId);
2848            if (displayContext == null) {
2849                // Can't show splash screen on requested display, so skip showing at all.
2850                return null;
2851            }
2852            context = displayContext;
2853
2854            if (theme != context.getThemeResId() || labelRes != 0) {
2855                try {
2856                    context = context.createPackageContext(packageName, CONTEXT_RESTRICTED);
2857                    context.setTheme(theme);
2858                } catch (PackageManager.NameNotFoundException e) {
2859                    // Ignore
2860                }
2861            }
2862
2863            if (overrideConfig != null && !overrideConfig.equals(EMPTY)) {
2864                if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: creating context based"
2865                        + " on overrideConfig" + overrideConfig + " for splash screen");
2866                final Context overrideContext = context.createConfigurationContext(overrideConfig);
2867                overrideContext.setTheme(theme);
2868                final TypedArray typedArray = overrideContext.obtainStyledAttributes(
2869                        com.android.internal.R.styleable.Window);
2870                final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
2871                if (resId != 0 && overrideContext.getDrawable(resId) != null) {
2872                    // We want to use the windowBackground for the override context if it is
2873                    // available, otherwise we use the default one to make sure a themed starting
2874                    // window is displayed for the app.
2875                    if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: apply overrideConfig"
2876                            + overrideConfig + " to starting window resId=" + resId);
2877                    context = overrideContext;
2878                }
2879                typedArray.recycle();
2880            }
2881
2882            final PhoneWindow win = new PhoneWindow(context);
2883            win.setIsStartingWindow(true);
2884
2885            CharSequence label = context.getResources().getText(labelRes, null);
2886            // Only change the accessibility title if the label is localized
2887            if (label != null) {
2888                win.setTitle(label, true);
2889            } else {
2890                win.setTitle(nonLocalizedLabel, false);
2891            }
2892
2893            win.setType(
2894                WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
2895
2896            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
2897                // Assumes it's safe to show starting windows of launched apps while
2898                // the keyguard is being hidden. This is okay because starting windows never show
2899                // secret information.
2900                if (mKeyguardOccluded) {
2901                    windowFlags |= FLAG_SHOW_WHEN_LOCKED;
2902                }
2903            }
2904
2905            // Force the window flags: this is a fake window, so it is not really
2906            // touchable or focusable by the user.  We also add in the ALT_FOCUSABLE_IM
2907            // flag because we do know that the next window will take input
2908            // focus, so we want to get the IME window up on top of us right away.
2909            win.setFlags(
2910                windowFlags|
2911                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2912                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2913                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
2914                windowFlags|
2915                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2916                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2917                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
2918
2919            win.setDefaultIcon(icon);
2920            win.setDefaultLogo(logo);
2921
2922            win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
2923                    WindowManager.LayoutParams.MATCH_PARENT);
2924
2925            final WindowManager.LayoutParams params = win.getAttributes();
2926            params.token = appToken;
2927            params.packageName = packageName;
2928            params.windowAnimations = win.getWindowStyle().getResourceId(
2929                    com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
2930            params.privateFlags |=
2931                    WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
2932            params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
2933
2934            if (!compatInfo.supportsScreen()) {
2935                params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
2936            }
2937
2938            params.setTitle("Splash Screen " + packageName);
2939            addSplashscreenContent(win, context);
2940
2941            wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
2942            view = win.getDecorView();
2943
2944            if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "Adding splash screen window for "
2945                + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null));
2946
2947            wm.addView(view, params);
2948
2949            // Only return the view if it was successfully added to the
2950            // window manager... which we can tell by it having a parent.
2951            return view.getParent() != null ? new SplashScreenSurface(view, appToken) : null;
2952        } catch (WindowManager.BadTokenException e) {
2953            // ignore
2954            Log.w(TAG, appToken + " already running, starting window not displayed. " +
2955                    e.getMessage());
2956        } catch (RuntimeException e) {
2957            // don't crash if something else bad happens, for example a
2958            // failure loading resources because we are loading from an app
2959            // on external storage that has been unmounted.
2960            Log.w(TAG, appToken + " failed creating starting window", e);
2961        } finally {
2962            if (view != null && view.getParent() == null) {
2963                Log.w(TAG, "view not successfully added to wm, removing view");
2964                wm.removeViewImmediate(view);
2965            }
2966        }
2967
2968        return null;
2969    }
2970
2971    private void addSplashscreenContent(PhoneWindow win, Context ctx) {
2972        final TypedArray a = ctx.obtainStyledAttributes(R.styleable.Window);
2973        final int resId = a.getResourceId(R.styleable.Window_windowSplashscreenContent, 0);
2974        a.recycle();
2975        if (resId == 0) {
2976            return;
2977        }
2978        final Drawable drawable = ctx.getDrawable(resId);
2979        if (drawable == null) {
2980            return;
2981        }
2982
2983        // We wrap this into a view so the system insets get applied to the drawable.
2984        final View v = new View(ctx);
2985        v.setBackground(drawable);
2986        win.setContentView(v);
2987    }
2988
2989    /** Obtain proper context for showing splash screen on the provided display. */
2990    private Context getDisplayContext(Context context, int displayId) {
2991        if (displayId == Display.DEFAULT_DISPLAY) {
2992            // The default context fits.
2993            return context;
2994        }
2995
2996        final DisplayManager dm = (DisplayManager) context.getSystemService(DISPLAY_SERVICE);
2997        final Display targetDisplay = dm.getDisplay(displayId);
2998        if (targetDisplay == null) {
2999            // Failed to obtain the non-default display where splash screen should be shown,
3000            // lets not show at all.
3001            return null;
3002        }
3003
3004        return context.createDisplayContext(targetDisplay);
3005    }
3006
3007    /**
3008     * Preflight adding a window to the system.
3009     *
3010     * Currently enforces that three window types are singletons:
3011     * <ul>
3012     * <li>STATUS_BAR_TYPE</li>
3013     * <li>KEYGUARD_TYPE</li>
3014     * </ul>
3015     *
3016     * @param win The window to be added
3017     * @param attrs Information about the window to be added
3018     *
3019     * @return If ok, WindowManagerImpl.ADD_OKAY.  If too many singletons,
3020     * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
3021     */
3022    @Override
3023    public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
3024        switch (attrs.type) {
3025            case TYPE_STATUS_BAR:
3026                mContext.enforceCallingOrSelfPermission(
3027                        android.Manifest.permission.STATUS_BAR_SERVICE,
3028                        "PhoneWindowManager");
3029                if (mStatusBar != null) {
3030                    if (mStatusBar.isAlive()) {
3031                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
3032                    }
3033                }
3034                mStatusBar = win;
3035                mStatusBarController.setWindow(win);
3036                setKeyguardOccludedLw(mKeyguardOccluded, true /* force */);
3037                break;
3038            case TYPE_NAVIGATION_BAR:
3039                mContext.enforceCallingOrSelfPermission(
3040                        android.Manifest.permission.STATUS_BAR_SERVICE,
3041                        "PhoneWindowManager");
3042                if (mNavigationBar != null) {
3043                    if (mNavigationBar.isAlive()) {
3044                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
3045                    }
3046                }
3047                mNavigationBar = win;
3048                mNavigationBarController.setWindow(win);
3049                mNavigationBarController.setOnBarVisibilityChangedListener(
3050                        mNavBarVisibilityListener, true);
3051                if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
3052                break;
3053            case TYPE_NAVIGATION_BAR_PANEL:
3054            case TYPE_STATUS_BAR_PANEL:
3055            case TYPE_STATUS_BAR_SUB_PANEL:
3056            case TYPE_VOICE_INTERACTION_STARTING:
3057                mContext.enforceCallingOrSelfPermission(
3058                        android.Manifest.permission.STATUS_BAR_SERVICE,
3059                        "PhoneWindowManager");
3060                break;
3061        }
3062        return ADD_OKAY;
3063    }
3064
3065    /** {@inheritDoc} */
3066    @Override
3067    public void removeWindowLw(WindowState win) {
3068        if (mStatusBar == win) {
3069            mStatusBar = null;
3070            mStatusBarController.setWindow(null);
3071        } else if (mNavigationBar == win) {
3072            mNavigationBar = null;
3073            mNavigationBarController.setWindow(null);
3074        }
3075    }
3076
3077    static final boolean PRINT_ANIM = false;
3078
3079    /** {@inheritDoc} */
3080    @Override
3081    public int selectAnimationLw(WindowState win, int transit) {
3082        if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
3083              + ": transit=" + transit);
3084        if (win == mStatusBar) {
3085            final boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
3086            final boolean expanded = win.getAttrs().height == MATCH_PARENT
3087                    && win.getAttrs().width == MATCH_PARENT;
3088            if (isKeyguard || expanded) {
3089                return -1;
3090            }
3091            if (transit == TRANSIT_EXIT
3092                    || transit == TRANSIT_HIDE) {
3093                return R.anim.dock_top_exit;
3094            } else if (transit == TRANSIT_ENTER
3095                    || transit == TRANSIT_SHOW) {
3096                return R.anim.dock_top_enter;
3097            }
3098        } else if (win == mNavigationBar) {
3099            if (win.getAttrs().windowAnimations != 0) {
3100                return 0;
3101            }
3102            // This can be on either the bottom or the right or the left.
3103            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
3104                if (transit == TRANSIT_EXIT
3105                        || transit == TRANSIT_HIDE) {
3106                    if (isKeyguardShowingAndNotOccluded()) {
3107                        return R.anim.dock_bottom_exit_keyguard;
3108                    } else {
3109                        return R.anim.dock_bottom_exit;
3110                    }
3111                } else if (transit == TRANSIT_ENTER
3112                        || transit == TRANSIT_SHOW) {
3113                    return R.anim.dock_bottom_enter;
3114                }
3115            } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
3116                if (transit == TRANSIT_EXIT
3117                        || transit == TRANSIT_HIDE) {
3118                    return R.anim.dock_right_exit;
3119                } else if (transit == TRANSIT_ENTER
3120                        || transit == TRANSIT_SHOW) {
3121                    return R.anim.dock_right_enter;
3122                }
3123            } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
3124                if (transit == TRANSIT_EXIT
3125                        || transit == TRANSIT_HIDE) {
3126                    return R.anim.dock_left_exit;
3127                } else if (transit == TRANSIT_ENTER
3128                        || transit == TRANSIT_SHOW) {
3129                    return R.anim.dock_left_enter;
3130                }
3131            }
3132        } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) {
3133            return selectDockedDividerAnimationLw(win, transit);
3134        }
3135
3136        if (transit == TRANSIT_PREVIEW_DONE) {
3137            if (win.hasAppShownWindows()) {
3138                if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
3139                return com.android.internal.R.anim.app_starting_exit;
3140            }
3141        } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
3142                && transit == TRANSIT_ENTER) {
3143            // Special case: we are animating in a dream, while the keyguard
3144            // is shown.  We don't want an animation on the dream, because
3145            // we need it shown immediately with the keyguard animating away
3146            // to reveal it.
3147            return -1;
3148        }
3149
3150        return 0;
3151    }
3152
3153    private int selectDockedDividerAnimationLw(WindowState win, int transit) {
3154        int insets = mWindowManagerFuncs.getDockedDividerInsetsLw();
3155
3156        // If the divider is behind the navigation bar, don't animate.
3157        final Rect frame = win.getFrameLw();
3158        final boolean behindNavBar = mNavigationBar != null
3159                && ((mNavigationBarPosition == NAV_BAR_BOTTOM
3160                        && frame.top + insets >= mNavigationBar.getFrameLw().top)
3161                || (mNavigationBarPosition == NAV_BAR_RIGHT
3162                        && frame.left + insets >= mNavigationBar.getFrameLw().left)
3163                || (mNavigationBarPosition == NAV_BAR_LEFT
3164                        && frame.right - insets <= mNavigationBar.getFrameLw().right));
3165        final boolean landscape = frame.height() > frame.width();
3166        final boolean offscreenLandscape = landscape && (frame.right - insets <= 0
3167                || frame.left + insets >= win.getDisplayFrameLw().right);
3168        final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0
3169                || frame.bottom + insets >= win.getDisplayFrameLw().bottom);
3170        final boolean offscreen = offscreenLandscape || offscreenPortrait;
3171        if (behindNavBar || offscreen) {
3172            return 0;
3173        }
3174        if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
3175            return R.anim.fade_in;
3176        } else if (transit == TRANSIT_EXIT) {
3177            return R.anim.fade_out;
3178        } else {
3179            return 0;
3180        }
3181    }
3182
3183    @Override
3184    public void selectRotationAnimationLw(int anim[]) {
3185        if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
3186                + mTopFullscreenOpaqueWindowState + " rotationAnimation="
3187                + (mTopFullscreenOpaqueWindowState == null ?
3188                        "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation));
3189        if (mTopFullscreenOpaqueWindowState != null) {
3190            int animationHint = mTopFullscreenOpaqueWindowState.getRotationAnimationHint();
3191            if (animationHint < 0 && mTopIsFullscreen) {
3192                animationHint = mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation;
3193            }
3194            switch (animationHint) {
3195                case ROTATION_ANIMATION_CROSSFADE:
3196                case ROTATION_ANIMATION_SEAMLESS: // Crossfade is fallback for seamless.
3197                    anim[0] = R.anim.rotation_animation_xfade_exit;
3198                    anim[1] = R.anim.rotation_animation_enter;
3199                    break;
3200                case ROTATION_ANIMATION_JUMPCUT:
3201                    anim[0] = R.anim.rotation_animation_jump_exit;
3202                    anim[1] = R.anim.rotation_animation_enter;
3203                    break;
3204                case ROTATION_ANIMATION_ROTATE:
3205                default:
3206                    anim[0] = anim[1] = 0;
3207                    break;
3208            }
3209        } else {
3210            anim[0] = anim[1] = 0;
3211        }
3212    }
3213
3214    @Override
3215    public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId,
3216            boolean forceDefault) {
3217        switch (exitAnimId) {
3218            case R.anim.rotation_animation_xfade_exit:
3219            case R.anim.rotation_animation_jump_exit:
3220                // These are the only cases that matter.
3221                if (forceDefault) {
3222                    return false;
3223                }
3224                int anim[] = new int[2];
3225                selectRotationAnimationLw(anim);
3226                return (exitAnimId == anim[0] && enterAnimId == anim[1]);
3227            default:
3228                return true;
3229        }
3230    }
3231
3232    @Override
3233    public Animation createHiddenByKeyguardExit(boolean onWallpaper,
3234            boolean goingToNotificationShade) {
3235        if (goingToNotificationShade) {
3236            return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
3237        }
3238
3239        AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ?
3240                    R.anim.lock_screen_behind_enter_wallpaper :
3241                    R.anim.lock_screen_behind_enter);
3242
3243        // TODO: Use XML interpolators when we have log interpolators available in XML.
3244        final List<Animation> animations = set.getAnimations();
3245        for (int i = animations.size() - 1; i >= 0; --i) {
3246            animations.get(i).setInterpolator(mLogDecelerateInterpolator);
3247        }
3248
3249        return set;
3250    }
3251
3252
3253    @Override
3254    public Animation createKeyguardWallpaperExit(boolean goingToNotificationShade) {
3255        if (goingToNotificationShade) {
3256            return null;
3257        } else {
3258            return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
3259        }
3260    }
3261
3262    private static void awakenDreams() {
3263        IDreamManager dreamManager = getDreamManager();
3264        if (dreamManager != null) {
3265            try {
3266                dreamManager.awaken();
3267            } catch (RemoteException e) {
3268                // fine, stay asleep then
3269            }
3270        }
3271    }
3272
3273    static IDreamManager getDreamManager() {
3274        return IDreamManager.Stub.asInterface(
3275                ServiceManager.checkService(DreamService.DREAM_SERVICE));
3276    }
3277
3278    TelecomManager getTelecommService() {
3279        return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
3280    }
3281
3282    static IAudioService getAudioService() {
3283        IAudioService audioService = IAudioService.Stub.asInterface(
3284                ServiceManager.checkService(Context.AUDIO_SERVICE));
3285        if (audioService == null) {
3286            Log.w(TAG, "Unable to find IAudioService interface.");
3287        }
3288        return audioService;
3289    }
3290
3291    boolean keyguardOn() {
3292        return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode();
3293    }
3294
3295    private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
3296            WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
3297            WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
3298        };
3299
3300    /** {@inheritDoc} */
3301    @Override
3302    public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
3303        final boolean keyguardOn = keyguardOn();
3304        final int keyCode = event.getKeyCode();
3305        final int repeatCount = event.getRepeatCount();
3306        final int metaState = event.getMetaState();
3307        final int flags = event.getFlags();
3308        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
3309        final boolean canceled = event.isCanceled();
3310
3311        if (DEBUG_INPUT) {
3312            Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
3313                    + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
3314                    + " canceled=" + canceled);
3315        }
3316
3317        // If we think we might have a volume down & power key chord on the way
3318        // but we're not sure, then tell the dispatcher to wait a little while and
3319        // try again later before dispatching.
3320        if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
3321            if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
3322                final long now = SystemClock.uptimeMillis();
3323                final long timeoutTime = mScreenshotChordVolumeDownKeyTime
3324                        + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
3325                if (now < timeoutTime) {
3326                    return timeoutTime - now;
3327                }
3328            }
3329            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3330                    && mScreenshotChordVolumeDownKeyConsumed) {
3331                if (!down) {
3332                    mScreenshotChordVolumeDownKeyConsumed = false;
3333                }
3334                return -1;
3335            }
3336        }
3337
3338        // If an accessibility shortcut might be partially complete, hold off dispatching until we
3339        // know if it is complete or not
3340        if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(false)
3341                && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
3342            if (mScreenshotChordVolumeDownKeyTriggered ^ mA11yShortcutChordVolumeUpKeyTriggered) {
3343                final long now = SystemClock.uptimeMillis();
3344                final long timeoutTime = (mScreenshotChordVolumeDownKeyTriggered
3345                        ? mScreenshotChordVolumeDownKeyTime : mA11yShortcutChordVolumeUpKeyTime)
3346                        + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
3347                if (now < timeoutTime) {
3348                    return timeoutTime - now;
3349                }
3350            }
3351            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && mScreenshotChordVolumeDownKeyConsumed) {
3352                if (!down) {
3353                    mScreenshotChordVolumeDownKeyConsumed = false;
3354                }
3355                return -1;
3356            }
3357            if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mA11yShortcutChordVolumeUpKeyConsumed) {
3358                if (!down) {
3359                    mA11yShortcutChordVolumeUpKeyConsumed = false;
3360                }
3361                return -1;
3362            }
3363        }
3364
3365        // Cancel any pending meta actions if we see any other keys being pressed between the down
3366        // of the meta key and its corresponding up.
3367        if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
3368            mPendingMetaAction = false;
3369        }
3370        // Any key that is not Alt or Meta cancels Caps Lock combo tracking.
3371        if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) {
3372            mPendingCapsLockToggle = false;
3373        }
3374
3375        // First we always handle the home key here, so applications
3376        // can never break it, although if keyguard is on, we do let
3377        // it handle it, because that gives us the correct 5 second
3378        // timeout.
3379        if (keyCode == KeyEvent.KEYCODE_HOME) {
3380
3381            // If we have released the home key, and didn't do anything else
3382            // while it was pressed, then it is time to go home!
3383            if (!down) {
3384                cancelPreloadRecentApps();
3385
3386                if (mHasFeatureLeanback) {
3387                    // Clear flags
3388                    mAccessibilityTvKey2Pressed = down;
3389                }
3390
3391                mHomePressed = false;
3392                if (mHomeConsumed) {
3393                    mHomeConsumed = false;
3394                    return -1;
3395                }
3396
3397                if (canceled) {
3398                    Log.i(TAG, "Ignoring HOME; event canceled.");
3399                    return -1;
3400                }
3401
3402                // Delay handling home if a double-tap is possible.
3403                if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
3404                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
3405                    mHomeDoubleTapPending = true;
3406                    mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
3407                            ViewConfiguration.getDoubleTapTimeout());
3408                    return -1;
3409                }
3410
3411                handleShortPressOnHome();
3412                return -1;
3413            }
3414
3415            // If a system window has focus, then it doesn't make sense
3416            // right now to interact with applications.
3417            WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
3418            if (attrs != null) {
3419                final int type = attrs.type;
3420                if (type == TYPE_KEYGUARD_DIALOG
3421                        || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
3422                    // the "app" is keyguard, so give it the key
3423                    return 0;
3424                }
3425                final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
3426                for (int i=0; i<typeCount; i++) {
3427                    if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
3428                        // don't do anything, but also don't pass it to the app
3429                        return -1;
3430                    }
3431                }
3432            }
3433
3434            // Remember that home is pressed and handle special actions.
3435            if (repeatCount == 0) {
3436                mHomePressed = true;
3437                if (mHomeDoubleTapPending) {
3438                    mHomeDoubleTapPending = false;
3439                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
3440                    handleDoubleTapOnHome();
3441                } else if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
3442                    preloadRecentApps();
3443                }
3444            } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
3445                if (mHasFeatureLeanback) {
3446                    mAccessibilityTvKey2Pressed = down;
3447                    if (interceptAccessibilityGestureTv()) {
3448                        return -1;
3449                    }
3450                }
3451
3452                if (!keyguardOn) {
3453                    handleLongPressOnHome(event.getDeviceId());
3454                }
3455            }
3456            return -1;
3457        } else if (keyCode == KeyEvent.KEYCODE_MENU) {
3458            // Hijack modified menu keys for debugging features
3459            final int chordBug = KeyEvent.META_SHIFT_ON;
3460
3461            if (down && repeatCount == 0) {
3462                if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
3463                    Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
3464                    mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
3465                            null, null, null, 0, null, null);
3466                    return -1;
3467                }
3468            }
3469        } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
3470            if (down) {
3471                if (repeatCount == 0) {
3472                    mSearchKeyShortcutPending = true;
3473                    mConsumeSearchKeyUp = false;
3474                }
3475            } else {
3476                mSearchKeyShortcutPending = false;
3477                if (mConsumeSearchKeyUp) {
3478                    mConsumeSearchKeyUp = false;
3479                    return -1;
3480                }
3481            }
3482            return 0;
3483        } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
3484            if (!keyguardOn) {
3485                if (down && repeatCount == 0) {
3486                    preloadRecentApps();
3487                } else if (!down) {
3488                    toggleRecentApps();
3489                }
3490            }
3491            return -1;
3492        } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) {
3493            if (down) {
3494                IStatusBarService service = getStatusBarService();
3495                if (service != null) {
3496                    try {
3497                        service.expandNotificationsPanel();
3498                    } catch (RemoteException e) {
3499                        // do nothing.
3500                    }
3501                }
3502            }
3503        } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed()
3504                && event.isCtrlPressed()) {
3505            if (down && repeatCount == 0) {
3506                int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION
3507                        : TAKE_SCREENSHOT_FULLSCREEN;
3508                mScreenshotRunnable.setScreenshotType(type);
3509                mHandler.post(mScreenshotRunnable);
3510                return -1;
3511            }
3512        } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
3513            if (down && repeatCount == 0 && !isKeyguardLocked()) {
3514                toggleKeyboardShortcutsMenu(event.getDeviceId());
3515            }
3516        } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
3517            if (down) {
3518                if (repeatCount == 0) {
3519                    mAssistKeyLongPressed = false;
3520                } else if (repeatCount == 1) {
3521                    mAssistKeyLongPressed = true;
3522                    if (!keyguardOn) {
3523                         launchAssistLongPressAction();
3524                    }
3525                }
3526            } else {
3527                if (mAssistKeyLongPressed) {
3528                    mAssistKeyLongPressed = false;
3529                } else {
3530                    if (!keyguardOn) {
3531                        launchAssistAction(null, event.getDeviceId());
3532                    }
3533                }
3534            }
3535            return -1;
3536        } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
3537            if (!down) {
3538                Intent voiceIntent;
3539                if (!keyguardOn) {
3540                    voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
3541                } else {
3542                    IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
3543                            ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
3544                    if (dic != null) {
3545                        try {
3546                            dic.exitIdle("voice-search");
3547                        } catch (RemoteException e) {
3548                        }
3549                    }
3550                    voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
3551                    voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
3552                }
3553                startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
3554            }
3555        } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
3556            if (down && repeatCount == 0) {
3557                mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
3558                mHandler.post(mScreenshotRunnable);
3559            }
3560            return -1;
3561        } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP
3562                || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) {
3563            if (down) {
3564                int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
3565
3566                // Disable autobrightness if it's on
3567                int auto = Settings.System.getIntForUser(
3568                        mContext.getContentResolver(),
3569                        Settings.System.SCREEN_BRIGHTNESS_MODE,
3570                        Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3571                        UserHandle.USER_CURRENT_OR_SELF);
3572                if (auto != 0) {
3573                    Settings.System.putIntForUser(mContext.getContentResolver(),
3574                            Settings.System.SCREEN_BRIGHTNESS_MODE,
3575                            Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3576                            UserHandle.USER_CURRENT_OR_SELF);
3577                }
3578
3579                int min = mPowerManager.getMinimumScreenBrightnessSetting();
3580                int max = mPowerManager.getMaximumScreenBrightnessSetting();
3581                int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction;
3582                int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
3583                        Settings.System.SCREEN_BRIGHTNESS,
3584                        mPowerManager.getDefaultScreenBrightnessSetting(),
3585                        UserHandle.USER_CURRENT_OR_SELF);
3586                brightness += step;
3587                // Make sure we don't go beyond the limits.
3588                brightness = Math.min(max, brightness);
3589                brightness = Math.max(min, brightness);
3590
3591                Settings.System.putIntForUser(mContext.getContentResolver(),
3592                        Settings.System.SCREEN_BRIGHTNESS, brightness,
3593                        UserHandle.USER_CURRENT_OR_SELF);
3594                startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
3595                        UserHandle.CURRENT_OR_SELF);
3596            }
3597            return -1;
3598        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
3599                || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3600                || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
3601            if (mUseTvRouting || mHandleVolumeKeysInWM) {
3602                // On TVs or when the configuration is enabled, volume keys never
3603                // go to the foreground app.
3604                dispatchDirectAudioEvent(event);
3605                return -1;
3606            }
3607
3608            // If the device is in Vr mode, drop the volume keys and don't
3609            // forward it to the application/dispatch the audio event.
3610            if (mPersistentVrModeEnabled) {
3611                return -1;
3612            }
3613        } else if (keyCode == KeyEvent.KEYCODE_TAB && event.isMetaPressed()) {
3614            // Pass through keyboard navigation keys.
3615            return 0;
3616        } else if (mHasFeatureLeanback && interceptBugreportGestureTv(keyCode, down)) {
3617            return -1;
3618        } else if (mHasFeatureLeanback && keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
3619            mAccessibilityTvKey1Pressed = down;
3620            if (interceptAccessibilityGestureTv()) {
3621                return -1;
3622            }
3623        }
3624
3625        // Toggle Caps Lock on META-ALT.
3626        boolean actionTriggered = false;
3627        if (KeyEvent.isModifierKey(keyCode)) {
3628            if (!mPendingCapsLockToggle) {
3629                // Start tracking meta state for combo.
3630                mInitialMetaState = mMetaState;
3631                mPendingCapsLockToggle = true;
3632            } else if (event.getAction() == KeyEvent.ACTION_UP) {
3633                int altOnMask = mMetaState & KeyEvent.META_ALT_MASK;
3634                int metaOnMask = mMetaState & KeyEvent.META_META_MASK;
3635
3636                // Check for Caps Lock toggle
3637                if ((metaOnMask != 0) && (altOnMask != 0)) {
3638                    // Check if nothing else is pressed
3639                    if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) {
3640                        // Handle Caps Lock Toggle
3641                        mInputManagerInternal.toggleCapsLock(event.getDeviceId());
3642                        actionTriggered = true;
3643                    }
3644                }
3645
3646                // Always stop tracking when key goes up.
3647                mPendingCapsLockToggle = false;
3648            }
3649        }
3650        // Store current meta state to be able to evaluate it later.
3651        mMetaState = metaState;
3652
3653        if (actionTriggered) {
3654            return -1;
3655        }
3656
3657        if (KeyEvent.isMetaKey(keyCode)) {
3658            if (down) {
3659                mPendingMetaAction = true;
3660            } else if (mPendingMetaAction) {
3661                launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId());
3662            }
3663            return -1;
3664        }
3665
3666        // Shortcuts are invoked through Search+key, so intercept those here
3667        // Any printing key that is chorded with Search should be consumed
3668        // even if no shortcut was invoked.  This prevents text from being
3669        // inadvertently inserted when using a keyboard that has built-in macro
3670        // shortcut keys (that emit Search+x) and some of them are not registered.
3671        if (mSearchKeyShortcutPending) {
3672            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3673            if (kcm.isPrintingKey(keyCode)) {
3674                mConsumeSearchKeyUp = true;
3675                mSearchKeyShortcutPending = false;
3676                if (down && repeatCount == 0 && !keyguardOn) {
3677                    Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
3678                    if (shortcutIntent != null) {
3679                        shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3680                        try {
3681                            startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3682                            dismissKeyboardShortcutsMenu();
3683                        } catch (ActivityNotFoundException ex) {
3684                            Slog.w(TAG, "Dropping shortcut key combination because "
3685                                    + "the activity to which it is registered was not found: "
3686                                    + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);
3687                        }
3688                    } else {
3689                        Slog.i(TAG, "Dropping unregistered shortcut key combination: "
3690                                + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));
3691                    }
3692                }
3693                return -1;
3694            }
3695        }
3696
3697        // Invoke shortcuts using Meta.
3698        if (down && repeatCount == 0 && !keyguardOn
3699                && (metaState & KeyEvent.META_META_ON) != 0) {
3700            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3701            if (kcm.isPrintingKey(keyCode)) {
3702                Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
3703                        metaState & ~(KeyEvent.META_META_ON
3704                                | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
3705                if (shortcutIntent != null) {
3706                    shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3707                    try {
3708                        startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3709                        dismissKeyboardShortcutsMenu();
3710                    } catch (ActivityNotFoundException ex) {
3711                        Slog.w(TAG, "Dropping shortcut key combination because "
3712                                + "the activity to which it is registered was not found: "
3713                                + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
3714                    }
3715                    return -1;
3716                }
3717            }
3718        }
3719
3720        // Handle application launch keys.
3721        if (down && repeatCount == 0 && !keyguardOn) {
3722            String category = sApplicationLaunchKeyCategories.get(keyCode);
3723            if (category != null) {
3724                Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
3725                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3726                try {
3727                    startActivityAsUser(intent, UserHandle.CURRENT);
3728                    dismissKeyboardShortcutsMenu();
3729                } catch (ActivityNotFoundException ex) {
3730                    Slog.w(TAG, "Dropping application launch key because "
3731                            + "the activity to which it is registered was not found: "
3732                            + "keyCode=" + keyCode + ", category=" + category, ex);
3733                }
3734                return -1;
3735            }
3736        }
3737
3738        // Display task switcher for ALT-TAB.
3739        if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
3740            if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
3741                final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
3742                if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
3743                    mRecentAppsHeldModifiers = shiftlessModifiers;
3744                    showRecentApps(true, false);
3745                    return -1;
3746                }
3747            }
3748        } else if (!down && mRecentAppsHeldModifiers != 0
3749                && (metaState & mRecentAppsHeldModifiers) == 0) {
3750            mRecentAppsHeldModifiers = 0;
3751            hideRecentApps(true, false);
3752        }
3753
3754        // Handle input method switching.
3755        if (down && repeatCount == 0
3756                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3757                        || (keyCode == KeyEvent.KEYCODE_SPACE
3758                                && (metaState & KeyEvent.META_META_MASK) != 0))) {
3759            final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0;
3760            mWindowManagerFuncs.switchInputMethod(forwardDirection);
3761            return -1;
3762        }
3763        if (mLanguageSwitchKeyPressed && !down
3764                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3765                        || keyCode == KeyEvent.KEYCODE_SPACE)) {
3766            mLanguageSwitchKeyPressed = false;
3767            return -1;
3768        }
3769
3770        if (isValidGlobalKey(keyCode)
3771                && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
3772            return -1;
3773        }
3774
3775        if (down) {
3776            long shortcutCode = keyCode;
3777            if (event.isCtrlPressed()) {
3778                shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
3779            }
3780
3781            if (event.isAltPressed()) {
3782                shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
3783            }
3784
3785            if (event.isShiftPressed()) {
3786                shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
3787            }
3788
3789            if (event.isMetaPressed()) {
3790                shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE;
3791            }
3792
3793            IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode);
3794            if (shortcutService != null) {
3795                try {
3796                    if (isUserSetupComplete()) {
3797                        shortcutService.notifyShortcutKeyPressed(shortcutCode);
3798                    }
3799                } catch (RemoteException e) {
3800                    mShortcutKeyServices.delete(shortcutCode);
3801                }
3802                return -1;
3803            }
3804        }
3805
3806        // Reserve all the META modifier combos for system behavior
3807        if ((metaState & KeyEvent.META_META_ON) != 0) {
3808            return -1;
3809        }
3810
3811        // Let the application handle the key.
3812        return 0;
3813    }
3814
3815    /**
3816     * TV only: recognizes a remote control gesture for capturing a bug report.
3817     */
3818    private boolean interceptBugreportGestureTv(int keyCode, boolean down) {
3819        // The bugreport capture chord is a long press on DPAD CENTER and BACK simultaneously.
3820        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
3821            mBugreportTvKey1Pressed = down;
3822        } else if (keyCode == KeyEvent.KEYCODE_BACK) {
3823            mBugreportTvKey2Pressed = down;
3824        }
3825
3826        if (mBugreportTvKey1Pressed && mBugreportTvKey2Pressed) {
3827            if (!mBugreportTvScheduled) {
3828                mBugreportTvScheduled = true;
3829                Message msg = Message.obtain(mHandler, MSG_BUGREPORT_TV);
3830                msg.setAsynchronous(true);
3831                mHandler.sendMessageDelayed(msg, BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS);
3832            }
3833        } else if (mBugreportTvScheduled) {
3834            mHandler.removeMessages(MSG_BUGREPORT_TV);
3835            mBugreportTvScheduled = false;
3836        }
3837
3838        return mBugreportTvScheduled;
3839    }
3840
3841    /**
3842     * TV only: recognizes a remote control gesture as Accessibility shortcut.
3843     * Shortcut: Long press (HOME + DPAD_CENTER)
3844     */
3845    private boolean interceptAccessibilityGestureTv() {
3846        if (mAccessibilityTvKey1Pressed && mAccessibilityTvKey2Pressed) {
3847            if (!mAccessibilityTvScheduled) {
3848                mAccessibilityTvScheduled = true;
3849                Message msg = Message.obtain(mHandler, MSG_ACCESSIBILITY_TV);
3850                msg.setAsynchronous(true);
3851                mHandler.sendMessage(msg);
3852            }
3853        } else if (mAccessibilityTvScheduled) {
3854            mHandler.removeMessages(MSG_ACCESSIBILITY_TV);
3855            mAccessibilityTvScheduled = false;
3856        }
3857        return mAccessibilityTvScheduled;
3858    }
3859
3860    private void takeBugreport() {
3861        if ("1".equals(SystemProperties.get("ro.debuggable"))
3862                || Settings.Global.getInt(mContext.getContentResolver(),
3863                        Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) == 1) {
3864            try {
3865                ActivityManager.getService()
3866                        .requestBugReport(ActivityManager.BUGREPORT_OPTION_INTERACTIVE);
3867            } catch (RemoteException e) {
3868                Slog.e(TAG, "Error taking bugreport", e);
3869            }
3870        }
3871    }
3872
3873    /** {@inheritDoc} */
3874    @Override
3875    public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
3876        // Note: This method is only called if the initial down was unhandled.
3877        if (DEBUG_INPUT) {
3878            Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
3879                    + ", flags=" + event.getFlags()
3880                    + ", keyCode=" + event.getKeyCode()
3881                    + ", scanCode=" + event.getScanCode()
3882                    + ", metaState=" + event.getMetaState()
3883                    + ", repeatCount=" + event.getRepeatCount()
3884                    + ", policyFlags=" + policyFlags);
3885        }
3886
3887        KeyEvent fallbackEvent = null;
3888        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3889            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3890            final int keyCode = event.getKeyCode();
3891            final int metaState = event.getMetaState();
3892            final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
3893                    && event.getRepeatCount() == 0;
3894
3895            // Check for fallback actions specified by the key character map.
3896            final FallbackAction fallbackAction;
3897            if (initialDown) {
3898                fallbackAction = kcm.getFallbackAction(keyCode, metaState);
3899            } else {
3900                fallbackAction = mFallbackActions.get(keyCode);
3901            }
3902
3903            if (fallbackAction != null) {
3904                if (DEBUG_INPUT) {
3905                    Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode
3906                            + " metaState=" + Integer.toHexString(fallbackAction.metaState));
3907                }
3908
3909                final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
3910                fallbackEvent = KeyEvent.obtain(
3911                        event.getDownTime(), event.getEventTime(),
3912                        event.getAction(), fallbackAction.keyCode,
3913                        event.getRepeatCount(), fallbackAction.metaState,
3914                        event.getDeviceId(), event.getScanCode(),
3915                        flags, event.getSource(), null);
3916
3917                if (!interceptFallback(win, fallbackEvent, policyFlags)) {
3918                    fallbackEvent.recycle();
3919                    fallbackEvent = null;
3920                }
3921
3922                if (initialDown) {
3923                    mFallbackActions.put(keyCode, fallbackAction);
3924                } else if (event.getAction() == KeyEvent.ACTION_UP) {
3925                    mFallbackActions.remove(keyCode);
3926                    fallbackAction.recycle();
3927                }
3928            }
3929        }
3930
3931        if (DEBUG_INPUT) {
3932            if (fallbackEvent == null) {
3933                Slog.d(TAG, "No fallback.");
3934            } else {
3935                Slog.d(TAG, "Performing fallback: " + fallbackEvent);
3936            }
3937        }
3938        return fallbackEvent;
3939    }
3940
3941    private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
3942        int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
3943        if ((actions & ACTION_PASS_TO_USER) != 0) {
3944            long delayMillis = interceptKeyBeforeDispatching(
3945                    win, fallbackEvent, policyFlags);
3946            if (delayMillis == 0) {
3947                return true;
3948            }
3949        }
3950        return false;
3951    }
3952
3953    @Override
3954    public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
3955            throws RemoteException {
3956        synchronized (mLock) {
3957            IShortcutService service = mShortcutKeyServices.get(shortcutCode);
3958            if (service != null && service.asBinder().pingBinder()) {
3959                throw new RemoteException("Key already exists.");
3960            }
3961
3962            mShortcutKeyServices.put(shortcutCode, shortcutService);
3963        }
3964    }
3965
3966    @Override
3967    public void onKeyguardOccludedChangedLw(boolean occluded) {
3968        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
3969            mPendingKeyguardOccluded = occluded;
3970            mKeyguardOccludedChanged = true;
3971        } else {
3972            setKeyguardOccludedLw(occluded, false /* force */);
3973        }
3974    }
3975
3976    private int handleStartTransitionForKeyguardLw(int transit, @Nullable Animation anim) {
3977        if (mKeyguardOccludedChanged) {
3978            if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded="
3979                    + mPendingKeyguardOccluded);
3980            mKeyguardOccludedChanged = false;
3981            if (setKeyguardOccludedLw(mPendingKeyguardOccluded, false /* force */)) {
3982                return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER;
3983            }
3984        }
3985        if (AppTransition.isKeyguardGoingAwayTransit(transit)) {
3986            if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation");
3987            final long startTime = anim != null
3988                    ? SystemClock.uptimeMillis() + anim.getStartOffset()
3989                    : SystemClock.uptimeMillis();
3990            final long duration = anim != null
3991                    ? anim.getDuration()
3992                    : 0;
3993            startKeyguardExitAnimation(startTime, duration);
3994        }
3995        return 0;
3996    }
3997
3998    private void launchAssistLongPressAction() {
3999        performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
4000        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
4001
4002        // launch the search activity
4003        Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
4004        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
4005        try {
4006            // TODO: This only stops the factory-installed search manager.
4007            // Need to formalize an API to handle others
4008            SearchManager searchManager = getSearchManager();
4009            if (searchManager != null) {
4010                searchManager.stopSearch();
4011            }
4012            startActivityAsUser(intent, UserHandle.CURRENT);
4013        } catch (ActivityNotFoundException e) {
4014            Slog.w(TAG, "No activity to handle assist long press action.", e);
4015        }
4016    }
4017
4018    private void launchAssistAction(String hint, int deviceId) {
4019        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
4020        if (!isUserSetupComplete()) {
4021            // Disable opening assist window during setup
4022            return;
4023        }
4024        Bundle args = null;
4025        if (deviceId > Integer.MIN_VALUE) {
4026            args = new Bundle();
4027            args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
4028        }
4029        if ((mContext.getResources().getConfiguration().uiMode
4030                & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
4031            // On TV, use legacy handling until assistants are implemented in the proper way.
4032            ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
4033                    .launchLegacyAssist(hint, UserHandle.myUserId(), args);
4034        } else {
4035            if (hint != null) {
4036                if (args == null) {
4037                    args = new Bundle();
4038                }
4039                args.putBoolean(hint, true);
4040            }
4041            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4042            if (statusbar != null) {
4043                statusbar.startAssist(args);
4044            }
4045        }
4046    }
4047
4048    private void startActivityAsUser(Intent intent, UserHandle handle) {
4049        if (isUserSetupComplete()) {
4050            mContext.startActivityAsUser(intent, handle);
4051        } else {
4052            Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent);
4053        }
4054    }
4055
4056    private SearchManager getSearchManager() {
4057        if (mSearchManager == null) {
4058            mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
4059        }
4060        return mSearchManager;
4061    }
4062
4063    private void preloadRecentApps() {
4064        mPreloadedRecentApps = true;
4065        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4066        if (statusbar != null) {
4067            statusbar.preloadRecentApps();
4068        }
4069    }
4070
4071    private void cancelPreloadRecentApps() {
4072        if (mPreloadedRecentApps) {
4073            mPreloadedRecentApps = false;
4074            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4075            if (statusbar != null) {
4076                statusbar.cancelPreloadRecentApps();
4077            }
4078        }
4079    }
4080
4081    private void toggleRecentApps() {
4082        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
4083        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4084        if (statusbar != null) {
4085            statusbar.toggleRecentApps();
4086        }
4087    }
4088
4089    @Override
4090    public void showRecentApps(boolean fromHome) {
4091        mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
4092        mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget();
4093    }
4094
4095    private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
4096        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
4097        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4098        if (statusbar != null) {
4099            statusbar.showRecentApps(triggeredFromAltTab, fromHome);
4100        }
4101    }
4102
4103    private void toggleKeyboardShortcutsMenu(int deviceId) {
4104        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4105        if (statusbar != null) {
4106            statusbar.toggleKeyboardShortcutsMenu(deviceId);
4107        }
4108    }
4109
4110    private void dismissKeyboardShortcutsMenu() {
4111        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4112        if (statusbar != null) {
4113            statusbar.dismissKeyboardShortcutsMenu();
4114        }
4115    }
4116
4117    private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
4118        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
4119        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
4120        if (statusbar != null) {
4121            statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
4122        }
4123    }
4124
4125    void launchHomeFromHotKey() {
4126        launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/);
4127    }
4128
4129    /**
4130     * A home key -> launch home action was detected.  Take the appropriate action
4131     * given the situation with the keyguard.
4132     */
4133    void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) {
4134        if (respectKeyguard) {
4135            if (isKeyguardShowingAndNotOccluded()) {
4136                // don't launch home if keyguard showing
4137                return;
4138            }
4139
4140            if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) {
4141                // when in keyguard restricted mode, must first verify unlock
4142                // before launching home
4143                mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
4144                    @Override
4145                    public void onKeyguardExitResult(boolean success) {
4146                        if (success) {
4147                            try {
4148                                ActivityManager.getService().stopAppSwitches();
4149                            } catch (RemoteException e) {
4150                            }
4151                            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
4152                            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
4153                        }
4154                    }
4155                });
4156                return;
4157            }
4158        }
4159
4160        // no keyguard stuff to worry about, just launch home!
4161        try {
4162            ActivityManager.getService().stopAppSwitches();
4163        } catch (RemoteException e) {
4164        }
4165        if (mRecentsVisible) {
4166            // Hide Recents and notify it to launch Home
4167            if (awakenFromDreams) {
4168                awakenDreams();
4169            }
4170            hideRecentApps(false, true);
4171        } else {
4172            // Otherwise, just launch Home
4173            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
4174            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
4175        }
4176    }
4177
4178    private final Runnable mClearHideNavigationFlag = new Runnable() {
4179        @Override
4180        public void run() {
4181            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
4182                // Clear flags.
4183                mForceClearedSystemUiFlags &=
4184                        ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
4185            }
4186            mWindowManagerFuncs.reevaluateStatusBarVisibility();
4187        }
4188    };
4189
4190    /**
4191     * Input handler used while nav bar is hidden.  Captures any touch on the screen,
4192     * to determine when the nav bar should be shown and prevent applications from
4193     * receiving those touches.
4194     */
4195    final class HideNavInputEventReceiver extends InputEventReceiver {
4196        public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
4197            super(inputChannel, looper);
4198        }
4199
4200        @Override
4201        public void onInputEvent(InputEvent event) {
4202            boolean handled = false;
4203            try {
4204                if (event instanceof MotionEvent
4205                        && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
4206                    final MotionEvent motionEvent = (MotionEvent)event;
4207                    if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
4208                        // When the user taps down, we re-show the nav bar.
4209                        boolean changed = false;
4210                        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
4211                            if (mInputConsumer == null) {
4212                                return;
4213                            }
4214                            // Any user activity always causes us to show the
4215                            // navigation controls, if they had been hidden.
4216                            // We also clear the low profile and only content
4217                            // flags so that tapping on the screen will atomically
4218                            // restore all currently hidden screen decorations.
4219                            int newVal = mResettingSystemUiFlags |
4220                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
4221                                    View.SYSTEM_UI_FLAG_LOW_PROFILE |
4222                                    View.SYSTEM_UI_FLAG_FULLSCREEN;
4223                            if (mResettingSystemUiFlags != newVal) {
4224                                mResettingSystemUiFlags = newVal;
4225                                changed = true;
4226                            }
4227                            // We don't allow the system's nav bar to be hidden
4228                            // again for 1 second, to prevent applications from
4229                            // spamming us and keeping it from being shown.
4230                            newVal = mForceClearedSystemUiFlags |
4231                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
4232                            if (mForceClearedSystemUiFlags != newVal) {
4233                                mForceClearedSystemUiFlags = newVal;
4234                                changed = true;
4235                                mHandler.postDelayed(mClearHideNavigationFlag, 1000);
4236                            }
4237                        }
4238                        if (changed) {
4239                            mWindowManagerFuncs.reevaluateStatusBarVisibility();
4240                        }
4241                    }
4242                }
4243            } finally {
4244                finishInputEvent(event, handled);
4245            }
4246        }
4247    }
4248
4249    @Override
4250    public void setRecentsVisibilityLw(boolean visible) {
4251        mRecentsVisible = visible;
4252    }
4253
4254    @Override
4255    public void setPipVisibilityLw(boolean visible) {
4256        mPictureInPictureVisible = visible;
4257    }
4258
4259    @Override
4260    public int adjustSystemUiVisibilityLw(int visibility) {
4261        mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4262        mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4263
4264        // Reset any bits in mForceClearingStatusBarVisibility that
4265        // are now clear.
4266        mResettingSystemUiFlags &= visibility;
4267        // Clear any bits in the new visibility that are currently being
4268        // force cleared, before reporting it.
4269        return visibility & ~mResettingSystemUiFlags
4270                & ~mForceClearedSystemUiFlags;
4271    }
4272
4273    @Override
4274    public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
4275            int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets,
4276            Rect outStableInsets, Rect outOutsets) {
4277        final int fl = PolicyControl.getWindowFlags(null, attrs);
4278        final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
4279        final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
4280
4281        final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
4282        if (useOutsets) {
4283            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
4284            if (outset > 0) {
4285                if (displayRotation == Surface.ROTATION_0) {
4286                    outOutsets.bottom += outset;
4287                } else if (displayRotation == Surface.ROTATION_90) {
4288                    outOutsets.right += outset;
4289                } else if (displayRotation == Surface.ROTATION_180) {
4290                    outOutsets.top += outset;
4291                } else if (displayRotation == Surface.ROTATION_270) {
4292                    outOutsets.left += outset;
4293                }
4294            }
4295        }
4296
4297        if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4298                == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4299            int availRight, availBottom;
4300            if (canHideNavigationBar() &&
4301                    (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
4302                availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4303                availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4304            } else {
4305                availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
4306                availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4307            }
4308            if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4309                if ((fl & FLAG_FULLSCREEN) != 0) {
4310                    outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop,
4311                            availRight - mStableFullscreenRight,
4312                            availBottom - mStableFullscreenBottom);
4313                } else {
4314                    outContentInsets.set(mStableLeft, mStableTop,
4315                            availRight - mStableRight, availBottom - mStableBottom);
4316                }
4317            } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
4318                outContentInsets.setEmpty();
4319            } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
4320                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
4321                outContentInsets.set(mCurLeft, mCurTop,
4322                        availRight - mCurRight, availBottom - mCurBottom);
4323            } else {
4324                outContentInsets.set(mCurLeft, mCurTop,
4325                        availRight - mCurRight, availBottom - mCurBottom);
4326            }
4327
4328            outStableInsets.set(mStableLeft, mStableTop,
4329                    availRight - mStableRight, availBottom - mStableBottom);
4330            if (taskBounds != null) {
4331                calculateRelevantTaskInsets(taskBounds, outContentInsets,
4332                        displayWidth, displayHeight);
4333                calculateRelevantTaskInsets(taskBounds, outStableInsets,
4334                        displayWidth, displayHeight);
4335            }
4336            return mForceShowSystemBars;
4337        }
4338        outContentInsets.setEmpty();
4339        outStableInsets.setEmpty();
4340        return mForceShowSystemBars;
4341    }
4342
4343    /**
4344     * For any given task bounds, the insets relevant for these bounds given the insets relevant
4345     * for the entire display.
4346     */
4347    private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth,
4348            int displayHeight) {
4349        mTmpRect.set(0, 0, displayWidth, displayHeight);
4350        mTmpRect.inset(inOutInsets);
4351        mTmpRect.intersect(taskBounds);
4352        int leftInset = mTmpRect.left - taskBounds.left;
4353        int topInset = mTmpRect.top - taskBounds.top;
4354        int rightInset = taskBounds.right - mTmpRect.right;
4355        int bottomInset = taskBounds.bottom - mTmpRect.bottom;
4356        inOutInsets.set(leftInset, topInset, rightInset, bottomInset);
4357    }
4358
4359    private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
4360        return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
4361                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
4362    }
4363
4364    /** {@inheritDoc} */
4365    @Override
4366    public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
4367                              int displayRotation, int uiMode) {
4368        mDisplayRotation = displayRotation;
4369        final int overscanLeft, overscanTop, overscanRight, overscanBottom;
4370        if (isDefaultDisplay) {
4371            switch (displayRotation) {
4372                case Surface.ROTATION_90:
4373                    overscanLeft = mOverscanTop;
4374                    overscanTop = mOverscanRight;
4375                    overscanRight = mOverscanBottom;
4376                    overscanBottom = mOverscanLeft;
4377                    break;
4378                case Surface.ROTATION_180:
4379                    overscanLeft = mOverscanRight;
4380                    overscanTop = mOverscanBottom;
4381                    overscanRight = mOverscanLeft;
4382                    overscanBottom = mOverscanTop;
4383                    break;
4384                case Surface.ROTATION_270:
4385                    overscanLeft = mOverscanBottom;
4386                    overscanTop = mOverscanLeft;
4387                    overscanRight = mOverscanTop;
4388                    overscanBottom = mOverscanRight;
4389                    break;
4390                default:
4391                    overscanLeft = mOverscanLeft;
4392                    overscanTop = mOverscanTop;
4393                    overscanRight = mOverscanRight;
4394                    overscanBottom = mOverscanBottom;
4395                    break;
4396            }
4397        } else {
4398            overscanLeft = 0;
4399            overscanTop = 0;
4400            overscanRight = 0;
4401            overscanBottom = 0;
4402        }
4403        mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0;
4404        mOverscanScreenTop = mRestrictedOverscanScreenTop = 0;
4405        mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth;
4406        mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight;
4407        mSystemLeft = 0;
4408        mSystemTop = 0;
4409        mSystemRight = displayWidth;
4410        mSystemBottom = displayHeight;
4411        mUnrestrictedScreenLeft = overscanLeft;
4412        mUnrestrictedScreenTop = overscanTop;
4413        mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight;
4414        mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom;
4415        mRestrictedScreenLeft = mUnrestrictedScreenLeft;
4416        mRestrictedScreenTop = mUnrestrictedScreenTop;
4417        mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth;
4418        mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight;
4419        mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft
4420                = mCurLeft = mUnrestrictedScreenLeft;
4421        mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop
4422                = mCurTop = mUnrestrictedScreenTop;
4423        mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight
4424                = mCurRight = displayWidth - overscanRight;
4425        mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom
4426                = mCurBottom = displayHeight - overscanBottom;
4427        mDockLayer = 0x10000000;
4428        mStatusBarLayer = -1;
4429
4430        // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
4431        final Rect pf = mTmpParentFrame;
4432        final Rect df = mTmpDisplayFrame;
4433        final Rect of = mTmpOverscanFrame;
4434        final Rect vf = mTmpVisibleFrame;
4435        final Rect dcf = mTmpDecorFrame;
4436        pf.left = df.left = of.left = vf.left = mDockLeft;
4437        pf.top = df.top = of.top = vf.top = mDockTop;
4438        pf.right = df.right = of.right = vf.right = mDockRight;
4439        pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom;
4440        dcf.setEmpty();  // Decor frame N/A for system bars.
4441
4442        if (isDefaultDisplay) {
4443            // For purposes of putting out fake window up to steal focus, we will
4444            // drive nav being hidden only by whether it is requested.
4445            final int sysui = mLastSystemUiFlags;
4446            boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
4447            boolean navTranslucent = (sysui
4448                    & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
4449            boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
4450            boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
4451            boolean navAllowedHidden = immersive || immersiveSticky;
4452            navTranslucent &= !immersiveSticky;  // transient trumps translucent
4453            boolean isKeyguardShowing = isStatusBarKeyguard() && !mKeyguardOccluded;
4454            if (!isKeyguardShowing) {
4455                navTranslucent &= areTranslucentBarsAllowed();
4456            }
4457            boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null
4458                    && mStatusBar.getAttrs().height == MATCH_PARENT
4459                    && mStatusBar.getAttrs().width == MATCH_PARENT;
4460
4461            // When the navigation bar isn't visible, we put up a fake
4462            // input window to catch all touch events.  This way we can
4463            // detect when the user presses anywhere to bring back the nav
4464            // bar and ensure the application doesn't see the event.
4465            if (navVisible || navAllowedHidden) {
4466                if (mInputConsumer != null) {
4467                    mHandler.sendMessage(
4468                            mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
4469                    mInputConsumer = null;
4470                }
4471            } else if (mInputConsumer == null) {
4472                mInputConsumer = mWindowManagerFuncs.createInputConsumer(mHandler.getLooper(),
4473                        INPUT_CONSUMER_NAVIGATION,
4474                        (channel, looper) -> new HideNavInputEventReceiver(channel, looper));
4475                // As long as mInputConsumer is active, hover events are not dispatched to the app
4476                // and the pointer icon is likely to become stale. Hide it to avoid confusion.
4477                InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL);
4478            }
4479
4480            // For purposes of positioning and showing the nav bar, if we have
4481            // decided that it can't be hidden (because of the screen aspect ratio),
4482            // then take that into account.
4483            navVisible |= !canHideNavigationBar();
4484
4485            boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight,
4486                    displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom, dcf, navVisible, navTranslucent,
4487                    navAllowedHidden, statusBarExpandedNotKeyguard);
4488            if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
4489                    mDockLeft, mDockTop, mDockRight, mDockBottom));
4490            updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing);
4491            if (updateSysUiVisibility) {
4492                updateSystemUiVisibilityLw();
4493            }
4494        }
4495    }
4496
4497    private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui,
4498            boolean isKeyguardShowing) {
4499        // decide where the status bar goes ahead of time
4500        if (mStatusBar != null) {
4501            // apply any navigation bar insets
4502            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4503            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4504            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4505            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
4506                    + mUnrestrictedScreenTop;
4507            vf.left = mStableLeft;
4508            vf.top = mStableTop;
4509            vf.right = mStableRight;
4510            vf.bottom = mStableBottom;
4511
4512            mStatusBarLayer = mStatusBar.getSurfaceLayer();
4513
4514            // Let the status bar determine its size.
4515            mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
4516                    vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
4517                    dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */);
4518
4519            // For layout, the status bar is always at the top with our fixed height.
4520            mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
4521
4522            boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
4523            boolean statusBarTranslucent = (sysui
4524                    & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
4525            if (!isKeyguardShowing) {
4526                statusBarTranslucent &= areTranslucentBarsAllowed();
4527            }
4528
4529            // If the status bar is hidden, we don't want to cause
4530            // windows behind it to scroll.
4531            if (mStatusBar.isVisibleLw() && !statusBarTransient) {
4532                // Status bar may go away, so the screen area it occupies
4533                // is available to apps but just covering them when the
4534                // status bar is visible.
4535                mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
4536
4537                mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4538                mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4539                mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4540                mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4541
4542                if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " +
4543                        String.format(
4544                                "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
4545                                mDockLeft, mDockTop, mDockRight, mDockBottom,
4546                                mContentLeft, mContentTop, mContentRight, mContentBottom,
4547                                mCurLeft, mCurTop, mCurRight, mCurBottom));
4548            }
4549            if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
4550                    && !statusBarTransient && !statusBarTranslucent
4551                    && !mStatusBarController.wasRecentlyTranslucent()) {
4552                // If the opaque status bar is currently requested to be visible,
4553                // and not in the process of animating on or off, then
4554                // we can tell the app that it is covered by it.
4555                mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
4556            }
4557            if (mStatusBarController.checkHiddenLw()) {
4558                return true;
4559            }
4560        }
4561        return false;
4562    }
4563
4564    private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation,
4565            int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf,
4566            boolean navVisible, boolean navTranslucent, boolean navAllowedHidden,
4567            boolean statusBarExpandedNotKeyguard) {
4568        if (mNavigationBar != null) {
4569            boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
4570            // Force the navigation bar to its appropriate place and
4571            // size.  We need to do this directly, instead of relying on
4572            // it to bubble up from the nav bar, because this needs to
4573            // change atomically with screen rotations.
4574            mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight,
4575                    displayRotation);
4576            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
4577                // It's a system nav bar or a portrait screen; nav bar goes on bottom.
4578                int top = displayHeight - overscanBottom
4579                        - getNavigationBarHeight(displayRotation, uiMode);
4580                mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
4581                mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
4582                if (transientNavBarShowing) {
4583                    mNavigationBarController.setBarShowingLw(true);
4584                } else if (navVisible) {
4585                    mNavigationBarController.setBarShowingLw(true);
4586                    mDockBottom = mTmpNavigationFrame.top;
4587                    mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
4588                    mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
4589                } else {
4590                    // We currently want to hide the navigation UI - unless we expanded the status
4591                    // bar.
4592                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4593                }
4594                if (navVisible && !navTranslucent && !navAllowedHidden
4595                        && !mNavigationBar.isAnimatingLw()
4596                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4597                    // If the opaque nav bar is currently requested to be visible,
4598                    // and not in the process of animating on or off, then
4599                    // we can tell the app that it is covered by it.
4600                    mSystemBottom = mTmpNavigationFrame.top;
4601                }
4602            } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4603                // Landscape screen; nav bar goes to the right.
4604                int left = displayWidth - overscanRight
4605                        - getNavigationBarWidth(displayRotation, uiMode);
4606                mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
4607                mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
4608                if (transientNavBarShowing) {
4609                    mNavigationBarController.setBarShowingLw(true);
4610                } else if (navVisible) {
4611                    mNavigationBarController.setBarShowingLw(true);
4612                    mDockRight = mTmpNavigationFrame.left;
4613                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4614                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4615                } else {
4616                    // We currently want to hide the navigation UI - unless we expanded the status
4617                    // bar.
4618                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4619                }
4620                if (navVisible && !navTranslucent && !navAllowedHidden
4621                        && !mNavigationBar.isAnimatingLw()
4622                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4623                    // If the nav bar is currently requested to be visible,
4624                    // and not in the process of animating on or off, then
4625                    // we can tell the app that it is covered by it.
4626                    mSystemRight = mTmpNavigationFrame.left;
4627                }
4628            } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4629                // Seascape screen; nav bar goes to the left.
4630                int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode);
4631                mTmpNavigationFrame.set(overscanLeft, 0, right, displayHeight);
4632                mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right;
4633                if (transientNavBarShowing) {
4634                    mNavigationBarController.setBarShowingLw(true);
4635                } else if (navVisible) {
4636                    mNavigationBarController.setBarShowingLw(true);
4637                    mDockLeft = mTmpNavigationFrame.right;
4638                    // TODO: not so sure about those:
4639                    mRestrictedScreenLeft = mRestrictedOverscanScreenLeft = mDockLeft;
4640                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4641                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4642                } else {
4643                    // We currently want to hide the navigation UI - unless we expanded the status
4644                    // bar.
4645                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4646                }
4647                if (navVisible && !navTranslucent && !navAllowedHidden
4648                        && !mNavigationBar.isAnimatingLw()
4649                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4650                    // If the nav bar is currently requested to be visible,
4651                    // and not in the process of animating on or off, then
4652                    // we can tell the app that it is covered by it.
4653                    mSystemLeft = mTmpNavigationFrame.right;
4654                }
4655            }
4656            // Make sure the content and current rectangles are updated to
4657            // account for the restrictions from the navigation bar.
4658            mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4659            mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4660            mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4661            mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4662            mStatusBarLayer = mNavigationBar.getSurfaceLayer();
4663            // And compute the final frame.
4664            mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
4665                    mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
4666                    mTmpNavigationFrame, mTmpNavigationFrame);
4667            if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
4668            if (mNavigationBarController.checkHiddenLw()) {
4669                return true;
4670            }
4671        }
4672        return false;
4673    }
4674
4675    private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
4676        if (mNavigationBarCanMove && displayWidth > displayHeight) {
4677            if (displayRotation == Surface.ROTATION_270) {
4678                return NAV_BAR_LEFT;
4679            } else {
4680                return NAV_BAR_RIGHT;
4681            }
4682        }
4683        return NAV_BAR_BOTTOM;
4684    }
4685
4686    /** {@inheritDoc} */
4687    @Override
4688    public int getSystemDecorLayerLw() {
4689        if (mStatusBar != null && mStatusBar.isVisibleLw()) {
4690            return mStatusBar.getSurfaceLayer();
4691        }
4692
4693        if (mNavigationBar != null && mNavigationBar.isVisibleLw()) {
4694            return mNavigationBar.getSurfaceLayer();
4695        }
4696
4697        return 0;
4698    }
4699
4700    @Override
4701    public void getContentRectLw(Rect r) {
4702        r.set(mContentLeft, mContentTop, mContentRight, mContentBottom);
4703    }
4704
4705    void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
4706            boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
4707        if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
4708            // Here's a special case: if this attached window is a panel that is
4709            // above the dock window, and the window it is attached to is below
4710            // the dock window, then the frames we computed for the window it is
4711            // attached to can not be used because the dock is effectively part
4712            // of the underlying window and the attached window is floating on top
4713            // of the whole thing.  So, we ignore the attached window and explicitly
4714            // compute the frames that would be appropriate without the dock.
4715            df.left = of.left = cf.left = vf.left = mDockLeft;
4716            df.top = of.top = cf.top = vf.top = mDockTop;
4717            df.right = of.right = cf.right = vf.right = mDockRight;
4718            df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom;
4719        } else {
4720            // The effective display frame of the attached window depends on
4721            // whether it is taking care of insetting its content.  If not,
4722            // we need to use the parent's content frame so that the entire
4723            // window is positioned within that content.  Otherwise we can use
4724            // the overscan frame and let the attached window take care of
4725            // positioning its content appropriately.
4726            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4727                // Set the content frame of the attached window to the parent's decor frame
4728                // (same as content frame when IME isn't present) if specifically requested by
4729                // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
4730                // Otherwise, use the overscan frame.
4731                cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
4732                        ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
4733            } else {
4734                // If the window is resizing, then we want to base the content
4735                // frame on our attached content frame to resize...  however,
4736                // things can be tricky if the attached window is NOT in resize
4737                // mode, in which case its content frame will be larger.
4738                // Ungh.  So to deal with that, make sure the content frame
4739                // we end up using is not covering the IM dock.
4740                cf.set(attached.getContentFrameLw());
4741                if (attached.isVoiceInteraction()) {
4742                    if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft;
4743                    if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop;
4744                    if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight;
4745                    if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom;
4746                } else if (attached.getSurfaceLayer() < mDockLayer) {
4747                    if (cf.left < mContentLeft) cf.left = mContentLeft;
4748                    if (cf.top < mContentTop) cf.top = mContentTop;
4749                    if (cf.right > mContentRight) cf.right = mContentRight;
4750                    if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
4751                }
4752            }
4753            df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
4754            of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
4755            vf.set(attached.getVisibleFrameLw());
4756        }
4757        // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
4758        // window should be positioned relative to its parent or the entire
4759        // screen.
4760        pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
4761                ? attached.getFrameLw() : df);
4762    }
4763
4764    private void applyStableConstraints(int sysui, int fl, Rect r) {
4765        if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4766            // If app is requesting a stable layout, don't let the
4767            // content insets go below the stable values.
4768            if ((fl & FLAG_FULLSCREEN) != 0) {
4769                if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft;
4770                if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop;
4771                if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight;
4772                if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom;
4773            } else {
4774                if (r.left < mStableLeft) r.left = mStableLeft;
4775                if (r.top < mStableTop) r.top = mStableTop;
4776                if (r.right > mStableRight) r.right = mStableRight;
4777                if (r.bottom > mStableBottom) r.bottom = mStableBottom;
4778            }
4779        }
4780    }
4781
4782    private boolean canReceiveInput(WindowState win) {
4783        boolean notFocusable =
4784                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
4785        boolean altFocusableIm =
4786                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
4787        boolean notFocusableForIm = notFocusable ^ altFocusableIm;
4788        return !notFocusableForIm;
4789    }
4790
4791    /** {@inheritDoc} */
4792    @Override
4793    public void layoutWindowLw(WindowState win, WindowState attached) {
4794        // We've already done the navigation bar and status bar. If the status bar can receive
4795        // input, we need to layout it again to accomodate for the IME window.
4796        if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) {
4797            return;
4798        }
4799        final WindowManager.LayoutParams attrs = win.getAttrs();
4800        final boolean isDefaultDisplay = win.isDefaultDisplay();
4801        final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
4802                (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
4803        if (needsToOffsetInputMethodTarget) {
4804            if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
4805            offsetInputMethodWindowLw(mLastInputMethodWindow);
4806        }
4807
4808        final int fl = PolicyControl.getWindowFlags(win, attrs);
4809        final int pfl = attrs.privateFlags;
4810        final int sim = attrs.softInputMode;
4811        final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
4812
4813        final Rect pf = mTmpParentFrame;
4814        final Rect df = mTmpDisplayFrame;
4815        final Rect of = mTmpOverscanFrame;
4816        final Rect cf = mTmpContentFrame;
4817        final Rect vf = mTmpVisibleFrame;
4818        final Rect dcf = mTmpDecorFrame;
4819        final Rect sf = mTmpStableFrame;
4820        Rect osf = null;
4821        dcf.setEmpty();
4822
4823        final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
4824                && mNavigationBar != null && mNavigationBar.isVisibleLw());
4825
4826        final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
4827
4828        if (isDefaultDisplay) {
4829            sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom);
4830        } else {
4831            sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom);
4832        }
4833
4834        if (!isDefaultDisplay) {
4835            if (attached != null) {
4836                // If this window is attached to another, our display
4837                // frame is the same as the one we are attached to.
4838                setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4839            } else {
4840                // Give the window full screen.
4841                pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4842                pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4843                pf.right = df.right = of.right = cf.right
4844                        = mOverscanScreenLeft + mOverscanScreenWidth;
4845                pf.bottom = df.bottom = of.bottom = cf.bottom
4846                        = mOverscanScreenTop + mOverscanScreenHeight;
4847            }
4848        } else if (attrs.type == TYPE_INPUT_METHOD) {
4849            pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
4850            pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
4851            pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
4852            // IM dock windows layout below the nav bar...
4853            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4854            // ...with content insets above the nav bar
4855            cf.bottom = vf.bottom = mStableBottom;
4856            if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
4857                // The status bar forces the navigation bar while it's visible. Make sure the IME
4858                // avoids the navigation bar in that case.
4859                if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4860                    pf.right = df.right = of.right = cf.right = vf.right = mStableRight;
4861                } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4862                    pf.left = df.left = of.left = cf.left = vf.left = mStableLeft;
4863                }
4864            }
4865            // IM dock windows always go to the bottom of the screen.
4866            attrs.gravity = Gravity.BOTTOM;
4867            mDockLayer = win.getSurfaceLayer();
4868        } else if (attrs.type == TYPE_VOICE_INTERACTION) {
4869            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4870            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4871            pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4872            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4873            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4874                cf.left = mDockLeft;
4875                cf.top = mDockTop;
4876                cf.right = mDockRight;
4877                cf.bottom = mDockBottom;
4878            } else {
4879                cf.left = mContentLeft;
4880                cf.top = mContentTop;
4881                cf.right = mContentRight;
4882                cf.bottom = mContentBottom;
4883            }
4884            if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4885                vf.left = mCurLeft;
4886                vf.top = mCurTop;
4887                vf.right = mCurRight;
4888                vf.bottom = mCurBottom;
4889            } else {
4890                vf.set(cf);
4891            }
4892        } else if (attrs.type == TYPE_WALLPAPER) {
4893           layoutWallpaper(win, pf, df, of, cf);
4894        } else if (win == mStatusBar) {
4895            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4896            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4897            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4898            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop;
4899            cf.left = vf.left = mStableLeft;
4900            cf.top = vf.top = mStableTop;
4901            cf.right = vf.right = mStableRight;
4902            vf.bottom = mStableBottom;
4903
4904            if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
4905                cf.bottom = mContentBottom;
4906            } else {
4907                cf.bottom = mDockBottom;
4908                vf.bottom = mContentBottom;
4909            }
4910        } else {
4911
4912            // Default policy decor for the default display
4913            dcf.left = mSystemLeft;
4914            dcf.top = mSystemTop;
4915            dcf.right = mSystemRight;
4916            dcf.bottom = mSystemBottom;
4917            final boolean inheritTranslucentDecor = (attrs.privateFlags
4918                    & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0;
4919            final boolean isAppWindow =
4920                    attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW &&
4921                    attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
4922            final boolean topAtRest =
4923                    win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
4924            if (isAppWindow && !inheritTranslucentDecor && !topAtRest) {
4925                if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
4926                        && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0
4927                        && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
4928                        && (fl & WindowManager.LayoutParams.
4929                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
4930                        && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) {
4931                    // Ensure policy decor includes status bar
4932                    dcf.top = mStableTop;
4933                }
4934                if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0
4935                        && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
4936                        && (fl & WindowManager.LayoutParams.
4937                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
4938                    // Ensure policy decor includes navigation bar
4939                    dcf.bottom = mStableBottom;
4940                    dcf.right = mStableRight;
4941                }
4942            }
4943
4944            if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4945                    == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4946                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
4947                            + "): IN_SCREEN, INSET_DECOR");
4948                // This is the case for a normal activity window: we want it
4949                // to cover all of the screen space, and it can take care of
4950                // moving its contents to account for screen decorations that
4951                // intrude into that space.
4952                if (attached != null) {
4953                    // If this window is attached to another, our display
4954                    // frame is the same as the one we are attached to.
4955                    setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4956                } else {
4957                    if (attrs.type == TYPE_STATUS_BAR_PANEL
4958                            || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
4959                        // Status bar panels are the only windows who can go on top of
4960                        // the status bar.  They are protected by the STATUS_BAR_SERVICE
4961                        // permission, so they have the same privileges as the status
4962                        // bar itself.
4963                        //
4964                        // However, they should still dodge the navigation bar if it exists.
4965
4966                        pf.left = df.left = of.left = hasNavBar
4967                                ? mDockLeft : mUnrestrictedScreenLeft;
4968                        pf.top = df.top = of.top = mUnrestrictedScreenTop;
4969                        pf.right = df.right = of.right = hasNavBar
4970                                ? mRestrictedScreenLeft+mRestrictedScreenWidth
4971                                : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4972                        pf.bottom = df.bottom = of.bottom = hasNavBar
4973                                ? mRestrictedScreenTop+mRestrictedScreenHeight
4974                                : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4975
4976                        if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4977                                        "Laying out status bar window: (%d,%d - %d,%d)",
4978                                        pf.left, pf.top, pf.right, pf.bottom));
4979                    } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4980                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4981                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4982                        // Asking to layout into the overscan region, so give it that pure
4983                        // unrestricted area.
4984                        pf.left = df.left = of.left = mOverscanScreenLeft;
4985                        pf.top = df.top = of.top = mOverscanScreenTop;
4986                        pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth;
4987                        pf.bottom = df.bottom = of.bottom = mOverscanScreenTop
4988                                + mOverscanScreenHeight;
4989                    } else if (canHideNavigationBar()
4990                            && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4991                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4992                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4993                        // Asking for layout as if the nav bar is hidden, lets the
4994                        // application extend into the unrestricted overscan screen area.  We
4995                        // only do this for application windows to ensure no window that
4996                        // can be above the nav bar can do this.
4997                        pf.left = df.left = mOverscanScreenLeft;
4998                        pf.top = df.top = mOverscanScreenTop;
4999                        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
5000                        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
5001                        // We need to tell the app about where the frame inside the overscan
5002                        // is, so it can inset its content by that amount -- it didn't ask
5003                        // to actually extend itself into the overscan region.
5004                        of.left = mUnrestrictedScreenLeft;
5005                        of.top = mUnrestrictedScreenTop;
5006                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5007                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5008                    } else {
5009                        pf.left = df.left = mRestrictedOverscanScreenLeft;
5010                        pf.top = df.top = mRestrictedOverscanScreenTop;
5011                        pf.right = df.right = mRestrictedOverscanScreenLeft
5012                                + mRestrictedOverscanScreenWidth;
5013                        pf.bottom = df.bottom = mRestrictedOverscanScreenTop
5014                                + mRestrictedOverscanScreenHeight;
5015                        // We need to tell the app about where the frame inside the overscan
5016                        // is, so it can inset its content by that amount -- it didn't ask
5017                        // to actually extend itself into the overscan region.
5018                        of.left = mUnrestrictedScreenLeft;
5019                        of.top = mUnrestrictedScreenTop;
5020                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5021                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5022                    }
5023
5024                    if ((fl & FLAG_FULLSCREEN) == 0) {
5025                        if (win.isVoiceInteraction()) {
5026                            cf.left = mVoiceContentLeft;
5027                            cf.top = mVoiceContentTop;
5028                            cf.right = mVoiceContentRight;
5029                            cf.bottom = mVoiceContentBottom;
5030                        } else {
5031                            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5032                                cf.left = mDockLeft;
5033                                cf.top = mDockTop;
5034                                cf.right = mDockRight;
5035                                cf.bottom = mDockBottom;
5036                            } else {
5037                                cf.left = mContentLeft;
5038                                cf.top = mContentTop;
5039                                cf.right = mContentRight;
5040                                cf.bottom = mContentBottom;
5041                            }
5042                        }
5043                    } else {
5044                        // Full screen windows are always given a layout that is as if the
5045                        // status bar and other transient decors are gone.  This is to avoid
5046                        // bad states when moving from a window that is not hding the
5047                        // status bar to one that is.
5048                        cf.left = mRestrictedScreenLeft;
5049                        cf.top = mRestrictedScreenTop;
5050                        cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
5051                        cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight;
5052                    }
5053                    applyStableConstraints(sysUiFl, fl, cf);
5054                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5055                        vf.left = mCurLeft;
5056                        vf.top = mCurTop;
5057                        vf.right = mCurRight;
5058                        vf.bottom = mCurBottom;
5059                    } else {
5060                        vf.set(cf);
5061                    }
5062                }
5063            } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
5064                    & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
5065                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
5066                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5067                        "): IN_SCREEN");
5068                // A window that has requested to fill the entire screen just
5069                // gets everything, period.
5070                if (attrs.type == TYPE_STATUS_BAR_PANEL
5071                        || attrs.type == TYPE_STATUS_BAR_SUB_PANEL
5072                        || attrs.type == TYPE_VOLUME_OVERLAY) {
5073                    pf.left = df.left = of.left = cf.left = hasNavBar
5074                            ? mDockLeft : mUnrestrictedScreenLeft;
5075                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
5076                    pf.right = df.right = of.right = cf.right = hasNavBar
5077                                        ? mRestrictedScreenLeft+mRestrictedScreenWidth
5078                                        : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5079                    pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar
5080                                          ? mRestrictedScreenTop+mRestrictedScreenHeight
5081                                          : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5082                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
5083                                    "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
5084                                    pf.left, pf.top, pf.right, pf.bottom));
5085                } else if (attrs.type == TYPE_NAVIGATION_BAR
5086                        || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
5087                    // The navigation bar has Real Ultimate Power.
5088                    pf.left = df.left = of.left = mUnrestrictedScreenLeft;
5089                    pf.top = df.top = of.top = mUnrestrictedScreenTop;
5090                    pf.right = df.right = of.right = mUnrestrictedScreenLeft
5091                            + mUnrestrictedScreenWidth;
5092                    pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop
5093                            + mUnrestrictedScreenHeight;
5094                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
5095                                    "Laying out navigation bar window: (%d,%d - %d,%d)",
5096                                    pf.left, pf.top, pf.right, pf.bottom));
5097                } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
5098                                || attrs.type == TYPE_BOOT_PROGRESS
5099                                || attrs.type == TYPE_SCREENSHOT)
5100                        && ((fl & FLAG_FULLSCREEN) != 0)) {
5101                    // Fullscreen secure system overlays get what they ask for. Screenshot region
5102                    // selection overlay should also expand to full screen.
5103                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
5104                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
5105                    pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
5106                            + mOverscanScreenWidth;
5107                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
5108                            + mOverscanScreenHeight;
5109                } else if (attrs.type == TYPE_BOOT_PROGRESS) {
5110                    // Boot progress screen always covers entire display.
5111                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
5112                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
5113                    pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
5114                            + mOverscanScreenWidth;
5115                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
5116                            + mOverscanScreenHeight;
5117                } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
5118                        && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
5119                        && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
5120                    // Asking to layout into the overscan region, so give it that pure
5121                    // unrestricted area.
5122                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
5123                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
5124                    pf.right = df.right = of.right = cf.right
5125                            = mOverscanScreenLeft + mOverscanScreenWidth;
5126                    pf.bottom = df.bottom = of.bottom = cf.bottom
5127                            = mOverscanScreenTop + mOverscanScreenHeight;
5128                } else if (canHideNavigationBar()
5129                        && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
5130                        && (attrs.type == TYPE_STATUS_BAR
5131                            || attrs.type == TYPE_TOAST
5132                            || attrs.type == TYPE_DOCK_DIVIDER
5133                            || attrs.type == TYPE_VOICE_INTERACTION_STARTING
5134                            || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
5135                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
5136                    // Asking for layout as if the nav bar is hidden, lets the
5137                    // application extend into the unrestricted screen area.  We
5138                    // only do this for application windows (or toasts) to ensure no window that
5139                    // can be above the nav bar can do this.
5140                    // XXX This assumes that an app asking for this will also
5141                    // ask for layout in only content.  We can't currently figure out
5142                    // what the screen would be if only laying out to hide the nav bar.
5143                    pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
5144                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
5145                    pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft
5146                            + mUnrestrictedScreenWidth;
5147                    pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
5148                            + mUnrestrictedScreenHeight;
5149                } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
5150                    pf.left = df.left = of.left = mRestrictedScreenLeft;
5151                    pf.top = df.top = of.top  = mRestrictedScreenTop;
5152                    pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
5153                    pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop
5154                            + mRestrictedScreenHeight;
5155                    if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5156                        cf.left = mDockLeft;
5157                        cf.top = mDockTop;
5158                        cf.right = mDockRight;
5159                        cf.bottom = mDockBottom;
5160                    } else {
5161                        cf.left = mContentLeft;
5162                        cf.top = mContentTop;
5163                        cf.right = mContentRight;
5164                        cf.bottom = mContentBottom;
5165                    }
5166                } else {
5167                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
5168                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
5169                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
5170                            + mRestrictedScreenWidth;
5171                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
5172                            + mRestrictedScreenHeight;
5173                }
5174
5175                applyStableConstraints(sysUiFl, fl, cf);
5176
5177                if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5178                    vf.left = mCurLeft;
5179                    vf.top = mCurTop;
5180                    vf.right = mCurRight;
5181                    vf.bottom = mCurBottom;
5182                } else {
5183                    vf.set(cf);
5184                }
5185            } else if (attached != null) {
5186                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5187                        "): attached to " + attached);
5188                // A child window should be placed inside of the same visible
5189                // frame that its parent had.
5190                setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf);
5191            } else {
5192                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
5193                        "): normal window");
5194                // Otherwise, a normal window must be placed inside the content
5195                // of all screen decorations.
5196                if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) {
5197                    // Status bar panels and the volume dialog are the only windows who can go on
5198                    // top of the status bar.  They are protected by the STATUS_BAR_SERVICE
5199                    // permission, so they have the same privileges as the status
5200                    // bar itself.
5201                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
5202                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
5203                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
5204                            + mRestrictedScreenWidth;
5205                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
5206                            + mRestrictedScreenHeight;
5207                } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) {
5208                    // These dialogs are stable to interim decor changes.
5209                    pf.left = df.left = of.left = cf.left = mStableLeft;
5210                    pf.top = df.top = of.top = cf.top = mStableTop;
5211                    pf.right = df.right = of.right = cf.right = mStableRight;
5212                    pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom;
5213                } else {
5214                    pf.left = mContentLeft;
5215                    pf.top = mContentTop;
5216                    pf.right = mContentRight;
5217                    pf.bottom = mContentBottom;
5218                    if (win.isVoiceInteraction()) {
5219                        df.left = of.left = cf.left = mVoiceContentLeft;
5220                        df.top = of.top = cf.top = mVoiceContentTop;
5221                        df.right = of.right = cf.right = mVoiceContentRight;
5222                        df.bottom = of.bottom = cf.bottom = mVoiceContentBottom;
5223                    } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5224                        df.left = of.left = cf.left = mDockLeft;
5225                        df.top = of.top = cf.top = mDockTop;
5226                        df.right = of.right = cf.right = mDockRight;
5227                        df.bottom = of.bottom = cf.bottom = mDockBottom;
5228                    } else {
5229                        df.left = of.left = cf.left = mContentLeft;
5230                        df.top = of.top = cf.top = mContentTop;
5231                        df.right = of.right = cf.right = mContentRight;
5232                        df.bottom = of.bottom = cf.bottom = mContentBottom;
5233                    }
5234                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5235                        vf.left = mCurLeft;
5236                        vf.top = mCurTop;
5237                        vf.right = mCurRight;
5238                        vf.bottom = mCurBottom;
5239                    } else {
5240                        vf.set(cf);
5241                    }
5242                }
5243            }
5244        }
5245
5246        // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
5247        // Also, we don't allow windows in multi-window mode to extend out of the screen.
5248        if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR
5249                && !win.isInMultiWindowMode()) {
5250            df.left = df.top = -10000;
5251            df.right = df.bottom = 10000;
5252            if (attrs.type != TYPE_WALLPAPER) {
5253                of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
5254                of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
5255            }
5256        }
5257
5258        // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we
5259        // need to provide information to the clients that want to pretend that you can draw there.
5260        // We only want to apply outsets to certain types of windows. For example, we never want to
5261        // apply the outsets to floating dialogs, because they wouldn't make sense there.
5262        final boolean useOutsets = shouldUseOutsets(attrs, fl);
5263        if (isDefaultDisplay && useOutsets) {
5264            osf = mTmpOutsetFrame;
5265            osf.set(cf.left, cf.top, cf.right, cf.bottom);
5266            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
5267            if (outset > 0) {
5268                int rotation = mDisplayRotation;
5269                if (rotation == Surface.ROTATION_0) {
5270                    osf.bottom += outset;
5271                } else if (rotation == Surface.ROTATION_90) {
5272                    osf.right += outset;
5273                } else if (rotation == Surface.ROTATION_180) {
5274                    osf.top -= outset;
5275                } else if (rotation == Surface.ROTATION_270) {
5276                    osf.left -= outset;
5277                }
5278                if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset
5279                        + " with rotation " + rotation + ", result: " + osf);
5280            }
5281        }
5282
5283        if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
5284                + ": sim=#" + Integer.toHexString(sim)
5285                + " attach=" + attached + " type=" + attrs.type
5286                + String.format(" flags=0x%08x", fl)
5287                + " pf=" + pf.toShortString() + " df=" + df.toShortString()
5288                + " of=" + of.toShortString()
5289                + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
5290                + " dcf=" + dcf.toShortString()
5291                + " sf=" + sf.toShortString()
5292                + " osf=" + (osf == null ? "null" : osf.toShortString()));
5293
5294        win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf);
5295
5296        // Dock windows carve out the bottom of the screen, so normal windows
5297        // can't appear underneath them.
5298        if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleLw()
5299                && !win.getGivenInsetsPendingLw()) {
5300            setLastInputMethodWindowLw(null, null);
5301            offsetInputMethodWindowLw(win);
5302        }
5303        if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleLw()
5304                && !win.getGivenInsetsPendingLw()) {
5305            offsetVoiceInputWindowLw(win);
5306        }
5307    }
5308
5309    private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) {
5310
5311        // The wallpaper also has Real Ultimate Power, but we want to tell
5312        // it about the overscan area.
5313        pf.left = df.left = mOverscanScreenLeft;
5314        pf.top = df.top = mOverscanScreenTop;
5315        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
5316        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
5317        of.left = cf.left = mUnrestrictedScreenLeft;
5318        of.top = cf.top = mUnrestrictedScreenTop;
5319        of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5320        of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5321    }
5322
5323    private void offsetInputMethodWindowLw(WindowState win) {
5324        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5325        top += win.getGivenContentInsetsLw().top;
5326        if (mContentBottom > top) {
5327            mContentBottom = top;
5328        }
5329        if (mVoiceContentBottom > top) {
5330            mVoiceContentBottom = top;
5331        }
5332        top = win.getVisibleFrameLw().top;
5333        top += win.getGivenVisibleInsetsLw().top;
5334        if (mCurBottom > top) {
5335            mCurBottom = top;
5336        }
5337        if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
5338                + mDockBottom + " mContentBottom="
5339                + mContentBottom + " mCurBottom=" + mCurBottom);
5340    }
5341
5342    private void offsetVoiceInputWindowLw(WindowState win) {
5343        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5344        top += win.getGivenContentInsetsLw().top;
5345        if (mVoiceContentBottom > top) {
5346            mVoiceContentBottom = top;
5347        }
5348    }
5349
5350    /** {@inheritDoc} */
5351    @Override
5352    public void finishLayoutLw() {
5353        return;
5354    }
5355
5356    /** {@inheritDoc} */
5357    @Override
5358    public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
5359        mTopFullscreenOpaqueWindowState = null;
5360        mTopFullscreenOpaqueOrDimmingWindowState = null;
5361        mTopDockedOpaqueWindowState = null;
5362        mTopDockedOpaqueOrDimmingWindowState = null;
5363        mForceStatusBar = false;
5364        mForceStatusBarFromKeyguard = false;
5365        mForceStatusBarTransparent = false;
5366        mForcingShowNavBar = false;
5367        mForcingShowNavBarLayer = -1;
5368
5369        mAllowLockscreenWhenOn = false;
5370        mShowingDream = false;
5371    }
5372
5373    /** {@inheritDoc} */
5374    @Override
5375    public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
5376            WindowState attached, WindowState imeTarget) {
5377        final boolean affectsSystemUi = win.canAffectSystemUiFlags();
5378        if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": affectsSystemUi=" + affectsSystemUi);
5379        applyKeyguardPolicyLw(win, imeTarget);
5380        final int fl = PolicyControl.getWindowFlags(win, attrs);
5381        if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi
5382                && attrs.type == TYPE_INPUT_METHOD) {
5383            mForcingShowNavBar = true;
5384            mForcingShowNavBarLayer = win.getSurfaceLayer();
5385        }
5386        if (attrs.type == TYPE_STATUS_BAR) {
5387            if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
5388                mForceStatusBarFromKeyguard = true;
5389            }
5390            if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
5391                mForceStatusBarTransparent = true;
5392            }
5393        }
5394
5395        boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
5396                && attrs.type < FIRST_SYSTEM_WINDOW;
5397        final int stackId = win.getStackId();
5398        if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi) {
5399            if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
5400                mForceStatusBar = true;
5401            }
5402            if (attrs.type == TYPE_DREAM) {
5403                // If the lockscreen was showing when the dream started then wait
5404                // for the dream to draw before hiding the lockscreen.
5405                if (!mDreamingLockscreen
5406                        || (win.isVisibleLw() && win.hasDrawnLw())) {
5407                    mShowingDream = true;
5408                    appWindow = true;
5409                }
5410            }
5411
5412            // For app windows that are not attached, we decide if all windows in the app they
5413            // represent should be hidden or if we should hide the lockscreen. For attached app
5414            // windows we defer the decision to the window it is attached to.
5415            if (appWindow && attached == null) {
5416                if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
5417                    if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
5418                    mTopFullscreenOpaqueWindowState = win;
5419                    if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5420                        mTopFullscreenOpaqueOrDimmingWindowState = win;
5421                    }
5422                    if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
5423                        mAllowLockscreenWhenOn = true;
5424                    }
5425                }
5426            }
5427        }
5428
5429        // Voice interaction overrides both top fullscreen and top docked.
5430        if (affectsSystemUi && win.getAttrs().type == TYPE_VOICE_INTERACTION) {
5431            if (mTopFullscreenOpaqueWindowState == null) {
5432                mTopFullscreenOpaqueWindowState = win;
5433                if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5434                    mTopFullscreenOpaqueOrDimmingWindowState = win;
5435                }
5436            }
5437            if (mTopDockedOpaqueWindowState == null) {
5438                mTopDockedOpaqueWindowState = win;
5439                if (mTopDockedOpaqueOrDimmingWindowState == null) {
5440                    mTopDockedOpaqueOrDimmingWindowState = win;
5441                }
5442            }
5443        }
5444
5445        // Keep track of the window if it's dimming but not necessarily fullscreen.
5446        if (mTopFullscreenOpaqueOrDimmingWindowState == null && affectsSystemUi
5447                && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
5448            mTopFullscreenOpaqueOrDimmingWindowState = win;
5449        }
5450
5451        // We need to keep track of the top "fullscreen" opaque window for the docked stack
5452        // separately, because both the "real fullscreen" opaque window and the one for the docked
5453        // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
5454        if (mTopDockedOpaqueWindowState == null && affectsSystemUi && appWindow && attached == null
5455                && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
5456            mTopDockedOpaqueWindowState = win;
5457            if (mTopDockedOpaqueOrDimmingWindowState == null) {
5458                mTopDockedOpaqueOrDimmingWindowState = win;
5459            }
5460        }
5461
5462        // Also keep track of any windows that are dimming but not necessarily fullscreen in the
5463        // docked stack.
5464        if (mTopDockedOpaqueOrDimmingWindowState == null && affectsSystemUi && win.isDimming()
5465                && stackId == DOCKED_STACK_ID) {
5466            mTopDockedOpaqueOrDimmingWindowState = win;
5467        }
5468    }
5469
5470    private void applyKeyguardPolicyLw(WindowState win, WindowState imeTarget) {
5471        if (canBeHiddenByKeyguardLw(win)) {
5472            if (shouldBeHiddenByKeyguard(win, imeTarget)) {
5473                win.hideLw(false /* doAnimation */);
5474            } else {
5475                win.showLw(false /* doAnimation */);
5476            }
5477        }
5478    }
5479
5480    private boolean isFullscreen(WindowManager.LayoutParams attrs) {
5481        return attrs.x == 0 && attrs.y == 0
5482                && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
5483                && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
5484    }
5485
5486    /** {@inheritDoc} */
5487    @Override
5488    public int finishPostLayoutPolicyLw() {
5489        int changes = 0;
5490        boolean topIsFullscreen = false;
5491
5492        final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
5493                ? mTopFullscreenOpaqueWindowState.getAttrs()
5494                : null;
5495
5496        // If we are not currently showing a dream then remember the current
5497        // lockscreen state.  We will use this to determine whether the dream
5498        // started while the lockscreen was showing and remember this state
5499        // while the dream is showing.
5500        if (!mShowingDream) {
5501            mDreamingLockscreen = isKeyguardShowingAndNotOccluded();
5502            if (mDreamingSleepTokenNeeded) {
5503                mDreamingSleepTokenNeeded = false;
5504                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
5505            }
5506        } else {
5507            if (!mDreamingSleepTokenNeeded) {
5508                mDreamingSleepTokenNeeded = true;
5509                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget();
5510            }
5511        }
5512
5513        if (mStatusBar != null) {
5514            if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
5515                    + " forcefkg=" + mForceStatusBarFromKeyguard
5516                    + " top=" + mTopFullscreenOpaqueWindowState);
5517            boolean shouldBeTransparent = mForceStatusBarTransparent
5518                    && !mForceStatusBar
5519                    && !mForceStatusBarFromKeyguard;
5520            if (!shouldBeTransparent) {
5521                mStatusBarController.setShowTransparent(false /* transparent */);
5522            } else if (!mStatusBar.isVisibleLw()) {
5523                mStatusBarController.setShowTransparent(true /* transparent */);
5524            }
5525
5526            WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs();
5527            boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT
5528                    && statusBarAttrs.width == MATCH_PARENT;
5529            if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
5530                    || statusBarExpanded) {
5531                if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
5532                if (mStatusBarController.setBarShowingLw(true)) {
5533                    changes |= FINISH_LAYOUT_REDO_LAYOUT;
5534                }
5535                // Maintain fullscreen layout until incoming animation is complete.
5536                topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
5537                // Transient status bar on the lockscreen is not allowed
5538                if ((mForceStatusBarFromKeyguard || statusBarExpanded)
5539                        && mStatusBarController.isTransientShowing()) {
5540                    mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
5541                            mLastSystemUiFlags, mLastSystemUiFlags);
5542                }
5543                if (statusBarExpanded && mNavigationBar != null) {
5544                    if (mNavigationBarController.setBarShowingLw(true)) {
5545                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5546                    }
5547                }
5548            } else if (mTopFullscreenOpaqueWindowState != null) {
5549                final int fl = PolicyControl.getWindowFlags(null, lp);
5550                if (localLOGV) {
5551                    Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
5552                            + " shown position: "
5553                            + mTopFullscreenOpaqueWindowState.getShownPositionLw());
5554                    Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
5555                            + " lp.flags=0x" + Integer.toHexString(fl));
5556                }
5557                topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
5558                        || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
5559                // The subtle difference between the window for mTopFullscreenOpaqueWindowState
5560                // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
5561                // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
5562                // case though.
5563                if (mStatusBarController.isTransientShowing()) {
5564                    if (mStatusBarController.setBarShowingLw(true)) {
5565                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5566                    }
5567                } else if (topIsFullscreen
5568                        && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)
5569                        && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) {
5570                    if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
5571                    if (mStatusBarController.setBarShowingLw(false)) {
5572                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5573                    } else {
5574                        if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
5575                    }
5576                } else {
5577                    if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
5578                    if (mStatusBarController.setBarShowingLw(true)) {
5579                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5580                    }
5581                }
5582            }
5583        }
5584
5585        if (mTopIsFullscreen != topIsFullscreen) {
5586            if (!topIsFullscreen) {
5587                // Force another layout when status bar becomes fully shown.
5588                changes |= FINISH_LAYOUT_REDO_LAYOUT;
5589            }
5590            mTopIsFullscreen = topIsFullscreen;
5591        }
5592
5593        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5594            // If the navigation bar has been hidden or shown, we need to do another
5595            // layout pass to update that window.
5596            changes |= FINISH_LAYOUT_REDO_LAYOUT;
5597        }
5598
5599        if (mShowingDream != mLastShowingDream) {
5600            mLastShowingDream = mShowingDream;
5601            mWindowManagerFuncs.notifyShowingDreamChanged();
5602        }
5603
5604        // update since mAllowLockscreenWhenOn might have changed
5605        updateLockScreenTimeout();
5606        return changes;
5607    }
5608
5609    /**
5610     * Updates the occluded state of the Keyguard.
5611     *
5612     * @return Whether the flags have changed and we have to redo the layout.
5613     */
5614    private boolean setKeyguardOccludedLw(boolean isOccluded, boolean force) {
5615        if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded);
5616        final boolean wasOccluded = mKeyguardOccluded;
5617        final boolean showing = mKeyguardDelegate.isShowing();
5618        final boolean changed = wasOccluded != isOccluded || force;
5619        if (!isOccluded && changed && showing) {
5620            mKeyguardOccluded = false;
5621            mKeyguardDelegate.setOccluded(false, true /* animate */);
5622            if (mStatusBar != null) {
5623                mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
5624                if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
5625                    mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5626                }
5627            }
5628            return true;
5629        } else if (isOccluded && changed && showing) {
5630            mKeyguardOccluded = true;
5631            mKeyguardDelegate.setOccluded(true, false /* animate */);
5632            if (mStatusBar != null) {
5633                mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
5634                mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
5635            }
5636            return true;
5637        } else if (changed) {
5638            mKeyguardOccluded = isOccluded;
5639            mKeyguardDelegate.setOccluded(isOccluded, false /* animate */);
5640            return false;
5641        } else {
5642            return false;
5643        }
5644    }
5645
5646    private boolean isStatusBarKeyguard() {
5647        return mStatusBar != null
5648                && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
5649    }
5650
5651    @Override
5652    public boolean allowAppAnimationsLw() {
5653        if (mShowingDream) {
5654            // If keyguard or dreams is currently visible, no reason to animate behind it.
5655            return false;
5656        }
5657        return true;
5658    }
5659
5660    @Override
5661    public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
5662        mFocusedWindow = newFocus;
5663        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5664            // If the navigation bar has been hidden or shown, we need to do another
5665            // layout pass to update that window.
5666            return FINISH_LAYOUT_REDO_LAYOUT;
5667        }
5668        return 0;
5669    }
5670
5671    /** {@inheritDoc} */
5672    @Override
5673    public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
5674        // lid changed state
5675        final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
5676        if (newLidState == mLidState) {
5677            return;
5678        }
5679
5680        mLidState = newLidState;
5681        applyLidSwitchState();
5682        updateRotation(true);
5683
5684        if (lidOpen) {
5685            wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
5686                    "android.policy:LID");
5687        } else if (!mLidControlsSleep) {
5688            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
5689        }
5690    }
5691
5692    @Override
5693    public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
5694        int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
5695        if (mCameraLensCoverState == lensCoverState) {
5696            return;
5697        }
5698        if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
5699                lensCoverState == CAMERA_LENS_UNCOVERED) {
5700            Intent intent;
5701            final boolean keyguardActive = mKeyguardDelegate == null ? false :
5702                    mKeyguardDelegate.isShowing();
5703            if (keyguardActive) {
5704                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
5705            } else {
5706                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
5707            }
5708            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
5709                    "android.policy:CAMERA_COVER");
5710            startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
5711        }
5712        mCameraLensCoverState = lensCoverState;
5713    }
5714
5715    void setHdmiPlugged(boolean plugged) {
5716        if (mHdmiPlugged != plugged) {
5717            mHdmiPlugged = plugged;
5718            updateRotation(true, true);
5719            Intent intent = new Intent(ACTION_HDMI_PLUGGED);
5720            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
5721            intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
5722            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
5723        }
5724    }
5725
5726    void initializeHdmiState() {
5727        boolean plugged = false;
5728        // watch for HDMI plug messages if the hdmi switch exists
5729        if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
5730            mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
5731
5732            final String filename = "/sys/class/switch/hdmi/state";
5733            FileReader reader = null;
5734            try {
5735                reader = new FileReader(filename);
5736                char[] buf = new char[15];
5737                int n = reader.read(buf);
5738                if (n > 1) {
5739                    plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
5740                }
5741            } catch (IOException ex) {
5742                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5743            } catch (NumberFormatException ex) {
5744                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5745            } finally {
5746                if (reader != null) {
5747                    try {
5748                        reader.close();
5749                    } catch (IOException ex) {
5750                    }
5751                }
5752            }
5753        }
5754        // This dance forces the code in setHdmiPlugged to run.
5755        // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
5756        mHdmiPlugged = !plugged;
5757        setHdmiPlugged(!mHdmiPlugged);
5758    }
5759
5760    final Object mScreenshotLock = new Object();
5761    ServiceConnection mScreenshotConnection = null;
5762
5763    final Runnable mScreenshotTimeout = new Runnable() {
5764        @Override public void run() {
5765            synchronized (mScreenshotLock) {
5766                if (mScreenshotConnection != null) {
5767                    mContext.unbindService(mScreenshotConnection);
5768                    mScreenshotConnection = null;
5769                    notifyScreenshotError();
5770                }
5771            }
5772        }
5773    };
5774
5775    // Assume this is called from the Handler thread.
5776    private void takeScreenshot(final int screenshotType) {
5777        synchronized (mScreenshotLock) {
5778            if (mScreenshotConnection != null) {
5779                return;
5780            }
5781            final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
5782                    SYSUI_SCREENSHOT_SERVICE);
5783            final Intent serviceIntent = new Intent();
5784            serviceIntent.setComponent(serviceComponent);
5785            ServiceConnection conn = new ServiceConnection() {
5786                @Override
5787                public void onServiceConnected(ComponentName name, IBinder service) {
5788                    synchronized (mScreenshotLock) {
5789                        if (mScreenshotConnection != this) {
5790                            return;
5791                        }
5792                        Messenger messenger = new Messenger(service);
5793                        Message msg = Message.obtain(null, screenshotType);
5794                        final ServiceConnection myConn = this;
5795                        Handler h = new Handler(mHandler.getLooper()) {
5796                            @Override
5797                            public void handleMessage(Message msg) {
5798                                synchronized (mScreenshotLock) {
5799                                    if (mScreenshotConnection == myConn) {
5800                                        mContext.unbindService(mScreenshotConnection);
5801                                        mScreenshotConnection = null;
5802                                        mHandler.removeCallbacks(mScreenshotTimeout);
5803                                    }
5804                                }
5805                            }
5806                        };
5807                        msg.replyTo = new Messenger(h);
5808                        msg.arg1 = msg.arg2 = 0;
5809                        if (mStatusBar != null && mStatusBar.isVisibleLw())
5810                            msg.arg1 = 1;
5811                        if (mNavigationBar != null && mNavigationBar.isVisibleLw())
5812                            msg.arg2 = 1;
5813                        try {
5814                            messenger.send(msg);
5815                        } catch (RemoteException e) {
5816                        }
5817                    }
5818                }
5819
5820                @Override
5821                public void onServiceDisconnected(ComponentName name) {
5822                    synchronized (mScreenshotLock) {
5823                        if (mScreenshotConnection != null) {
5824                            mContext.unbindService(mScreenshotConnection);
5825                            mScreenshotConnection = null;
5826                            mHandler.removeCallbacks(mScreenshotTimeout);
5827                            notifyScreenshotError();
5828                        }
5829                    }
5830                }
5831            };
5832            if (mContext.bindServiceAsUser(serviceIntent, conn,
5833                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
5834                    UserHandle.CURRENT)) {
5835                mScreenshotConnection = conn;
5836                mHandler.postDelayed(mScreenshotTimeout, 10000);
5837            }
5838        }
5839    }
5840
5841    /**
5842     * Notifies the screenshot service to show an error.
5843     */
5844    private void notifyScreenshotError() {
5845        // If the service process is killed, then ask it to clean up after itself
5846        final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
5847                SYSUI_SCREENSHOT_ERROR_RECEIVER);
5848        Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
5849        errorIntent.setComponent(errorComponent);
5850        errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
5851                Intent.FLAG_RECEIVER_FOREGROUND);
5852        mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT);
5853    }
5854
5855    /** {@inheritDoc} */
5856    @Override
5857    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
5858        if (!mSystemBooted) {
5859            // If we have not yet booted, don't let key events do anything.
5860            return 0;
5861        }
5862
5863        final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
5864        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
5865        final boolean canceled = event.isCanceled();
5866        final int keyCode = event.getKeyCode();
5867
5868        final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
5869
5870        // If screen is off then we treat the case where the keyguard is open but hidden
5871        // the same as if it were open and in front.
5872        // This will prevent any keys other than the power button from waking the screen
5873        // when the keyguard is hidden by another activity.
5874        final boolean keyguardActive = (mKeyguardDelegate == null ? false :
5875                                            (interactive ?
5876                                                isKeyguardShowingAndNotOccluded() :
5877                                                mKeyguardDelegate.isShowing()));
5878
5879        if (DEBUG_INPUT) {
5880            Log.d(TAG, "interceptKeyTq keycode=" + keyCode
5881                    + " interactive=" + interactive + " keyguardActive=" + keyguardActive
5882                    + " policyFlags=" + Integer.toHexString(policyFlags));
5883        }
5884
5885        // Basic policy based on interactive state.
5886        int result;
5887        boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
5888                || event.isWakeKey();
5889        if (interactive || (isInjected && !isWakeKey)) {
5890            // When the device is interactive or the key is injected pass the
5891            // key to the application.
5892            result = ACTION_PASS_TO_USER;
5893            isWakeKey = false;
5894
5895            if (interactive) {
5896                // If the screen is awake, but the button pressed was the one that woke the device
5897                // then don't pass it to the application
5898                if (keyCode == mPendingWakeKey && !down) {
5899                    result = 0;
5900                }
5901                // Reset the pending key
5902                mPendingWakeKey = PENDING_KEY_NULL;
5903            }
5904        } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
5905            // If we're currently dozing with the screen on and the keyguard showing, pass the key
5906            // to the application but preserve its wake key status to make sure we still move
5907            // from dozing to fully interactive if we would normally go from off to fully
5908            // interactive.
5909            result = ACTION_PASS_TO_USER;
5910            // Since we're dispatching the input, reset the pending key
5911            mPendingWakeKey = PENDING_KEY_NULL;
5912        } else {
5913            // When the screen is off and the key is not injected, determine whether
5914            // to wake the device but don't pass the key to the application.
5915            result = 0;
5916            if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
5917                isWakeKey = false;
5918            }
5919            // Cache the wake key on down event so we can also avoid sending the up event to the app
5920            if (isWakeKey && down) {
5921                mPendingWakeKey = keyCode;
5922            }
5923        }
5924
5925        // If the key would be handled globally, just return the result, don't worry about special
5926        // key processing.
5927        if (isValidGlobalKey(keyCode)
5928                && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
5929            if (isWakeKey) {
5930                wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5931            }
5932            return result;
5933        }
5934
5935        boolean useHapticFeedback = down
5936                && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
5937                && event.getRepeatCount() == 0;
5938
5939        // Handle special keys.
5940        switch (keyCode) {
5941            case KeyEvent.KEYCODE_BACK: {
5942                if (down) {
5943                    interceptBackKeyDown();
5944                } else {
5945                    boolean handled = interceptBackKeyUp(event);
5946
5947                    // Don't pass back press to app if we've already handled it via long press
5948                    if (handled) {
5949                        result &= ~ACTION_PASS_TO_USER;
5950                    }
5951                }
5952                break;
5953            }
5954
5955            case KeyEvent.KEYCODE_VOLUME_DOWN:
5956            case KeyEvent.KEYCODE_VOLUME_UP:
5957            case KeyEvent.KEYCODE_VOLUME_MUTE: {
5958                if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
5959                    if (down) {
5960                        if (interactive && !mScreenshotChordVolumeDownKeyTriggered
5961                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5962                            mScreenshotChordVolumeDownKeyTriggered = true;
5963                            mScreenshotChordVolumeDownKeyTime = event.getDownTime();
5964                            mScreenshotChordVolumeDownKeyConsumed = false;
5965                            cancelPendingPowerKeyAction();
5966                            interceptScreenshotChord();
5967                            interceptAccessibilityShortcutChord();
5968                        }
5969                    } else {
5970                        mScreenshotChordVolumeDownKeyTriggered = false;
5971                        cancelPendingScreenshotChordAction();
5972                        cancelPendingAccessibilityShortcutAction();
5973                    }
5974                } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
5975                    if (down) {
5976                        if (interactive && !mA11yShortcutChordVolumeUpKeyTriggered
5977                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5978                            mA11yShortcutChordVolumeUpKeyTriggered = true;
5979                            mA11yShortcutChordVolumeUpKeyTime = event.getDownTime();
5980                            mA11yShortcutChordVolumeUpKeyConsumed = false;
5981                            cancelPendingPowerKeyAction();
5982                            cancelPendingScreenshotChordAction();
5983                            interceptAccessibilityShortcutChord();
5984                        }
5985                    } else {
5986                        mA11yShortcutChordVolumeUpKeyTriggered = false;
5987                        cancelPendingScreenshotChordAction();
5988                        cancelPendingAccessibilityShortcutAction();
5989                    }
5990                }
5991                if (down) {
5992                    TelecomManager telecomManager = getTelecommService();
5993                    if (telecomManager != null) {
5994                        if (telecomManager.isRinging()) {
5995                            // If an incoming call is ringing, either VOLUME key means
5996                            // "silence ringer".  We handle these keys here, rather than
5997                            // in the InCallScreen, to make sure we'll respond to them
5998                            // even if the InCallScreen hasn't come to the foreground yet.
5999                            // Look for the DOWN event here, to agree with the "fallback"
6000                            // behavior in the InCallScreen.
6001                            Log.i(TAG, "interceptKeyBeforeQueueing:"
6002                                  + " VOLUME key-down while ringing: Silence ringer!");
6003
6004                            // Silence the ringer.  (It's safe to call this
6005                            // even if the ringer has already been silenced.)
6006                            telecomManager.silenceRinger();
6007
6008                            // And *don't* pass this key thru to the current activity
6009                            // (which is probably the InCallScreen.)
6010                            result &= ~ACTION_PASS_TO_USER;
6011                            break;
6012                        }
6013                    }
6014                    int audioMode = AudioManager.MODE_NORMAL;
6015                    try {
6016                        audioMode = getAudioService().getMode();
6017                    } catch (Exception e) {
6018                        Log.e(TAG, "Error getting AudioService in interceptKeyBeforeQueueing.", e);
6019                    }
6020                    boolean isInCall = (telecomManager != null && telecomManager.isInCall()) ||
6021                            audioMode == AudioManager.MODE_IN_COMMUNICATION;
6022                    if (isInCall && (result & ACTION_PASS_TO_USER) == 0) {
6023                        // If we are in call but we decided not to pass the key to
6024                        // the application, just pass it to the session service.
6025                        MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
6026                                event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
6027                        break;
6028                    }
6029
6030                }
6031                if (mUseTvRouting || mHandleVolumeKeysInWM) {
6032                    // Defer special key handlings to
6033                    // {@link interceptKeyBeforeDispatching()}.
6034                    result |= ACTION_PASS_TO_USER;
6035                } else if ((result & ACTION_PASS_TO_USER) == 0) {
6036                    // If we aren't passing to the user and no one else
6037                    // handled it send it to the session manager to
6038                    // figure out.
6039                    MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
6040                            event, AudioManager.USE_DEFAULT_STREAM_TYPE, true);
6041                }
6042                break;
6043            }
6044
6045            case KeyEvent.KEYCODE_ENDCALL: {
6046                result &= ~ACTION_PASS_TO_USER;
6047                if (down) {
6048                    TelecomManager telecomManager = getTelecommService();
6049                    boolean hungUp = false;
6050                    if (telecomManager != null) {
6051                        hungUp = telecomManager.endCall();
6052                    }
6053                    if (interactive && !hungUp) {
6054                        mEndCallKeyHandled = false;
6055                        mHandler.postDelayed(mEndCallLongPress,
6056                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
6057                    } else {
6058                        mEndCallKeyHandled = true;
6059                    }
6060                } else {
6061                    if (!mEndCallKeyHandled) {
6062                        mHandler.removeCallbacks(mEndCallLongPress);
6063                        if (!canceled) {
6064                            if ((mEndcallBehavior
6065                                    & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
6066                                if (goHome()) {
6067                                    break;
6068                                }
6069                            }
6070                            if ((mEndcallBehavior
6071                                    & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
6072                                mPowerManager.goToSleep(event.getEventTime(),
6073                                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
6074                                isWakeKey = false;
6075                            }
6076                        }
6077                    }
6078                }
6079                break;
6080            }
6081
6082            case KeyEvent.KEYCODE_POWER: {
6083                // Any activity on the power button stops the accessibility shortcut
6084                cancelPendingAccessibilityShortcutAction();
6085                result &= ~ACTION_PASS_TO_USER;
6086                isWakeKey = false; // wake-up will be handled separately
6087                if (down) {
6088                    interceptPowerKeyDown(event, interactive);
6089                } else {
6090                    interceptPowerKeyUp(event, interactive, canceled);
6091                }
6092                break;
6093            }
6094
6095            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
6096                // fall through
6097            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
6098                // fall through
6099            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
6100                // fall through
6101            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
6102                result &= ~ACTION_PASS_TO_USER;
6103                interceptSystemNavigationKey(event);
6104                break;
6105            }
6106
6107            case KeyEvent.KEYCODE_SLEEP: {
6108                result &= ~ACTION_PASS_TO_USER;
6109                isWakeKey = false;
6110                if (!mPowerManager.isInteractive()) {
6111                    useHapticFeedback = false; // suppress feedback if already non-interactive
6112                }
6113                if (down) {
6114                    sleepPress(event.getEventTime());
6115                } else {
6116                    sleepRelease(event.getEventTime());
6117                }
6118                break;
6119            }
6120
6121            case KeyEvent.KEYCODE_SOFT_SLEEP: {
6122                result &= ~ACTION_PASS_TO_USER;
6123                isWakeKey = false;
6124                if (!down) {
6125                    mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
6126                }
6127                break;
6128            }
6129
6130            case KeyEvent.KEYCODE_WAKEUP: {
6131                result &= ~ACTION_PASS_TO_USER;
6132                isWakeKey = true;
6133                break;
6134            }
6135
6136            case KeyEvent.KEYCODE_MEDIA_PLAY:
6137            case KeyEvent.KEYCODE_MEDIA_PAUSE:
6138            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6139            case KeyEvent.KEYCODE_HEADSETHOOK:
6140            case KeyEvent.KEYCODE_MUTE:
6141            case KeyEvent.KEYCODE_MEDIA_STOP:
6142            case KeyEvent.KEYCODE_MEDIA_NEXT:
6143            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6144            case KeyEvent.KEYCODE_MEDIA_REWIND:
6145            case KeyEvent.KEYCODE_MEDIA_RECORD:
6146            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6147            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
6148                if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
6149                    // If the global session is active pass all media keys to it
6150                    // instead of the active window.
6151                    result &= ~ACTION_PASS_TO_USER;
6152                }
6153                if ((result & ACTION_PASS_TO_USER) == 0) {
6154                    // Only do this if we would otherwise not pass it to the user. In that
6155                    // case, the PhoneWindow class will do the same thing, except it will
6156                    // only do it if the showing app doesn't process the key on its own.
6157                    // Note that we need to make a copy of the key event here because the
6158                    // original key event will be recycled when we return.
6159                    mBroadcastWakeLock.acquire();
6160                    Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
6161                            new KeyEvent(event));
6162                    msg.setAsynchronous(true);
6163                    msg.sendToTarget();
6164                }
6165                break;
6166            }
6167
6168            case KeyEvent.KEYCODE_CALL: {
6169                if (down) {
6170                    TelecomManager telecomManager = getTelecommService();
6171                    if (telecomManager != null) {
6172                        if (telecomManager.isRinging()) {
6173                            Log.i(TAG, "interceptKeyBeforeQueueing:"
6174                                  + " CALL key-down while ringing: Answer the call!");
6175                            telecomManager.acceptRingingCall();
6176
6177                            // And *don't* pass this key thru to the current activity
6178                            // (which is presumably the InCallScreen.)
6179                            result &= ~ACTION_PASS_TO_USER;
6180                        }
6181                    }
6182                }
6183                break;
6184            }
6185            case KeyEvent.KEYCODE_VOICE_ASSIST: {
6186                // Only do this if we would otherwise not pass it to the user. In that case,
6187                // interceptKeyBeforeDispatching would apply a similar but different policy in
6188                // order to invoke voice assist actions. Note that we need to make a copy of the
6189                // key event here because the original key event will be recycled when we return.
6190                if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
6191                    mBroadcastWakeLock.acquire();
6192                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
6193                            keyguardActive ? 1 : 0, 0);
6194                    msg.setAsynchronous(true);
6195                    msg.sendToTarget();
6196                }
6197                break;
6198            }
6199            case KeyEvent.KEYCODE_WINDOW: {
6200                if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
6201                    if (mPictureInPictureVisible) {
6202                        // Consumes the key only if picture-in-picture is visible to show
6203                        // picture-in-picture control menu. This gives a chance to the foreground
6204                        // activity to customize PIP key behavior.
6205                        if (!down) {
6206                            showPictureInPictureMenu(event);
6207                        }
6208                        result &= ~ACTION_PASS_TO_USER;
6209                    }
6210                }
6211                break;
6212            }
6213        }
6214
6215        if (useHapticFeedback) {
6216            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
6217        }
6218
6219        if (isWakeKey) {
6220            wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
6221        }
6222
6223        return result;
6224    }
6225
6226    /**
6227     * Handle statusbar expansion events.
6228     * @param event
6229     */
6230    private void interceptSystemNavigationKey(KeyEvent event) {
6231        if (event.getAction() == KeyEvent.ACTION_UP) {
6232            if (!mAccessibilityManager.isEnabled()
6233                    || !mAccessibilityManager.sendFingerprintGesture(event.getKeyCode())) {
6234                if (areSystemNavigationKeysEnabled()) {
6235                    IStatusBarService sbar = getStatusBarService();
6236                    if (sbar != null) {
6237                        try {
6238                            sbar.handleSystemNavigationKey(event.getKeyCode());
6239                        } catch (RemoteException e1) {
6240                            // oops, no statusbar. Ignore event.
6241                        }
6242                    }
6243                }
6244            }
6245        }
6246    }
6247
6248    /**
6249     * Returns true if the key can have global actions attached to it.
6250     * We reserve all power management keys for the system since they require
6251     * very careful handling.
6252     */
6253    private static boolean isValidGlobalKey(int keyCode) {
6254        switch (keyCode) {
6255            case KeyEvent.KEYCODE_POWER:
6256            case KeyEvent.KEYCODE_WAKEUP:
6257            case KeyEvent.KEYCODE_SLEEP:
6258                return false;
6259            default:
6260                return true;
6261        }
6262    }
6263
6264    /**
6265     * When the screen is off we ignore some keys that might otherwise typically
6266     * be considered wake keys.  We filter them out here.
6267     *
6268     * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
6269     * is always considered a wake key.
6270     */
6271    private boolean isWakeKeyWhenScreenOff(int keyCode) {
6272        switch (keyCode) {
6273            // ignore volume keys unless docked
6274            case KeyEvent.KEYCODE_VOLUME_UP:
6275            case KeyEvent.KEYCODE_VOLUME_DOWN:
6276            case KeyEvent.KEYCODE_VOLUME_MUTE:
6277                return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
6278
6279            // ignore media and camera keys
6280            case KeyEvent.KEYCODE_MUTE:
6281            case KeyEvent.KEYCODE_HEADSETHOOK:
6282            case KeyEvent.KEYCODE_MEDIA_PLAY:
6283            case KeyEvent.KEYCODE_MEDIA_PAUSE:
6284            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6285            case KeyEvent.KEYCODE_MEDIA_STOP:
6286            case KeyEvent.KEYCODE_MEDIA_NEXT:
6287            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6288            case KeyEvent.KEYCODE_MEDIA_REWIND:
6289            case KeyEvent.KEYCODE_MEDIA_RECORD:
6290            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6291            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
6292            case KeyEvent.KEYCODE_CAMERA:
6293                return false;
6294        }
6295        return true;
6296    }
6297
6298
6299    /** {@inheritDoc} */
6300    @Override
6301    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
6302        if ((policyFlags & FLAG_WAKE) != 0) {
6303            if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
6304                    "android.policy:MOTION")) {
6305                return 0;
6306            }
6307        }
6308
6309        if (shouldDispatchInputWhenNonInteractive(null)) {
6310            return ACTION_PASS_TO_USER;
6311        }
6312
6313        // If we have not passed the action up and we are in theater mode without dreaming,
6314        // there will be no dream to intercept the touch and wake into ambient.  The device should
6315        // wake up in this case.
6316        if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
6317            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
6318                    "android.policy:MOTION");
6319        }
6320
6321        return 0;
6322    }
6323
6324    private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
6325        final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
6326
6327        if (displayOff && !mHasFeatureWatch) {
6328            return false;
6329        }
6330
6331        // Send events to keyguard while the screen is on and it's showing.
6332        if (isKeyguardShowingAndNotOccluded() && !displayOff) {
6333            return true;
6334        }
6335
6336        // Watches handle BACK specially
6337        if (mHasFeatureWatch
6338                && event != null
6339                && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
6340                        || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
6341            return false;
6342        }
6343
6344        // Send events to a dozing dream even if the screen is off since the dream
6345        // is in control of the state of the screen.
6346        IDreamManager dreamManager = getDreamManager();
6347
6348        try {
6349            if (dreamManager != null && dreamManager.isDreaming()) {
6350                return true;
6351            }
6352        } catch (RemoteException e) {
6353            Slog.e(TAG, "RemoteException when checking if dreaming", e);
6354        }
6355
6356        // Otherwise, consume events since the user can't see what is being
6357        // interacted with.
6358        return false;
6359    }
6360
6361    private void dispatchDirectAudioEvent(KeyEvent event) {
6362        if (event.getAction() != KeyEvent.ACTION_DOWN) {
6363            return;
6364        }
6365        int keyCode = event.getKeyCode();
6366        int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
6367                | AudioManager.FLAG_FROM_KEY;
6368        String pkgName = mContext.getOpPackageName();
6369        switch (keyCode) {
6370            case KeyEvent.KEYCODE_VOLUME_UP:
6371                try {
6372                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
6373                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6374                } catch (Exception e) {
6375                    Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
6376                }
6377                break;
6378            case KeyEvent.KEYCODE_VOLUME_DOWN:
6379                try {
6380                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
6381                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6382                } catch (Exception e) {
6383                    Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
6384                }
6385                break;
6386            case KeyEvent.KEYCODE_VOLUME_MUTE:
6387                try {
6388                    if (event.getRepeatCount() == 0) {
6389                        getAudioService().adjustSuggestedStreamVolume(
6390                                AudioManager.ADJUST_TOGGLE_MUTE,
6391                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6392                    }
6393                } catch (Exception e) {
6394                    Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
6395                }
6396                break;
6397        }
6398    }
6399
6400    void dispatchMediaKeyWithWakeLock(KeyEvent event) {
6401        if (DEBUG_INPUT) {
6402            Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
6403        }
6404
6405        if (mHavePendingMediaKeyRepeatWithWakeLock) {
6406            if (DEBUG_INPUT) {
6407                Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
6408            }
6409
6410            mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
6411            mHavePendingMediaKeyRepeatWithWakeLock = false;
6412            mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
6413        }
6414
6415        dispatchMediaKeyWithWakeLockToAudioService(event);
6416
6417        if (event.getAction() == KeyEvent.ACTION_DOWN
6418                && event.getRepeatCount() == 0) {
6419            mHavePendingMediaKeyRepeatWithWakeLock = true;
6420
6421            Message msg = mHandler.obtainMessage(
6422                    MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
6423            msg.setAsynchronous(true);
6424            mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
6425        } else {
6426            mBroadcastWakeLock.release();
6427        }
6428    }
6429
6430    void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
6431        mHavePendingMediaKeyRepeatWithWakeLock = false;
6432
6433        KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
6434                SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6435        if (DEBUG_INPUT) {
6436            Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
6437        }
6438
6439        dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
6440        mBroadcastWakeLock.release();
6441    }
6442
6443    void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
6444        if (mActivityManagerInternal.isSystemReady()) {
6445            MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
6446        }
6447    }
6448
6449    void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
6450        IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
6451                ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
6452        if (dic != null) {
6453            try {
6454                dic.exitIdle("voice-search");
6455            } catch (RemoteException e) {
6456            }
6457        }
6458        Intent voiceIntent =
6459            new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
6460        voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
6461        startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
6462        mBroadcastWakeLock.release();
6463    }
6464
6465    BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
6466        @Override
6467        public void onReceive(Context context, Intent intent) {
6468            if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
6469                mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6470                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
6471            } else {
6472                try {
6473                    IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
6474                            ServiceManager.getService(Context.UI_MODE_SERVICE));
6475                    mUiMode = uiModeService.getCurrentModeType();
6476                } catch (RemoteException e) {
6477                }
6478            }
6479            updateRotation(true);
6480            synchronized (mLock) {
6481                updateOrientationListenerLp();
6482            }
6483        }
6484    };
6485
6486    BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
6487        @Override
6488        public void onReceive(Context context, Intent intent) {
6489            if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
6490                if (mKeyguardDelegate != null) {
6491                    mKeyguardDelegate.onDreamingStarted();
6492                }
6493            } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
6494                if (mKeyguardDelegate != null) {
6495                    mKeyguardDelegate.onDreamingStopped();
6496                }
6497            }
6498        }
6499    };
6500
6501    BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
6502        @Override
6503        public void onReceive(Context context, Intent intent) {
6504            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
6505                // tickle the settings observer: this first ensures that we're
6506                // observing the relevant settings for the newly-active user,
6507                // and then updates our own bookkeeping based on the now-
6508                // current user.
6509                mSettingsObserver.onChange(false);
6510
6511                // force a re-application of focused window sysui visibility.
6512                // the window may never have been shown for this user
6513                // e.g. the keyguard when going through the new-user setup flow
6514                synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6515                    mLastSystemUiFlags = 0;
6516                    updateSystemUiVisibilityLw();
6517                }
6518            }
6519        }
6520    };
6521
6522    private final Runnable mHiddenNavPanic = new Runnable() {
6523        @Override
6524        public void run() {
6525            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6526                if (!isUserSetupComplete()) {
6527                    // Swipe-up for navigation bar is disabled during setup
6528                    return;
6529                }
6530                mPendingPanicGestureUptime = SystemClock.uptimeMillis();
6531                if (!isNavBarEmpty(mLastSystemUiFlags)) {
6532                    mNavigationBarController.showTransient();
6533                }
6534            }
6535        }
6536    };
6537
6538    private void requestTransientBars(WindowState swipeTarget) {
6539        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6540            if (!isUserSetupComplete()) {
6541                // Swipe-up for navigation bar is disabled during setup
6542                return;
6543            }
6544            boolean sb = mStatusBarController.checkShowTransientBarLw();
6545            boolean nb = mNavigationBarController.checkShowTransientBarLw()
6546                    && !isNavBarEmpty(mLastSystemUiFlags);
6547            if (sb || nb) {
6548                // Don't show status bar when swiping on already visible navigation bar
6549                if (!nb && swipeTarget == mNavigationBar) {
6550                    if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
6551                    return;
6552                }
6553                if (sb) mStatusBarController.showTransient();
6554                if (nb) mNavigationBarController.showTransient();
6555                mImmersiveModeConfirmation.confirmCurrentPrompt();
6556                updateSystemUiVisibilityLw();
6557            }
6558        }
6559    }
6560
6561    // Called on the PowerManager's Notifier thread.
6562    @Override
6563    public void startedGoingToSleep(int why) {
6564        if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
6565        mCameraGestureTriggeredDuringGoingToSleep = false;
6566        mGoingToSleep = true;
6567        if (mKeyguardDelegate != null) {
6568            mKeyguardDelegate.onStartedGoingToSleep(why);
6569        }
6570    }
6571
6572    // Called on the PowerManager's Notifier thread.
6573    @Override
6574    public void finishedGoingToSleep(int why) {
6575        EventLog.writeEvent(70000, 0);
6576        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
6577        MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
6578
6579        mGoingToSleep = false;
6580
6581        // We must get this work done here because the power manager will drop
6582        // the wake lock and let the system suspend once this function returns.
6583        synchronized (mLock) {
6584            mAwake = false;
6585            updateWakeGestureListenerLp();
6586            updateOrientationListenerLp();
6587            updateLockScreenTimeout();
6588        }
6589        if (mKeyguardDelegate != null) {
6590            mKeyguardDelegate.onFinishedGoingToSleep(why,
6591                    mCameraGestureTriggeredDuringGoingToSleep);
6592        }
6593        mCameraGestureTriggeredDuringGoingToSleep = false;
6594    }
6595
6596    // Called on the PowerManager's Notifier thread.
6597    @Override
6598    public void startedWakingUp() {
6599        EventLog.writeEvent(70000, 1);
6600        if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
6601
6602        // Since goToSleep performs these functions synchronously, we must
6603        // do the same here.  We cannot post this work to a handler because
6604        // that might cause it to become reordered with respect to what
6605        // may happen in a future call to goToSleep.
6606        synchronized (mLock) {
6607            mAwake = true;
6608
6609            updateWakeGestureListenerLp();
6610            updateOrientationListenerLp();
6611            updateLockScreenTimeout();
6612        }
6613
6614        if (mKeyguardDelegate != null) {
6615            mKeyguardDelegate.onStartedWakingUp();
6616        }
6617    }
6618
6619    // Called on the PowerManager's Notifier thread.
6620    @Override
6621    public void finishedWakingUp() {
6622        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
6623    }
6624
6625    private void wakeUpFromPowerKey(long eventTime) {
6626        wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
6627    }
6628
6629    private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
6630        final boolean theaterModeEnabled = isTheaterModeEnabled();
6631        if (!wakeInTheaterMode && theaterModeEnabled) {
6632            return false;
6633        }
6634
6635        if (theaterModeEnabled) {
6636            Settings.Global.putInt(mContext.getContentResolver(),
6637                    Settings.Global.THEATER_MODE_ON, 0);
6638        }
6639
6640        mPowerManager.wakeUp(wakeTime, reason);
6641        return true;
6642    }
6643
6644    private void finishKeyguardDrawn() {
6645        synchronized (mLock) {
6646            if (!mScreenOnEarly || mKeyguardDrawComplete) {
6647                return; // We are not awake yet or we have already informed of this event.
6648            }
6649
6650            mKeyguardDrawComplete = true;
6651            if (mKeyguardDelegate != null) {
6652                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6653            }
6654            mWindowManagerDrawComplete = false;
6655        }
6656
6657        // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
6658        // as well as enabling the orientation change logic/sensor.
6659        mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
6660                WAITING_FOR_DRAWN_TIMEOUT);
6661    }
6662
6663    // Called on the DisplayManager's DisplayPowerController thread.
6664    @Override
6665    public void screenTurnedOff() {
6666        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
6667
6668        updateScreenOffSleepToken(true);
6669        synchronized (mLock) {
6670            mScreenOnEarly = false;
6671            mScreenOnFully = false;
6672            mKeyguardDrawComplete = false;
6673            mWindowManagerDrawComplete = false;
6674            mScreenOnListener = null;
6675            updateOrientationListenerLp();
6676
6677            if (mKeyguardDelegate != null) {
6678                mKeyguardDelegate.onScreenTurnedOff();
6679            }
6680        }
6681        reportScreenStateToVrManager(false);
6682    }
6683
6684    private long getKeyguardDrawnTimeout() {
6685        final boolean bootCompleted =
6686                LocalServices.getService(SystemServiceManager.class).isBootCompleted();
6687        // Set longer timeout if it has not booted yet to prevent showing empty window.
6688        return bootCompleted ? 1000 : 5000;
6689    }
6690
6691    // Called on the DisplayManager's DisplayPowerController thread.
6692    @Override
6693    public void screenTurningOn(final ScreenOnListener screenOnListener) {
6694        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
6695
6696        updateScreenOffSleepToken(false);
6697        synchronized (mLock) {
6698            mScreenOnEarly = true;
6699            mScreenOnFully = false;
6700            mKeyguardDrawComplete = false;
6701            mWindowManagerDrawComplete = false;
6702            mScreenOnListener = screenOnListener;
6703
6704            if (mKeyguardDelegate != null) {
6705                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6706                mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT,
6707                        getKeyguardDrawnTimeout());
6708                mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
6709            } else {
6710                if (DEBUG_WAKEUP) Slog.d(TAG,
6711                        "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
6712                finishKeyguardDrawn();
6713            }
6714        }
6715    }
6716
6717    // Called on the DisplayManager's DisplayPowerController thread.
6718    @Override
6719    public void screenTurnedOn() {
6720        synchronized (mLock) {
6721            if (mKeyguardDelegate != null) {
6722                mKeyguardDelegate.onScreenTurnedOn();
6723            }
6724        }
6725        reportScreenStateToVrManager(true);
6726    }
6727
6728    @Override
6729    public void screenTurningOff(ScreenOffListener screenOffListener) {
6730        mWindowManagerFuncs.screenTurningOff(screenOffListener);
6731    }
6732
6733    private void reportScreenStateToVrManager(boolean isScreenOn) {
6734        if (mVrManagerInternal == null) {
6735            return;
6736        }
6737        mVrManagerInternal.onScreenStateChanged(isScreenOn);
6738    }
6739
6740    private void finishWindowsDrawn() {
6741        synchronized (mLock) {
6742            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
6743                return; // Screen is not turned on or we did already handle this case earlier.
6744            }
6745
6746            mWindowManagerDrawComplete = true;
6747        }
6748
6749        finishScreenTurningOn();
6750    }
6751
6752    private void finishScreenTurningOn() {
6753        synchronized (mLock) {
6754            // We have just finished drawing screen content. Since the orientation listener
6755            // gets only installed when all windows are drawn, we try to install it again.
6756            updateOrientationListenerLp();
6757        }
6758        final ScreenOnListener listener;
6759        final boolean enableScreen;
6760        synchronized (mLock) {
6761            if (DEBUG_WAKEUP) Slog.d(TAG,
6762                    "finishScreenTurningOn: mAwake=" + mAwake
6763                            + ", mScreenOnEarly=" + mScreenOnEarly
6764                            + ", mScreenOnFully=" + mScreenOnFully
6765                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
6766                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
6767
6768            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
6769                    || (mAwake && !mKeyguardDrawComplete)) {
6770                return; // spurious or not ready yet
6771            }
6772
6773            if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
6774            listener = mScreenOnListener;
6775            mScreenOnListener = null;
6776            mScreenOnFully = true;
6777
6778            // Remember the first time we draw the keyguard so we know when we're done with
6779            // the main part of booting and can enable the screen and hide boot messages.
6780            if (!mKeyguardDrawnOnce && mAwake) {
6781                mKeyguardDrawnOnce = true;
6782                enableScreen = true;
6783                if (mBootMessageNeedsHiding) {
6784                    mBootMessageNeedsHiding = false;
6785                    hideBootMessages();
6786                }
6787            } else {
6788                enableScreen = false;
6789            }
6790        }
6791
6792        if (listener != null) {
6793            listener.onScreenOn();
6794        }
6795
6796        if (enableScreen) {
6797            try {
6798                mWindowManager.enableScreenIfNeeded();
6799            } catch (RemoteException unhandled) {
6800            }
6801        }
6802    }
6803
6804    private void handleHideBootMessage() {
6805        synchronized (mLock) {
6806            if (!mKeyguardDrawnOnce) {
6807                mBootMessageNeedsHiding = true;
6808                return; // keyguard hasn't drawn the first time yet, not done booting
6809            }
6810        }
6811
6812        if (mBootMsgDialog != null) {
6813            if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
6814            mBootMsgDialog.dismiss();
6815            mBootMsgDialog = null;
6816        }
6817    }
6818
6819    @Override
6820    public boolean isScreenOn() {
6821        synchronized (mLock) {
6822            return mScreenOnEarly;
6823        }
6824    }
6825
6826    /** {@inheritDoc} */
6827    @Override
6828    public void enableKeyguard(boolean enabled) {
6829        if (mKeyguardDelegate != null) {
6830            mKeyguardDelegate.setKeyguardEnabled(enabled);
6831        }
6832    }
6833
6834    /** {@inheritDoc} */
6835    @Override
6836    public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
6837        if (mKeyguardDelegate != null) {
6838            mKeyguardDelegate.verifyUnlock(callback);
6839        }
6840    }
6841
6842    @Override
6843    public boolean isKeyguardShowingAndNotOccluded() {
6844        if (mKeyguardDelegate == null) return false;
6845        return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
6846    }
6847
6848    @Override
6849    public boolean isKeyguardTrustedLw() {
6850        if (mKeyguardDelegate == null) return false;
6851        return mKeyguardDelegate.isTrusted();
6852    }
6853
6854    /** {@inheritDoc} */
6855    @Override
6856    public boolean isKeyguardLocked() {
6857        return keyguardOn();
6858    }
6859
6860    /** {@inheritDoc} */
6861    @Override
6862    public boolean isKeyguardSecure(int userId) {
6863        if (mKeyguardDelegate == null) return false;
6864        return mKeyguardDelegate.isSecure(userId);
6865    }
6866
6867    /** {@inheritDoc} */
6868    @Override
6869    public boolean isKeyguardOccluded() {
6870        if (mKeyguardDelegate == null) return false;
6871        return mKeyguardOccluded;
6872    }
6873
6874    /** {@inheritDoc} */
6875    @Override
6876    public boolean inKeyguardRestrictedKeyInputMode() {
6877        if (mKeyguardDelegate == null) return false;
6878        return mKeyguardDelegate.isInputRestricted();
6879    }
6880
6881    @Override
6882    public void dismissKeyguardLw(IKeyguardDismissCallback callback) {
6883        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
6884            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
6885
6886            // ask the keyguard to prompt the user to authenticate if necessary
6887            mKeyguardDelegate.dismiss(callback);
6888        } else if (callback != null) {
6889            try {
6890                callback.onDismissError();
6891            } catch (RemoteException e) {
6892                Slog.w(TAG, "Failed to call callback", e);
6893            }
6894        }
6895    }
6896
6897    @Override
6898    public boolean isKeyguardDrawnLw() {
6899        synchronized (mLock) {
6900            return mKeyguardDrawnOnce;
6901        }
6902    }
6903
6904    @Override
6905    public boolean isShowingDreamLw() {
6906        return mShowingDream;
6907    }
6908
6909    @Override
6910    public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
6911        if (mKeyguardDelegate != null) {
6912            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
6913            mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
6914        }
6915    }
6916
6917    @Override
6918    public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6919            Rect outInsets) {
6920        outInsets.setEmpty();
6921
6922        // Navigation bar and status bar.
6923        getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
6924        outInsets.top = mStatusBarHeight;
6925    }
6926
6927    @Override
6928    public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6929            Rect outInsets) {
6930        outInsets.setEmpty();
6931
6932        // Only navigation bar
6933        if (mHasNavigationBar) {
6934            int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
6935            if (position == NAV_BAR_BOTTOM) {
6936                outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
6937            } else if (position == NAV_BAR_RIGHT) {
6938                outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
6939            } else if (position == NAV_BAR_LEFT) {
6940                outInsets.left = getNavigationBarWidth(displayRotation, mUiMode);
6941            }
6942        }
6943    }
6944
6945    @Override
6946    public boolean isNavBarForcedShownLw(WindowState windowState) {
6947        return mForceShowSystemBars;
6948    }
6949
6950    @Override
6951    public boolean isDockSideAllowed(int dockSide) {
6952
6953        // We do not allow all dock sides at which the navigation bar touches the docked stack.
6954        if (!mNavigationBarCanMove) {
6955            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT;
6956        } else {
6957            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT;
6958        }
6959    }
6960
6961    void sendCloseSystemWindows() {
6962        PhoneWindow.sendCloseSystemWindows(mContext, null);
6963    }
6964
6965    void sendCloseSystemWindows(String reason) {
6966        PhoneWindow.sendCloseSystemWindows(mContext, reason);
6967    }
6968
6969    @Override
6970    public int rotationForOrientationLw(int orientation, int lastRotation) {
6971        if (false) {
6972            Slog.v(TAG, "rotationForOrientationLw(orient="
6973                        + orientation + ", last=" + lastRotation
6974                        + "); user=" + mUserRotation + " "
6975                        + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
6976                            ? "USER_ROTATION_LOCKED" : "")
6977                        );
6978        }
6979
6980        if (mForceDefaultOrientation) {
6981            return Surface.ROTATION_0;
6982        }
6983
6984        synchronized (mLock) {
6985            int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
6986            if (sensorRotation < 0) {
6987                sensorRotation = lastRotation;
6988            }
6989
6990            final int preferredRotation;
6991            if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
6992                // Ignore sensor when lid switch is open and rotation is forced.
6993                preferredRotation = mLidOpenRotation;
6994            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
6995                    && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
6996                // Ignore sensor when in car dock unless explicitly enabled.
6997                // This case can override the behavior of NOSENSOR, and can also
6998                // enable 180 degree rotation while docked.
6999                preferredRotation = mCarDockEnablesAccelerometer
7000                        ? sensorRotation : mCarDockRotation;
7001            } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7002                    || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
7003                    || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
7004                    && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
7005                // Ignore sensor when in desk dock unless explicitly enabled.
7006                // This case can override the behavior of NOSENSOR, and can also
7007                // enable 180 degree rotation while docked.
7008                preferredRotation = mDeskDockEnablesAccelerometer
7009                        ? sensorRotation : mDeskDockRotation;
7010            } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
7011                // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
7012                // Note that the dock orientation overrides the HDMI orientation.
7013                preferredRotation = mDemoHdmiRotation;
7014            } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
7015                    && mUndockedHdmiRotation >= 0) {
7016                // Ignore sensor when plugged into HDMI and an undocked orientation has
7017                // been specified in the configuration (only for legacy devices without
7018                // full multi-display support).
7019                // Note that the dock orientation overrides the HDMI orientation.
7020                preferredRotation = mUndockedHdmiRotation;
7021            } else if (mDemoRotationLock) {
7022                // Ignore sensor when demo rotation lock is enabled.
7023                // Note that the dock orientation and HDMI rotation lock override this.
7024                preferredRotation = mDemoRotation;
7025            } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
7026                // Application just wants to remain locked in the last rotation.
7027                preferredRotation = lastRotation;
7028            } else if (!mSupportAutoRotation) {
7029                // If we don't support auto-rotation then bail out here and ignore
7030                // the sensor and any rotation lock settings.
7031                preferredRotation = -1;
7032            } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
7033                            && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
7034                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
7035                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
7036                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
7037                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
7038                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
7039                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
7040                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
7041                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
7042                // Otherwise, use sensor only if requested by the application or enabled
7043                // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
7044                if (mAllowAllRotations < 0) {
7045                    // Can't read this during init() because the context doesn't
7046                    // have display metrics at that time so we cannot determine
7047                    // tablet vs. phone then.
7048                    mAllowAllRotations = mContext.getResources().getBoolean(
7049                            com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
7050                }
7051                if (sensorRotation != Surface.ROTATION_180
7052                        || mAllowAllRotations == 1
7053                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
7054                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
7055                    // In VrMode, we report the sensor as always being in default orientation so:
7056                    // 1) The orientation doesn't change as the user moves their head.
7057                    // 2) 2D apps within VR show in the device's default orientation.
7058                    // This only overwrites the sensor-provided orientation and does not affect any
7059                    // explicit orientation preferences specified by any activities.
7060                    preferredRotation =
7061                            mPersistentVrModeEnabled ? Surface.ROTATION_0 : sensorRotation;
7062                } else {
7063                    preferredRotation = lastRotation;
7064                }
7065            } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
7066                    && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
7067                // Apply rotation lock.  Does not apply to NOSENSOR.
7068                // The idea is that the user rotation expresses a weak preference for the direction
7069                // of gravity and as NOSENSOR is never affected by gravity, then neither should
7070                // NOSENSOR be affected by rotation lock (although it will be affected by docks).
7071                preferredRotation = mUserRotation;
7072            } else {
7073                // No overriding preference.
7074                // We will do exactly what the application asked us to do.
7075                preferredRotation = -1;
7076            }
7077
7078            switch (orientation) {
7079                case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
7080                    // Return portrait unless overridden.
7081                    if (isAnyPortrait(preferredRotation)) {
7082                        return preferredRotation;
7083                    }
7084                    return mPortraitRotation;
7085
7086                case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
7087                    // Return landscape unless overridden.
7088                    if (isLandscapeOrSeascape(preferredRotation)) {
7089                        return preferredRotation;
7090                    }
7091                    return mLandscapeRotation;
7092
7093                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
7094                    // Return reverse portrait unless overridden.
7095                    if (isAnyPortrait(preferredRotation)) {
7096                        return preferredRotation;
7097                    }
7098                    return mUpsideDownRotation;
7099
7100                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
7101                    // Return seascape unless overridden.
7102                    if (isLandscapeOrSeascape(preferredRotation)) {
7103                        return preferredRotation;
7104                    }
7105                    return mSeascapeRotation;
7106
7107                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
7108                case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
7109                    // Return either landscape rotation.
7110                    if (isLandscapeOrSeascape(preferredRotation)) {
7111                        return preferredRotation;
7112                    }
7113                    if (isLandscapeOrSeascape(lastRotation)) {
7114                        return lastRotation;
7115                    }
7116                    return mLandscapeRotation;
7117
7118                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
7119                case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
7120                    // Return either portrait rotation.
7121                    if (isAnyPortrait(preferredRotation)) {
7122                        return preferredRotation;
7123                    }
7124                    if (isAnyPortrait(lastRotation)) {
7125                        return lastRotation;
7126                    }
7127                    return mPortraitRotation;
7128
7129                default:
7130                    // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
7131                    // just return the preferred orientation we already calculated.
7132                    if (preferredRotation >= 0) {
7133                        return preferredRotation;
7134                    }
7135                    return Surface.ROTATION_0;
7136            }
7137        }
7138    }
7139
7140    @Override
7141    public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
7142        switch (orientation) {
7143            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
7144            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
7145            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
7146                return isAnyPortrait(rotation);
7147
7148            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
7149            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
7150            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
7151                return isLandscapeOrSeascape(rotation);
7152
7153            default:
7154                return true;
7155        }
7156    }
7157
7158    @Override
7159    public void setRotationLw(int rotation) {
7160        mOrientationListener.setCurrentRotation(rotation);
7161    }
7162
7163    private boolean isLandscapeOrSeascape(int rotation) {
7164        return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
7165    }
7166
7167    private boolean isAnyPortrait(int rotation) {
7168        return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
7169    }
7170
7171    @Override
7172    public int getUserRotationMode() {
7173        return Settings.System.getIntForUser(mContext.getContentResolver(),
7174                Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
7175                        WindowManagerPolicy.USER_ROTATION_FREE :
7176                                WindowManagerPolicy.USER_ROTATION_LOCKED;
7177    }
7178
7179    // User rotation: to be used when all else fails in assigning an orientation to the device
7180    @Override
7181    public void setUserRotationMode(int mode, int rot) {
7182        ContentResolver res = mContext.getContentResolver();
7183
7184        // mUserRotationMode and mUserRotation will be assigned by the content observer
7185        if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
7186            Settings.System.putIntForUser(res,
7187                    Settings.System.USER_ROTATION,
7188                    rot,
7189                    UserHandle.USER_CURRENT);
7190            Settings.System.putIntForUser(res,
7191                    Settings.System.ACCELEROMETER_ROTATION,
7192                    0,
7193                    UserHandle.USER_CURRENT);
7194        } else {
7195            Settings.System.putIntForUser(res,
7196                    Settings.System.ACCELEROMETER_ROTATION,
7197                    1,
7198                    UserHandle.USER_CURRENT);
7199        }
7200    }
7201
7202    @Override
7203    public void setSafeMode(boolean safeMode) {
7204        mSafeMode = safeMode;
7205        performHapticFeedbackLw(null, safeMode
7206                ? HapticFeedbackConstants.SAFE_MODE_ENABLED
7207                : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
7208    }
7209
7210    static long[] getLongIntArray(Resources r, int resid) {
7211        int[] ar = r.getIntArray(resid);
7212        if (ar == null) {
7213            return null;
7214        }
7215        long[] out = new long[ar.length];
7216        for (int i=0; i<ar.length; i++) {
7217            out[i] = ar[i];
7218        }
7219        return out;
7220    }
7221
7222    private void bindKeyguard() {
7223        synchronized (mLock) {
7224            if (mKeyguardBound) {
7225                return;
7226            }
7227            mKeyguardBound = true;
7228        }
7229        mKeyguardDelegate.bindService(mContext);
7230    }
7231
7232    @Override
7233    public void onSystemUiStarted() {
7234        bindKeyguard();
7235    }
7236
7237    /** {@inheritDoc} */
7238    @Override
7239    public void systemReady() {
7240        // In normal flow, systemReady is called before other system services are ready.
7241        // So it is better not to bind keyguard here.
7242        mKeyguardDelegate.onSystemReady();
7243
7244        mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
7245        if (mVrManagerInternal != null) {
7246            mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
7247        }
7248
7249        readCameraLensCoverState();
7250        updateUiMode();
7251        synchronized (mLock) {
7252            updateOrientationListenerLp();
7253            mSystemReady = true;
7254            mHandler.post(new Runnable() {
7255                @Override
7256                public void run() {
7257                    updateSettings();
7258                }
7259            });
7260            // If this happens, for whatever reason, systemReady came later than systemBooted.
7261            // And keyguard should be already bound from systemBooted
7262            if (mSystemBooted) {
7263                mKeyguardDelegate.onBootCompleted();
7264            }
7265        }
7266
7267        mSystemGestures.systemReady();
7268        mImmersiveModeConfirmation.systemReady();
7269
7270        mAutofillManagerInternal = LocalServices.getService(AutofillManagerInternal.class);
7271    }
7272
7273    /** {@inheritDoc} */
7274    @Override
7275    public void systemBooted() {
7276        bindKeyguard();
7277        synchronized (mLock) {
7278            mSystemBooted = true;
7279            if (mSystemReady) {
7280                mKeyguardDelegate.onBootCompleted();
7281            }
7282        }
7283        startedWakingUp();
7284        screenTurningOn(null);
7285        screenTurnedOn();
7286    }
7287
7288    @Override
7289    public boolean canDismissBootAnimation() {
7290        synchronized (mLock) {
7291            return mKeyguardDrawComplete;
7292        }
7293    }
7294
7295    ProgressDialog mBootMsgDialog = null;
7296
7297    /** {@inheritDoc} */
7298    @Override
7299    public void showBootMessage(final CharSequence msg, final boolean always) {
7300        mHandler.post(new Runnable() {
7301            @Override public void run() {
7302                if (mBootMsgDialog == null) {
7303                    int theme;
7304                    if (mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK)) {
7305                        theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
7306                    } else {
7307                        theme = 0;
7308                    }
7309
7310                    mBootMsgDialog = new ProgressDialog(mContext, theme) {
7311                        // This dialog will consume all events coming in to
7312                        // it, to avoid it trying to do things too early in boot.
7313                        @Override public boolean dispatchKeyEvent(KeyEvent event) {
7314                            return true;
7315                        }
7316                        @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7317                            return true;
7318                        }
7319                        @Override public boolean dispatchTouchEvent(MotionEvent ev) {
7320                            return true;
7321                        }
7322                        @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
7323                            return true;
7324                        }
7325                        @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
7326                            return true;
7327                        }
7328                        @Override public boolean dispatchPopulateAccessibilityEvent(
7329                                AccessibilityEvent event) {
7330                            return true;
7331                        }
7332                    };
7333                    if (mContext.getPackageManager().isUpgrade()) {
7334                        mBootMsgDialog.setTitle(R.string.android_upgrading_title);
7335                    } else {
7336                        mBootMsgDialog.setTitle(R.string.android_start_title);
7337                    }
7338                    mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
7339                    mBootMsgDialog.setIndeterminate(true);
7340                    mBootMsgDialog.getWindow().setType(
7341                            WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
7342                    mBootMsgDialog.getWindow().addFlags(
7343                            WindowManager.LayoutParams.FLAG_DIM_BEHIND
7344                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
7345                    mBootMsgDialog.getWindow().setDimAmount(1);
7346                    WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
7347                    lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
7348                    mBootMsgDialog.getWindow().setAttributes(lp);
7349                    mBootMsgDialog.setCancelable(false);
7350                    mBootMsgDialog.show();
7351                }
7352                mBootMsgDialog.setMessage(msg);
7353            }
7354        });
7355    }
7356
7357    /** {@inheritDoc} */
7358    @Override
7359    public void hideBootMessages() {
7360        mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
7361    }
7362
7363    /** {@inheritDoc} */
7364    @Override
7365    public void userActivity() {
7366        // ***************************************
7367        // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
7368        // ***************************************
7369        // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
7370        // WITH ITS LOCKS HELD.
7371        //
7372        // This code must be VERY careful about the locks
7373        // it acquires.
7374        // In fact, the current code acquires way too many,
7375        // and probably has lurking deadlocks.
7376
7377        synchronized (mScreenLockTimeout) {
7378            if (mLockScreenTimerActive) {
7379                // reset the timer
7380                mHandler.removeCallbacks(mScreenLockTimeout);
7381                mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7382            }
7383        }
7384    }
7385
7386    class ScreenLockTimeout implements Runnable {
7387        Bundle options;
7388
7389        @Override
7390        public void run() {
7391            synchronized (this) {
7392                if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
7393                if (mKeyguardDelegate != null) {
7394                    mKeyguardDelegate.doKeyguardTimeout(options);
7395                }
7396                mLockScreenTimerActive = false;
7397                options = null;
7398            }
7399        }
7400
7401        public void setLockOptions(Bundle options) {
7402            this.options = options;
7403        }
7404    }
7405
7406    ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
7407
7408    @Override
7409    public void lockNow(Bundle options) {
7410        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
7411        mHandler.removeCallbacks(mScreenLockTimeout);
7412        if (options != null) {
7413            // In case multiple calls are made to lockNow, we don't wipe out the options
7414            // until the runnable actually executes.
7415            mScreenLockTimeout.setLockOptions(options);
7416        }
7417        mHandler.post(mScreenLockTimeout);
7418    }
7419
7420    private void updateLockScreenTimeout() {
7421        synchronized (mScreenLockTimeout) {
7422            boolean enable = (mAllowLockscreenWhenOn && mAwake &&
7423                    mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
7424            if (mLockScreenTimerActive != enable) {
7425                if (enable) {
7426                    if (localLOGV) Log.v(TAG, "setting lockscreen timer");
7427                    mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
7428                    mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7429                } else {
7430                    if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
7431                    mHandler.removeCallbacks(mScreenLockTimeout);
7432                }
7433                mLockScreenTimerActive = enable;
7434            }
7435        }
7436    }
7437
7438    private void updateDreamingSleepToken(boolean acquire) {
7439        if (acquire) {
7440            if (mDreamingSleepToken == null) {
7441                mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream");
7442            }
7443        } else {
7444            if (mDreamingSleepToken != null) {
7445                mDreamingSleepToken.release();
7446                mDreamingSleepToken = null;
7447            }
7448        }
7449    }
7450
7451    private void updateScreenOffSleepToken(boolean acquire) {
7452        if (acquire) {
7453            if (mScreenOffSleepToken == null) {
7454                mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff");
7455            }
7456        } else {
7457            if (mScreenOffSleepToken != null) {
7458                mScreenOffSleepToken.release();
7459                mScreenOffSleepToken = null;
7460            }
7461        }
7462    }
7463
7464    /** {@inheritDoc} */
7465    @Override
7466    public void enableScreenAfterBoot() {
7467        readLidState();
7468        applyLidSwitchState();
7469        updateRotation(true);
7470    }
7471
7472    private void applyLidSwitchState() {
7473        if (mLidState == LID_CLOSED && mLidControlsSleep) {
7474            mPowerManager.goToSleep(SystemClock.uptimeMillis(),
7475                    PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
7476                    PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
7477        } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
7478            mWindowManagerFuncs.lockDeviceNow();
7479        }
7480
7481        synchronized (mLock) {
7482            updateWakeGestureListenerLp();
7483        }
7484    }
7485
7486    void updateUiMode() {
7487        if (mUiModeManager == null) {
7488            mUiModeManager = IUiModeManager.Stub.asInterface(
7489                    ServiceManager.getService(Context.UI_MODE_SERVICE));
7490        }
7491        try {
7492            mUiMode = mUiModeManager.getCurrentModeType();
7493        } catch (RemoteException e) {
7494        }
7495    }
7496
7497    void updateRotation(boolean alwaysSendConfiguration) {
7498        try {
7499            //set orientation on WindowManager
7500            mWindowManager.updateRotation(alwaysSendConfiguration, false);
7501        } catch (RemoteException e) {
7502            // Ignore
7503        }
7504    }
7505
7506    void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
7507        try {
7508            //set orientation on WindowManager
7509            mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
7510        } catch (RemoteException e) {
7511            // Ignore
7512        }
7513    }
7514
7515    /**
7516     * Return an Intent to launch the currently active dock app as home.  Returns
7517     * null if the standard home should be launched, which is the case if any of the following is
7518     * true:
7519     * <ul>
7520     *  <li>The device is not in either car mode or desk mode
7521     *  <li>The device is in car mode but mEnableCarDockHomeCapture is false
7522     *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
7523     *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
7524     *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
7525     * </ul>
7526     * @return A dock intent.
7527     */
7528    Intent createHomeDockIntent() {
7529        Intent intent = null;
7530
7531        // What home does is based on the mode, not the dock state.  That
7532        // is, when in car mode you should be taken to car home regardless
7533        // of whether we are actually in a car dock.
7534        if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
7535            if (mEnableCarDockHomeCapture) {
7536                intent = mCarDockIntent;
7537            }
7538        } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
7539            if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
7540                intent = mDeskDockIntent;
7541            }
7542        } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
7543                && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7544                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
7545                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
7546            // Always launch dock home from home when watch is docked, if it exists.
7547            intent = mDeskDockIntent;
7548        } else if (mUiMode == Configuration.UI_MODE_TYPE_VR_HEADSET) {
7549            if (ENABLE_VR_HEADSET_HOME_CAPTURE) {
7550                intent = mVrHeadsetHomeIntent;
7551            }
7552        }
7553
7554        if (intent == null) {
7555            return null;
7556        }
7557
7558        ActivityInfo ai = null;
7559        ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
7560                intent,
7561                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
7562                mCurrentUserId);
7563        if (info != null) {
7564            ai = info.activityInfo;
7565        }
7566        if (ai != null
7567                && ai.metaData != null
7568                && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
7569            intent = new Intent(intent);
7570            intent.setClassName(ai.packageName, ai.name);
7571            return intent;
7572        }
7573
7574        return null;
7575    }
7576
7577    void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
7578        if (awakenFromDreams) {
7579            awakenDreams();
7580        }
7581
7582        Intent dock = createHomeDockIntent();
7583        if (dock != null) {
7584            try {
7585                if (fromHomeKey) {
7586                    dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7587                }
7588                startActivityAsUser(dock, UserHandle.CURRENT);
7589                return;
7590            } catch (ActivityNotFoundException e) {
7591            }
7592        }
7593
7594        Intent intent;
7595
7596        if (fromHomeKey) {
7597            intent = new Intent(mHomeIntent);
7598            intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7599        } else {
7600            intent = mHomeIntent;
7601        }
7602
7603        startActivityAsUser(intent, UserHandle.CURRENT);
7604    }
7605
7606    /**
7607     * goes to the home screen
7608     * @return whether it did anything
7609     */
7610    boolean goHome() {
7611        if (!isUserSetupComplete()) {
7612            Slog.i(TAG, "Not going home because user setup is in progress.");
7613            return false;
7614        }
7615        if (false) {
7616            // This code always brings home to the front.
7617            try {
7618                ActivityManager.getService().stopAppSwitches();
7619            } catch (RemoteException e) {
7620            }
7621            sendCloseSystemWindows();
7622            startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
7623        } else {
7624            // This code brings home to the front or, if it is already
7625            // at the front, puts the device to sleep.
7626            try {
7627                if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
7628                    /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
7629                    Log.d(TAG, "UTS-TEST-MODE");
7630                } else {
7631                    ActivityManager.getService().stopAppSwitches();
7632                    sendCloseSystemWindows();
7633                    Intent dock = createHomeDockIntent();
7634                    if (dock != null) {
7635                        int result = ActivityManager.getService()
7636                                .startActivityAsUser(null, null, dock,
7637                                        dock.resolveTypeIfNeeded(mContext.getContentResolver()),
7638                                        null, null, 0,
7639                                        ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7640                                        null, null, UserHandle.USER_CURRENT);
7641                        if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7642                            return false;
7643                        }
7644                    }
7645                }
7646                int result = ActivityManager.getService()
7647                        .startActivityAsUser(null, null, mHomeIntent,
7648                                mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
7649                                null, null, 0,
7650                                ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7651                                null, null, UserHandle.USER_CURRENT);
7652                if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7653                    return false;
7654                }
7655            } catch (RemoteException ex) {
7656                // bummer, the activity manager, which is in this process, is dead
7657            }
7658        }
7659        return true;
7660    }
7661
7662    @Override
7663    public void setCurrentOrientationLw(int newOrientation) {
7664        synchronized (mLock) {
7665            if (newOrientation != mCurrentAppOrientation) {
7666                mCurrentAppOrientation = newOrientation;
7667                updateOrientationListenerLp();
7668            }
7669        }
7670    }
7671
7672    private boolean isTheaterModeEnabled() {
7673        return Settings.Global.getInt(mContext.getContentResolver(),
7674                Settings.Global.THEATER_MODE_ON, 0) == 1;
7675    }
7676
7677    private boolean areSystemNavigationKeysEnabled() {
7678        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
7679                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
7680    }
7681
7682    @Override
7683    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
7684        if (!mVibrator.hasVibrator()) {
7685            return false;
7686        }
7687        final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
7688                Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
7689        if (hapticsDisabled && !always) {
7690            return false;
7691        }
7692
7693        VibrationEffect effect = getVibrationEffect(effectId);
7694        if (effect == null) {
7695            return false;
7696        }
7697
7698        int owningUid;
7699        String owningPackage;
7700        if (win != null) {
7701            owningUid = win.getOwningUid();
7702            owningPackage = win.getOwningPackage();
7703        } else {
7704            owningUid = android.os.Process.myUid();
7705            owningPackage = mContext.getOpPackageName();
7706        }
7707        mVibrator.vibrate(owningUid, owningPackage, effect, VIBRATION_ATTRIBUTES);
7708        return true;
7709    }
7710
7711    private VibrationEffect getVibrationEffect(int effectId) {
7712        long[] pattern;
7713        switch (effectId) {
7714            case HapticFeedbackConstants.VIRTUAL_KEY:
7715                return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
7716            case HapticFeedbackConstants.LONG_PRESS:
7717                pattern = mLongPressVibePattern;
7718                break;
7719            case HapticFeedbackConstants.KEYBOARD_TAP:
7720                return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
7721            case HapticFeedbackConstants.CLOCK_TICK:
7722                pattern = mClockTickVibePattern;
7723                break;
7724            case HapticFeedbackConstants.CALENDAR_DATE:
7725                pattern = mCalendarDateVibePattern;
7726                break;
7727            case HapticFeedbackConstants.SAFE_MODE_DISABLED:
7728                pattern = mSafeModeDisabledVibePattern;
7729                break;
7730            case HapticFeedbackConstants.SAFE_MODE_ENABLED:
7731                pattern = mSafeModeEnabledVibePattern;
7732                break;
7733            case HapticFeedbackConstants.CONTEXT_CLICK:
7734                pattern = mContextClickVibePattern;
7735                break;
7736            default:
7737                return null;
7738        }
7739        if (pattern.length == 0) {
7740            // No vibration
7741            return null;
7742        } else if (pattern.length == 1) {
7743            // One-shot vibration
7744            return VibrationEffect.createOneShot(pattern[0], VibrationEffect.DEFAULT_AMPLITUDE);
7745        } else {
7746            // Pattern vibration
7747            return VibrationEffect.createWaveform(pattern, -1);
7748        }
7749    }
7750
7751    @Override
7752    public void keepScreenOnStartedLw() {
7753    }
7754
7755    @Override
7756    public void keepScreenOnStoppedLw() {
7757        if (isKeyguardShowingAndNotOccluded()) {
7758            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
7759        }
7760    }
7761
7762    private int updateSystemUiVisibilityLw() {
7763        // If there is no window focused, there will be nobody to handle the events
7764        // anyway, so just hang on in whatever state we're in until things settle down.
7765        WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
7766                : mTopFullscreenOpaqueWindowState;
7767        if (winCandidate == null) {
7768            return 0;
7769        }
7770        if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
7771            // The immersive mode confirmation should never affect the system bar visibility,
7772            // otherwise it will unhide the navigation bar and hide itself.
7773            winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState;
7774            if (winCandidate == null) {
7775                return 0;
7776            }
7777        }
7778        final WindowState win = winCandidate;
7779        if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mKeyguardOccluded) {
7780            // We are updating at a point where the keyguard has gotten
7781            // focus, but we were last in a state where the top window is
7782            // hiding it.  This is probably because the keyguard as been
7783            // shown while the top window was displayed, so we want to ignore
7784            // it here because this is just a very transient change and it
7785            // will quickly lose focus once it correctly gets hidden.
7786            return 0;
7787        }
7788
7789        int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
7790                & ~mResettingSystemUiFlags
7791                & ~mForceClearedSystemUiFlags;
7792        if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
7793            tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
7794        }
7795
7796        final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
7797                mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
7798        final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
7799                mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
7800        mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);
7801        mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);
7802        final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
7803        final int diff = visibility ^ mLastSystemUiFlags;
7804        final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
7805        final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
7806        final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
7807        if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
7808                && mFocusedApp == win.getAppToken()
7809                && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
7810                && mLastDockedStackBounds.equals(mDockedStackBounds)) {
7811            return 0;
7812        }
7813        mLastSystemUiFlags = visibility;
7814        mLastFullscreenStackSysUiFlags = fullscreenVisibility;
7815        mLastDockedStackSysUiFlags = dockedVisibility;
7816        mLastFocusNeedsMenu = needsMenu;
7817        mFocusedApp = win.getAppToken();
7818        final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
7819        final Rect dockedStackBounds = new Rect(mDockedStackBounds);
7820        mHandler.post(new Runnable() {
7821                @Override
7822                public void run() {
7823                    StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
7824                    if (statusbar != null) {
7825                        statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
7826                                dockedVisibility, 0xffffffff, fullscreenStackBounds,
7827                                dockedStackBounds, win.toString());
7828                        statusbar.topAppWindowChanged(needsMenu);
7829                    }
7830                }
7831            });
7832        return diff;
7833    }
7834
7835    private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
7836        WindowState statusColorWin = isStatusBarKeyguard() && !mKeyguardOccluded
7837                ? mStatusBar
7838                : opaqueOrDimming;
7839
7840        if (statusColorWin != null) {
7841            if (statusColorWin == opaque) {
7842                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7843                // its light flag.
7844                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7845                vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
7846                        & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7847            } else if (statusColorWin != null && statusColorWin.isDimming()) {
7848                // Otherwise if it's dimming, clear the light flag.
7849                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7850            }
7851        }
7852        return vis;
7853    }
7854
7855    private int updateLightNavigationBarLw(int vis, WindowState opaque,
7856            WindowState opaqueOrDimming) {
7857        final WindowState imeWin = mWindowManagerFuncs.getInputMethodWindowLw();
7858
7859        final WindowState navColorWin;
7860        if (imeWin != null && imeWin.isVisibleLw()) {
7861            navColorWin = imeWin;
7862        } else {
7863            navColorWin = opaqueOrDimming;
7864        }
7865
7866        if (navColorWin != null) {
7867            if (navColorWin == opaque) {
7868                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7869                // its light flag.
7870                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7871                vis |= PolicyControl.getSystemUiVisibility(navColorWin, null)
7872                        & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7873            } else if (navColorWin.isDimming() || navColorWin == imeWin) {
7874                // Otherwise if it's dimming or it's the IME window, clear the light flag.
7875                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7876            }
7877        }
7878        return vis;
7879    }
7880
7881    private boolean drawsSystemBarBackground(WindowState win) {
7882        return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
7883    }
7884
7885    private boolean forcesDrawStatusBarBackground(WindowState win) {
7886        return win == null || (win.getAttrs().privateFlags
7887                & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
7888    }
7889
7890    private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
7891        final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
7892        final boolean freeformStackVisible =
7893                mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
7894        final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
7895
7896        // We need to force system bars when the docked stack is visible, when the freeform stack
7897        // is visible but also when we are resizing for the transitions when docked stack
7898        // visibility changes.
7899        mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
7900        final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
7901
7902        // apply translucent bar vis flags
7903        WindowState fullscreenTransWin = isStatusBarKeyguard() && !mKeyguardOccluded
7904                ? mStatusBar
7905                : mTopFullscreenOpaqueWindowState;
7906        vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7907        vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7908        final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
7909                mTopDockedOpaqueWindowState, 0, 0);
7910
7911        final boolean fullscreenDrawsStatusBarBackground =
7912                (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
7913                        && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
7914                || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
7915        final boolean dockedDrawsStatusBarBackground =
7916                (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
7917                        && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
7918                || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
7919
7920        // prevent status bar interaction from clearing certain flags
7921        int type = win.getAttrs().type;
7922        boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
7923        if (statusBarHasFocus && !isStatusBarKeyguard()) {
7924            int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
7925                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
7926                    | View.SYSTEM_UI_FLAG_IMMERSIVE
7927                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
7928                    | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7929            if (mKeyguardOccluded) {
7930                flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
7931            }
7932            vis = (vis & ~flags) | (oldVis & flags);
7933        }
7934
7935        if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
7936            vis |= View.STATUS_BAR_TRANSPARENT;
7937            vis &= ~View.STATUS_BAR_TRANSLUCENT;
7938        } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
7939                || forceOpaqueStatusBar) {
7940            vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
7941        }
7942
7943        vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
7944
7945        // update status bar
7946        boolean immersiveSticky =
7947                (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7948        final boolean hideStatusBarWM =
7949                mTopFullscreenOpaqueWindowState != null
7950                && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
7951                        & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
7952        final boolean hideStatusBarSysui =
7953                (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
7954        final boolean hideNavBarSysui =
7955                (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
7956
7957        final boolean transientStatusBarAllowed = mStatusBar != null
7958                && (statusBarHasFocus || (!mForceShowSystemBars
7959                        && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
7960
7961        final boolean transientNavBarAllowed = mNavigationBar != null
7962                && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
7963
7964        final long now = SystemClock.uptimeMillis();
7965        final boolean pendingPanic = mPendingPanicGestureUptime != 0
7966                && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
7967        if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
7968            // The user performed the panic gesture recently, we're about to hide the bars,
7969            // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
7970            mPendingPanicGestureUptime = 0;
7971            mStatusBarController.showTransient();
7972            if (!isNavBarEmpty(vis)) {
7973                mNavigationBarController.showTransient();
7974            }
7975        }
7976
7977        final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
7978                && !transientStatusBarAllowed && hideStatusBarSysui;
7979        final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
7980                && !transientNavBarAllowed;
7981        if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
7982            // clear the clearable flags instead
7983            clearClearableFlagsLw();
7984            vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
7985        }
7986
7987        final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
7988        immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7989        final boolean navAllowedHidden = immersive || immersiveSticky;
7990
7991        if (hideNavBarSysui && !navAllowedHidden
7992                && getWindowLayerLw(win) > getWindowLayerFromTypeLw(TYPE_INPUT_CONSUMER)) {
7993            // We can't hide the navbar from this window otherwise the input consumer would not get
7994            // the input events.
7995            vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
7996        }
7997
7998        vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
7999
8000        // update navigation bar
8001        boolean oldImmersiveMode = isImmersiveMode(oldVis);
8002        boolean newImmersiveMode = isImmersiveMode(vis);
8003        if (win != null && oldImmersiveMode != newImmersiveMode) {
8004            final String pkg = win.getOwningPackage();
8005            mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
8006                    isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility()));
8007        }
8008
8009        vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
8010
8011        vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState,
8012                mTopFullscreenOpaqueOrDimmingWindowState);
8013
8014        return vis;
8015    }
8016
8017    /**
8018     * @return the current visibility flags with the nav-bar opacity related flags toggled based
8019     *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
8020     */
8021    private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
8022            boolean freeformStackVisible, boolean isDockedDividerResizing) {
8023        if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
8024            if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
8025                visibility = setNavBarOpaqueFlag(visibility);
8026            }
8027        } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
8028            if (isDockedDividerResizing) {
8029                visibility = setNavBarOpaqueFlag(visibility);
8030            } else if (freeformStackVisible) {
8031                visibility = setNavBarTranslucentFlag(visibility);
8032            } else {
8033                visibility = setNavBarOpaqueFlag(visibility);
8034            }
8035        }
8036
8037        if (!areTranslucentBarsAllowed()) {
8038            visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
8039        }
8040        return visibility;
8041    }
8042
8043    private int setNavBarOpaqueFlag(int visibility) {
8044        return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
8045    }
8046
8047    private int setNavBarTranslucentFlag(int visibility) {
8048        visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
8049        return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
8050    }
8051
8052    private void clearClearableFlagsLw() {
8053        int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
8054        if (newVal != mResettingSystemUiFlags) {
8055            mResettingSystemUiFlags = newVal;
8056            mWindowManagerFuncs.reevaluateStatusBarVisibility();
8057        }
8058    }
8059
8060    private boolean isImmersiveMode(int vis) {
8061        final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
8062        return mNavigationBar != null
8063                && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
8064                && (vis & flags) != 0
8065                && canHideNavigationBar();
8066    }
8067
8068    private static boolean isNavBarEmpty(int systemUiFlags) {
8069        final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
8070                | View.STATUS_BAR_DISABLE_BACK
8071                | View.STATUS_BAR_DISABLE_RECENT);
8072
8073        return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
8074    }
8075
8076    /**
8077     * @return whether the navigation or status bar can be made translucent
8078     *
8079     * This should return true unless touch exploration is not enabled or
8080     * R.boolean.config_enableTranslucentDecor is false.
8081     */
8082    private boolean areTranslucentBarsAllowed() {
8083        return mTranslucentDecorEnabled;
8084    }
8085
8086    // Use this instead of checking config_showNavigationBar so that it can be consistently
8087    // overridden by qemu.hw.mainkeys in the emulator.
8088    @Override
8089    public boolean hasNavigationBar() {
8090        return mHasNavigationBar;
8091    }
8092
8093    @Override
8094    public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
8095        mLastInputMethodWindow = ime;
8096        mLastInputMethodTargetWindow = target;
8097    }
8098
8099    @Override
8100    public void setDismissImeOnBackKeyPressed(boolean newValue) {
8101        mDismissImeOnBackKeyPressed = newValue;
8102    }
8103
8104    @Override
8105    public int getInputMethodWindowVisibleHeightLw() {
8106        return mDockBottom - mCurBottom;
8107    }
8108
8109    @Override
8110    public void setCurrentUserLw(int newUserId) {
8111        mCurrentUserId = newUserId;
8112        if (mKeyguardDelegate != null) {
8113            mKeyguardDelegate.setCurrentUser(newUserId);
8114        }
8115        if (mAccessibilityShortcutController != null) {
8116            mAccessibilityShortcutController.setCurrentUser(newUserId);
8117        }
8118        StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
8119        if (statusBar != null) {
8120            statusBar.setCurrentUser(newUserId);
8121        }
8122        setLastInputMethodWindowLw(null, null);
8123    }
8124
8125    @Override
8126    public void setSwitchingUser(boolean switching) {
8127        mKeyguardDelegate.setSwitchingUser(switching);
8128    }
8129
8130    @Override
8131    public boolean canMagnifyWindow(int windowType) {
8132        switch (windowType) {
8133            case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
8134            case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
8135            case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
8136            case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
8137                return false;
8138            }
8139        }
8140        return true;
8141    }
8142
8143    @Override
8144    public boolean isTopLevelWindow(int windowType) {
8145        if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
8146                && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
8147            return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
8148        }
8149        return true;
8150    }
8151
8152    @Override
8153    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
8154        // For the upside down rotation we don't rotate seamlessly as the navigation
8155        // bar moves position.
8156        // Note most apps (using orientation:sensor or user as opposed to fullSensor)
8157        // will not enter the reverse portrait orientation, so actually the
8158        // orientation won't change at all.
8159        if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
8160            return false;
8161        }
8162        // If the navigation bar can't change sides, then it will
8163        // jump when we change orientations and we don't rotate
8164        // seamlessly.
8165        if (!mNavigationBarCanMove) {
8166            return false;
8167        }
8168        int delta = newRotation - oldRotation;
8169        if (delta < 0) delta += 4;
8170        // Likewise we don't rotate seamlessly for 180 degree rotations
8171        // in this case the surfaces never resize, and our logic to
8172        // revert the transformations on size change will fail. We could
8173        // fix this in the future with the "tagged" frames idea.
8174        if (delta == Surface.ROTATION_180) {
8175            return false;
8176        }
8177
8178        final WindowState w = mTopFullscreenOpaqueWindowState;
8179        if (w != mFocusedWindow) {
8180            return false;
8181        }
8182
8183        // We only enable seamless rotation if the top window has requested
8184        // it and is in the fullscreen opaque state. Seamless rotation
8185        // requires freezing various Surface states and won't work well
8186        // with animations, so we disable it in the animation case for now.
8187        if (w != null && !w.isAnimatingLw() &&
8188                ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) ||
8189                        (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) {
8190            return true;
8191        }
8192        return false;
8193    }
8194
8195    @Override
8196    public void dump(String prefix, PrintWriter pw, String[] args) {
8197        pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
8198                pw.print(" mSystemReady="); pw.print(mSystemReady);
8199                pw.print(" mSystemBooted="); pw.println(mSystemBooted);
8200        pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
8201                pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
8202                pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
8203                pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
8204        if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
8205                || mForceClearedSystemUiFlags != 0) {
8206            pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
8207                    pw.print(Integer.toHexString(mLastSystemUiFlags));
8208                    pw.print(" mResettingSystemUiFlags=0x");
8209                    pw.print(Integer.toHexString(mResettingSystemUiFlags));
8210                    pw.print(" mForceClearedSystemUiFlags=0x");
8211                    pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
8212        }
8213        if (mLastFocusNeedsMenu) {
8214            pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
8215                    pw.println(mLastFocusNeedsMenu);
8216        }
8217        pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
8218                pw.println(mWakeGestureEnabledSetting);
8219
8220        pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
8221        pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
8222                pw.print(" mDockMode="); pw.print(mDockMode);
8223                pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
8224                pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
8225                pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
8226        pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
8227                pw.print(" mUserRotation="); pw.print(mUserRotation);
8228                pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
8229        pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
8230        pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
8231                pw.print(mCarDockEnablesAccelerometer);
8232                pw.print(" mDeskDockEnablesAccelerometer=");
8233                pw.println(mDeskDockEnablesAccelerometer);
8234        pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
8235                pw.print(mLidKeyboardAccessibility);
8236                pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
8237                pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
8238                pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
8239        pw.print(prefix);
8240                pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
8241        pw.print(prefix);
8242                pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
8243                pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
8244        pw.print(prefix);
8245                pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
8246                pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
8247        pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
8248        pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
8249        pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
8250                pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
8251        pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
8252                pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
8253        pw.print(prefix); pw.print("mOrientationSensorEnabled=");
8254                pw.println(mOrientationSensorEnabled);
8255        pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
8256                pw.print(","); pw.print(mOverscanScreenTop);
8257                pw.print(") "); pw.print(mOverscanScreenWidth);
8258                pw.print("x"); pw.println(mOverscanScreenHeight);
8259        if (mOverscanLeft != 0 || mOverscanTop != 0
8260                || mOverscanRight != 0 || mOverscanBottom != 0) {
8261            pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
8262                    pw.print(" top="); pw.print(mOverscanTop);
8263                    pw.print(" right="); pw.print(mOverscanRight);
8264                    pw.print(" bottom="); pw.println(mOverscanBottom);
8265        }
8266        pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
8267                pw.print(mRestrictedOverscanScreenLeft);
8268                pw.print(","); pw.print(mRestrictedOverscanScreenTop);
8269                pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
8270                pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
8271        pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
8272                pw.print(","); pw.print(mUnrestrictedScreenTop);
8273                pw.print(") "); pw.print(mUnrestrictedScreenWidth);
8274                pw.print("x"); pw.println(mUnrestrictedScreenHeight);
8275        pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
8276                pw.print(","); pw.print(mRestrictedScreenTop);
8277                pw.print(") "); pw.print(mRestrictedScreenWidth);
8278                pw.print("x"); pw.println(mRestrictedScreenHeight);
8279        pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
8280                pw.print(","); pw.print(mStableFullscreenTop);
8281                pw.print(")-("); pw.print(mStableFullscreenRight);
8282                pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
8283        pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
8284                pw.print(","); pw.print(mStableTop);
8285                pw.print(")-("); pw.print(mStableRight);
8286                pw.print(","); pw.print(mStableBottom); pw.println(")");
8287        pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
8288                pw.print(","); pw.print(mSystemTop);
8289                pw.print(")-("); pw.print(mSystemRight);
8290                pw.print(","); pw.print(mSystemBottom); pw.println(")");
8291        pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
8292                pw.print(","); pw.print(mCurTop);
8293                pw.print(")-("); pw.print(mCurRight);
8294                pw.print(","); pw.print(mCurBottom); pw.println(")");
8295        pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
8296                pw.print(","); pw.print(mContentTop);
8297                pw.print(")-("); pw.print(mContentRight);
8298                pw.print(","); pw.print(mContentBottom); pw.println(")");
8299        pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft);
8300                pw.print(","); pw.print(mVoiceContentTop);
8301                pw.print(")-("); pw.print(mVoiceContentRight);
8302                pw.print(","); pw.print(mVoiceContentBottom); pw.println(")");
8303        pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
8304                pw.print(","); pw.print(mDockTop);
8305                pw.print(")-("); pw.print(mDockRight);
8306                pw.print(","); pw.print(mDockBottom); pw.println(")");
8307        pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
8308                pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
8309        pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
8310                pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
8311                pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
8312        if (mLastInputMethodWindow != null) {
8313            pw.print(prefix); pw.print("mLastInputMethodWindow=");
8314                    pw.println(mLastInputMethodWindow);
8315        }
8316        if (mLastInputMethodTargetWindow != null) {
8317            pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
8318                    pw.println(mLastInputMethodTargetWindow);
8319        }
8320        pw.print(prefix); pw.print("mDismissImeOnBackKeyPressed=");
8321                pw.println(mDismissImeOnBackKeyPressed);
8322        if (mStatusBar != null) {
8323            pw.print(prefix); pw.print("mStatusBar=");
8324                    pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
8325                    pw.println(isStatusBarKeyguard());
8326        }
8327        if (mNavigationBar != null) {
8328            pw.print(prefix); pw.print("mNavigationBar=");
8329                    pw.println(mNavigationBar);
8330        }
8331        if (mFocusedWindow != null) {
8332            pw.print(prefix); pw.print("mFocusedWindow=");
8333                    pw.println(mFocusedWindow);
8334        }
8335        if (mFocusedApp != null) {
8336            pw.print(prefix); pw.print("mFocusedApp=");
8337                    pw.println(mFocusedApp);
8338        }
8339        if (mTopFullscreenOpaqueWindowState != null) {
8340            pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
8341                    pw.println(mTopFullscreenOpaqueWindowState);
8342        }
8343        if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
8344            pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
8345                    pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
8346        }
8347        if (mForcingShowNavBar) {
8348            pw.print(prefix); pw.print("mForcingShowNavBar=");
8349                    pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
8350                    pw.println(mForcingShowNavBarLayer);
8351        }
8352        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
8353                pw.print(" mKeyguardOccluded="); pw.println(mKeyguardOccluded);
8354                pw.print(" mKeyguardOccludedChanged="); pw.println(mKeyguardOccludedChanged);
8355                pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded);
8356        pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
8357                pw.print(" mForceStatusBarFromKeyguard=");
8358                pw.println(mForceStatusBarFromKeyguard);
8359        pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
8360        pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
8361                pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
8362                pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
8363        pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
8364                pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
8365                pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior);
8366                pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
8367        pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
8368                pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
8369        pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
8370                pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
8371        pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
8372                pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
8373        pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
8374        if (mHasFeatureLeanback) {
8375            pw.print(prefix);
8376            pw.print("mAccessibilityTvKey1Pressed="); pw.println(mAccessibilityTvKey1Pressed);
8377            pw.print(prefix);
8378            pw.print("mAccessibilityTvKey2Pressed="); pw.println(mAccessibilityTvKey2Pressed);
8379            pw.print(prefix);
8380            pw.print("mAccessibilityTvScheduled="); pw.println(mAccessibilityTvScheduled);
8381        }
8382
8383        mGlobalKeyManager.dump(prefix, pw);
8384        mStatusBarController.dump(pw, prefix);
8385        mNavigationBarController.dump(pw, prefix);
8386        PolicyControl.dump(prefix, pw);
8387
8388        if (mWakeGestureListener != null) {
8389            mWakeGestureListener.dump(pw, prefix);
8390        }
8391        if (mOrientationListener != null) {
8392            mOrientationListener.dump(pw, prefix);
8393        }
8394        if (mBurnInProtectionHelper != null) {
8395            mBurnInProtectionHelper.dump(prefix, pw);
8396        }
8397        if (mKeyguardDelegate != null) {
8398            mKeyguardDelegate.dump(prefix, pw);
8399        }
8400    }
8401}
8402