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