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