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