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