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