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