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