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