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