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