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