PhoneWindowManager.java revision fb1bf69d5d7fc8c45e3ddbb8916e21ae57432ff1
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
5900                            MediaSessionLegacyHelper.getHelper(mContext)
5901                                    .sendVolumeKeyEvent(event, false);
5902                            break;
5903                        }
5904                    }
5905                }
5906                if (mUseTvRouting) {
5907                    // On TVs, defer special key handlings to
5908                    // {@link interceptKeyBeforeDispatching()}.
5909                    result |= ACTION_PASS_TO_USER;
5910                } else if ((result & ACTION_PASS_TO_USER) == 0) {
5911                    // If we aren't passing to the user and no one else
5912                    // handled it send it to the session manager to
5913                    // figure out.
5914                    MediaSessionLegacyHelper.getHelper(mContext)
5915                            .sendVolumeKeyEvent(event, true);
5916                }
5917                break;
5918            }
5919
5920            case KeyEvent.KEYCODE_ENDCALL: {
5921                result &= ~ACTION_PASS_TO_USER;
5922                if (down) {
5923                    TelecomManager telecomManager = getTelecommService();
5924                    boolean hungUp = false;
5925                    if (telecomManager != null) {
5926                        hungUp = telecomManager.endCall();
5927                    }
5928                    if (interactive && !hungUp) {
5929                        mEndCallKeyHandled = false;
5930                        mHandler.postDelayed(mEndCallLongPress,
5931                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
5932                    } else {
5933                        mEndCallKeyHandled = true;
5934                    }
5935                } else {
5936                    if (!mEndCallKeyHandled) {
5937                        mHandler.removeCallbacks(mEndCallLongPress);
5938                        if (!canceled) {
5939                            if ((mEndcallBehavior
5940                                    & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
5941                                if (goHome()) {
5942                                    break;
5943                                }
5944                            }
5945                            if ((mEndcallBehavior
5946                                    & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
5947                                mPowerManager.goToSleep(event.getEventTime(),
5948                                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
5949                                isWakeKey = false;
5950                            }
5951                        }
5952                    }
5953                }
5954                break;
5955            }
5956
5957            case KeyEvent.KEYCODE_POWER: {
5958                // Any activity on the power button stops the accessibility shortcut
5959                cancelPendingAccessibilityShortcutAction();
5960                result &= ~ACTION_PASS_TO_USER;
5961                isWakeKey = false; // wake-up will be handled separately
5962                if (down) {
5963                    interceptPowerKeyDown(event, interactive);
5964                } else {
5965                    interceptPowerKeyUp(event, interactive, canceled);
5966                }
5967                break;
5968            }
5969
5970            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
5971                // fall through
5972            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
5973                // fall through
5974            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
5975                // fall through
5976            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
5977                result &= ~ACTION_PASS_TO_USER;
5978                interceptSystemNavigationKey(event);
5979                break;
5980            }
5981
5982            case KeyEvent.KEYCODE_SLEEP: {
5983                result &= ~ACTION_PASS_TO_USER;
5984                isWakeKey = false;
5985                if (!mPowerManager.isInteractive()) {
5986                    useHapticFeedback = false; // suppress feedback if already non-interactive
5987                }
5988                if (down) {
5989                    sleepPress(event.getEventTime());
5990                } else {
5991                    sleepRelease(event.getEventTime());
5992                }
5993                break;
5994            }
5995
5996            case KeyEvent.KEYCODE_SOFT_SLEEP: {
5997                result &= ~ACTION_PASS_TO_USER;
5998                isWakeKey = false;
5999                if (!down) {
6000                    mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
6001                }
6002                break;
6003            }
6004
6005            case KeyEvent.KEYCODE_WAKEUP: {
6006                result &= ~ACTION_PASS_TO_USER;
6007                isWakeKey = true;
6008                break;
6009            }
6010
6011            case KeyEvent.KEYCODE_MEDIA_PLAY:
6012            case KeyEvent.KEYCODE_MEDIA_PAUSE:
6013            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6014            case KeyEvent.KEYCODE_HEADSETHOOK:
6015            case KeyEvent.KEYCODE_MUTE:
6016            case KeyEvent.KEYCODE_MEDIA_STOP:
6017            case KeyEvent.KEYCODE_MEDIA_NEXT:
6018            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6019            case KeyEvent.KEYCODE_MEDIA_REWIND:
6020            case KeyEvent.KEYCODE_MEDIA_RECORD:
6021            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6022            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
6023                if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
6024                    // If the global session is active pass all media keys to it
6025                    // instead of the active window.
6026                    result &= ~ACTION_PASS_TO_USER;
6027                }
6028                if ((result & ACTION_PASS_TO_USER) == 0) {
6029                    // Only do this if we would otherwise not pass it to the user. In that
6030                    // case, the PhoneWindow class will do the same thing, except it will
6031                    // only do it if the showing app doesn't process the key on its own.
6032                    // Note that we need to make a copy of the key event here because the
6033                    // original key event will be recycled when we return.
6034                    mBroadcastWakeLock.acquire();
6035                    Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
6036                            new KeyEvent(event));
6037                    msg.setAsynchronous(true);
6038                    msg.sendToTarget();
6039                }
6040                break;
6041            }
6042
6043            case KeyEvent.KEYCODE_CALL: {
6044                if (down) {
6045                    TelecomManager telecomManager = getTelecommService();
6046                    if (telecomManager != null) {
6047                        if (telecomManager.isRinging()) {
6048                            Log.i(TAG, "interceptKeyBeforeQueueing:"
6049                                  + " CALL key-down while ringing: Answer the call!");
6050                            telecomManager.acceptRingingCall();
6051
6052                            // And *don't* pass this key thru to the current activity
6053                            // (which is presumably the InCallScreen.)
6054                            result &= ~ACTION_PASS_TO_USER;
6055                        }
6056                    }
6057                }
6058                break;
6059            }
6060            case KeyEvent.KEYCODE_VOICE_ASSIST: {
6061                // Only do this if we would otherwise not pass it to the user. In that case,
6062                // interceptKeyBeforeDispatching would apply a similar but different policy in
6063                // order to invoke voice assist actions. Note that we need to make a copy of the
6064                // key event here because the original key event will be recycled when we return.
6065                if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
6066                    mBroadcastWakeLock.acquire();
6067                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
6068                            keyguardActive ? 1 : 0, 0);
6069                    msg.setAsynchronous(true);
6070                    msg.sendToTarget();
6071                }
6072                break;
6073            }
6074            case KeyEvent.KEYCODE_WINDOW: {
6075                if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
6076                    if (mTvPictureInPictureVisible) {
6077                        // Consumes the key only if picture-in-picture is visible
6078                        // to show picture-in-picture control menu.
6079                        // This gives a chance to the foreground activity
6080                        // to customize PIP key behavior.
6081                        if (!down) {
6082                            showTvPictureInPictureMenu(event);
6083                        }
6084                        result &= ~ACTION_PASS_TO_USER;
6085                    }
6086                }
6087                break;
6088            }
6089        }
6090
6091        if (useHapticFeedback) {
6092            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
6093        }
6094
6095        if (isWakeKey) {
6096            wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
6097        }
6098
6099        return result;
6100    }
6101
6102    /**
6103     * Handle statusbar expansion events.
6104     * @param event
6105     */
6106    private void interceptSystemNavigationKey(KeyEvent event) {
6107        if (event.getAction() == KeyEvent.ACTION_UP && areSystemNavigationKeysEnabled()) {
6108            IStatusBarService sbar = getStatusBarService();
6109            if (sbar != null) {
6110                try {
6111                    sbar.handleSystemNavigationKey(event.getKeyCode());
6112                } catch (RemoteException e1) {
6113                    // oops, no statusbar. Ignore event.
6114                }
6115            }
6116        }
6117    }
6118
6119    /**
6120     * Returns true if the key can have global actions attached to it.
6121     * We reserve all power management keys for the system since they require
6122     * very careful handling.
6123     */
6124    private static boolean isValidGlobalKey(int keyCode) {
6125        switch (keyCode) {
6126            case KeyEvent.KEYCODE_POWER:
6127            case KeyEvent.KEYCODE_WAKEUP:
6128            case KeyEvent.KEYCODE_SLEEP:
6129                return false;
6130            default:
6131                return true;
6132        }
6133    }
6134
6135    /**
6136     * When the screen is off we ignore some keys that might otherwise typically
6137     * be considered wake keys.  We filter them out here.
6138     *
6139     * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
6140     * is always considered a wake key.
6141     */
6142    private boolean isWakeKeyWhenScreenOff(int keyCode) {
6143        switch (keyCode) {
6144            // ignore volume keys unless docked
6145            case KeyEvent.KEYCODE_VOLUME_UP:
6146            case KeyEvent.KEYCODE_VOLUME_DOWN:
6147            case KeyEvent.KEYCODE_VOLUME_MUTE:
6148                return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
6149
6150            // ignore media and camera keys
6151            case KeyEvent.KEYCODE_MUTE:
6152            case KeyEvent.KEYCODE_HEADSETHOOK:
6153            case KeyEvent.KEYCODE_MEDIA_PLAY:
6154            case KeyEvent.KEYCODE_MEDIA_PAUSE:
6155            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6156            case KeyEvent.KEYCODE_MEDIA_STOP:
6157            case KeyEvent.KEYCODE_MEDIA_NEXT:
6158            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6159            case KeyEvent.KEYCODE_MEDIA_REWIND:
6160            case KeyEvent.KEYCODE_MEDIA_RECORD:
6161            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6162            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
6163            case KeyEvent.KEYCODE_CAMERA:
6164                return false;
6165        }
6166        return true;
6167    }
6168
6169
6170    /** {@inheritDoc} */
6171    @Override
6172    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
6173        if ((policyFlags & FLAG_WAKE) != 0) {
6174            if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
6175                    "android.policy:MOTION")) {
6176                return 0;
6177            }
6178        }
6179
6180        if (shouldDispatchInputWhenNonInteractive(null)) {
6181            return ACTION_PASS_TO_USER;
6182        }
6183
6184        // If we have not passed the action up and we are in theater mode without dreaming,
6185        // there will be no dream to intercept the touch and wake into ambient.  The device should
6186        // wake up in this case.
6187        if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
6188            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
6189                    "android.policy:MOTION");
6190        }
6191
6192        return 0;
6193    }
6194
6195    private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
6196        final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
6197
6198        if (displayOff && !mHasFeatureWatch) {
6199            return false;
6200        }
6201
6202        // Send events to keyguard while the screen is on and it's showing.
6203        if (isKeyguardShowingAndNotOccluded() && !displayOff) {
6204            return true;
6205        }
6206
6207        // Watches handle BACK specially
6208        if (mHasFeatureWatch
6209                && event != null
6210                && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
6211                        || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
6212            return false;
6213        }
6214
6215        // Send events to a dozing dream even if the screen is off since the dream
6216        // is in control of the state of the screen.
6217        IDreamManager dreamManager = getDreamManager();
6218
6219        try {
6220            if (dreamManager != null && dreamManager.isDreaming()) {
6221                return true;
6222            }
6223        } catch (RemoteException e) {
6224            Slog.e(TAG, "RemoteException when checking if dreaming", e);
6225        }
6226
6227        // Otherwise, consume events since the user can't see what is being
6228        // interacted with.
6229        return false;
6230    }
6231
6232    private void dispatchDirectAudioEvent(KeyEvent event) {
6233        if (event.getAction() != KeyEvent.ACTION_DOWN) {
6234            return;
6235        }
6236        int keyCode = event.getKeyCode();
6237        int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
6238                | AudioManager.FLAG_FROM_KEY;
6239        String pkgName = mContext.getOpPackageName();
6240        switch (keyCode) {
6241            case KeyEvent.KEYCODE_VOLUME_UP:
6242                try {
6243                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
6244                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6245                } catch (RemoteException e) {
6246                    Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
6247                }
6248                break;
6249            case KeyEvent.KEYCODE_VOLUME_DOWN:
6250                try {
6251                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
6252                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6253                } catch (RemoteException e) {
6254                    Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
6255                }
6256                break;
6257            case KeyEvent.KEYCODE_VOLUME_MUTE:
6258                try {
6259                    if (event.getRepeatCount() == 0) {
6260                        getAudioService().adjustSuggestedStreamVolume(
6261                                AudioManager.ADJUST_TOGGLE_MUTE,
6262                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6263                    }
6264                } catch (RemoteException e) {
6265                    Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
6266                }
6267                break;
6268        }
6269    }
6270
6271    void dispatchMediaKeyWithWakeLock(KeyEvent event) {
6272        if (DEBUG_INPUT) {
6273            Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
6274        }
6275
6276        if (mHavePendingMediaKeyRepeatWithWakeLock) {
6277            if (DEBUG_INPUT) {
6278                Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
6279            }
6280
6281            mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
6282            mHavePendingMediaKeyRepeatWithWakeLock = false;
6283            mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
6284        }
6285
6286        dispatchMediaKeyWithWakeLockToAudioService(event);
6287
6288        if (event.getAction() == KeyEvent.ACTION_DOWN
6289                && event.getRepeatCount() == 0) {
6290            mHavePendingMediaKeyRepeatWithWakeLock = true;
6291
6292            Message msg = mHandler.obtainMessage(
6293                    MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
6294            msg.setAsynchronous(true);
6295            mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
6296        } else {
6297            mBroadcastWakeLock.release();
6298        }
6299    }
6300
6301    void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
6302        mHavePendingMediaKeyRepeatWithWakeLock = false;
6303
6304        KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
6305                SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6306        if (DEBUG_INPUT) {
6307            Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
6308        }
6309
6310        dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
6311        mBroadcastWakeLock.release();
6312    }
6313
6314    void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
6315        if (mActivityManagerInternal.isSystemReady()) {
6316            MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
6317        }
6318    }
6319
6320    void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
6321        IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
6322                ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
6323        if (dic != null) {
6324            try {
6325                dic.exitIdle("voice-search");
6326            } catch (RemoteException e) {
6327            }
6328        }
6329        Intent voiceIntent =
6330            new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
6331        voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
6332        startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
6333        mBroadcastWakeLock.release();
6334    }
6335
6336    BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
6337        @Override
6338        public void onReceive(Context context, Intent intent) {
6339            if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
6340                mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6341                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
6342            } else {
6343                try {
6344                    IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
6345                            ServiceManager.getService(Context.UI_MODE_SERVICE));
6346                    mUiMode = uiModeService.getCurrentModeType();
6347                } catch (RemoteException e) {
6348                }
6349            }
6350            updateRotation(true);
6351            synchronized (mLock) {
6352                updateOrientationListenerLp();
6353            }
6354        }
6355    };
6356
6357    BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
6358        @Override
6359        public void onReceive(Context context, Intent intent) {
6360            if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
6361                if (mKeyguardDelegate != null) {
6362                    mKeyguardDelegate.onDreamingStarted();
6363                }
6364            } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
6365                if (mKeyguardDelegate != null) {
6366                    mKeyguardDelegate.onDreamingStopped();
6367                }
6368            }
6369        }
6370    };
6371
6372    BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
6373        @Override
6374        public void onReceive(Context context, Intent intent) {
6375            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
6376                // tickle the settings observer: this first ensures that we're
6377                // observing the relevant settings for the newly-active user,
6378                // and then updates our own bookkeeping based on the now-
6379                // current user.
6380                mSettingsObserver.onChange(false);
6381
6382                // force a re-application of focused window sysui visibility.
6383                // the window may never have been shown for this user
6384                // e.g. the keyguard when going through the new-user setup flow
6385                synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6386                    mLastSystemUiFlags = 0;
6387                    updateSystemUiVisibilityLw();
6388                }
6389            }
6390        }
6391    };
6392
6393    private final Runnable mHiddenNavPanic = new Runnable() {
6394        @Override
6395        public void run() {
6396            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6397                if (!isUserSetupComplete()) {
6398                    // Swipe-up for navigation bar is disabled during setup
6399                    return;
6400                }
6401                mPendingPanicGestureUptime = SystemClock.uptimeMillis();
6402                if (!isNavBarEmpty(mLastSystemUiFlags)) {
6403                    mNavigationBarController.showTransient();
6404                }
6405            }
6406        }
6407    };
6408
6409    private void requestTransientBars(WindowState swipeTarget) {
6410        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6411            if (!isUserSetupComplete()) {
6412                // Swipe-up for navigation bar is disabled during setup
6413                return;
6414            }
6415            boolean sb = mStatusBarController.checkShowTransientBarLw();
6416            boolean nb = mNavigationBarController.checkShowTransientBarLw()
6417                    && !isNavBarEmpty(mLastSystemUiFlags);
6418            if (sb || nb) {
6419                // Don't show status bar when swiping on already visible navigation bar
6420                if (!nb && swipeTarget == mNavigationBar) {
6421                    if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
6422                    return;
6423                }
6424                if (sb) mStatusBarController.showTransient();
6425                if (nb) mNavigationBarController.showTransient();
6426                mImmersiveModeConfirmation.confirmCurrentPrompt();
6427                updateSystemUiVisibilityLw();
6428            }
6429        }
6430    }
6431
6432    // Called on the PowerManager's Notifier thread.
6433    @Override
6434    public void startedGoingToSleep(int why) {
6435        if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
6436        mCameraGestureTriggeredDuringGoingToSleep = false;
6437        mGoingToSleep = true;
6438        if (mKeyguardDelegate != null) {
6439            mKeyguardDelegate.onStartedGoingToSleep(why);
6440        }
6441    }
6442
6443    // Called on the PowerManager's Notifier thread.
6444    @Override
6445    public void finishedGoingToSleep(int why) {
6446        EventLog.writeEvent(70000, 0);
6447        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
6448        MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
6449
6450        mGoingToSleep = false;
6451
6452        // We must get this work done here because the power manager will drop
6453        // the wake lock and let the system suspend once this function returns.
6454        synchronized (mLock) {
6455            mAwake = false;
6456            updateWakeGestureListenerLp();
6457            updateOrientationListenerLp();
6458            updateLockScreenTimeout();
6459        }
6460        if (mKeyguardDelegate != null) {
6461            mKeyguardDelegate.onFinishedGoingToSleep(why,
6462                    mCameraGestureTriggeredDuringGoingToSleep);
6463        }
6464        mCameraGestureTriggeredDuringGoingToSleep = false;
6465    }
6466
6467    // Called on the PowerManager's Notifier thread.
6468    @Override
6469    public void startedWakingUp() {
6470        EventLog.writeEvent(70000, 1);
6471        if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
6472
6473        // Since goToSleep performs these functions synchronously, we must
6474        // do the same here.  We cannot post this work to a handler because
6475        // that might cause it to become reordered with respect to what
6476        // may happen in a future call to goToSleep.
6477        synchronized (mLock) {
6478            mAwake = true;
6479
6480            updateWakeGestureListenerLp();
6481            updateOrientationListenerLp();
6482            updateLockScreenTimeout();
6483        }
6484
6485        if (mKeyguardDelegate != null) {
6486            mKeyguardDelegate.onStartedWakingUp();
6487        }
6488    }
6489
6490    // Called on the PowerManager's Notifier thread.
6491    @Override
6492    public void finishedWakingUp() {
6493        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
6494    }
6495
6496    private void wakeUpFromPowerKey(long eventTime) {
6497        wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
6498    }
6499
6500    private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
6501        final boolean theaterModeEnabled = isTheaterModeEnabled();
6502        if (!wakeInTheaterMode && theaterModeEnabled) {
6503            return false;
6504        }
6505
6506        if (theaterModeEnabled) {
6507            Settings.Global.putInt(mContext.getContentResolver(),
6508                    Settings.Global.THEATER_MODE_ON, 0);
6509        }
6510
6511        mPowerManager.wakeUp(wakeTime, reason);
6512        return true;
6513    }
6514
6515    private void finishKeyguardDrawn() {
6516        synchronized (mLock) {
6517            if (!mScreenOnEarly || mKeyguardDrawComplete) {
6518                return; // We are not awake yet or we have already informed of this event.
6519            }
6520
6521            mKeyguardDrawComplete = true;
6522            if (mKeyguardDelegate != null) {
6523                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6524            }
6525            mWindowManagerDrawComplete = false;
6526        }
6527
6528        // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
6529        // as well as enabling the orientation change logic/sensor.
6530        mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
6531                WAITING_FOR_DRAWN_TIMEOUT);
6532    }
6533
6534    // Called on the DisplayManager's DisplayPowerController thread.
6535    @Override
6536    public void screenTurnedOff() {
6537        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
6538
6539        updateScreenOffSleepToken(true);
6540        synchronized (mLock) {
6541            mScreenOnEarly = false;
6542            mScreenOnFully = false;
6543            mKeyguardDrawComplete = false;
6544            mWindowManagerDrawComplete = false;
6545            mScreenOnListener = null;
6546            updateOrientationListenerLp();
6547
6548            if (mKeyguardDelegate != null) {
6549                mKeyguardDelegate.onScreenTurnedOff();
6550            }
6551        }
6552        reportScreenStateToVrManager(false);
6553    }
6554
6555    // Called on the DisplayManager's DisplayPowerController thread.
6556    @Override
6557    public void screenTurningOn(final ScreenOnListener screenOnListener) {
6558        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
6559
6560        updateScreenOffSleepToken(false);
6561        synchronized (mLock) {
6562            mScreenOnEarly = true;
6563            mScreenOnFully = false;
6564            mKeyguardDrawComplete = false;
6565            mWindowManagerDrawComplete = false;
6566            mScreenOnListener = screenOnListener;
6567
6568            if (mKeyguardDelegate != null) {
6569                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6570                mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
6571                mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
6572            } else {
6573                if (DEBUG_WAKEUP) Slog.d(TAG,
6574                        "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
6575                finishKeyguardDrawn();
6576            }
6577        }
6578    }
6579
6580    // Called on the DisplayManager's DisplayPowerController thread.
6581    @Override
6582    public void screenTurnedOn() {
6583        synchronized (mLock) {
6584            if (mKeyguardDelegate != null) {
6585                mKeyguardDelegate.onScreenTurnedOn();
6586            }
6587        }
6588        reportScreenStateToVrManager(true);
6589    }
6590
6591    private void reportScreenStateToVrManager(boolean isScreenOn) {
6592        VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
6593        if (vrService == null) {
6594            return;
6595        }
6596        vrService.onScreenStateChanged(isScreenOn);
6597    }
6598
6599    private void finishWindowsDrawn() {
6600        synchronized (mLock) {
6601            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
6602                return; // Screen is not turned on or we did already handle this case earlier.
6603            }
6604
6605            mWindowManagerDrawComplete = true;
6606        }
6607
6608        finishScreenTurningOn();
6609    }
6610
6611    private void finishScreenTurningOn() {
6612        synchronized (mLock) {
6613            // We have just finished drawing screen content. Since the orientation listener
6614            // gets only installed when all windows are drawn, we try to install it again.
6615            updateOrientationListenerLp();
6616        }
6617        final ScreenOnListener listener;
6618        final boolean enableScreen;
6619        synchronized (mLock) {
6620            if (DEBUG_WAKEUP) Slog.d(TAG,
6621                    "finishScreenTurningOn: mAwake=" + mAwake
6622                            + ", mScreenOnEarly=" + mScreenOnEarly
6623                            + ", mScreenOnFully=" + mScreenOnFully
6624                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
6625                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
6626
6627            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
6628                    || (mAwake && !mKeyguardDrawComplete)) {
6629                return; // spurious or not ready yet
6630            }
6631
6632            if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
6633            listener = mScreenOnListener;
6634            mScreenOnListener = null;
6635            mScreenOnFully = true;
6636
6637            // Remember the first time we draw the keyguard so we know when we're done with
6638            // the main part of booting and can enable the screen and hide boot messages.
6639            if (!mKeyguardDrawnOnce && mAwake) {
6640                mKeyguardDrawnOnce = true;
6641                enableScreen = true;
6642                if (mBootMessageNeedsHiding) {
6643                    mBootMessageNeedsHiding = false;
6644                    hideBootMessages();
6645                }
6646            } else {
6647                enableScreen = false;
6648            }
6649        }
6650
6651        if (listener != null) {
6652            listener.onScreenOn();
6653        }
6654
6655        if (enableScreen) {
6656            try {
6657                mWindowManager.enableScreenIfNeeded();
6658            } catch (RemoteException unhandled) {
6659            }
6660        }
6661    }
6662
6663    private void handleHideBootMessage() {
6664        synchronized (mLock) {
6665            if (!mKeyguardDrawnOnce) {
6666                mBootMessageNeedsHiding = true;
6667                return; // keyguard hasn't drawn the first time yet, not done booting
6668            }
6669        }
6670
6671        if (mBootMsgDialog != null) {
6672            if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
6673            mBootMsgDialog.dismiss();
6674            mBootMsgDialog = null;
6675        }
6676    }
6677
6678    @Override
6679    public boolean isScreenOn() {
6680        return mScreenOnFully;
6681    }
6682
6683    /** {@inheritDoc} */
6684    @Override
6685    public void enableKeyguard(boolean enabled) {
6686        if (mKeyguardDelegate != null) {
6687            mKeyguardDelegate.setKeyguardEnabled(enabled);
6688        }
6689    }
6690
6691    /** {@inheritDoc} */
6692    @Override
6693    public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
6694        if (mKeyguardDelegate != null) {
6695            mKeyguardDelegate.verifyUnlock(callback);
6696        }
6697    }
6698
6699    @Override
6700    public boolean isKeyguardShowingAndNotOccluded() {
6701        if (mKeyguardDelegate == null) return false;
6702        return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
6703    }
6704
6705    @Override
6706    public boolean isKeyguardTrustedLw() {
6707        if (mKeyguardDelegate == null) return false;
6708        return mKeyguardDelegate.isTrusted();
6709    }
6710
6711    /** {@inheritDoc} */
6712    @Override
6713    public boolean isKeyguardLocked() {
6714        return keyguardOn();
6715    }
6716
6717    /** {@inheritDoc} */
6718    @Override
6719    public boolean isKeyguardSecure(int userId) {
6720        if (mKeyguardDelegate == null) return false;
6721        return mKeyguardDelegate.isSecure(userId);
6722    }
6723
6724    /** {@inheritDoc} */
6725    @Override
6726    public boolean isKeyguardOccluded() {
6727        if (mKeyguardDelegate == null) return false;
6728        return mKeyguardOccluded;
6729    }
6730
6731    /** {@inheritDoc} */
6732    @Override
6733    public boolean inKeyguardRestrictedKeyInputMode() {
6734        if (mKeyguardDelegate == null) return false;
6735        return mKeyguardDelegate.isInputRestricted();
6736    }
6737
6738    @Override
6739    public void dismissKeyguardLw(IKeyguardDismissCallback callback) {
6740        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
6741            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
6742
6743            // ask the keyguard to prompt the user to authenticate if necessary
6744            mKeyguardDelegate.dismiss(callback);
6745        } else if (callback != null) {
6746            try {
6747                callback.onDismissError();
6748            } catch (RemoteException e) {
6749                Slog.w(TAG, "Failed to call callback", e);
6750            }
6751        }
6752    }
6753
6754    @Override
6755    public boolean isKeyguardDrawnLw() {
6756        synchronized (mLock) {
6757            return mKeyguardDrawnOnce;
6758        }
6759    }
6760
6761    @Override
6762    public boolean isShowingDreamLw() {
6763        return mShowingDream;
6764    }
6765
6766    @Override
6767    public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
6768        if (mKeyguardDelegate != null) {
6769            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
6770            mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
6771        }
6772    }
6773
6774    @Override
6775    public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6776            Rect outInsets) {
6777        outInsets.setEmpty();
6778
6779        // Navigation bar and status bar.
6780        getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
6781        outInsets.top = mStatusBarHeight;
6782    }
6783
6784    @Override
6785    public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6786            Rect outInsets) {
6787        outInsets.setEmpty();
6788
6789        // Only navigation bar
6790        if (mHasNavigationBar) {
6791            int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
6792            if (position == NAV_BAR_BOTTOM) {
6793                outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
6794            } else if (position == NAV_BAR_RIGHT) {
6795                outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
6796            } else if (position == NAV_BAR_LEFT) {
6797                outInsets.left = getNavigationBarWidth(displayRotation, mUiMode);
6798            }
6799        }
6800    }
6801
6802    @Override
6803    public boolean isNavBarForcedShownLw(WindowState windowState) {
6804        return mForceShowSystemBars;
6805    }
6806
6807    @Override
6808    public boolean isDockSideAllowed(int dockSide) {
6809
6810        // We do not allow all dock sides at which the navigation bar touches the docked stack.
6811        if (!mNavigationBarCanMove) {
6812            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT;
6813        } else {
6814            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT;
6815        }
6816    }
6817
6818    void sendCloseSystemWindows() {
6819        PhoneWindow.sendCloseSystemWindows(mContext, null);
6820    }
6821
6822    void sendCloseSystemWindows(String reason) {
6823        PhoneWindow.sendCloseSystemWindows(mContext, reason);
6824    }
6825
6826    @Override
6827    public int rotationForOrientationLw(int orientation, int lastRotation) {
6828        if (false) {
6829            Slog.v(TAG, "rotationForOrientationLw(orient="
6830                        + orientation + ", last=" + lastRotation
6831                        + "); user=" + mUserRotation + " "
6832                        + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
6833                            ? "USER_ROTATION_LOCKED" : "")
6834                        );
6835        }
6836
6837        if (mForceDefaultOrientation) {
6838            return Surface.ROTATION_0;
6839        }
6840
6841        synchronized (mLock) {
6842            int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
6843            if (sensorRotation < 0) {
6844                sensorRotation = lastRotation;
6845            }
6846
6847            final int preferredRotation;
6848            if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
6849                // Ignore sensor when lid switch is open and rotation is forced.
6850                preferredRotation = mLidOpenRotation;
6851            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
6852                    && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
6853                // Ignore sensor when in car dock unless explicitly enabled.
6854                // This case can override the behavior of NOSENSOR, and can also
6855                // enable 180 degree rotation while docked.
6856                preferredRotation = mCarDockEnablesAccelerometer
6857                        ? sensorRotation : mCarDockRotation;
6858            } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
6859                    || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
6860                    || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
6861                    && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
6862                // Ignore sensor when in desk dock unless explicitly enabled.
6863                // This case can override the behavior of NOSENSOR, and can also
6864                // enable 180 degree rotation while docked.
6865                preferredRotation = mDeskDockEnablesAccelerometer
6866                        ? sensorRotation : mDeskDockRotation;
6867            } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
6868                // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
6869                // Note that the dock orientation overrides the HDMI orientation.
6870                preferredRotation = mDemoHdmiRotation;
6871            } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
6872                    && mUndockedHdmiRotation >= 0) {
6873                // Ignore sensor when plugged into HDMI and an undocked orientation has
6874                // been specified in the configuration (only for legacy devices without
6875                // full multi-display support).
6876                // Note that the dock orientation overrides the HDMI orientation.
6877                preferredRotation = mUndockedHdmiRotation;
6878            } else if (mDemoRotationLock) {
6879                // Ignore sensor when demo rotation lock is enabled.
6880                // Note that the dock orientation and HDMI rotation lock override this.
6881                preferredRotation = mDemoRotation;
6882            } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
6883                // Application just wants to remain locked in the last rotation.
6884                preferredRotation = lastRotation;
6885            } else if (!mSupportAutoRotation) {
6886                // If we don't support auto-rotation then bail out here and ignore
6887                // the sensor and any rotation lock settings.
6888                preferredRotation = -1;
6889            } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
6890                            && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
6891                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
6892                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
6893                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
6894                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
6895                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
6896                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6897                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
6898                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
6899                // Otherwise, use sensor only if requested by the application or enabled
6900                // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
6901                if (mAllowAllRotations < 0) {
6902                    // Can't read this during init() because the context doesn't
6903                    // have display metrics at that time so we cannot determine
6904                    // tablet vs. phone then.
6905                    mAllowAllRotations = mContext.getResources().getBoolean(
6906                            com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
6907                }
6908                if (sensorRotation != Surface.ROTATION_180
6909                        || mAllowAllRotations == 1
6910                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6911                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
6912                    preferredRotation = sensorRotation;
6913                } else {
6914                    preferredRotation = lastRotation;
6915                }
6916            } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
6917                    && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
6918                // Apply rotation lock.  Does not apply to NOSENSOR.
6919                // The idea is that the user rotation expresses a weak preference for the direction
6920                // of gravity and as NOSENSOR is never affected by gravity, then neither should
6921                // NOSENSOR be affected by rotation lock (although it will be affected by docks).
6922                preferredRotation = mUserRotation;
6923            } else {
6924                // No overriding preference.
6925                // We will do exactly what the application asked us to do.
6926                preferredRotation = -1;
6927            }
6928
6929            switch (orientation) {
6930                case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6931                    // Return portrait unless overridden.
6932                    if (isAnyPortrait(preferredRotation)) {
6933                        return preferredRotation;
6934                    }
6935                    return mPortraitRotation;
6936
6937                case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6938                    // Return landscape unless overridden.
6939                    if (isLandscapeOrSeascape(preferredRotation)) {
6940                        return preferredRotation;
6941                    }
6942                    return mLandscapeRotation;
6943
6944                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6945                    // Return reverse portrait unless overridden.
6946                    if (isAnyPortrait(preferredRotation)) {
6947                        return preferredRotation;
6948                    }
6949                    return mUpsideDownRotation;
6950
6951                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6952                    // Return seascape unless overridden.
6953                    if (isLandscapeOrSeascape(preferredRotation)) {
6954                        return preferredRotation;
6955                    }
6956                    return mSeascapeRotation;
6957
6958                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6959                case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
6960                    // Return either landscape rotation.
6961                    if (isLandscapeOrSeascape(preferredRotation)) {
6962                        return preferredRotation;
6963                    }
6964                    if (isLandscapeOrSeascape(lastRotation)) {
6965                        return lastRotation;
6966                    }
6967                    return mLandscapeRotation;
6968
6969                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6970                case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
6971                    // Return either portrait rotation.
6972                    if (isAnyPortrait(preferredRotation)) {
6973                        return preferredRotation;
6974                    }
6975                    if (isAnyPortrait(lastRotation)) {
6976                        return lastRotation;
6977                    }
6978                    return mPortraitRotation;
6979
6980                default:
6981                    // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
6982                    // just return the preferred orientation we already calculated.
6983                    if (preferredRotation >= 0) {
6984                        return preferredRotation;
6985                    }
6986                    return Surface.ROTATION_0;
6987            }
6988        }
6989    }
6990
6991    @Override
6992    public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
6993        switch (orientation) {
6994            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6995            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6996            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6997                return isAnyPortrait(rotation);
6998
6999            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
7000            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
7001            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
7002                return isLandscapeOrSeascape(rotation);
7003
7004            default:
7005                return true;
7006        }
7007    }
7008
7009    @Override
7010    public void setRotationLw(int rotation) {
7011        mOrientationListener.setCurrentRotation(rotation);
7012    }
7013
7014    private boolean isLandscapeOrSeascape(int rotation) {
7015        return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
7016    }
7017
7018    private boolean isAnyPortrait(int rotation) {
7019        return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
7020    }
7021
7022    @Override
7023    public int getUserRotationMode() {
7024        return Settings.System.getIntForUser(mContext.getContentResolver(),
7025                Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
7026                        WindowManagerPolicy.USER_ROTATION_FREE :
7027                                WindowManagerPolicy.USER_ROTATION_LOCKED;
7028    }
7029
7030    // User rotation: to be used when all else fails in assigning an orientation to the device
7031    @Override
7032    public void setUserRotationMode(int mode, int rot) {
7033        ContentResolver res = mContext.getContentResolver();
7034
7035        // mUserRotationMode and mUserRotation will be assigned by the content observer
7036        if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
7037            Settings.System.putIntForUser(res,
7038                    Settings.System.USER_ROTATION,
7039                    rot,
7040                    UserHandle.USER_CURRENT);
7041            Settings.System.putIntForUser(res,
7042                    Settings.System.ACCELEROMETER_ROTATION,
7043                    0,
7044                    UserHandle.USER_CURRENT);
7045        } else {
7046            Settings.System.putIntForUser(res,
7047                    Settings.System.ACCELEROMETER_ROTATION,
7048                    1,
7049                    UserHandle.USER_CURRENT);
7050        }
7051    }
7052
7053    @Override
7054    public void setSafeMode(boolean safeMode) {
7055        mSafeMode = safeMode;
7056        performHapticFeedbackLw(null, safeMode
7057                ? HapticFeedbackConstants.SAFE_MODE_ENABLED
7058                : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
7059    }
7060
7061    static long[] getLongIntArray(Resources r, int resid) {
7062        int[] ar = r.getIntArray(resid);
7063        if (ar == null) {
7064            return null;
7065        }
7066        long[] out = new long[ar.length];
7067        for (int i=0; i<ar.length; i++) {
7068            out[i] = ar[i];
7069        }
7070        return out;
7071    }
7072
7073    /** {@inheritDoc} */
7074    @Override
7075    public void systemReady() {
7076        mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
7077                new StateCallback() {
7078                    @Override
7079                    public void onTrustedChanged() {
7080                        mWindowManagerFuncs.notifyKeyguardTrustedChanged();
7081                    }
7082                });
7083        mKeyguardDelegate.onSystemReady();
7084
7085        readCameraLensCoverState();
7086        updateUiMode();
7087        boolean bindKeyguardNow;
7088        synchronized (mLock) {
7089            updateOrientationListenerLp();
7090            mSystemReady = true;
7091            mHandler.post(new Runnable() {
7092                @Override
7093                public void run() {
7094                    updateSettings();
7095                }
7096            });
7097
7098            bindKeyguardNow = mDeferBindKeyguard;
7099            if (bindKeyguardNow) {
7100                // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now.
7101                mDeferBindKeyguard = false;
7102            }
7103        }
7104
7105        if (bindKeyguardNow) {
7106            mKeyguardDelegate.bindService(mContext);
7107            mKeyguardDelegate.onBootCompleted();
7108        }
7109        mSystemGestures.systemReady();
7110        mImmersiveModeConfirmation.systemReady();
7111    }
7112
7113    /** {@inheritDoc} */
7114    @Override
7115    public void systemBooted() {
7116        boolean bindKeyguardNow = false;
7117        synchronized (mLock) {
7118            // Time to bind Keyguard; take care to only bind it once, either here if ready or
7119            // in systemReady if not.
7120            if (mKeyguardDelegate != null) {
7121                bindKeyguardNow = true;
7122            } else {
7123                // Because mKeyguardDelegate is null, we know that the synchronized block in
7124                // systemReady didn't run yet and setting this will actually have an effect.
7125                mDeferBindKeyguard = true;
7126            }
7127        }
7128        if (bindKeyguardNow) {
7129            mKeyguardDelegate.bindService(mContext);
7130            mKeyguardDelegate.onBootCompleted();
7131        }
7132        synchronized (mLock) {
7133            mSystemBooted = true;
7134        }
7135        startedWakingUp();
7136        screenTurningOn(null);
7137        screenTurnedOn();
7138    }
7139
7140    ProgressDialog mBootMsgDialog = null;
7141
7142    /** {@inheritDoc} */
7143    @Override
7144    public void showBootMessage(final CharSequence msg, final boolean always) {
7145        mHandler.post(new Runnable() {
7146            @Override public void run() {
7147                if (mBootMsgDialog == null) {
7148                    int theme;
7149                    if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) {
7150                        theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
7151                    } else {
7152                        theme = 0;
7153                    }
7154
7155                    mBootMsgDialog = new ProgressDialog(mContext, theme) {
7156                        // This dialog will consume all events coming in to
7157                        // it, to avoid it trying to do things too early in boot.
7158                        @Override public boolean dispatchKeyEvent(KeyEvent event) {
7159                            return true;
7160                        }
7161                        @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7162                            return true;
7163                        }
7164                        @Override public boolean dispatchTouchEvent(MotionEvent ev) {
7165                            return true;
7166                        }
7167                        @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
7168                            return true;
7169                        }
7170                        @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
7171                            return true;
7172                        }
7173                        @Override public boolean dispatchPopulateAccessibilityEvent(
7174                                AccessibilityEvent event) {
7175                            return true;
7176                        }
7177                    };
7178                    if (mContext.getPackageManager().isUpgrade()) {
7179                        mBootMsgDialog.setTitle(R.string.android_upgrading_title);
7180                    } else {
7181                        mBootMsgDialog.setTitle(R.string.android_start_title);
7182                    }
7183                    mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
7184                    mBootMsgDialog.setIndeterminate(true);
7185                    mBootMsgDialog.getWindow().setType(
7186                            WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
7187                    mBootMsgDialog.getWindow().addFlags(
7188                            WindowManager.LayoutParams.FLAG_DIM_BEHIND
7189                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
7190                    mBootMsgDialog.getWindow().setDimAmount(1);
7191                    WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
7192                    lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
7193                    mBootMsgDialog.getWindow().setAttributes(lp);
7194                    mBootMsgDialog.setCancelable(false);
7195                    mBootMsgDialog.show();
7196                }
7197                mBootMsgDialog.setMessage(msg);
7198            }
7199        });
7200    }
7201
7202    /** {@inheritDoc} */
7203    @Override
7204    public void hideBootMessages() {
7205        mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
7206    }
7207
7208    /** {@inheritDoc} */
7209    @Override
7210    public void userActivity() {
7211        // ***************************************
7212        // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
7213        // ***************************************
7214        // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
7215        // WITH ITS LOCKS HELD.
7216        //
7217        // This code must be VERY careful about the locks
7218        // it acquires.
7219        // In fact, the current code acquires way too many,
7220        // and probably has lurking deadlocks.
7221
7222        synchronized (mScreenLockTimeout) {
7223            if (mLockScreenTimerActive) {
7224                // reset the timer
7225                mHandler.removeCallbacks(mScreenLockTimeout);
7226                mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7227            }
7228        }
7229    }
7230
7231    class ScreenLockTimeout implements Runnable {
7232        Bundle options;
7233
7234        @Override
7235        public void run() {
7236            synchronized (this) {
7237                if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
7238                if (mKeyguardDelegate != null) {
7239                    mKeyguardDelegate.doKeyguardTimeout(options);
7240                }
7241                mLockScreenTimerActive = false;
7242                options = null;
7243            }
7244        }
7245
7246        public void setLockOptions(Bundle options) {
7247            this.options = options;
7248        }
7249    }
7250
7251    ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
7252
7253    @Override
7254    public void lockNow(Bundle options) {
7255        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
7256        mHandler.removeCallbacks(mScreenLockTimeout);
7257        if (options != null) {
7258            // In case multiple calls are made to lockNow, we don't wipe out the options
7259            // until the runnable actually executes.
7260            mScreenLockTimeout.setLockOptions(options);
7261        }
7262        mHandler.post(mScreenLockTimeout);
7263    }
7264
7265    private void updateLockScreenTimeout() {
7266        synchronized (mScreenLockTimeout) {
7267            boolean enable = (mAllowLockscreenWhenOn && mAwake &&
7268                    mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
7269            if (mLockScreenTimerActive != enable) {
7270                if (enable) {
7271                    if (localLOGV) Log.v(TAG, "setting lockscreen timer");
7272                    mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
7273                    mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7274                } else {
7275                    if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
7276                    mHandler.removeCallbacks(mScreenLockTimeout);
7277                }
7278                mLockScreenTimerActive = enable;
7279            }
7280        }
7281    }
7282
7283    private void updateDreamingSleepToken(boolean acquire) {
7284        if (acquire) {
7285            if (mDreamingSleepToken == null) {
7286                mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream");
7287            }
7288        } else {
7289            if (mDreamingSleepToken != null) {
7290                mDreamingSleepToken.release();
7291                mDreamingSleepToken = null;
7292            }
7293        }
7294    }
7295
7296    private void updateScreenOffSleepToken(boolean acquire) {
7297        if (acquire) {
7298            if (mScreenOffSleepToken == null) {
7299                mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff");
7300            }
7301        } else {
7302            if (mScreenOffSleepToken != null) {
7303                mScreenOffSleepToken.release();
7304                mScreenOffSleepToken = null;
7305            }
7306        }
7307    }
7308
7309    /** {@inheritDoc} */
7310    @Override
7311    public void enableScreenAfterBoot() {
7312        readLidState();
7313        applyLidSwitchState();
7314        updateRotation(true);
7315    }
7316
7317    private void applyLidSwitchState() {
7318        if (mLidState == LID_CLOSED && mLidControlsSleep) {
7319            mPowerManager.goToSleep(SystemClock.uptimeMillis(),
7320                    PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
7321                    PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
7322        } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
7323            mWindowManagerFuncs.lockDeviceNow();
7324        }
7325
7326        synchronized (mLock) {
7327            updateWakeGestureListenerLp();
7328        }
7329    }
7330
7331    void updateUiMode() {
7332        if (mUiModeManager == null) {
7333            mUiModeManager = IUiModeManager.Stub.asInterface(
7334                    ServiceManager.getService(Context.UI_MODE_SERVICE));
7335        }
7336        try {
7337            mUiMode = mUiModeManager.getCurrentModeType();
7338        } catch (RemoteException e) {
7339        }
7340    }
7341
7342    void updateRotation(boolean alwaysSendConfiguration) {
7343        try {
7344            //set orientation on WindowManager
7345            mWindowManager.updateRotation(alwaysSendConfiguration, false);
7346        } catch (RemoteException e) {
7347            // Ignore
7348        }
7349    }
7350
7351    void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
7352        try {
7353            //set orientation on WindowManager
7354            mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
7355        } catch (RemoteException e) {
7356            // Ignore
7357        }
7358    }
7359
7360    /**
7361     * Return an Intent to launch the currently active dock app as home.  Returns
7362     * null if the standard home should be launched, which is the case if any of the following is
7363     * true:
7364     * <ul>
7365     *  <li>The device is not in either car mode or desk mode
7366     *  <li>The device is in car mode but mEnableCarDockHomeCapture is false
7367     *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
7368     *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
7369     *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
7370     * </ul>
7371     * @return A dock intent.
7372     */
7373    Intent createHomeDockIntent() {
7374        Intent intent = null;
7375
7376        // What home does is based on the mode, not the dock state.  That
7377        // is, when in car mode you should be taken to car home regardless
7378        // of whether we are actually in a car dock.
7379        if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
7380            if (mEnableCarDockHomeCapture) {
7381                intent = mCarDockIntent;
7382            }
7383        } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
7384            if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
7385                intent = mDeskDockIntent;
7386            }
7387        } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
7388                && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7389                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
7390                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
7391            // Always launch dock home from home when watch is docked, if it exists.
7392            intent = mDeskDockIntent;
7393        }
7394
7395        if (intent == null) {
7396            return null;
7397        }
7398
7399        ActivityInfo ai = null;
7400        ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
7401                intent,
7402                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
7403                mCurrentUserId);
7404        if (info != null) {
7405            ai = info.activityInfo;
7406        }
7407        if (ai != null
7408                && ai.metaData != null
7409                && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
7410            intent = new Intent(intent);
7411            intent.setClassName(ai.packageName, ai.name);
7412            return intent;
7413        }
7414
7415        return null;
7416    }
7417
7418    void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
7419        if (awakenFromDreams) {
7420            awakenDreams();
7421        }
7422
7423        Intent dock = createHomeDockIntent();
7424        if (dock != null) {
7425            try {
7426                if (fromHomeKey) {
7427                    dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7428                }
7429                startActivityAsUser(dock, UserHandle.CURRENT);
7430                return;
7431            } catch (ActivityNotFoundException e) {
7432            }
7433        }
7434
7435        Intent intent;
7436
7437        if (fromHomeKey) {
7438            intent = new Intent(mHomeIntent);
7439            intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7440        } else {
7441            intent = mHomeIntent;
7442        }
7443
7444        startActivityAsUser(intent, UserHandle.CURRENT);
7445    }
7446
7447    /**
7448     * goes to the home screen
7449     * @return whether it did anything
7450     */
7451    boolean goHome() {
7452        if (!isUserSetupComplete()) {
7453            Slog.i(TAG, "Not going home because user setup is in progress.");
7454            return false;
7455        }
7456        if (false) {
7457            // This code always brings home to the front.
7458            try {
7459                ActivityManager.getService().stopAppSwitches();
7460            } catch (RemoteException e) {
7461            }
7462            sendCloseSystemWindows();
7463            startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
7464        } else {
7465            // This code brings home to the front or, if it is already
7466            // at the front, puts the device to sleep.
7467            try {
7468                if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
7469                    /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
7470                    Log.d(TAG, "UTS-TEST-MODE");
7471                } else {
7472                    ActivityManager.getService().stopAppSwitches();
7473                    sendCloseSystemWindows();
7474                    Intent dock = createHomeDockIntent();
7475                    if (dock != null) {
7476                        int result = ActivityManager.getService()
7477                                .startActivityAsUser(null, null, dock,
7478                                        dock.resolveTypeIfNeeded(mContext.getContentResolver()),
7479                                        null, null, 0,
7480                                        ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7481                                        null, null, UserHandle.USER_CURRENT);
7482                        if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7483                            return false;
7484                        }
7485                    }
7486                }
7487                int result = ActivityManager.getService()
7488                        .startActivityAsUser(null, null, mHomeIntent,
7489                                mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
7490                                null, null, 0,
7491                                ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7492                                null, null, UserHandle.USER_CURRENT);
7493                if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7494                    return false;
7495                }
7496            } catch (RemoteException ex) {
7497                // bummer, the activity manager, which is in this process, is dead
7498            }
7499        }
7500        return true;
7501    }
7502
7503    @Override
7504    public void setCurrentOrientationLw(int newOrientation) {
7505        synchronized (mLock) {
7506            if (newOrientation != mCurrentAppOrientation) {
7507                mCurrentAppOrientation = newOrientation;
7508                updateOrientationListenerLp();
7509            }
7510        }
7511    }
7512
7513    private boolean isTheaterModeEnabled() {
7514        return Settings.Global.getInt(mContext.getContentResolver(),
7515                Settings.Global.THEATER_MODE_ON, 0) == 1;
7516    }
7517
7518    private boolean areSystemNavigationKeysEnabled() {
7519        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
7520                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
7521    }
7522
7523    @Override
7524    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
7525        if (!mVibrator.hasVibrator()) {
7526            return false;
7527        }
7528        final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
7529                Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
7530        if (hapticsDisabled && !always) {
7531            return false;
7532        }
7533        long[] pattern = null;
7534        switch (effectId) {
7535            case HapticFeedbackConstants.LONG_PRESS:
7536                pattern = mLongPressVibePattern;
7537                break;
7538            case HapticFeedbackConstants.VIRTUAL_KEY:
7539                pattern = mVirtualKeyVibePattern;
7540                break;
7541            case HapticFeedbackConstants.KEYBOARD_TAP:
7542                pattern = mKeyboardTapVibePattern;
7543                break;
7544            case HapticFeedbackConstants.CLOCK_TICK:
7545                pattern = mClockTickVibePattern;
7546                break;
7547            case HapticFeedbackConstants.CALENDAR_DATE:
7548                pattern = mCalendarDateVibePattern;
7549                break;
7550            case HapticFeedbackConstants.SAFE_MODE_DISABLED:
7551                pattern = mSafeModeDisabledVibePattern;
7552                break;
7553            case HapticFeedbackConstants.SAFE_MODE_ENABLED:
7554                pattern = mSafeModeEnabledVibePattern;
7555                break;
7556            case HapticFeedbackConstants.CONTEXT_CLICK:
7557                pattern = mContextClickVibePattern;
7558                break;
7559            default:
7560                return false;
7561        }
7562        int owningUid;
7563        String owningPackage;
7564        if (win != null) {
7565            owningUid = win.getOwningUid();
7566            owningPackage = win.getOwningPackage();
7567        } else {
7568            owningUid = android.os.Process.myUid();
7569            owningPackage = mContext.getOpPackageName();
7570        }
7571        if (pattern.length == 1) {
7572            // One-shot vibration
7573            mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES);
7574        } else {
7575            // Pattern vibration
7576            mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES);
7577        }
7578        return true;
7579    }
7580
7581    @Override
7582    public void keepScreenOnStartedLw() {
7583    }
7584
7585    @Override
7586    public void keepScreenOnStoppedLw() {
7587        if (isKeyguardShowingAndNotOccluded()) {
7588            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
7589        }
7590    }
7591
7592    private int updateSystemUiVisibilityLw() {
7593        // If there is no window focused, there will be nobody to handle the events
7594        // anyway, so just hang on in whatever state we're in until things settle down.
7595        WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
7596                : mTopFullscreenOpaqueWindowState;
7597        if (winCandidate == null) {
7598            return 0;
7599        }
7600        if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
7601            // The immersive mode confirmation should never affect the system bar visibility,
7602            // otherwise it will unhide the navigation bar and hide itself.
7603            winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState;
7604            if (winCandidate == null) {
7605                return 0;
7606            }
7607        }
7608        final WindowState win = winCandidate;
7609        if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mKeyguardOccluded) {
7610            // We are updating at a point where the keyguard has gotten
7611            // focus, but we were last in a state where the top window is
7612            // hiding it.  This is probably because the keyguard as been
7613            // shown while the top window was displayed, so we want to ignore
7614            // it here because this is just a very transient change and it
7615            // will quickly lose focus once it correctly gets hidden.
7616            return 0;
7617        }
7618
7619        int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
7620                & ~mResettingSystemUiFlags
7621                & ~mForceClearedSystemUiFlags;
7622        if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
7623            tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
7624        }
7625
7626        final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
7627                mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
7628        final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
7629                mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
7630        mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);
7631        mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);
7632        final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
7633        final int diff = visibility ^ mLastSystemUiFlags;
7634        final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
7635        final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
7636        final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
7637        if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
7638                && mFocusedApp == win.getAppToken()
7639                && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
7640                && mLastDockedStackBounds.equals(mDockedStackBounds)) {
7641            return 0;
7642        }
7643        mLastSystemUiFlags = visibility;
7644        mLastFullscreenStackSysUiFlags = fullscreenVisibility;
7645        mLastDockedStackSysUiFlags = dockedVisibility;
7646        mLastFocusNeedsMenu = needsMenu;
7647        mFocusedApp = win.getAppToken();
7648        final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
7649        final Rect dockedStackBounds = new Rect(mDockedStackBounds);
7650        mHandler.post(new Runnable() {
7651                @Override
7652                public void run() {
7653                    StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
7654                    if (statusbar != null) {
7655                        statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
7656                                dockedVisibility, 0xffffffff, fullscreenStackBounds,
7657                                dockedStackBounds, win.toString());
7658                        statusbar.topAppWindowChanged(needsMenu);
7659                    }
7660                }
7661            });
7662        return diff;
7663    }
7664
7665    private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
7666        WindowState statusColorWin = isStatusBarKeyguard() && !mKeyguardOccluded
7667                ? mStatusBar
7668                : opaqueOrDimming;
7669
7670        if (statusColorWin != null) {
7671            if (statusColorWin == opaque) {
7672                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7673                // its light flag.
7674                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7675                vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
7676                        & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7677            } else if (statusColorWin != null && statusColorWin.isDimming()) {
7678                // Otherwise if it's dimming, clear the light flag.
7679                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7680            }
7681        }
7682        return vis;
7683    }
7684
7685    private int updateLightNavigationBarLw(int vis, WindowState opaque,
7686            WindowState opaqueOrDimming) {
7687        final WindowState imeWin = mWindowManagerFuncs.getInputMethodWindowLw();
7688
7689        final WindowState navColorWin;
7690        if (imeWin != null && imeWin.isVisibleLw()) {
7691            navColorWin = imeWin;
7692        } else {
7693            navColorWin = opaqueOrDimming;
7694        }
7695
7696        if (navColorWin != null) {
7697            if (navColorWin == opaque) {
7698                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7699                // its light flag.
7700                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7701                vis |= PolicyControl.getSystemUiVisibility(navColorWin, null)
7702                        & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7703            } else if (navColorWin.isDimming() || navColorWin == imeWin) {
7704                // Otherwise if it's dimming or it's the IME window, clear the light flag.
7705                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7706            }
7707        }
7708        return vis;
7709    }
7710
7711    private boolean drawsSystemBarBackground(WindowState win) {
7712        return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
7713    }
7714
7715    private boolean forcesDrawStatusBarBackground(WindowState win) {
7716        return win == null || (win.getAttrs().privateFlags
7717                & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
7718    }
7719
7720    private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
7721        final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
7722        final boolean freeformStackVisible =
7723                mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
7724        final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
7725
7726        // We need to force system bars when the docked stack is visible, when the freeform stack
7727        // is visible but also when we are resizing for the transitions when docked stack
7728        // visibility changes.
7729        mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
7730        final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
7731
7732        // apply translucent bar vis flags
7733        WindowState fullscreenTransWin = isStatusBarKeyguard() && !mKeyguardOccluded
7734                ? mStatusBar
7735                : mTopFullscreenOpaqueWindowState;
7736        vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7737        vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7738        final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
7739                mTopDockedOpaqueWindowState, 0, 0);
7740
7741        final boolean fullscreenDrawsStatusBarBackground =
7742                (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
7743                        && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
7744                || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
7745        final boolean dockedDrawsStatusBarBackground =
7746                (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
7747                        && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
7748                || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
7749
7750        // prevent status bar interaction from clearing certain flags
7751        int type = win.getAttrs().type;
7752        boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
7753        if (statusBarHasFocus && !isStatusBarKeyguard()) {
7754            int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
7755                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
7756                    | View.SYSTEM_UI_FLAG_IMMERSIVE
7757                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
7758                    | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7759            if (mKeyguardOccluded) {
7760                flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
7761            }
7762            vis = (vis & ~flags) | (oldVis & flags);
7763        }
7764
7765        if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
7766            vis |= View.STATUS_BAR_TRANSPARENT;
7767            vis &= ~View.STATUS_BAR_TRANSLUCENT;
7768        } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
7769                || forceOpaqueStatusBar) {
7770            vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
7771        }
7772
7773        vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
7774
7775        // update status bar
7776        boolean immersiveSticky =
7777                (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7778        final boolean hideStatusBarWM =
7779                mTopFullscreenOpaqueWindowState != null
7780                && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
7781                        & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
7782        final boolean hideStatusBarSysui =
7783                (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
7784        final boolean hideNavBarSysui =
7785                (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
7786
7787        final boolean transientStatusBarAllowed = mStatusBar != null
7788                && (statusBarHasFocus || (!mForceShowSystemBars
7789                        && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
7790
7791        final boolean transientNavBarAllowed = mNavigationBar != null
7792                && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
7793
7794        final long now = SystemClock.uptimeMillis();
7795        final boolean pendingPanic = mPendingPanicGestureUptime != 0
7796                && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
7797        if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
7798            // The user performed the panic gesture recently, we're about to hide the bars,
7799            // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
7800            mPendingPanicGestureUptime = 0;
7801            mStatusBarController.showTransient();
7802            if (!isNavBarEmpty(vis)) {
7803                mNavigationBarController.showTransient();
7804            }
7805        }
7806
7807        final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
7808                && !transientStatusBarAllowed && hideStatusBarSysui;
7809        final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
7810                && !transientNavBarAllowed;
7811        if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
7812            // clear the clearable flags instead
7813            clearClearableFlagsLw();
7814            vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
7815        }
7816
7817        final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
7818        immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7819        final boolean navAllowedHidden = immersive || immersiveSticky;
7820
7821        if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType())
7822                > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) {
7823            // We can't hide the navbar from this window otherwise the input consumer would not get
7824            // the input events.
7825            vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
7826        }
7827
7828        vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
7829
7830        // update navigation bar
7831        boolean oldImmersiveMode = isImmersiveMode(oldVis);
7832        boolean newImmersiveMode = isImmersiveMode(vis);
7833        if (win != null && oldImmersiveMode != newImmersiveMode) {
7834            final String pkg = win.getOwningPackage();
7835            mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
7836                    isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility()));
7837        }
7838
7839        vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
7840
7841        vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState,
7842                mTopFullscreenOpaqueOrDimmingWindowState);
7843
7844        return vis;
7845    }
7846
7847    /**
7848     * @return the current visibility flags with the nav-bar opacity related flags toggled based
7849     *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
7850     */
7851    private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
7852            boolean freeformStackVisible, boolean isDockedDividerResizing) {
7853        if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
7854            if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
7855                visibility = setNavBarOpaqueFlag(visibility);
7856            }
7857        } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
7858            if (isDockedDividerResizing) {
7859                visibility = setNavBarOpaqueFlag(visibility);
7860            } else if (freeformStackVisible) {
7861                visibility = setNavBarTranslucentFlag(visibility);
7862            } else {
7863                visibility = setNavBarOpaqueFlag(visibility);
7864            }
7865        }
7866
7867        if (!areTranslucentBarsAllowed()) {
7868            visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
7869        }
7870        return visibility;
7871    }
7872
7873    private int setNavBarOpaqueFlag(int visibility) {
7874        return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
7875    }
7876
7877    private int setNavBarTranslucentFlag(int visibility) {
7878        visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
7879        return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
7880    }
7881
7882    private void clearClearableFlagsLw() {
7883        int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
7884        if (newVal != mResettingSystemUiFlags) {
7885            mResettingSystemUiFlags = newVal;
7886            mWindowManagerFuncs.reevaluateStatusBarVisibility();
7887        }
7888    }
7889
7890    private boolean isImmersiveMode(int vis) {
7891        final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
7892        return mNavigationBar != null
7893                && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
7894                && (vis & flags) != 0
7895                && canHideNavigationBar();
7896    }
7897
7898    private static boolean isNavBarEmpty(int systemUiFlags) {
7899        final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
7900                | View.STATUS_BAR_DISABLE_BACK
7901                | View.STATUS_BAR_DISABLE_RECENT);
7902
7903        return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
7904    }
7905
7906    /**
7907     * @return whether the navigation or status bar can be made translucent
7908     *
7909     * This should return true unless touch exploration is not enabled or
7910     * R.boolean.config_enableTranslucentDecor is false.
7911     */
7912    private boolean areTranslucentBarsAllowed() {
7913        return mTranslucentDecorEnabled;
7914    }
7915
7916    // Use this instead of checking config_showNavigationBar so that it can be consistently
7917    // overridden by qemu.hw.mainkeys in the emulator.
7918    @Override
7919    public boolean hasNavigationBar() {
7920        return mHasNavigationBar;
7921    }
7922
7923    @Override
7924    public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
7925        mLastInputMethodWindow = ime;
7926        mLastInputMethodTargetWindow = target;
7927    }
7928
7929    @Override
7930    public int getInputMethodWindowVisibleHeightLw() {
7931        return mDockBottom - mCurBottom;
7932    }
7933
7934    @Override
7935    public void setCurrentUserLw(int newUserId) {
7936        mCurrentUserId = newUserId;
7937        if (mKeyguardDelegate != null) {
7938            mKeyguardDelegate.setCurrentUser(newUserId);
7939        }
7940        StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
7941        if (statusBar != null) {
7942            statusBar.setCurrentUser(newUserId);
7943        }
7944        setLastInputMethodWindowLw(null, null);
7945    }
7946
7947    @Override
7948    public void setSwitchingUser(boolean switching) {
7949        mKeyguardDelegate.setSwitchingUser(switching);
7950    }
7951
7952    @Override
7953    public boolean canMagnifyWindow(int windowType) {
7954        switch (windowType) {
7955            case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
7956            case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
7957            case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
7958            case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
7959                return false;
7960            }
7961        }
7962        return true;
7963    }
7964
7965    @Override
7966    public boolean isTopLevelWindow(int windowType) {
7967        if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
7968                && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
7969            return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
7970        }
7971        return true;
7972    }
7973
7974    @Override
7975    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
7976        // For the upside down rotation we don't rotate seamlessly as the navigation
7977        // bar moves position.
7978        // Note most apps (using orientation:sensor or user as opposed to fullSensor)
7979        // will not enter the reverse portrait orientation, so actually the
7980        // orientation won't change at all.
7981        if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
7982            return false;
7983        }
7984        // If the navigation bar can't change sides, then it will
7985        // jump when we change orientations and we don't rotate
7986        // seamlessly.
7987        if (!mNavigationBarCanMove) {
7988            return false;
7989        }
7990        int delta = newRotation - oldRotation;
7991        if (delta < 0) delta += 4;
7992        // Likewise we don't rotate seamlessly for 180 degree rotations
7993        // in this case the surfaces never resize, and our logic to
7994        // revert the transformations on size change will fail. We could
7995        // fix this in the future with the "tagged" frames idea.
7996        if (delta == Surface.ROTATION_180) {
7997            return false;
7998        }
7999
8000        final WindowState w = mTopFullscreenOpaqueWindowState;
8001        if (w != mFocusedWindow) {
8002            return false;
8003        }
8004
8005        // We only enable seamless rotation if the top window has requested
8006        // it and is in the fullscreen opaque state. Seamless rotation
8007        // requires freezing various Surface states and won't work well
8008        // with animations, so we disable it in the animation case for now.
8009        if (w != null && !w.isAnimatingLw() &&
8010                ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) ||
8011                        (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) {
8012            return true;
8013        }
8014        return false;
8015    }
8016
8017    @Override
8018    public void dump(String prefix, PrintWriter pw, String[] args) {
8019        pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
8020                pw.print(" mSystemReady="); pw.print(mSystemReady);
8021                pw.print(" mSystemBooted="); pw.println(mSystemBooted);
8022        pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
8023                pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
8024                pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
8025                pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
8026        if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
8027                || mForceClearedSystemUiFlags != 0) {
8028            pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
8029                    pw.print(Integer.toHexString(mLastSystemUiFlags));
8030                    pw.print(" mResettingSystemUiFlags=0x");
8031                    pw.print(Integer.toHexString(mResettingSystemUiFlags));
8032                    pw.print(" mForceClearedSystemUiFlags=0x");
8033                    pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
8034        }
8035        if (mLastFocusNeedsMenu) {
8036            pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
8037                    pw.println(mLastFocusNeedsMenu);
8038        }
8039        pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
8040                pw.println(mWakeGestureEnabledSetting);
8041
8042        pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
8043        pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
8044                pw.print(" mDockMode="); pw.print(mDockMode);
8045                pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
8046                pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
8047                pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
8048        pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
8049                pw.print(" mUserRotation="); pw.print(mUserRotation);
8050                pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
8051        pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
8052        pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
8053                pw.print(mCarDockEnablesAccelerometer);
8054                pw.print(" mDeskDockEnablesAccelerometer=");
8055                pw.println(mDeskDockEnablesAccelerometer);
8056        pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
8057                pw.print(mLidKeyboardAccessibility);
8058                pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
8059                pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
8060                pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
8061        pw.print(prefix);
8062                pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
8063        pw.print(prefix);
8064                pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
8065                pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
8066        pw.print(prefix);
8067                pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
8068                pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
8069        pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
8070        pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
8071        pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
8072                pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
8073        pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
8074                pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
8075        pw.print(prefix); pw.print("mOrientationSensorEnabled=");
8076                pw.println(mOrientationSensorEnabled);
8077        pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
8078                pw.print(","); pw.print(mOverscanScreenTop);
8079                pw.print(") "); pw.print(mOverscanScreenWidth);
8080                pw.print("x"); pw.println(mOverscanScreenHeight);
8081        if (mOverscanLeft != 0 || mOverscanTop != 0
8082                || mOverscanRight != 0 || mOverscanBottom != 0) {
8083            pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
8084                    pw.print(" top="); pw.print(mOverscanTop);
8085                    pw.print(" right="); pw.print(mOverscanRight);
8086                    pw.print(" bottom="); pw.println(mOverscanBottom);
8087        }
8088        pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
8089                pw.print(mRestrictedOverscanScreenLeft);
8090                pw.print(","); pw.print(mRestrictedOverscanScreenTop);
8091                pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
8092                pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
8093        pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
8094                pw.print(","); pw.print(mUnrestrictedScreenTop);
8095                pw.print(") "); pw.print(mUnrestrictedScreenWidth);
8096                pw.print("x"); pw.println(mUnrestrictedScreenHeight);
8097        pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
8098                pw.print(","); pw.print(mRestrictedScreenTop);
8099                pw.print(") "); pw.print(mRestrictedScreenWidth);
8100                pw.print("x"); pw.println(mRestrictedScreenHeight);
8101        pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
8102                pw.print(","); pw.print(mStableFullscreenTop);
8103                pw.print(")-("); pw.print(mStableFullscreenRight);
8104                pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
8105        pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
8106                pw.print(","); pw.print(mStableTop);
8107                pw.print(")-("); pw.print(mStableRight);
8108                pw.print(","); pw.print(mStableBottom); pw.println(")");
8109        pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
8110                pw.print(","); pw.print(mSystemTop);
8111                pw.print(")-("); pw.print(mSystemRight);
8112                pw.print(","); pw.print(mSystemBottom); pw.println(")");
8113        pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
8114                pw.print(","); pw.print(mCurTop);
8115                pw.print(")-("); pw.print(mCurRight);
8116                pw.print(","); pw.print(mCurBottom); pw.println(")");
8117        pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
8118                pw.print(","); pw.print(mContentTop);
8119                pw.print(")-("); pw.print(mContentRight);
8120                pw.print(","); pw.print(mContentBottom); pw.println(")");
8121        pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft);
8122                pw.print(","); pw.print(mVoiceContentTop);
8123                pw.print(")-("); pw.print(mVoiceContentRight);
8124                pw.print(","); pw.print(mVoiceContentBottom); pw.println(")");
8125        pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
8126                pw.print(","); pw.print(mDockTop);
8127                pw.print(")-("); pw.print(mDockRight);
8128                pw.print(","); pw.print(mDockBottom); pw.println(")");
8129        pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
8130                pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
8131        pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
8132                pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
8133                pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
8134        if (mLastInputMethodWindow != null) {
8135            pw.print(prefix); pw.print("mLastInputMethodWindow=");
8136                    pw.println(mLastInputMethodWindow);
8137        }
8138        if (mLastInputMethodTargetWindow != null) {
8139            pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
8140                    pw.println(mLastInputMethodTargetWindow);
8141        }
8142        if (mStatusBar != null) {
8143            pw.print(prefix); pw.print("mStatusBar=");
8144                    pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
8145                    pw.println(isStatusBarKeyguard());
8146        }
8147        if (mNavigationBar != null) {
8148            pw.print(prefix); pw.print("mNavigationBar=");
8149                    pw.println(mNavigationBar);
8150        }
8151        if (mFocusedWindow != null) {
8152            pw.print(prefix); pw.print("mFocusedWindow=");
8153                    pw.println(mFocusedWindow);
8154        }
8155        if (mFocusedApp != null) {
8156            pw.print(prefix); pw.print("mFocusedApp=");
8157                    pw.println(mFocusedApp);
8158        }
8159        if (mTopFullscreenOpaqueWindowState != null) {
8160            pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
8161                    pw.println(mTopFullscreenOpaqueWindowState);
8162        }
8163        if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
8164            pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
8165                    pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
8166        }
8167        if (mForcingShowNavBar) {
8168            pw.print(prefix); pw.print("mForcingShowNavBar=");
8169                    pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
8170                    pw.println(mForcingShowNavBarLayer);
8171        }
8172        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
8173                pw.print(" mKeyguardOccluded="); pw.println(mKeyguardOccluded);
8174                pw.print(" mKeyguardOccludedChanged="); pw.println(mKeyguardOccludedChanged);
8175                pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded);
8176        pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
8177                pw.print(" mForceStatusBarFromKeyguard=");
8178                pw.println(mForceStatusBarFromKeyguard);
8179        pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
8180        pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
8181                pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
8182                pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
8183        pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
8184                pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
8185                pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior);
8186                pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
8187        pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
8188                pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
8189        pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
8190                pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
8191        pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
8192                pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
8193        pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
8194
8195        mGlobalKeyManager.dump(prefix, pw);
8196        mStatusBarController.dump(pw, prefix);
8197        mNavigationBarController.dump(pw, prefix);
8198        PolicyControl.dump(prefix, pw);
8199
8200        if (mWakeGestureListener != null) {
8201            mWakeGestureListener.dump(pw, prefix);
8202        }
8203        if (mOrientationListener != null) {
8204            mOrientationListener.dump(pw, prefix);
8205        }
8206        if (mBurnInProtectionHelper != null) {
8207            mBurnInProtectionHelper.dump(prefix, pw);
8208        }
8209        if (mKeyguardDelegate != null) {
8210            mKeyguardDelegate.dump(prefix, pw);
8211        }
8212    }
8213}
8214