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