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