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