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