PhoneWindowManager.java revision 329011cf402666678c47cd238a5170208a5bbc27
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        // TODO(multi-display): Define policy for secondary displays.
1936        if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) {
1937            return;
1938        }
1939        mDisplay = display;
1940
1941        final Resources res = mContext.getResources();
1942        int shortSize, longSize;
1943        if (width > height) {
1944            shortSize = height;
1945            longSize = width;
1946            mLandscapeRotation = Surface.ROTATION_0;
1947            mSeascapeRotation = Surface.ROTATION_180;
1948            if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
1949                mPortraitRotation = Surface.ROTATION_90;
1950                mUpsideDownRotation = Surface.ROTATION_270;
1951            } else {
1952                mPortraitRotation = Surface.ROTATION_270;
1953                mUpsideDownRotation = Surface.ROTATION_90;
1954            }
1955        } else {
1956            shortSize = width;
1957            longSize = height;
1958            mPortraitRotation = Surface.ROTATION_0;
1959            mUpsideDownRotation = Surface.ROTATION_180;
1960            if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
1961                mLandscapeRotation = Surface.ROTATION_270;
1962                mSeascapeRotation = Surface.ROTATION_90;
1963            } else {
1964                mLandscapeRotation = Surface.ROTATION_90;
1965                mSeascapeRotation = Surface.ROTATION_270;
1966            }
1967        }
1968
1969        // SystemUI (status bar) layout policy
1970        int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
1971        int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
1972
1973        // Allow the navigation bar to move on non-square small devices (phones).
1974        mNavigationBarCanMove = width != height && shortSizeDp < 600;
1975
1976        mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
1977
1978        // Allow a system property to override this. Used by the emulator.
1979        // See also hasNavigationBar().
1980        String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
1981        if ("1".equals(navBarOverride)) {
1982            mHasNavigationBar = false;
1983        } else if ("0".equals(navBarOverride)) {
1984            mHasNavigationBar = true;
1985        }
1986
1987        // For demo purposes, allow the rotation of the HDMI display to be controlled.
1988        // By default, HDMI locks rotation to landscape.
1989        if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
1990            mDemoHdmiRotation = mPortraitRotation;
1991        } else {
1992            mDemoHdmiRotation = mLandscapeRotation;
1993        }
1994        mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
1995
1996        // For demo purposes, allow the rotation of the remote display to be controlled.
1997        // By default, remote display locks rotation to landscape.
1998        if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
1999            mDemoRotation = mPortraitRotation;
2000        } else {
2001            mDemoRotation = mLandscapeRotation;
2002        }
2003        mDemoRotationLock = SystemProperties.getBoolean(
2004                "persist.demo.rotationlock", false);
2005
2006        // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
2007        // http://developer.android.com/guide/practices/screens_support.html#range
2008        mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 &&
2009                res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
2010                // For debug purposes the next line turns this feature off with:
2011                // $ adb shell setprop config.override_forced_orient true
2012                // $ adb shell wm size reset
2013                !"true".equals(SystemProperties.get("config.override_forced_orient"));
2014    }
2015
2016    /**
2017     * @return whether the navigation bar can be hidden, e.g. the device has a
2018     *         navigation bar and touch exploration is not enabled
2019     */
2020    private boolean canHideNavigationBar() {
2021        return mHasNavigationBar;
2022    }
2023
2024    @Override
2025    public boolean isDefaultOrientationForced() {
2026        return mForceDefaultOrientation;
2027    }
2028
2029    @Override
2030    public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) {
2031        // TODO(multi-display): Define policy for secondary displays.
2032        if (display.getDisplayId() == Display.DEFAULT_DISPLAY) {
2033            mOverscanLeft = left;
2034            mOverscanTop = top;
2035            mOverscanRight = right;
2036            mOverscanBottom = bottom;
2037        }
2038    }
2039
2040    public void updateSettings() {
2041        ContentResolver resolver = mContext.getContentResolver();
2042        boolean updateRotation = false;
2043        synchronized (mLock) {
2044            mEndcallBehavior = Settings.System.getIntForUser(resolver,
2045                    Settings.System.END_BUTTON_BEHAVIOR,
2046                    Settings.System.END_BUTTON_BEHAVIOR_DEFAULT,
2047                    UserHandle.USER_CURRENT);
2048            mIncallPowerBehavior = Settings.Secure.getIntForUser(resolver,
2049                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
2050                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT,
2051                    UserHandle.USER_CURRENT);
2052            mIncallBackBehavior = Settings.Secure.getIntForUser(resolver,
2053                    Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR,
2054                    Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_DEFAULT,
2055                    UserHandle.USER_CURRENT);
2056
2057            // Configure wake gesture.
2058            boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver,
2059                    Settings.Secure.WAKE_GESTURE_ENABLED, 0,
2060                    UserHandle.USER_CURRENT) != 0;
2061            if (mWakeGestureEnabledSetting != wakeGestureEnabledSetting) {
2062                mWakeGestureEnabledSetting = wakeGestureEnabledSetting;
2063                updateWakeGestureListenerLp();
2064            }
2065
2066            // Configure rotation lock.
2067            int userRotation = Settings.System.getIntForUser(resolver,
2068                    Settings.System.USER_ROTATION, Surface.ROTATION_0,
2069                    UserHandle.USER_CURRENT);
2070            if (mUserRotation != userRotation) {
2071                mUserRotation = userRotation;
2072                updateRotation = true;
2073            }
2074            int userRotationMode = Settings.System.getIntForUser(resolver,
2075                    Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
2076                            WindowManagerPolicy.USER_ROTATION_FREE :
2077                                    WindowManagerPolicy.USER_ROTATION_LOCKED;
2078            if (mUserRotationMode != userRotationMode) {
2079                mUserRotationMode = userRotationMode;
2080                updateRotation = true;
2081                updateOrientationListenerLp();
2082            }
2083
2084            if (mSystemReady) {
2085                int pointerLocation = Settings.System.getIntForUser(resolver,
2086                        Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT);
2087                if (mPointerLocationMode != pointerLocation) {
2088                    mPointerLocationMode = pointerLocation;
2089                    mHandler.sendEmptyMessage(pointerLocation != 0 ?
2090                            MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
2091                }
2092            }
2093            // use screen off timeout setting as the timeout for the lockscreen
2094            mLockScreenTimeout = Settings.System.getIntForUser(resolver,
2095                    Settings.System.SCREEN_OFF_TIMEOUT, 0, UserHandle.USER_CURRENT);
2096            String imId = Settings.Secure.getStringForUser(resolver,
2097                    Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.USER_CURRENT);
2098            boolean hasSoftInput = imId != null && imId.length() > 0;
2099            if (mHasSoftInput != hasSoftInput) {
2100                mHasSoftInput = hasSoftInput;
2101                updateRotation = true;
2102            }
2103            if (mImmersiveModeConfirmation != null) {
2104                mImmersiveModeConfirmation.loadSetting(mCurrentUserId);
2105            }
2106        }
2107        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
2108            PolicyControl.reloadFromSetting(mContext);
2109        }
2110        if (updateRotation) {
2111            updateRotation(true);
2112        }
2113    }
2114
2115    private void updateWakeGestureListenerLp() {
2116        if (shouldEnableWakeGestureLp()) {
2117            mWakeGestureListener.requestWakeUpTrigger();
2118        } else {
2119            mWakeGestureListener.cancelWakeUpTrigger();
2120        }
2121    }
2122
2123    private boolean shouldEnableWakeGestureLp() {
2124        return mWakeGestureEnabledSetting && !mAwake
2125                && (!mLidControlsSleep || mLidState != LID_CLOSED)
2126                && mWakeGestureListener.isSupported();
2127    }
2128
2129    private void enablePointerLocation() {
2130        if (mPointerLocationView == null) {
2131            mPointerLocationView = new PointerLocationView(mContext);
2132            mPointerLocationView.setPrintCoords(false);
2133            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
2134                    WindowManager.LayoutParams.MATCH_PARENT,
2135                    WindowManager.LayoutParams.MATCH_PARENT);
2136            lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
2137            lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
2138                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
2139                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2140                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
2141            if (ActivityManager.isHighEndGfx()) {
2142                lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
2143                lp.privateFlags |=
2144                        WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
2145            }
2146            lp.format = PixelFormat.TRANSLUCENT;
2147            lp.setTitle("PointerLocation");
2148            WindowManager wm = (WindowManager)
2149                    mContext.getSystemService(Context.WINDOW_SERVICE);
2150            lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
2151            wm.addView(mPointerLocationView, lp);
2152            mWindowManagerFuncs.registerPointerEventListener(mPointerLocationView);
2153        }
2154    }
2155
2156    private void disablePointerLocation() {
2157        if (mPointerLocationView != null) {
2158            mWindowManagerFuncs.unregisterPointerEventListener(mPointerLocationView);
2159            WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
2160            wm.removeView(mPointerLocationView);
2161            mPointerLocationView = null;
2162        }
2163    }
2164
2165    private int readRotation(int resID) {
2166        try {
2167            int rotation = mContext.getResources().getInteger(resID);
2168            switch (rotation) {
2169                case 0:
2170                    return Surface.ROTATION_0;
2171                case 90:
2172                    return Surface.ROTATION_90;
2173                case 180:
2174                    return Surface.ROTATION_180;
2175                case 270:
2176                    return Surface.ROTATION_270;
2177            }
2178        } catch (Resources.NotFoundException e) {
2179            // fall through
2180        }
2181        return -1;
2182    }
2183
2184    /** {@inheritDoc} */
2185    @Override
2186    public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) {
2187        int type = attrs.type;
2188
2189        outAppOp[0] = AppOpsManager.OP_NONE;
2190
2191        if (!((type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW)
2192                || (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW)
2193                || (type >= FIRST_SYSTEM_WINDOW && type <= LAST_SYSTEM_WINDOW))) {
2194            return WindowManagerGlobal.ADD_INVALID_TYPE;
2195        }
2196
2197        if (type < FIRST_SYSTEM_WINDOW || type > LAST_SYSTEM_WINDOW) {
2198            // Window manager will make sure these are okay.
2199            return WindowManagerGlobal.ADD_OKAY;
2200        }
2201        String permission = null;
2202        switch (type) {
2203            case TYPE_TOAST:
2204                // XXX right now the app process has complete control over
2205                // this...  should introduce a token to let the system
2206                // monitor/control what they are doing.
2207                outAppOp[0] = AppOpsManager.OP_TOAST_WINDOW;
2208                break;
2209            case TYPE_DREAM:
2210            case TYPE_INPUT_METHOD:
2211            case TYPE_WALLPAPER:
2212            case TYPE_PRIVATE_PRESENTATION:
2213            case TYPE_VOICE_INTERACTION:
2214            case TYPE_ACCESSIBILITY_OVERLAY:
2215            case TYPE_QS_DIALOG:
2216                // The window manager will check these.
2217                break;
2218            case TYPE_PHONE:
2219            case TYPE_PRIORITY_PHONE:
2220            case TYPE_SYSTEM_ALERT:
2221            case TYPE_SYSTEM_ERROR:
2222            case TYPE_SYSTEM_OVERLAY:
2223                permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
2224                outAppOp[0] = AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
2225                break;
2226            default:
2227                permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
2228        }
2229        if (permission != null) {
2230            if (android.Manifest.permission.SYSTEM_ALERT_WINDOW.equals(permission)) {
2231                final int callingUid = Binder.getCallingUid();
2232                // system processes will be automatically allowed privilege to draw
2233                if (callingUid == Process.SYSTEM_UID) {
2234                    return WindowManagerGlobal.ADD_OKAY;
2235                }
2236
2237                // check if user has enabled this operation. SecurityException will be thrown if
2238                // this app has not been allowed by the user
2239                final int mode = mAppOpsManager.checkOpNoThrow(outAppOp[0], callingUid,
2240                        attrs.packageName);
2241                switch (mode) {
2242                    case AppOpsManager.MODE_ALLOWED:
2243                    case AppOpsManager.MODE_IGNORED:
2244                        // although we return ADD_OKAY for MODE_IGNORED, the added window will
2245                        // actually be hidden in WindowManagerService
2246                        return WindowManagerGlobal.ADD_OKAY;
2247                    case AppOpsManager.MODE_ERRORED:
2248                        try {
2249                            ApplicationInfo appInfo = mContext.getPackageManager()
2250                                    .getApplicationInfo(attrs.packageName,
2251                                            UserHandle.getUserId(callingUid));
2252                            // Don't crash legacy apps
2253                            if (appInfo.targetSdkVersion < Build.VERSION_CODES.M) {
2254                                return WindowManagerGlobal.ADD_OKAY;
2255                            }
2256                        } catch (PackageManager.NameNotFoundException e) {
2257                            /* ignore */
2258                        }
2259                        return WindowManagerGlobal.ADD_PERMISSION_DENIED;
2260                    default:
2261                        // in the default mode, we will make a decision here based on
2262                        // checkCallingPermission()
2263                        if (mContext.checkCallingPermission(permission) !=
2264                                PackageManager.PERMISSION_GRANTED) {
2265                            return WindowManagerGlobal.ADD_PERMISSION_DENIED;
2266                        } else {
2267                            return WindowManagerGlobal.ADD_OKAY;
2268                        }
2269                }
2270            }
2271
2272            if (mContext.checkCallingOrSelfPermission(permission)
2273                    != PackageManager.PERMISSION_GRANTED) {
2274                return WindowManagerGlobal.ADD_PERMISSION_DENIED;
2275            }
2276        }
2277        return WindowManagerGlobal.ADD_OKAY;
2278    }
2279
2280    @Override
2281    public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) {
2282
2283        // If this switch statement is modified, modify the comment in the declarations of
2284        // the type in {@link WindowManager.LayoutParams} as well.
2285        switch (attrs.type) {
2286            default:
2287                // These are the windows that by default are shown only to the user that created
2288                // them. If this needs to be overridden, set
2289                // {@link WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS} in
2290                // {@link WindowManager.LayoutParams}. Note that permission
2291                // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well.
2292                if ((attrs.privateFlags & PRIVATE_FLAG_SHOW_FOR_ALL_USERS) == 0) {
2293                    return true;
2294                }
2295                break;
2296
2297            // These are the windows that by default are shown to all users. However, to
2298            // protect against spoofing, check permissions below.
2299            case TYPE_APPLICATION_STARTING:
2300            case TYPE_BOOT_PROGRESS:
2301            case TYPE_DISPLAY_OVERLAY:
2302            case TYPE_INPUT_CONSUMER:
2303            case TYPE_KEYGUARD_SCRIM:
2304            case TYPE_KEYGUARD_DIALOG:
2305            case TYPE_MAGNIFICATION_OVERLAY:
2306            case TYPE_NAVIGATION_BAR:
2307            case TYPE_NAVIGATION_BAR_PANEL:
2308            case TYPE_PHONE:
2309            case TYPE_POINTER:
2310            case TYPE_PRIORITY_PHONE:
2311            case TYPE_SEARCH_BAR:
2312            case TYPE_STATUS_BAR:
2313            case TYPE_STATUS_BAR_PANEL:
2314            case TYPE_STATUS_BAR_SUB_PANEL:
2315            case TYPE_SYSTEM_DIALOG:
2316            case TYPE_VOLUME_OVERLAY:
2317            case TYPE_PRIVATE_PRESENTATION:
2318            case TYPE_DOCK_DIVIDER:
2319                break;
2320        }
2321
2322        // Check if third party app has set window to system window type.
2323        return mContext.checkCallingOrSelfPermission(
2324                android.Manifest.permission.INTERNAL_SYSTEM_WINDOW)
2325                        != PackageManager.PERMISSION_GRANTED;
2326    }
2327
2328    @Override
2329    public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
2330        switch (attrs.type) {
2331            case TYPE_SYSTEM_OVERLAY:
2332            case TYPE_SECURE_SYSTEM_OVERLAY:
2333                // These types of windows can't receive input events.
2334                attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2335                        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
2336                attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
2337                break;
2338            case TYPE_STATUS_BAR:
2339
2340                // If the Keyguard is in a hidden state (occluded by another window), we force to
2341                // remove the wallpaper and keyguard flag so that any change in-flight after setting
2342                // the keyguard as occluded wouldn't set these flags again.
2343                // See {@link #processKeyguardSetHiddenResultLw}.
2344                if (mKeyguardHidden) {
2345                    attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
2346                    attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2347                }
2348                break;
2349
2350            case TYPE_SCREENSHOT:
2351                attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
2352                break;
2353
2354            case TYPE_TOAST:
2355                // While apps should use the dedicated toast APIs to add such windows
2356                // it possible legacy apps to add the window directly. Therefore, we
2357                // make windows added directly by the app behave as a toast as much
2358                // as possible in terms of timeout and animation.
2359                if (attrs.hideTimeoutMilliseconds < 0
2360                        || attrs.hideTimeoutMilliseconds > TOAST_WINDOW_TIMEOUT) {
2361                    attrs.hideTimeoutMilliseconds = TOAST_WINDOW_TIMEOUT;
2362                }
2363                attrs.windowAnimations = com.android.internal.R.style.Animation_Toast;
2364                break;
2365        }
2366
2367        if (attrs.type != TYPE_STATUS_BAR) {
2368            // The status bar is the only window allowed to exhibit keyguard behavior.
2369            attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
2370        }
2371
2372        if (ActivityManager.isHighEndGfx()) {
2373            if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
2374                attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
2375            }
2376            final boolean forceWindowDrawsStatusBarBackground =
2377                    (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND)
2378                            != 0;
2379            if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
2380                    || forceWindowDrawsStatusBarBackground
2381                            && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) {
2382                attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2383            }
2384        }
2385    }
2386
2387    void readLidState() {
2388        mLidState = mWindowManagerFuncs.getLidState();
2389    }
2390
2391    private void readCameraLensCoverState() {
2392        mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState();
2393    }
2394
2395    private boolean isHidden(int accessibilityMode) {
2396        switch (accessibilityMode) {
2397            case 1:
2398                return mLidState == LID_CLOSED;
2399            case 2:
2400                return mLidState == LID_OPEN;
2401            default:
2402                return false;
2403        }
2404    }
2405
2406    /** {@inheritDoc} */
2407    @Override
2408    public void adjustConfigurationLw(Configuration config, int keyboardPresence,
2409            int navigationPresence) {
2410        mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0;
2411
2412        readConfigurationDependentBehaviors();
2413        readLidState();
2414
2415        if (config.keyboard == Configuration.KEYBOARD_NOKEYS
2416                || (keyboardPresence == PRESENCE_INTERNAL
2417                        && isHidden(mLidKeyboardAccessibility))) {
2418            config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
2419            if (!mHasSoftInput) {
2420                config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
2421            }
2422        }
2423
2424        if (config.navigation == Configuration.NAVIGATION_NONAV
2425                || (navigationPresence == PRESENCE_INTERNAL
2426                        && isHidden(mLidNavigationAccessibility))) {
2427            config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
2428        }
2429    }
2430
2431    @Override
2432    public void onConfigurationChanged() {
2433        // TODO(multi-display): Define policy for secondary displays.
2434        final Resources res = mContext.getResources();
2435
2436        mStatusBarHeight =
2437                res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
2438
2439        // Height of the navigation bar when presented horizontally at bottom
2440        mNavigationBarHeightForRotationDefault[mPortraitRotation] =
2441        mNavigationBarHeightForRotationDefault[mUpsideDownRotation] =
2442                res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
2443        mNavigationBarHeightForRotationDefault[mLandscapeRotation] =
2444        mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize(
2445                com.android.internal.R.dimen.navigation_bar_height_landscape);
2446
2447        // Width of the navigation bar when presented vertically along one side
2448        mNavigationBarWidthForRotationDefault[mPortraitRotation] =
2449        mNavigationBarWidthForRotationDefault[mUpsideDownRotation] =
2450        mNavigationBarWidthForRotationDefault[mLandscapeRotation] =
2451        mNavigationBarWidthForRotationDefault[mSeascapeRotation] =
2452                res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
2453
2454        // Height of the navigation bar when presented horizontally at bottom
2455        mNavigationBarHeightForRotationInCarMode[mPortraitRotation] =
2456        mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] =
2457                res.getDimensionPixelSize(
2458                        com.android.internal.R.dimen.navigation_bar_height_car_mode);
2459        mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] =
2460        mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize(
2461                com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode);
2462
2463        // Width of the navigation bar when presented vertically along one side
2464        mNavigationBarWidthForRotationInCarMode[mPortraitRotation] =
2465        mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] =
2466        mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] =
2467        mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] =
2468                res.getDimensionPixelSize(
2469                        com.android.internal.R.dimen.navigation_bar_width_car_mode);
2470    }
2471
2472    /** {@inheritDoc} */
2473    @Override
2474    public int windowTypeToLayerLw(int type) {
2475        if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
2476            return 2;
2477        }
2478        switch (type) {
2479        case TYPE_PRIVATE_PRESENTATION:
2480            return 2;
2481        case TYPE_WALLPAPER:
2482            // wallpaper is at the bottom, though the window manager may move it.
2483            return 2;
2484        case TYPE_DOCK_DIVIDER:
2485            return 2;
2486        case TYPE_QS_DIALOG:
2487            return 2;
2488        case TYPE_PHONE:
2489            return 3;
2490        case TYPE_SEARCH_BAR:
2491        case TYPE_VOICE_INTERACTION_STARTING:
2492            return 4;
2493        case TYPE_VOICE_INTERACTION:
2494            // voice interaction layer is almost immediately above apps.
2495            return 5;
2496        case TYPE_INPUT_CONSUMER:
2497            return 6;
2498        case TYPE_SYSTEM_DIALOG:
2499            return 7;
2500        case TYPE_TOAST:
2501            // toasts and the plugged-in battery thing
2502            return 8;
2503        case TYPE_PRIORITY_PHONE:
2504            // SIM errors and unlock.  Not sure if this really should be in a high layer.
2505            return 9;
2506        case TYPE_DREAM:
2507            // used for Dreams (screensavers with TYPE_DREAM windows)
2508            return 10;
2509        case TYPE_SYSTEM_ALERT:
2510            // like the ANR / app crashed dialogs
2511            return 11;
2512        case TYPE_INPUT_METHOD:
2513            // on-screen keyboards and other such input method user interfaces go here.
2514            return 12;
2515        case TYPE_INPUT_METHOD_DIALOG:
2516            // on-screen keyboards and other such input method user interfaces go here.
2517            return 13;
2518        case TYPE_KEYGUARD_SCRIM:
2519            // the safety window that shows behind keyguard while keyguard is starting
2520            return 14;
2521        case TYPE_STATUS_BAR_SUB_PANEL:
2522            return 15;
2523        case TYPE_STATUS_BAR:
2524            return 16;
2525        case TYPE_STATUS_BAR_PANEL:
2526            return 17;
2527        case TYPE_KEYGUARD_DIALOG:
2528            return 18;
2529        case TYPE_VOLUME_OVERLAY:
2530            // the on-screen volume indicator and controller shown when the user
2531            // changes the device volume
2532            return 19;
2533        case TYPE_SYSTEM_OVERLAY:
2534            // the on-screen volume indicator and controller shown when the user
2535            // changes the device volume
2536            return 20;
2537        case TYPE_NAVIGATION_BAR:
2538            // the navigation bar, if available, shows atop most things
2539            return 21;
2540        case TYPE_NAVIGATION_BAR_PANEL:
2541            // some panels (e.g. search) need to show on top of the navigation bar
2542            return 22;
2543        case TYPE_SCREENSHOT:
2544            // screenshot selection layer shouldn't go above system error, but it should cover
2545            // navigation bars at the very least.
2546            return 23;
2547        case TYPE_SYSTEM_ERROR:
2548            // system-level error dialogs
2549            return 24;
2550        case TYPE_MAGNIFICATION_OVERLAY:
2551            // used to highlight the magnified portion of a display
2552            return 25;
2553        case TYPE_DISPLAY_OVERLAY:
2554            // used to simulate secondary display devices
2555            return 26;
2556        case TYPE_DRAG:
2557            // the drag layer: input for drag-and-drop is associated with this window,
2558            // which sits above all other focusable windows
2559            return 27;
2560        case TYPE_ACCESSIBILITY_OVERLAY:
2561            // overlay put by accessibility services to intercept user interaction
2562            return 28;
2563        case TYPE_SECURE_SYSTEM_OVERLAY:
2564            return 29;
2565        case TYPE_BOOT_PROGRESS:
2566            return 30;
2567        case TYPE_POINTER:
2568            // the (mouse) pointer layer
2569            return 31;
2570        }
2571        Log.e(TAG, "Unknown window type: " + type);
2572        return 2;
2573    }
2574
2575    /** {@inheritDoc} */
2576    @Override
2577    public int subWindowTypeToLayerLw(int type) {
2578        switch (type) {
2579        case TYPE_APPLICATION_PANEL:
2580        case TYPE_APPLICATION_ATTACHED_DIALOG:
2581            return APPLICATION_PANEL_SUBLAYER;
2582        case TYPE_APPLICATION_MEDIA:
2583            return APPLICATION_MEDIA_SUBLAYER;
2584        case TYPE_APPLICATION_MEDIA_OVERLAY:
2585            return APPLICATION_MEDIA_OVERLAY_SUBLAYER;
2586        case TYPE_APPLICATION_SUB_PANEL:
2587            return APPLICATION_SUB_PANEL_SUBLAYER;
2588        case TYPE_APPLICATION_ABOVE_SUB_PANEL:
2589            return APPLICATION_ABOVE_SUB_PANEL_SUBLAYER;
2590        }
2591        Log.e(TAG, "Unknown sub-window type: " + type);
2592        return 0;
2593    }
2594
2595    @Override
2596    public int getMaxWallpaperLayer() {
2597        return windowTypeToLayerLw(TYPE_STATUS_BAR);
2598    }
2599
2600    private int getNavigationBarWidth(int rotation, int uiMode) {
2601        if ((uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2602            return mNavigationBarWidthForRotationInCarMode[rotation];
2603        } else {
2604            return mNavigationBarWidthForRotationDefault[rotation];
2605        }
2606    }
2607
2608    @Override
2609    public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation,
2610            int uiMode) {
2611        if (mHasNavigationBar) {
2612            // For a basic navigation bar, when we are in landscape mode we place
2613            // the navigation bar to the side.
2614            if (mNavigationBarCanMove && fullWidth > fullHeight) {
2615                return fullWidth - getNavigationBarWidth(rotation, uiMode);
2616            }
2617        }
2618        return fullWidth;
2619    }
2620
2621    private int getNavigationBarHeight(int rotation, int uiMode) {
2622        if ((uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2623            return mNavigationBarHeightForRotationInCarMode[rotation];
2624        } else {
2625            return mNavigationBarHeightForRotationDefault[rotation];
2626        }
2627    }
2628
2629    @Override
2630    public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation,
2631            int uiMode) {
2632        if (mHasNavigationBar) {
2633            // For a basic navigation bar, when we are in portrait mode we place
2634            // the navigation bar to the bottom.
2635            if (!mNavigationBarCanMove || fullWidth < fullHeight) {
2636                return fullHeight - getNavigationBarHeight(rotation, uiMode);
2637            }
2638        }
2639        return fullHeight;
2640    }
2641
2642    @Override
2643    public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode) {
2644        return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode);
2645    }
2646
2647    @Override
2648    public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode) {
2649        // There is a separate status bar at the top of the display.  We don't count that as part
2650        // of the fixed decor, since it can hide; however, for purposes of configurations,
2651        // we do want to exclude it since applications can't generally use that part
2652        // of the screen.
2653        return getNonDecorDisplayHeight(
2654                fullWidth, fullHeight, rotation, uiMode) - mStatusBarHeight;
2655    }
2656
2657    @Override
2658    public boolean isForceHiding(WindowManager.LayoutParams attrs) {
2659        return (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
2660                (isKeyguardHostWindow(attrs) &&
2661                        (mKeyguardDelegate != null && mKeyguardDelegate.isShowing())) ||
2662                (attrs.type == TYPE_KEYGUARD_SCRIM);
2663    }
2664
2665    @Override
2666    public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) {
2667        return attrs.type == TYPE_STATUS_BAR;
2668    }
2669
2670    @Override
2671    public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
2672        switch (attrs.type) {
2673            case TYPE_STATUS_BAR:
2674            case TYPE_NAVIGATION_BAR:
2675            case TYPE_WALLPAPER:
2676            case TYPE_DREAM:
2677            case TYPE_KEYGUARD_SCRIM:
2678                return false;
2679            default:
2680                // Hide only windows below the keyguard host window.
2681                return windowTypeToLayerLw(win.getBaseType())
2682                        < windowTypeToLayerLw(TYPE_STATUS_BAR);
2683        }
2684    }
2685
2686    @Override
2687    public WindowState getWinShowWhenLockedLw() {
2688        return mWinShowWhenLocked;
2689    }
2690
2691    /** {@inheritDoc} */
2692    @Override
2693    public View addStartingWindow(IBinder appToken, String packageName, int theme,
2694            CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
2695            int icon, int logo, int windowFlags, Configuration overrideConfig) {
2696        if (!SHOW_STARTING_ANIMATIONS) {
2697            return null;
2698        }
2699        if (packageName == null) {
2700            return null;
2701        }
2702
2703        WindowManager wm = null;
2704        View view = null;
2705
2706        try {
2707            Context context = mContext;
2708            if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow " + packageName
2709                    + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
2710                    + Integer.toHexString(theme));
2711            if (theme != context.getThemeResId() || labelRes != 0) {
2712                try {
2713                    context = context.createPackageContext(packageName, 0);
2714                    context.setTheme(theme);
2715                } catch (PackageManager.NameNotFoundException e) {
2716                    // Ignore
2717                }
2718            }
2719
2720            if (overrideConfig != null && overrideConfig != EMPTY) {
2721                if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: creating context based"
2722                        + " on overrideConfig" + overrideConfig + " for starting window");
2723                final Context overrideContext = context.createConfigurationContext(overrideConfig);
2724                overrideContext.setTheme(theme);
2725                final TypedArray typedArray = overrideContext.obtainStyledAttributes(
2726                        com.android.internal.R.styleable.Window);
2727                final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
2728                if (resId != 0 && overrideContext.getDrawable(resId) != null) {
2729                    // We want to use the windowBackground for the override context if it is
2730                    // available, otherwise we use the default one to make sure a themed starting
2731                    // window is displayed for the app.
2732                    if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: apply overrideConfig"
2733                            + overrideConfig + " to starting window resId=" + resId);
2734                    context = overrideContext;
2735                }
2736            }
2737
2738            final PhoneWindow win = new PhoneWindow(context);
2739            win.setIsStartingWindow(true);
2740
2741            CharSequence label = context.getResources().getText(labelRes, null);
2742            // Only change the accessibility title if the label is localized
2743            if (label != null) {
2744                win.setTitle(label, true);
2745            } else {
2746                win.setTitle(nonLocalizedLabel, false);
2747            }
2748
2749            win.setType(
2750                WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
2751
2752            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
2753                // Assumes it's safe to show starting windows of launched apps while
2754                // the keyguard is being hidden. This is okay because starting windows never show
2755                // secret information.
2756                if (mKeyguardHidden) {
2757                    windowFlags |= FLAG_SHOW_WHEN_LOCKED;
2758                }
2759            }
2760
2761            // Force the window flags: this is a fake window, so it is not really
2762            // touchable or focusable by the user.  We also add in the ALT_FOCUSABLE_IM
2763            // flag because we do know that the next window will take input
2764            // focus, so we want to get the IME window up on top of us right away.
2765            win.setFlags(
2766                windowFlags|
2767                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2768                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2769                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
2770                windowFlags|
2771                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2772                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2773                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
2774
2775            win.setDefaultIcon(icon);
2776            win.setDefaultLogo(logo);
2777
2778            win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
2779                    WindowManager.LayoutParams.MATCH_PARENT);
2780
2781            final WindowManager.LayoutParams params = win.getAttributes();
2782            params.token = appToken;
2783            params.packageName = packageName;
2784            params.windowAnimations = win.getWindowStyle().getResourceId(
2785                    com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
2786            params.privateFlags |=
2787                    WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
2788            params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
2789
2790            if (!compatInfo.supportsScreen()) {
2791                params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
2792            }
2793
2794            params.setTitle("Starting " + packageName);
2795
2796            wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
2797            view = win.getDecorView();
2798
2799            if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Adding starting window for "
2800                + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null));
2801
2802            wm.addView(view, params);
2803
2804            // Only return the view if it was successfully added to the
2805            // window manager... which we can tell by it having a parent.
2806            return view.getParent() != null ? view : null;
2807        } catch (WindowManager.BadTokenException e) {
2808            // ignore
2809            Log.w(TAG, appToken + " already running, starting window not displayed. " +
2810                    e.getMessage());
2811        } catch (RuntimeException e) {
2812            // don't crash if something else bad happens, for example a
2813            // failure loading resources because we are loading from an app
2814            // on external storage that has been unmounted.
2815            Log.w(TAG, appToken + " failed creating starting window", e);
2816        } finally {
2817            if (view != null && view.getParent() == null) {
2818                Log.w(TAG, "view not successfully added to wm, removing view");
2819                wm.removeViewImmediate(view);
2820            }
2821        }
2822
2823        return null;
2824    }
2825
2826    /** {@inheritDoc} */
2827    @Override
2828    public void removeStartingWindow(IBinder appToken, View window) {
2829        if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Removing starting window for " + appToken + ": "
2830                + window + " Callers=" + Debug.getCallers(4));
2831
2832        if (window != null) {
2833            WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
2834            wm.removeView(window);
2835        }
2836    }
2837
2838    /**
2839     * Preflight adding a window to the system.
2840     *
2841     * Currently enforces that three window types are singletons:
2842     * <ul>
2843     * <li>STATUS_BAR_TYPE</li>
2844     * <li>KEYGUARD_TYPE</li>
2845     * </ul>
2846     *
2847     * @param win The window to be added
2848     * @param attrs Information about the window to be added
2849     *
2850     * @return If ok, WindowManagerImpl.ADD_OKAY.  If too many singletons,
2851     * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
2852     */
2853    @Override
2854    public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
2855        switch (attrs.type) {
2856            case TYPE_STATUS_BAR:
2857                mContext.enforceCallingOrSelfPermission(
2858                        android.Manifest.permission.STATUS_BAR_SERVICE,
2859                        "PhoneWindowManager");
2860                if (mStatusBar != null) {
2861                    if (mStatusBar.isAlive()) {
2862                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2863                    }
2864                }
2865                mStatusBar = win;
2866                mStatusBarController.setWindow(win);
2867                break;
2868            case TYPE_NAVIGATION_BAR:
2869                mContext.enforceCallingOrSelfPermission(
2870                        android.Manifest.permission.STATUS_BAR_SERVICE,
2871                        "PhoneWindowManager");
2872                if (mNavigationBar != null) {
2873                    if (mNavigationBar.isAlive()) {
2874                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2875                    }
2876                }
2877                mNavigationBar = win;
2878                mNavigationBarController.setWindow(win);
2879                if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
2880                break;
2881            case TYPE_NAVIGATION_BAR_PANEL:
2882            case TYPE_STATUS_BAR_PANEL:
2883            case TYPE_STATUS_BAR_SUB_PANEL:
2884            case TYPE_VOICE_INTERACTION_STARTING:
2885                mContext.enforceCallingOrSelfPermission(
2886                        android.Manifest.permission.STATUS_BAR_SERVICE,
2887                        "PhoneWindowManager");
2888                break;
2889            case TYPE_KEYGUARD_SCRIM:
2890                if (mKeyguardScrim != null) {
2891                    return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2892                }
2893                mKeyguardScrim = win;
2894                break;
2895        }
2896        return WindowManagerGlobal.ADD_OKAY;
2897    }
2898
2899    /** {@inheritDoc} */
2900    @Override
2901    public void removeWindowLw(WindowState win) {
2902        if (mStatusBar == win) {
2903            mStatusBar = null;
2904            mStatusBarController.setWindow(null);
2905            mKeyguardDelegate.showScrim();
2906        } else if (mKeyguardScrim == win) {
2907            Log.v(TAG, "Removing keyguard scrim");
2908            mKeyguardScrim = null;
2909        } if (mNavigationBar == win) {
2910            mNavigationBar = null;
2911            mNavigationBarController.setWindow(null);
2912        }
2913    }
2914
2915    static final boolean PRINT_ANIM = false;
2916
2917    /** {@inheritDoc} */
2918    @Override
2919    public int selectAnimationLw(WindowState win, int transit) {
2920        if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
2921              + ": transit=" + transit);
2922        if (win == mStatusBar) {
2923            boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
2924            if (transit == TRANSIT_EXIT
2925                    || transit == TRANSIT_HIDE) {
2926                return isKeyguard ? -1 : R.anim.dock_top_exit;
2927            } else if (transit == TRANSIT_ENTER
2928                    || transit == TRANSIT_SHOW) {
2929                return isKeyguard ? -1 : R.anim.dock_top_enter;
2930            }
2931        } else if (win == mNavigationBar) {
2932            if (win.getAttrs().windowAnimations != 0) {
2933                return 0;
2934            }
2935            // This can be on either the bottom or the right or the left.
2936            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
2937                if (transit == TRANSIT_EXIT
2938                        || transit == TRANSIT_HIDE) {
2939                    if (isKeyguardShowingAndNotOccluded()) {
2940                        return R.anim.dock_bottom_exit_keyguard;
2941                    } else {
2942                        return R.anim.dock_bottom_exit;
2943                    }
2944                } else if (transit == TRANSIT_ENTER
2945                        || transit == TRANSIT_SHOW) {
2946                    return R.anim.dock_bottom_enter;
2947                }
2948            } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
2949                if (transit == TRANSIT_EXIT
2950                        || transit == TRANSIT_HIDE) {
2951                    return R.anim.dock_right_exit;
2952                } else if (transit == TRANSIT_ENTER
2953                        || transit == TRANSIT_SHOW) {
2954                    return R.anim.dock_right_enter;
2955                }
2956            } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
2957                if (transit == TRANSIT_EXIT
2958                        || transit == TRANSIT_HIDE) {
2959                    return R.anim.dock_left_exit;
2960                } else if (transit == TRANSIT_ENTER
2961                        || transit == TRANSIT_SHOW) {
2962                    return R.anim.dock_left_enter;
2963                }
2964            }
2965        } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) {
2966            return selectDockedDividerAnimationLw(win, transit);
2967        }
2968
2969        if (transit == TRANSIT_PREVIEW_DONE) {
2970            if (win.hasAppShownWindows()) {
2971                if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
2972                return com.android.internal.R.anim.app_starting_exit;
2973            }
2974        } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
2975                && transit == TRANSIT_ENTER) {
2976            // Special case: we are animating in a dream, while the keyguard
2977            // is shown.  We don't want an animation on the dream, because
2978            // we need it shown immediately with the keyguard animating away
2979            // to reveal it.
2980            return -1;
2981        }
2982
2983        return 0;
2984    }
2985
2986    private int selectDockedDividerAnimationLw(WindowState win, int transit) {
2987        int insets = mWindowManagerFuncs.getDockedDividerInsetsLw();
2988
2989        // If the divider is behind the navigation bar, don't animate.
2990        final Rect frame = win.getFrameLw();
2991        final boolean behindNavBar = mNavigationBar != null
2992                && ((mNavigationBarPosition == NAV_BAR_BOTTOM
2993                        && frame.top + insets >= mNavigationBar.getFrameLw().top)
2994                || (mNavigationBarPosition == NAV_BAR_RIGHT
2995                        && frame.left + insets >= mNavigationBar.getFrameLw().left)
2996                || (mNavigationBarPosition == NAV_BAR_LEFT
2997                        && frame.right - insets <= mNavigationBar.getFrameLw().right));
2998        final boolean landscape = frame.height() > frame.width();
2999        final boolean offscreenLandscape = landscape && (frame.right - insets <= 0
3000                || frame.left + insets >= win.getDisplayFrameLw().right);
3001        final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0
3002                || frame.bottom + insets >= win.getDisplayFrameLw().bottom);
3003        final boolean offscreen = offscreenLandscape || offscreenPortrait;
3004        if (behindNavBar || offscreen) {
3005            return 0;
3006        }
3007        if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
3008            return R.anim.fade_in;
3009        } else if (transit == TRANSIT_EXIT) {
3010            return R.anim.fade_out;
3011        } else {
3012            return 0;
3013        }
3014    }
3015
3016    @Override
3017    public void selectRotationAnimationLw(int anim[]) {
3018        if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
3019                + mTopFullscreenOpaqueWindowState + " rotationAnimation="
3020                + (mTopFullscreenOpaqueWindowState == null ?
3021                        "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation));
3022        if (mTopFullscreenOpaqueWindowState != null) {
3023            int animationHint = mTopFullscreenOpaqueWindowState.getRotationAnimationHint();
3024            if (animationHint < 0 && mTopIsFullscreen) {
3025                animationHint = mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation;
3026            }
3027            switch (animationHint) {
3028                case ROTATION_ANIMATION_CROSSFADE:
3029                case ROTATION_ANIMATION_SEAMLESS: // Crossfade is fallback for seamless.
3030                    anim[0] = R.anim.rotation_animation_xfade_exit;
3031                    anim[1] = R.anim.rotation_animation_enter;
3032                    break;
3033                case ROTATION_ANIMATION_JUMPCUT:
3034                    anim[0] = R.anim.rotation_animation_jump_exit;
3035                    anim[1] = R.anim.rotation_animation_enter;
3036                    break;
3037                case ROTATION_ANIMATION_ROTATE:
3038                default:
3039                    anim[0] = anim[1] = 0;
3040                    break;
3041            }
3042        } else {
3043            anim[0] = anim[1] = 0;
3044        }
3045    }
3046
3047    @Override
3048    public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId,
3049            boolean forceDefault) {
3050        switch (exitAnimId) {
3051            case R.anim.rotation_animation_xfade_exit:
3052            case R.anim.rotation_animation_jump_exit:
3053                // These are the only cases that matter.
3054                if (forceDefault) {
3055                    return false;
3056                }
3057                int anim[] = new int[2];
3058                selectRotationAnimationLw(anim);
3059                return (exitAnimId == anim[0] && enterAnimId == anim[1]);
3060            default:
3061                return true;
3062        }
3063    }
3064
3065    @Override
3066    public Animation createForceHideEnterAnimation(boolean onWallpaper,
3067            boolean goingToNotificationShade) {
3068        if (goingToNotificationShade) {
3069            return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
3070        }
3071
3072        AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ?
3073                    R.anim.lock_screen_behind_enter_wallpaper :
3074                    R.anim.lock_screen_behind_enter);
3075
3076        // TODO: Use XML interpolators when we have log interpolators available in XML.
3077        final List<Animation> animations = set.getAnimations();
3078        for (int i = animations.size() - 1; i >= 0; --i) {
3079            animations.get(i).setInterpolator(mLogDecelerateInterpolator);
3080        }
3081
3082        return set;
3083    }
3084
3085
3086    @Override
3087    public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade) {
3088        if (goingToNotificationShade) {
3089            return null;
3090        } else {
3091            return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
3092        }
3093    }
3094
3095    private static void awakenDreams() {
3096        IDreamManager dreamManager = getDreamManager();
3097        if (dreamManager != null) {
3098            try {
3099                dreamManager.awaken();
3100            } catch (RemoteException e) {
3101                // fine, stay asleep then
3102            }
3103        }
3104    }
3105
3106    static IDreamManager getDreamManager() {
3107        return IDreamManager.Stub.asInterface(
3108                ServiceManager.checkService(DreamService.DREAM_SERVICE));
3109    }
3110
3111    TelecomManager getTelecommService() {
3112        return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
3113    }
3114
3115    static IAudioService getAudioService() {
3116        IAudioService audioService = IAudioService.Stub.asInterface(
3117                ServiceManager.checkService(Context.AUDIO_SERVICE));
3118        if (audioService == null) {
3119            Log.w(TAG, "Unable to find IAudioService interface.");
3120        }
3121        return audioService;
3122    }
3123
3124    boolean keyguardOn() {
3125        return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode();
3126    }
3127
3128    private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
3129            WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
3130            WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
3131        };
3132
3133    /** {@inheritDoc} */
3134    @Override
3135    public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
3136        final boolean keyguardOn = keyguardOn();
3137        final int keyCode = event.getKeyCode();
3138        final int repeatCount = event.getRepeatCount();
3139        final int metaState = event.getMetaState();
3140        final int flags = event.getFlags();
3141        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
3142        final boolean canceled = event.isCanceled();
3143
3144        if (DEBUG_INPUT) {
3145            Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
3146                    + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
3147                    + " canceled=" + canceled);
3148        }
3149
3150        // If we think we might have a volume down & power key chord on the way
3151        // but we're not sure, then tell the dispatcher to wait a little while and
3152        // try again later before dispatching.
3153        if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
3154            if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
3155                final long now = SystemClock.uptimeMillis();
3156                final long timeoutTime = mScreenshotChordVolumeDownKeyTime
3157                        + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
3158                if (now < timeoutTime) {
3159                    return timeoutTime - now;
3160                }
3161            }
3162            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3163                    && mScreenshotChordVolumeDownKeyConsumed) {
3164                if (!down) {
3165                    mScreenshotChordVolumeDownKeyConsumed = false;
3166                }
3167                return -1;
3168            }
3169        }
3170
3171        // Cancel any pending meta actions if we see any other keys being pressed between the down
3172        // of the meta key and its corresponding up.
3173        if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
3174            mPendingMetaAction = false;
3175        }
3176        // Any key that is not Alt or Meta cancels Caps Lock combo tracking.
3177        if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) {
3178            mPendingCapsLockToggle = false;
3179        }
3180
3181        // First we always handle the home key here, so applications
3182        // can never break it, although if keyguard is on, we do let
3183        // it handle it, because that gives us the correct 5 second
3184        // timeout.
3185        if (keyCode == KeyEvent.KEYCODE_HOME) {
3186
3187            // If we have released the home key, and didn't do anything else
3188            // while it was pressed, then it is time to go home!
3189            if (!down) {
3190                cancelPreloadRecentApps();
3191
3192                mHomePressed = false;
3193                if (mHomeConsumed) {
3194                    mHomeConsumed = false;
3195                    return -1;
3196                }
3197
3198                if (canceled) {
3199                    Log.i(TAG, "Ignoring HOME; event canceled.");
3200                    return -1;
3201                }
3202
3203                // Delay handling home if a double-tap is possible.
3204                if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
3205                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
3206                    mHomeDoubleTapPending = true;
3207                    mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
3208                            ViewConfiguration.getDoubleTapTimeout());
3209                    return -1;
3210                }
3211
3212                handleShortPressOnHome();
3213                return -1;
3214            }
3215
3216            // If a system window has focus, then it doesn't make sense
3217            // right now to interact with applications.
3218            WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
3219            if (attrs != null) {
3220                final int type = attrs.type;
3221                if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM
3222                        || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
3223                        || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
3224                    // the "app" is keyguard, so give it the key
3225                    return 0;
3226                }
3227                final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
3228                for (int i=0; i<typeCount; i++) {
3229                    if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
3230                        // don't do anything, but also don't pass it to the app
3231                        return -1;
3232                    }
3233                }
3234            }
3235
3236            // Remember that home is pressed and handle special actions.
3237            if (repeatCount == 0) {
3238                mHomePressed = true;
3239                if (mHomeDoubleTapPending) {
3240                    mHomeDoubleTapPending = false;
3241                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
3242                    handleDoubleTapOnHome();
3243                } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI
3244                        || mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
3245                    preloadRecentApps();
3246                }
3247            } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
3248                if (!keyguardOn) {
3249                    handleLongPressOnHome(event.getDeviceId());
3250                }
3251            }
3252            return -1;
3253        } else if (keyCode == KeyEvent.KEYCODE_MENU) {
3254            // Hijack modified menu keys for debugging features
3255            final int chordBug = KeyEvent.META_SHIFT_ON;
3256
3257            if (down && repeatCount == 0) {
3258                if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
3259                    Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
3260                    mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
3261                            null, null, null, 0, null, null);
3262                    return -1;
3263                } else if (SHOW_PROCESSES_ON_ALT_MENU &&
3264                        (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
3265                    Intent service = new Intent();
3266                    service.setClassName(mContext, "com.android.server.LoadAverageService");
3267                    ContentResolver res = mContext.getContentResolver();
3268                    boolean shown = Settings.Global.getInt(
3269                            res, Settings.Global.SHOW_PROCESSES, 0) != 0;
3270                    if (!shown) {
3271                        mContext.startService(service);
3272                    } else {
3273                        mContext.stopService(service);
3274                    }
3275                    Settings.Global.putInt(
3276                            res, Settings.Global.SHOW_PROCESSES, shown ? 0 : 1);
3277                    return -1;
3278                }
3279            }
3280        } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
3281            if (down) {
3282                if (repeatCount == 0) {
3283                    mSearchKeyShortcutPending = true;
3284                    mConsumeSearchKeyUp = false;
3285                }
3286            } else {
3287                mSearchKeyShortcutPending = false;
3288                if (mConsumeSearchKeyUp) {
3289                    mConsumeSearchKeyUp = false;
3290                    return -1;
3291                }
3292            }
3293            return 0;
3294        } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
3295            if (!keyguardOn) {
3296                if (down && repeatCount == 0) {
3297                    preloadRecentApps();
3298                } else if (!down) {
3299                    toggleRecentApps();
3300                }
3301            }
3302            return -1;
3303        } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) {
3304            if (down) {
3305                IStatusBarService service = getStatusBarService();
3306                if (service != null) {
3307                    try {
3308                        service.expandNotificationsPanel();
3309                    } catch (RemoteException e) {
3310                        // do nothing.
3311                    }
3312                }
3313            }
3314        } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed()
3315                && event.isCtrlPressed()) {
3316            if (down && repeatCount == 0) {
3317                int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION
3318                        : TAKE_SCREENSHOT_FULLSCREEN;
3319                mScreenshotRunnable.setScreenshotType(type);
3320                mHandler.post(mScreenshotRunnable);
3321                return -1;
3322            }
3323        } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
3324            if (down && repeatCount == 0 && !isKeyguardLocked()) {
3325                toggleKeyboardShortcutsMenu(event.getDeviceId());
3326            }
3327        } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
3328            if (down) {
3329                if (repeatCount == 0) {
3330                    mAssistKeyLongPressed = false;
3331                } else if (repeatCount == 1) {
3332                    mAssistKeyLongPressed = true;
3333                    if (!keyguardOn) {
3334                         launchAssistLongPressAction();
3335                    }
3336                }
3337            } else {
3338                if (mAssistKeyLongPressed) {
3339                    mAssistKeyLongPressed = false;
3340                } else {
3341                    if (!keyguardOn) {
3342                        launchAssistAction(null, event.getDeviceId());
3343                    }
3344                }
3345            }
3346            return -1;
3347        } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
3348            if (!down) {
3349                Intent voiceIntent;
3350                if (!keyguardOn) {
3351                    voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
3352                } else {
3353                    IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
3354                            ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
3355                    if (dic != null) {
3356                        try {
3357                            dic.exitIdle("voice-search");
3358                        } catch (RemoteException e) {
3359                        }
3360                    }
3361                    voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
3362                    voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
3363                }
3364                startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
3365            }
3366        } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
3367            if (down && repeatCount == 0) {
3368                mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
3369                mHandler.post(mScreenshotRunnable);
3370            }
3371            return -1;
3372        } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP
3373                || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) {
3374            if (down) {
3375                int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
3376
3377                // Disable autobrightness if it's on
3378                int auto = Settings.System.getIntForUser(
3379                        mContext.getContentResolver(),
3380                        Settings.System.SCREEN_BRIGHTNESS_MODE,
3381                        Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3382                        UserHandle.USER_CURRENT_OR_SELF);
3383                if (auto != 0) {
3384                    Settings.System.putIntForUser(mContext.getContentResolver(),
3385                            Settings.System.SCREEN_BRIGHTNESS_MODE,
3386                            Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3387                            UserHandle.USER_CURRENT_OR_SELF);
3388                }
3389
3390                int min = mPowerManager.getMinimumScreenBrightnessSetting();
3391                int max = mPowerManager.getMaximumScreenBrightnessSetting();
3392                int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction;
3393                int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
3394                        Settings.System.SCREEN_BRIGHTNESS,
3395                        mPowerManager.getDefaultScreenBrightnessSetting(),
3396                        UserHandle.USER_CURRENT_OR_SELF);
3397                brightness += step;
3398                // Make sure we don't go beyond the limits.
3399                brightness = Math.min(max, brightness);
3400                brightness = Math.max(min, brightness);
3401
3402                Settings.System.putIntForUser(mContext.getContentResolver(),
3403                        Settings.System.SCREEN_BRIGHTNESS, brightness,
3404                        UserHandle.USER_CURRENT_OR_SELF);
3405                startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
3406                        UserHandle.CURRENT_OR_SELF);
3407            }
3408            return -1;
3409        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
3410                || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3411                || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
3412            if (mUseTvRouting) {
3413                // On TVs volume keys never go to the foreground app.
3414                dispatchDirectAudioEvent(event);
3415                return -1;
3416            }
3417        }
3418
3419        // Toggle Caps Lock on META-ALT.
3420        boolean actionTriggered = false;
3421        if (KeyEvent.isModifierKey(keyCode)) {
3422            if (!mPendingCapsLockToggle) {
3423                // Start tracking meta state for combo.
3424                mInitialMetaState = mMetaState;
3425                mPendingCapsLockToggle = true;
3426            } else if (event.getAction() == KeyEvent.ACTION_UP) {
3427                int altOnMask = mMetaState & KeyEvent.META_ALT_MASK;
3428                int metaOnMask = mMetaState & KeyEvent.META_META_MASK;
3429
3430                // Check for Caps Lock toggle
3431                if ((metaOnMask != 0) && (altOnMask != 0)) {
3432                    // Check if nothing else is pressed
3433                    if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) {
3434                        // Handle Caps Lock Toggle
3435                        mInputManagerInternal.toggleCapsLock(event.getDeviceId());
3436                        actionTriggered = true;
3437                    }
3438                }
3439
3440                // Always stop tracking when key goes up.
3441                mPendingCapsLockToggle = false;
3442            }
3443        }
3444        // Store current meta state to be able to evaluate it later.
3445        mMetaState = metaState;
3446
3447        if (actionTriggered) {
3448            return -1;
3449        }
3450
3451        if (KeyEvent.isMetaKey(keyCode)) {
3452            if (down) {
3453                mPendingMetaAction = true;
3454            } else if (mPendingMetaAction) {
3455                launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId());
3456            }
3457            return -1;
3458        }
3459
3460        // Shortcuts are invoked through Search+key, so intercept those here
3461        // Any printing key that is chorded with Search should be consumed
3462        // even if no shortcut was invoked.  This prevents text from being
3463        // inadvertently inserted when using a keyboard that has built-in macro
3464        // shortcut keys (that emit Search+x) and some of them are not registered.
3465        if (mSearchKeyShortcutPending) {
3466            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3467            if (kcm.isPrintingKey(keyCode)) {
3468                mConsumeSearchKeyUp = true;
3469                mSearchKeyShortcutPending = false;
3470                if (down && repeatCount == 0 && !keyguardOn) {
3471                    Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
3472                    if (shortcutIntent != null) {
3473                        shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3474                        try {
3475                            startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3476                            dismissKeyboardShortcutsMenu();
3477                        } catch (ActivityNotFoundException ex) {
3478                            Slog.w(TAG, "Dropping shortcut key combination because "
3479                                    + "the activity to which it is registered was not found: "
3480                                    + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);
3481                        }
3482                    } else {
3483                        Slog.i(TAG, "Dropping unregistered shortcut key combination: "
3484                                + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));
3485                    }
3486                }
3487                return -1;
3488            }
3489        }
3490
3491        // Invoke shortcuts using Meta.
3492        if (down && repeatCount == 0 && !keyguardOn
3493                && (metaState & KeyEvent.META_META_ON) != 0) {
3494            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3495            if (kcm.isPrintingKey(keyCode)) {
3496                Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
3497                        metaState & ~(KeyEvent.META_META_ON
3498                                | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
3499                if (shortcutIntent != null) {
3500                    shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3501                    try {
3502                        startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3503                        dismissKeyboardShortcutsMenu();
3504                    } catch (ActivityNotFoundException ex) {
3505                        Slog.w(TAG, "Dropping shortcut key combination because "
3506                                + "the activity to which it is registered was not found: "
3507                                + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
3508                    }
3509                    return -1;
3510                }
3511            }
3512        }
3513
3514        // Handle application launch keys.
3515        if (down && repeatCount == 0 && !keyguardOn) {
3516            String category = sApplicationLaunchKeyCategories.get(keyCode);
3517            if (category != null) {
3518                Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
3519                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3520                try {
3521                    startActivityAsUser(intent, UserHandle.CURRENT);
3522                    dismissKeyboardShortcutsMenu();
3523                } catch (ActivityNotFoundException ex) {
3524                    Slog.w(TAG, "Dropping application launch key because "
3525                            + "the activity to which it is registered was not found: "
3526                            + "keyCode=" + keyCode + ", category=" + category, ex);
3527                }
3528                return -1;
3529            }
3530        }
3531
3532        // Display task switcher for ALT-TAB.
3533        if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
3534            if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
3535                final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
3536                if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
3537                    mRecentAppsHeldModifiers = shiftlessModifiers;
3538                    showRecentApps(true, false);
3539                    return -1;
3540                }
3541            }
3542        } else if (!down && mRecentAppsHeldModifiers != 0
3543                && (metaState & mRecentAppsHeldModifiers) == 0) {
3544            mRecentAppsHeldModifiers = 0;
3545            hideRecentApps(true, false);
3546        }
3547
3548        // Handle input method switching.
3549        if (down && repeatCount == 0
3550                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3551                        || (keyCode == KeyEvent.KEYCODE_SPACE
3552                                && (metaState & KeyEvent.META_META_MASK) != 0))) {
3553            final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0;
3554            mWindowManagerFuncs.switchInputMethod(forwardDirection);
3555            return -1;
3556        }
3557        if (mLanguageSwitchKeyPressed && !down
3558                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3559                        || keyCode == KeyEvent.KEYCODE_SPACE)) {
3560            mLanguageSwitchKeyPressed = false;
3561            return -1;
3562        }
3563
3564        if (isValidGlobalKey(keyCode)
3565                && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
3566            return -1;
3567        }
3568
3569        if (down) {
3570            long shortcutCode = keyCode;
3571            if (event.isCtrlPressed()) {
3572                shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
3573            }
3574
3575            if (event.isAltPressed()) {
3576                shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
3577            }
3578
3579            if (event.isShiftPressed()) {
3580                shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
3581            }
3582
3583            if (event.isMetaPressed()) {
3584                shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE;
3585            }
3586
3587            IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode);
3588            if (shortcutService != null) {
3589                try {
3590                    if (isUserSetupComplete()) {
3591                        shortcutService.notifyShortcutKeyPressed(shortcutCode);
3592                    }
3593                } catch (RemoteException e) {
3594                    mShortcutKeyServices.delete(shortcutCode);
3595                }
3596                return -1;
3597            }
3598        }
3599
3600        // Reserve all the META modifier combos for system behavior
3601        if ((metaState & KeyEvent.META_META_ON) != 0) {
3602            return -1;
3603        }
3604
3605        // Let the application handle the key.
3606        return 0;
3607    }
3608
3609    /** {@inheritDoc} */
3610    @Override
3611    public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
3612        // Note: This method is only called if the initial down was unhandled.
3613        if (DEBUG_INPUT) {
3614            Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
3615                    + ", flags=" + event.getFlags()
3616                    + ", keyCode=" + event.getKeyCode()
3617                    + ", scanCode=" + event.getScanCode()
3618                    + ", metaState=" + event.getMetaState()
3619                    + ", repeatCount=" + event.getRepeatCount()
3620                    + ", policyFlags=" + policyFlags);
3621        }
3622
3623        KeyEvent fallbackEvent = null;
3624        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3625            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3626            final int keyCode = event.getKeyCode();
3627            final int metaState = event.getMetaState();
3628            final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
3629                    && event.getRepeatCount() == 0;
3630
3631            // Check for fallback actions specified by the key character map.
3632            final FallbackAction fallbackAction;
3633            if (initialDown) {
3634                fallbackAction = kcm.getFallbackAction(keyCode, metaState);
3635            } else {
3636                fallbackAction = mFallbackActions.get(keyCode);
3637            }
3638
3639            if (fallbackAction != null) {
3640                if (DEBUG_INPUT) {
3641                    Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode
3642                            + " metaState=" + Integer.toHexString(fallbackAction.metaState));
3643                }
3644
3645                final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
3646                fallbackEvent = KeyEvent.obtain(
3647                        event.getDownTime(), event.getEventTime(),
3648                        event.getAction(), fallbackAction.keyCode,
3649                        event.getRepeatCount(), fallbackAction.metaState,
3650                        event.getDeviceId(), event.getScanCode(),
3651                        flags, event.getSource(), null);
3652
3653                if (!interceptFallback(win, fallbackEvent, policyFlags)) {
3654                    fallbackEvent.recycle();
3655                    fallbackEvent = null;
3656                }
3657
3658                if (initialDown) {
3659                    mFallbackActions.put(keyCode, fallbackAction);
3660                } else if (event.getAction() == KeyEvent.ACTION_UP) {
3661                    mFallbackActions.remove(keyCode);
3662                    fallbackAction.recycle();
3663                }
3664            }
3665        }
3666
3667        if (DEBUG_INPUT) {
3668            if (fallbackEvent == null) {
3669                Slog.d(TAG, "No fallback.");
3670            } else {
3671                Slog.d(TAG, "Performing fallback: " + fallbackEvent);
3672            }
3673        }
3674        return fallbackEvent;
3675    }
3676
3677    private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
3678        int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
3679        if ((actions & ACTION_PASS_TO_USER) != 0) {
3680            long delayMillis = interceptKeyBeforeDispatching(
3681                    win, fallbackEvent, policyFlags);
3682            if (delayMillis == 0) {
3683                return true;
3684            }
3685        }
3686        return false;
3687    }
3688
3689    @Override
3690    public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
3691            throws RemoteException {
3692        synchronized (mLock) {
3693            IShortcutService service = mShortcutKeyServices.get(shortcutCode);
3694            if (service != null && service.asBinder().pingBinder()) {
3695                throw new RemoteException("Key already exists.");
3696            }
3697
3698            mShortcutKeyServices.put(shortcutCode, shortcutService);
3699        }
3700    }
3701
3702    @Override
3703    public boolean canShowDismissingWindowWhileLockedLw() {
3704        // If the keyguard is trusted, it will unlock without a challange. Therefore, windows with
3705        // FLAG_DISMISS_KEYGUARD don't need to be force hidden, as they will unlock the phone right
3706        // away anyways.
3707        return mKeyguardDelegate != null && mKeyguardDelegate.isTrusted();
3708    }
3709
3710    private void launchAssistLongPressAction() {
3711        performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
3712        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
3713
3714        // launch the search activity
3715        Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
3716        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3717        try {
3718            // TODO: This only stops the factory-installed search manager.
3719            // Need to formalize an API to handle others
3720            SearchManager searchManager = getSearchManager();
3721            if (searchManager != null) {
3722                searchManager.stopSearch();
3723            }
3724            startActivityAsUser(intent, UserHandle.CURRENT);
3725        } catch (ActivityNotFoundException e) {
3726            Slog.w(TAG, "No activity to handle assist long press action.", e);
3727        }
3728    }
3729
3730    private void launchAssistAction(String hint, int deviceId) {
3731        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
3732        if (!isUserSetupComplete()) {
3733            // Disable opening assist window during setup
3734            return;
3735        }
3736        Bundle args = null;
3737        if (deviceId > Integer.MIN_VALUE) {
3738            args = new Bundle();
3739            args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
3740        }
3741        if ((mContext.getResources().getConfiguration().uiMode
3742                & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
3743            // On TV, use legacy handling until assistants are implemented in the proper way.
3744            ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
3745                    .launchLegacyAssist(hint, UserHandle.myUserId(), args);
3746        } else {
3747            if (hint != null) {
3748                if (args == null) {
3749                    args = new Bundle();
3750                }
3751                args.putBoolean(hint, true);
3752            }
3753            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3754            if (statusbar != null) {
3755                statusbar.startAssist(args);
3756            }
3757        }
3758    }
3759
3760    private void startActivityAsUser(Intent intent, UserHandle handle) {
3761        if (isUserSetupComplete()) {
3762            mContext.startActivityAsUser(intent, handle);
3763        } else {
3764            Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent);
3765        }
3766    }
3767
3768    private SearchManager getSearchManager() {
3769        if (mSearchManager == null) {
3770            mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
3771        }
3772        return mSearchManager;
3773    }
3774
3775    private void preloadRecentApps() {
3776        mPreloadedRecentApps = true;
3777        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3778        if (statusbar != null) {
3779            statusbar.preloadRecentApps();
3780        }
3781    }
3782
3783    private void cancelPreloadRecentApps() {
3784        if (mPreloadedRecentApps) {
3785            mPreloadedRecentApps = false;
3786            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3787            if (statusbar != null) {
3788                statusbar.cancelPreloadRecentApps();
3789            }
3790        }
3791    }
3792
3793    private void toggleRecentApps() {
3794        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3795        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3796        if (statusbar != null) {
3797            statusbar.toggleRecentApps();
3798        }
3799    }
3800
3801    @Override
3802    public void showRecentApps(boolean fromHome) {
3803        mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
3804        mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget();
3805    }
3806
3807    private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
3808        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3809        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3810        if (statusbar != null) {
3811            statusbar.showRecentApps(triggeredFromAltTab, fromHome);
3812        }
3813    }
3814
3815    private void toggleKeyboardShortcutsMenu(int deviceId) {
3816        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3817        if (statusbar != null) {
3818            statusbar.toggleKeyboardShortcutsMenu(deviceId);
3819        }
3820    }
3821
3822    private void dismissKeyboardShortcutsMenu() {
3823        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3824        if (statusbar != null) {
3825            statusbar.dismissKeyboardShortcutsMenu();
3826        }
3827    }
3828
3829    private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
3830        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3831        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3832        if (statusbar != null) {
3833            statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
3834        }
3835    }
3836
3837    void launchHomeFromHotKey() {
3838        launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/);
3839    }
3840
3841    /**
3842     * A home key -> launch home action was detected.  Take the appropriate action
3843     * given the situation with the keyguard.
3844     */
3845    void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) {
3846        if (respectKeyguard) {
3847            if (isKeyguardShowingAndNotOccluded()) {
3848                // don't launch home if keyguard showing
3849                return;
3850            }
3851
3852            if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) {
3853                // when in keyguard restricted mode, must first verify unlock
3854                // before launching home
3855                mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
3856                    @Override
3857                    public void onKeyguardExitResult(boolean success) {
3858                        if (success) {
3859                            try {
3860                                ActivityManagerNative.getDefault().stopAppSwitches();
3861                            } catch (RemoteException e) {
3862                            }
3863                            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
3864                            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
3865                        }
3866                    }
3867                });
3868                return;
3869            }
3870        }
3871
3872        // no keyguard stuff to worry about, just launch home!
3873        try {
3874            ActivityManagerNative.getDefault().stopAppSwitches();
3875        } catch (RemoteException e) {
3876        }
3877        if (mRecentsVisible) {
3878            // Hide Recents and notify it to launch Home
3879            if (awakenFromDreams) {
3880                awakenDreams();
3881            }
3882            hideRecentApps(false, true);
3883        } else {
3884            // Otherwise, just launch Home
3885            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
3886            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
3887        }
3888    }
3889
3890    private final Runnable mClearHideNavigationFlag = new Runnable() {
3891        @Override
3892        public void run() {
3893            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
3894                // Clear flags.
3895                mForceClearedSystemUiFlags &=
3896                        ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
3897            }
3898            mWindowManagerFuncs.reevaluateStatusBarVisibility();
3899        }
3900    };
3901
3902    /**
3903     * Input handler used while nav bar is hidden.  Captures any touch on the screen,
3904     * to determine when the nav bar should be shown and prevent applications from
3905     * receiving those touches.
3906     */
3907    final class HideNavInputEventReceiver extends InputEventReceiver {
3908        public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
3909            super(inputChannel, looper);
3910        }
3911
3912        @Override
3913        public void onInputEvent(InputEvent event) {
3914            boolean handled = false;
3915            try {
3916                if (event instanceof MotionEvent
3917                        && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
3918                    final MotionEvent motionEvent = (MotionEvent)event;
3919                    if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
3920                        // When the user taps down, we re-show the nav bar.
3921                        boolean changed = false;
3922                        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
3923                            if (mInputConsumer == null) {
3924                                return;
3925                            }
3926                            // Any user activity always causes us to show the
3927                            // navigation controls, if they had been hidden.
3928                            // We also clear the low profile and only content
3929                            // flags so that tapping on the screen will atomically
3930                            // restore all currently hidden screen decorations.
3931                            int newVal = mResettingSystemUiFlags |
3932                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
3933                                    View.SYSTEM_UI_FLAG_LOW_PROFILE |
3934                                    View.SYSTEM_UI_FLAG_FULLSCREEN;
3935                            if (mResettingSystemUiFlags != newVal) {
3936                                mResettingSystemUiFlags = newVal;
3937                                changed = true;
3938                            }
3939                            // We don't allow the system's nav bar to be hidden
3940                            // again for 1 second, to prevent applications from
3941                            // spamming us and keeping it from being shown.
3942                            newVal = mForceClearedSystemUiFlags |
3943                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
3944                            if (mForceClearedSystemUiFlags != newVal) {
3945                                mForceClearedSystemUiFlags = newVal;
3946                                changed = true;
3947                                mHandler.postDelayed(mClearHideNavigationFlag, 1000);
3948                            }
3949                        }
3950                        if (changed) {
3951                            mWindowManagerFuncs.reevaluateStatusBarVisibility();
3952                        }
3953                    }
3954                }
3955            } finally {
3956                finishInputEvent(event, handled);
3957            }
3958        }
3959    }
3960    final InputEventReceiver.Factory mHideNavInputEventReceiverFactory =
3961            new InputEventReceiver.Factory() {
3962        @Override
3963        public InputEventReceiver createInputEventReceiver(
3964                InputChannel inputChannel, Looper looper) {
3965            return new HideNavInputEventReceiver(inputChannel, looper);
3966        }
3967    };
3968
3969    @Override
3970    public void setRecentsVisibilityLw(boolean visible) {
3971        mRecentsVisible = visible;
3972    }
3973
3974    @Override
3975    public void setTvPipVisibilityLw(boolean visible) {
3976        mTvPictureInPictureVisible = visible;
3977    }
3978
3979    @Override
3980    public int adjustSystemUiVisibilityLw(int visibility) {
3981        mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
3982        mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
3983
3984        // Reset any bits in mForceClearingStatusBarVisibility that
3985        // are now clear.
3986        mResettingSystemUiFlags &= visibility;
3987        // Clear any bits in the new visibility that are currently being
3988        // force cleared, before reporting it.
3989        return visibility & ~mResettingSystemUiFlags
3990                & ~mForceClearedSystemUiFlags;
3991    }
3992
3993    @Override
3994    public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
3995            int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets,
3996            Rect outStableInsets, Rect outOutsets) {
3997        final int fl = PolicyControl.getWindowFlags(null, attrs);
3998        final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
3999        final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
4000
4001        final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
4002        if (useOutsets) {
4003            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
4004            if (outset > 0) {
4005                if (displayRotation == Surface.ROTATION_0) {
4006                    outOutsets.bottom += outset;
4007                } else if (displayRotation == Surface.ROTATION_90) {
4008                    outOutsets.right += outset;
4009                } else if (displayRotation == Surface.ROTATION_180) {
4010                    outOutsets.top += outset;
4011                } else if (displayRotation == Surface.ROTATION_270) {
4012                    outOutsets.left += outset;
4013                }
4014            }
4015        }
4016
4017        if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4018                == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4019            int availRight, availBottom;
4020            if (canHideNavigationBar() &&
4021                    (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
4022                availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4023                availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4024            } else {
4025                availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
4026                availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4027            }
4028            if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4029                if ((fl & FLAG_FULLSCREEN) != 0) {
4030                    outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop,
4031                            availRight - mStableFullscreenRight,
4032                            availBottom - mStableFullscreenBottom);
4033                } else {
4034                    outContentInsets.set(mStableLeft, mStableTop,
4035                            availRight - mStableRight, availBottom - mStableBottom);
4036                }
4037            } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
4038                outContentInsets.setEmpty();
4039            } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
4040                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
4041                outContentInsets.set(mCurLeft, mCurTop,
4042                        availRight - mCurRight, availBottom - mCurBottom);
4043            } else {
4044                outContentInsets.set(mCurLeft, mCurTop,
4045                        availRight - mCurRight, availBottom - mCurBottom);
4046            }
4047
4048            outStableInsets.set(mStableLeft, mStableTop,
4049                    availRight - mStableRight, availBottom - mStableBottom);
4050            if (taskBounds != null) {
4051                calculateRelevantTaskInsets(taskBounds, outContentInsets,
4052                        displayWidth, displayHeight);
4053                calculateRelevantTaskInsets(taskBounds, outStableInsets,
4054                        displayWidth, displayHeight);
4055            }
4056            return mForceShowSystemBars;
4057        }
4058        outContentInsets.setEmpty();
4059        outStableInsets.setEmpty();
4060        return mForceShowSystemBars;
4061    }
4062
4063    /**
4064     * For any given task bounds, the insets relevant for these bounds given the insets relevant
4065     * for the entire display.
4066     */
4067    private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth,
4068            int displayHeight) {
4069        mTmpRect.set(0, 0, displayWidth, displayHeight);
4070        mTmpRect.inset(inOutInsets);
4071        mTmpRect.intersect(taskBounds);
4072        int leftInset = mTmpRect.left - taskBounds.left;
4073        int topInset = mTmpRect.top - taskBounds.top;
4074        int rightInset = taskBounds.right - mTmpRect.right;
4075        int bottomInset = taskBounds.bottom - mTmpRect.bottom;
4076        inOutInsets.set(leftInset, topInset, rightInset, bottomInset);
4077    }
4078
4079    private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
4080        return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
4081                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
4082    }
4083
4084    /** {@inheritDoc} */
4085    @Override
4086    public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
4087                              int displayRotation, int uiMode) {
4088        mDisplayRotation = displayRotation;
4089        final int overscanLeft, overscanTop, overscanRight, overscanBottom;
4090        if (isDefaultDisplay) {
4091            switch (displayRotation) {
4092                case Surface.ROTATION_90:
4093                    overscanLeft = mOverscanTop;
4094                    overscanTop = mOverscanRight;
4095                    overscanRight = mOverscanBottom;
4096                    overscanBottom = mOverscanLeft;
4097                    break;
4098                case Surface.ROTATION_180:
4099                    overscanLeft = mOverscanRight;
4100                    overscanTop = mOverscanBottom;
4101                    overscanRight = mOverscanLeft;
4102                    overscanBottom = mOverscanTop;
4103                    break;
4104                case Surface.ROTATION_270:
4105                    overscanLeft = mOverscanBottom;
4106                    overscanTop = mOverscanLeft;
4107                    overscanRight = mOverscanTop;
4108                    overscanBottom = mOverscanRight;
4109                    break;
4110                default:
4111                    overscanLeft = mOverscanLeft;
4112                    overscanTop = mOverscanTop;
4113                    overscanRight = mOverscanRight;
4114                    overscanBottom = mOverscanBottom;
4115                    break;
4116            }
4117        } else {
4118            overscanLeft = 0;
4119            overscanTop = 0;
4120            overscanRight = 0;
4121            overscanBottom = 0;
4122        }
4123        mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0;
4124        mOverscanScreenTop = mRestrictedOverscanScreenTop = 0;
4125        mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth;
4126        mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight;
4127        mSystemLeft = 0;
4128        mSystemTop = 0;
4129        mSystemRight = displayWidth;
4130        mSystemBottom = displayHeight;
4131        mUnrestrictedScreenLeft = overscanLeft;
4132        mUnrestrictedScreenTop = overscanTop;
4133        mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight;
4134        mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom;
4135        mRestrictedScreenLeft = mUnrestrictedScreenLeft;
4136        mRestrictedScreenTop = mUnrestrictedScreenTop;
4137        mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth;
4138        mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight;
4139        mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft
4140                = mCurLeft = mUnrestrictedScreenLeft;
4141        mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop
4142                = mCurTop = mUnrestrictedScreenTop;
4143        mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight
4144                = mCurRight = displayWidth - overscanRight;
4145        mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom
4146                = mCurBottom = displayHeight - overscanBottom;
4147        mDockLayer = 0x10000000;
4148        mStatusBarLayer = -1;
4149
4150        // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
4151        final Rect pf = mTmpParentFrame;
4152        final Rect df = mTmpDisplayFrame;
4153        final Rect of = mTmpOverscanFrame;
4154        final Rect vf = mTmpVisibleFrame;
4155        final Rect dcf = mTmpDecorFrame;
4156        pf.left = df.left = of.left = vf.left = mDockLeft;
4157        pf.top = df.top = of.top = vf.top = mDockTop;
4158        pf.right = df.right = of.right = vf.right = mDockRight;
4159        pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom;
4160        dcf.setEmpty();  // Decor frame N/A for system bars.
4161
4162        if (isDefaultDisplay) {
4163            // For purposes of putting out fake window up to steal focus, we will
4164            // drive nav being hidden only by whether it is requested.
4165            final int sysui = mLastSystemUiFlags;
4166            boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
4167            boolean navTranslucent = (sysui
4168                    & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
4169            boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
4170            boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
4171            boolean navAllowedHidden = immersive || immersiveSticky;
4172            navTranslucent &= !immersiveSticky;  // transient trumps translucent
4173            boolean isKeyguardShowing = isStatusBarKeyguard() && !mHideLockScreen;
4174            if (!isKeyguardShowing) {
4175                navTranslucent &= areTranslucentBarsAllowed();
4176            }
4177            boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null
4178                    && mStatusBar.getAttrs().height == MATCH_PARENT
4179                    && mStatusBar.getAttrs().width == MATCH_PARENT;
4180
4181            // When the navigation bar isn't visible, we put up a fake
4182            // input window to catch all touch events.  This way we can
4183            // detect when the user presses anywhere to bring back the nav
4184            // bar and ensure the application doesn't see the event.
4185            if (navVisible || navAllowedHidden) {
4186                if (mInputConsumer != null) {
4187                    mHandler.sendMessage(
4188                            mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
4189                    mInputConsumer = null;
4190                }
4191            } else if (mInputConsumer == null) {
4192                mInputConsumer = mWindowManagerFuncs.addInputConsumer(mHandler.getLooper(),
4193                        mHideNavInputEventReceiverFactory);
4194            }
4195
4196            // For purposes of positioning and showing the nav bar, if we have
4197            // decided that it can't be hidden (because of the screen aspect ratio),
4198            // then take that into account.
4199            navVisible |= !canHideNavigationBar();
4200
4201            boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight,
4202                    displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom, dcf, navVisible, navTranslucent,
4203                    navAllowedHidden, statusBarExpandedNotKeyguard);
4204            if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
4205                    mDockLeft, mDockTop, mDockRight, mDockBottom));
4206            updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing);
4207            if (updateSysUiVisibility) {
4208                updateSystemUiVisibilityLw();
4209            }
4210        }
4211    }
4212
4213    private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui,
4214            boolean isKeyguardShowing) {
4215        // decide where the status bar goes ahead of time
4216        if (mStatusBar != null) {
4217            // apply any navigation bar insets
4218            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4219            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4220            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4221            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
4222                    + mUnrestrictedScreenTop;
4223            vf.left = mStableLeft;
4224            vf.top = mStableTop;
4225            vf.right = mStableRight;
4226            vf.bottom = mStableBottom;
4227
4228            mStatusBarLayer = mStatusBar.getSurfaceLayer();
4229
4230            // Let the status bar determine its size.
4231            mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
4232                    vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
4233                    dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */);
4234
4235            // For layout, the status bar is always at the top with our fixed height.
4236            mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
4237
4238            boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
4239            boolean statusBarTranslucent = (sysui
4240                    & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
4241            if (!isKeyguardShowing) {
4242                statusBarTranslucent &= areTranslucentBarsAllowed();
4243            }
4244
4245            // If the status bar is hidden, we don't want to cause
4246            // windows behind it to scroll.
4247            if (mStatusBar.isVisibleLw() && !statusBarTransient) {
4248                // Status bar may go away, so the screen area it occupies
4249                // is available to apps but just covering them when the
4250                // status bar is visible.
4251                mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
4252
4253                mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4254                mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4255                mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4256                mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4257
4258                if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " +
4259                        String.format(
4260                                "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
4261                                mDockLeft, mDockTop, mDockRight, mDockBottom,
4262                                mContentLeft, mContentTop, mContentRight, mContentBottom,
4263                                mCurLeft, mCurTop, mCurRight, mCurBottom));
4264            }
4265            if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
4266                    && !statusBarTransient && !statusBarTranslucent
4267                    && !mStatusBarController.wasRecentlyTranslucent()) {
4268                // If the opaque status bar is currently requested to be visible,
4269                // and not in the process of animating on or off, then
4270                // we can tell the app that it is covered by it.
4271                mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
4272            }
4273            if (mStatusBarController.checkHiddenLw()) {
4274                return true;
4275            }
4276        }
4277        return false;
4278    }
4279
4280    private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation,
4281            int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf,
4282            boolean navVisible, boolean navTranslucent, boolean navAllowedHidden,
4283            boolean statusBarExpandedNotKeyguard) {
4284        if (mNavigationBar != null) {
4285            boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
4286            // Force the navigation bar to its appropriate place and
4287            // size.  We need to do this directly, instead of relying on
4288            // it to bubble up from the nav bar, because this needs to
4289            // change atomically with screen rotations.
4290            mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight,
4291                    displayRotation);
4292            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
4293                // It's a system nav bar or a portrait screen; nav bar goes on bottom.
4294                int top = displayHeight - overscanBottom
4295                        - getNavigationBarHeight(displayRotation, uiMode);
4296                mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
4297                mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
4298                if (transientNavBarShowing) {
4299                    mNavigationBarController.setBarShowingLw(true);
4300                } else if (navVisible) {
4301                    mNavigationBarController.setBarShowingLw(true);
4302                    mDockBottom = mTmpNavigationFrame.top;
4303                    mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
4304                    mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
4305                } else {
4306                    // We currently want to hide the navigation UI - unless we expanded the status
4307                    // bar.
4308                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4309                }
4310                if (navVisible && !navTranslucent && !navAllowedHidden
4311                        && !mNavigationBar.isAnimatingLw()
4312                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4313                    // If the opaque nav bar is currently requested to be visible,
4314                    // and not in the process of animating on or off, then
4315                    // we can tell the app that it is covered by it.
4316                    mSystemBottom = mTmpNavigationFrame.top;
4317                }
4318            } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4319                // Landscape screen; nav bar goes to the right.
4320                int left = displayWidth - overscanRight
4321                        - getNavigationBarWidth(displayRotation, uiMode);
4322                mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
4323                mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
4324                if (transientNavBarShowing) {
4325                    mNavigationBarController.setBarShowingLw(true);
4326                } else if (navVisible) {
4327                    mNavigationBarController.setBarShowingLw(true);
4328                    mDockRight = mTmpNavigationFrame.left;
4329                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4330                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4331                } else {
4332                    // We currently want to hide the navigation UI - unless we expanded the status
4333                    // bar.
4334                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4335                }
4336                if (navVisible && !navTranslucent && !navAllowedHidden
4337                        && !mNavigationBar.isAnimatingLw()
4338                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4339                    // If the nav bar is currently requested to be visible,
4340                    // and not in the process of animating on or off, then
4341                    // we can tell the app that it is covered by it.
4342                    mSystemRight = mTmpNavigationFrame.left;
4343                }
4344            } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4345                // Seascape screen; nav bar goes to the left.
4346                int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode);
4347                mTmpNavigationFrame.set(overscanLeft, 0, right, displayHeight);
4348                mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right;
4349                if (transientNavBarShowing) {
4350                    mNavigationBarController.setBarShowingLw(true);
4351                } else if (navVisible) {
4352                    mNavigationBarController.setBarShowingLw(true);
4353                    mDockLeft = mTmpNavigationFrame.right;
4354                    // TODO: not so sure about those:
4355                    mRestrictedScreenLeft = mRestrictedOverscanScreenLeft = mDockLeft;
4356                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4357                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4358                } else {
4359                    // We currently want to hide the navigation UI - unless we expanded the status
4360                    // bar.
4361                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4362                }
4363                if (navVisible && !navTranslucent && !navAllowedHidden
4364                        && !mNavigationBar.isAnimatingLw()
4365                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4366                    // If the nav bar is currently requested to be visible,
4367                    // and not in the process of animating on or off, then
4368                    // we can tell the app that it is covered by it.
4369                    mSystemLeft = mTmpNavigationFrame.right;
4370                }
4371            }
4372            // Make sure the content and current rectangles are updated to
4373            // account for the restrictions from the navigation bar.
4374            mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4375            mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4376            mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4377            mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4378            mStatusBarLayer = mNavigationBar.getSurfaceLayer();
4379            // And compute the final frame.
4380            mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
4381                    mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
4382                    mTmpNavigationFrame, mTmpNavigationFrame);
4383            if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
4384            if (mNavigationBarController.checkHiddenLw()) {
4385                return true;
4386            }
4387        }
4388        return false;
4389    }
4390
4391    private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
4392        if (mNavigationBarCanMove && displayWidth > displayHeight) {
4393            if (displayRotation == Surface.ROTATION_270) {
4394                return NAV_BAR_LEFT;
4395            } else {
4396                return NAV_BAR_RIGHT;
4397            }
4398        }
4399        return NAV_BAR_BOTTOM;
4400    }
4401
4402    /** {@inheritDoc} */
4403    @Override
4404    public int getSystemDecorLayerLw() {
4405        if (mStatusBar != null && mStatusBar.isVisibleLw()) {
4406            return mStatusBar.getSurfaceLayer();
4407        }
4408
4409        if (mNavigationBar != null && mNavigationBar.isVisibleLw()) {
4410            return mNavigationBar.getSurfaceLayer();
4411        }
4412
4413        return 0;
4414    }
4415
4416    @Override
4417    public void getContentRectLw(Rect r) {
4418        r.set(mContentLeft, mContentTop, mContentRight, mContentBottom);
4419    }
4420
4421    void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
4422            boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
4423        if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
4424            // Here's a special case: if this attached window is a panel that is
4425            // above the dock window, and the window it is attached to is below
4426            // the dock window, then the frames we computed for the window it is
4427            // attached to can not be used because the dock is effectively part
4428            // of the underlying window and the attached window is floating on top
4429            // of the whole thing.  So, we ignore the attached window and explicitly
4430            // compute the frames that would be appropriate without the dock.
4431            df.left = of.left = cf.left = vf.left = mDockLeft;
4432            df.top = of.top = cf.top = vf.top = mDockTop;
4433            df.right = of.right = cf.right = vf.right = mDockRight;
4434            df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom;
4435        } else {
4436            // The effective display frame of the attached window depends on
4437            // whether it is taking care of insetting its content.  If not,
4438            // we need to use the parent's content frame so that the entire
4439            // window is positioned within that content.  Otherwise we can use
4440            // the overscan frame and let the attached window take care of
4441            // positioning its content appropriately.
4442            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4443                // Set the content frame of the attached window to the parent's decor frame
4444                // (same as content frame when IME isn't present) if specifically requested by
4445                // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
4446                // Otherwise, use the overscan frame.
4447                cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
4448                        ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
4449            } else {
4450                // If the window is resizing, then we want to base the content
4451                // frame on our attached content frame to resize...  however,
4452                // things can be tricky if the attached window is NOT in resize
4453                // mode, in which case its content frame will be larger.
4454                // Ungh.  So to deal with that, make sure the content frame
4455                // we end up using is not covering the IM dock.
4456                cf.set(attached.getContentFrameLw());
4457                if (attached.isVoiceInteraction()) {
4458                    if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft;
4459                    if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop;
4460                    if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight;
4461                    if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom;
4462                } else if (attached.getSurfaceLayer() < mDockLayer) {
4463                    if (cf.left < mContentLeft) cf.left = mContentLeft;
4464                    if (cf.top < mContentTop) cf.top = mContentTop;
4465                    if (cf.right > mContentRight) cf.right = mContentRight;
4466                    if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
4467                }
4468            }
4469            df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
4470            of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
4471            vf.set(attached.getVisibleFrameLw());
4472        }
4473        // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
4474        // window should be positioned relative to its parent or the entire
4475        // screen.
4476        pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
4477                ? attached.getFrameLw() : df);
4478    }
4479
4480    private void applyStableConstraints(int sysui, int fl, Rect r) {
4481        if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4482            // If app is requesting a stable layout, don't let the
4483            // content insets go below the stable values.
4484            if ((fl & FLAG_FULLSCREEN) != 0) {
4485                if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft;
4486                if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop;
4487                if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight;
4488                if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom;
4489            } else {
4490                if (r.left < mStableLeft) r.left = mStableLeft;
4491                if (r.top < mStableTop) r.top = mStableTop;
4492                if (r.right > mStableRight) r.right = mStableRight;
4493                if (r.bottom > mStableBottom) r.bottom = mStableBottom;
4494            }
4495        }
4496    }
4497
4498    private boolean canReceiveInput(WindowState win) {
4499        boolean notFocusable =
4500                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
4501        boolean altFocusableIm =
4502                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
4503        boolean notFocusableForIm = notFocusable ^ altFocusableIm;
4504        return !notFocusableForIm;
4505    }
4506
4507    /** {@inheritDoc} */
4508    @Override
4509    public void layoutWindowLw(WindowState win, WindowState attached) {
4510        // We've already done the navigation bar and status bar. If the status bar can receive
4511        // input, we need to layout it again to accomodate for the IME window.
4512        if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) {
4513            return;
4514        }
4515        final WindowManager.LayoutParams attrs = win.getAttrs();
4516        final boolean isDefaultDisplay = win.isDefaultDisplay();
4517        final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
4518                (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
4519        if (needsToOffsetInputMethodTarget) {
4520            if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
4521            offsetInputMethodWindowLw(mLastInputMethodWindow);
4522        }
4523
4524        final int fl = PolicyControl.getWindowFlags(win, attrs);
4525        final int pfl = attrs.privateFlags;
4526        final int sim = attrs.softInputMode;
4527        final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
4528
4529        final Rect pf = mTmpParentFrame;
4530        final Rect df = mTmpDisplayFrame;
4531        final Rect of = mTmpOverscanFrame;
4532        final Rect cf = mTmpContentFrame;
4533        final Rect vf = mTmpVisibleFrame;
4534        final Rect dcf = mTmpDecorFrame;
4535        final Rect sf = mTmpStableFrame;
4536        Rect osf = null;
4537        dcf.setEmpty();
4538
4539        final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
4540                && mNavigationBar != null && mNavigationBar.isVisibleLw());
4541
4542        final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
4543
4544        if (isDefaultDisplay) {
4545            sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom);
4546        } else {
4547            sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom);
4548        }
4549
4550        if (!isDefaultDisplay) {
4551            if (attached != null) {
4552                // If this window is attached to another, our display
4553                // frame is the same as the one we are attached to.
4554                setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4555            } else {
4556                // Give the window full screen.
4557                pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4558                pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4559                pf.right = df.right = of.right = cf.right
4560                        = mOverscanScreenLeft + mOverscanScreenWidth;
4561                pf.bottom = df.bottom = of.bottom = cf.bottom
4562                        = mOverscanScreenTop + mOverscanScreenHeight;
4563            }
4564        } else if (attrs.type == TYPE_INPUT_METHOD) {
4565            pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
4566            pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
4567            pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
4568            // IM dock windows layout below the nav bar...
4569            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4570            // ...with content insets above the nav bar
4571            cf.bottom = vf.bottom = mStableBottom;
4572            if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
4573                // The status bar forces the navigation bar while it's visible. Make sure the IME
4574                // avoids the navigation bar in that case.
4575                if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4576                    pf.right = df.right = of.right = cf.right = vf.right = mStableRight;
4577                } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4578                    pf.left = df.left = of.left = cf.left = vf.left = mStableLeft;
4579                }
4580            }
4581            // IM dock windows always go to the bottom of the screen.
4582            attrs.gravity = Gravity.BOTTOM;
4583            mDockLayer = win.getSurfaceLayer();
4584        } else if (attrs.type == TYPE_VOICE_INTERACTION) {
4585            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4586            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4587            pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4588            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4589            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4590                cf.left = mDockLeft;
4591                cf.top = mDockTop;
4592                cf.right = mDockRight;
4593                cf.bottom = mDockBottom;
4594            } else {
4595                cf.left = mContentLeft;
4596                cf.top = mContentTop;
4597                cf.right = mContentRight;
4598                cf.bottom = mContentBottom;
4599            }
4600            if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4601                vf.left = mCurLeft;
4602                vf.top = mCurTop;
4603                vf.right = mCurRight;
4604                vf.bottom = mCurBottom;
4605            } else {
4606                vf.set(cf);
4607            }
4608        } else if (attrs.type == TYPE_WALLPAPER) {
4609           layoutWallpaper(win, pf, df, of, cf);
4610        } else if (win == mStatusBar) {
4611            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4612            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4613            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4614            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop;
4615            cf.left = vf.left = mStableLeft;
4616            cf.top = vf.top = mStableTop;
4617            cf.right = vf.right = mStableRight;
4618            vf.bottom = mStableBottom;
4619
4620            if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
4621                cf.bottom = mContentBottom;
4622            } else {
4623                cf.bottom = mDockBottom;
4624                vf.bottom = mContentBottom;
4625            }
4626        } else {
4627
4628            // Default policy decor for the default display
4629            dcf.left = mSystemLeft;
4630            dcf.top = mSystemTop;
4631            dcf.right = mSystemRight;
4632            dcf.bottom = mSystemBottom;
4633            final boolean inheritTranslucentDecor = (attrs.privateFlags
4634                    & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0;
4635            final boolean isAppWindow =
4636                    attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW &&
4637                    attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
4638            final boolean topAtRest =
4639                    win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
4640            if (isAppWindow && !inheritTranslucentDecor && !topAtRest) {
4641                if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
4642                        && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0
4643                        && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
4644                        && (fl & WindowManager.LayoutParams.
4645                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
4646                        && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) {
4647                    // Ensure policy decor includes status bar
4648                    dcf.top = mStableTop;
4649                }
4650                if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0
4651                        && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
4652                        && (fl & WindowManager.LayoutParams.
4653                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
4654                    // Ensure policy decor includes navigation bar
4655                    dcf.bottom = mStableBottom;
4656                    dcf.right = mStableRight;
4657                }
4658            }
4659
4660            if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4661                    == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4662                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
4663                            + "): IN_SCREEN, INSET_DECOR");
4664                // This is the case for a normal activity window: we want it
4665                // to cover all of the screen space, and it can take care of
4666                // moving its contents to account for screen decorations that
4667                // intrude into that space.
4668                if (attached != null) {
4669                    // If this window is attached to another, our display
4670                    // frame is the same as the one we are attached to.
4671                    setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4672                } else {
4673                    if (attrs.type == TYPE_STATUS_BAR_PANEL
4674                            || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
4675                        // Status bar panels are the only windows who can go on top of
4676                        // the status bar.  They are protected by the STATUS_BAR_SERVICE
4677                        // permission, so they have the same privileges as the status
4678                        // bar itself.
4679                        //
4680                        // However, they should still dodge the navigation bar if it exists.
4681
4682                        pf.left = df.left = of.left = hasNavBar
4683                                ? mDockLeft : mUnrestrictedScreenLeft;
4684                        pf.top = df.top = of.top = mUnrestrictedScreenTop;
4685                        pf.right = df.right = of.right = hasNavBar
4686                                ? mRestrictedScreenLeft+mRestrictedScreenWidth
4687                                : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4688                        pf.bottom = df.bottom = of.bottom = hasNavBar
4689                                ? mRestrictedScreenTop+mRestrictedScreenHeight
4690                                : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4691
4692                        if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4693                                        "Laying out status bar window: (%d,%d - %d,%d)",
4694                                        pf.left, pf.top, pf.right, pf.bottom));
4695                    } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4696                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4697                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4698                        // Asking to layout into the overscan region, so give it that pure
4699                        // unrestricted area.
4700                        pf.left = df.left = of.left = mOverscanScreenLeft;
4701                        pf.top = df.top = of.top = mOverscanScreenTop;
4702                        pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth;
4703                        pf.bottom = df.bottom = of.bottom = mOverscanScreenTop
4704                                + mOverscanScreenHeight;
4705                    } else if (canHideNavigationBar()
4706                            && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4707                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4708                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4709                        // Asking for layout as if the nav bar is hidden, lets the
4710                        // application extend into the unrestricted overscan screen area.  We
4711                        // only do this for application windows to ensure no window that
4712                        // can be above the nav bar can do this.
4713                        pf.left = df.left = mOverscanScreenLeft;
4714                        pf.top = df.top = mOverscanScreenTop;
4715                        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
4716                        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
4717                        // We need to tell the app about where the frame inside the overscan
4718                        // is, so it can inset its content by that amount -- it didn't ask
4719                        // to actually extend itself into the overscan region.
4720                        of.left = mUnrestrictedScreenLeft;
4721                        of.top = mUnrestrictedScreenTop;
4722                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4723                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4724                    } else {
4725                        pf.left = df.left = mRestrictedOverscanScreenLeft;
4726                        pf.top = df.top = mRestrictedOverscanScreenTop;
4727                        pf.right = df.right = mRestrictedOverscanScreenLeft
4728                                + mRestrictedOverscanScreenWidth;
4729                        pf.bottom = df.bottom = mRestrictedOverscanScreenTop
4730                                + mRestrictedOverscanScreenHeight;
4731                        // We need to tell the app about where the frame inside the overscan
4732                        // is, so it can inset its content by that amount -- it didn't ask
4733                        // to actually extend itself into the overscan region.
4734                        of.left = mUnrestrictedScreenLeft;
4735                        of.top = mUnrestrictedScreenTop;
4736                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4737                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4738                    }
4739
4740                    if ((fl & FLAG_FULLSCREEN) == 0) {
4741                        if (win.isVoiceInteraction()) {
4742                            cf.left = mVoiceContentLeft;
4743                            cf.top = mVoiceContentTop;
4744                            cf.right = mVoiceContentRight;
4745                            cf.bottom = mVoiceContentBottom;
4746                        } else {
4747                            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4748                                cf.left = mDockLeft;
4749                                cf.top = mDockTop;
4750                                cf.right = mDockRight;
4751                                cf.bottom = mDockBottom;
4752                            } else {
4753                                cf.left = mContentLeft;
4754                                cf.top = mContentTop;
4755                                cf.right = mContentRight;
4756                                cf.bottom = mContentBottom;
4757                            }
4758                        }
4759                    } else {
4760                        // Full screen windows are always given a layout that is as if the
4761                        // status bar and other transient decors are gone.  This is to avoid
4762                        // bad states when moving from a window that is not hding the
4763                        // status bar to one that is.
4764                        cf.left = mRestrictedScreenLeft;
4765                        cf.top = mRestrictedScreenTop;
4766                        cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
4767                        cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4768                    }
4769                    applyStableConstraints(sysUiFl, fl, cf);
4770                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4771                        vf.left = mCurLeft;
4772                        vf.top = mCurTop;
4773                        vf.right = mCurRight;
4774                        vf.bottom = mCurBottom;
4775                    } else {
4776                        vf.set(cf);
4777                    }
4778                }
4779            } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
4780                    & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
4781                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
4782                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4783                        "): IN_SCREEN");
4784                // A window that has requested to fill the entire screen just
4785                // gets everything, period.
4786                if (attrs.type == TYPE_STATUS_BAR_PANEL
4787                        || attrs.type == TYPE_STATUS_BAR_SUB_PANEL
4788                        || attrs.type == TYPE_VOLUME_OVERLAY) {
4789                    pf.left = df.left = of.left = cf.left = hasNavBar
4790                            ? mDockLeft : mUnrestrictedScreenLeft;
4791                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
4792                    pf.right = df.right = of.right = cf.right = hasNavBar
4793                                        ? mRestrictedScreenLeft+mRestrictedScreenWidth
4794                                        : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4795                    pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar
4796                                          ? mRestrictedScreenTop+mRestrictedScreenHeight
4797                                          : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4798                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4799                                    "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
4800                                    pf.left, pf.top, pf.right, pf.bottom));
4801                } else if (attrs.type == TYPE_NAVIGATION_BAR
4802                        || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
4803                    // The navigation bar has Real Ultimate Power.
4804                    pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4805                    pf.top = df.top = of.top = mUnrestrictedScreenTop;
4806                    pf.right = df.right = of.right = mUnrestrictedScreenLeft
4807                            + mUnrestrictedScreenWidth;
4808                    pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop
4809                            + mUnrestrictedScreenHeight;
4810                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4811                                    "Laying out navigation bar window: (%d,%d - %d,%d)",
4812                                    pf.left, pf.top, pf.right, pf.bottom));
4813                } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
4814                                || attrs.type == TYPE_BOOT_PROGRESS
4815                                || attrs.type == TYPE_SCREENSHOT)
4816                        && ((fl & FLAG_FULLSCREEN) != 0)) {
4817                    // Fullscreen secure system overlays get what they ask for. Screenshot region
4818                    // selection overlay should also expand to full screen.
4819                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4820                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4821                    pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
4822                            + mOverscanScreenWidth;
4823                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
4824                            + mOverscanScreenHeight;
4825                } else if (attrs.type == TYPE_BOOT_PROGRESS) {
4826                    // Boot progress screen always covers entire display.
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 = mOverscanScreenLeft
4830                            + mOverscanScreenWidth;
4831                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
4832                            + mOverscanScreenHeight;
4833                } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4834                        && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4835                        && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4836                    // Asking to layout into the overscan region, so give it that pure
4837                    // unrestricted area.
4838                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4839                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4840                    pf.right = df.right = of.right = cf.right
4841                            = mOverscanScreenLeft + mOverscanScreenWidth;
4842                    pf.bottom = df.bottom = of.bottom = cf.bottom
4843                            = mOverscanScreenTop + mOverscanScreenHeight;
4844                } else if (canHideNavigationBar()
4845                        && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4846                        && (attrs.type == TYPE_STATUS_BAR
4847                            || attrs.type == TYPE_TOAST
4848                            || attrs.type == TYPE_DOCK_DIVIDER
4849                            || attrs.type == TYPE_VOICE_INTERACTION_STARTING
4850                            || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4851                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
4852                    // Asking for layout as if the nav bar is hidden, lets the
4853                    // application extend into the unrestricted screen area.  We
4854                    // only do this for application windows (or toasts) to ensure no window that
4855                    // can be above the nav bar can do this.
4856                    // XXX This assumes that an app asking for this will also
4857                    // ask for layout in only content.  We can't currently figure out
4858                    // what the screen would be if only laying out to hide the nav bar.
4859                    pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
4860                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
4861                    pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft
4862                            + mUnrestrictedScreenWidth;
4863                    pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
4864                            + mUnrestrictedScreenHeight;
4865                } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
4866                    pf.left = df.left = of.left = mRestrictedScreenLeft;
4867                    pf.top = df.top = of.top  = mRestrictedScreenTop;
4868                    pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
4869                    pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop
4870                            + mRestrictedScreenHeight;
4871                    if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4872                        cf.left = mDockLeft;
4873                        cf.top = mDockTop;
4874                        cf.right = mDockRight;
4875                        cf.bottom = mDockBottom;
4876                    } else {
4877                        cf.left = mContentLeft;
4878                        cf.top = mContentTop;
4879                        cf.right = mContentRight;
4880                        cf.bottom = mContentBottom;
4881                    }
4882                } else {
4883                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
4884                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
4885                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
4886                            + mRestrictedScreenWidth;
4887                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
4888                            + mRestrictedScreenHeight;
4889                }
4890
4891                applyStableConstraints(sysUiFl, fl, cf);
4892
4893                if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4894                    vf.left = mCurLeft;
4895                    vf.top = mCurTop;
4896                    vf.right = mCurRight;
4897                    vf.bottom = mCurBottom;
4898                } else {
4899                    vf.set(cf);
4900                }
4901            } else if (attached != null) {
4902                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4903                        "): attached to " + attached);
4904                // A child window should be placed inside of the same visible
4905                // frame that its parent had.
4906                setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf);
4907            } else {
4908                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4909                        "): normal window");
4910                // Otherwise, a normal window must be placed inside the content
4911                // of all screen decorations.
4912                if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) {
4913                    // Status bar panels and the volume dialog are the only windows who can go on
4914                    // top of the status bar.  They are protected by the STATUS_BAR_SERVICE
4915                    // permission, so they have the same privileges as the status
4916                    // bar itself.
4917                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
4918                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
4919                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
4920                            + mRestrictedScreenWidth;
4921                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
4922                            + mRestrictedScreenHeight;
4923                } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) {
4924                    // These dialogs are stable to interim decor changes.
4925                    pf.left = df.left = of.left = cf.left = mStableLeft;
4926                    pf.top = df.top = of.top = cf.top = mStableTop;
4927                    pf.right = df.right = of.right = cf.right = mStableRight;
4928                    pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom;
4929                } else {
4930                    pf.left = mContentLeft;
4931                    pf.top = mContentTop;
4932                    pf.right = mContentRight;
4933                    pf.bottom = mContentBottom;
4934                    if (win.isVoiceInteraction()) {
4935                        df.left = of.left = cf.left = mVoiceContentLeft;
4936                        df.top = of.top = cf.top = mVoiceContentTop;
4937                        df.right = of.right = cf.right = mVoiceContentRight;
4938                        df.bottom = of.bottom = cf.bottom = mVoiceContentBottom;
4939                    } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4940                        df.left = of.left = cf.left = mDockLeft;
4941                        df.top = of.top = cf.top = mDockTop;
4942                        df.right = of.right = cf.right = mDockRight;
4943                        df.bottom = of.bottom = cf.bottom = mDockBottom;
4944                    } else {
4945                        df.left = of.left = cf.left = mContentLeft;
4946                        df.top = of.top = cf.top = mContentTop;
4947                        df.right = of.right = cf.right = mContentRight;
4948                        df.bottom = of.bottom = cf.bottom = mContentBottom;
4949                    }
4950                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4951                        vf.left = mCurLeft;
4952                        vf.top = mCurTop;
4953                        vf.right = mCurRight;
4954                        vf.bottom = mCurBottom;
4955                    } else {
4956                        vf.set(cf);
4957                    }
4958                }
4959            }
4960        }
4961
4962        // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
4963        // Also, we don't allow windows in multi-window mode to extend out of the screen.
4964        if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR
4965                && !win.isInMultiWindowMode()) {
4966            df.left = df.top = -10000;
4967            df.right = df.bottom = 10000;
4968            if (attrs.type != TYPE_WALLPAPER) {
4969                of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
4970                of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
4971            }
4972        }
4973
4974        // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we
4975        // need to provide information to the clients that want to pretend that you can draw there.
4976        // We only want to apply outsets to certain types of windows. For example, we never want to
4977        // apply the outsets to floating dialogs, because they wouldn't make sense there.
4978        final boolean useOutsets = shouldUseOutsets(attrs, fl);
4979        if (isDefaultDisplay && useOutsets) {
4980            osf = mTmpOutsetFrame;
4981            osf.set(cf.left, cf.top, cf.right, cf.bottom);
4982            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
4983            if (outset > 0) {
4984                int rotation = mDisplayRotation;
4985                if (rotation == Surface.ROTATION_0) {
4986                    osf.bottom += outset;
4987                } else if (rotation == Surface.ROTATION_90) {
4988                    osf.right += outset;
4989                } else if (rotation == Surface.ROTATION_180) {
4990                    osf.top -= outset;
4991                } else if (rotation == Surface.ROTATION_270) {
4992                    osf.left -= outset;
4993                }
4994                if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset
4995                        + " with rotation " + rotation + ", result: " + osf);
4996            }
4997        }
4998
4999        if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
5000                + ": sim=#" + Integer.toHexString(sim)
5001                + " attach=" + attached + " type=" + attrs.type
5002                + String.format(" flags=0x%08x", fl)
5003                + " pf=" + pf.toShortString() + " df=" + df.toShortString()
5004                + " of=" + of.toShortString()
5005                + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
5006                + " dcf=" + dcf.toShortString()
5007                + " sf=" + sf.toShortString()
5008                + " osf=" + (osf == null ? "null" : osf.toShortString()));
5009
5010        win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf);
5011
5012        // Dock windows carve out the bottom of the screen, so normal windows
5013        // can't appear underneath them.
5014        if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleOrBehindKeyguardLw()
5015                && win.isDisplayedLw() && !win.getGivenInsetsPendingLw()) {
5016            setLastInputMethodWindowLw(null, null);
5017            offsetInputMethodWindowLw(win);
5018        }
5019        if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleOrBehindKeyguardLw()
5020                && !win.getGivenInsetsPendingLw()) {
5021            offsetVoiceInputWindowLw(win);
5022        }
5023    }
5024
5025    private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) {
5026
5027        // The wallpaper also has Real Ultimate Power, but we want to tell
5028        // it about the overscan area.
5029        pf.left = df.left = mOverscanScreenLeft;
5030        pf.top = df.top = mOverscanScreenTop;
5031        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
5032        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
5033        of.left = cf.left = mUnrestrictedScreenLeft;
5034        of.top = cf.top = mUnrestrictedScreenTop;
5035        of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5036        of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5037    }
5038
5039    private void offsetInputMethodWindowLw(WindowState win) {
5040        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5041        top += win.getGivenContentInsetsLw().top;
5042        if (mContentBottom > top) {
5043            mContentBottom = top;
5044        }
5045        if (mVoiceContentBottom > top) {
5046            mVoiceContentBottom = top;
5047        }
5048        top = win.getVisibleFrameLw().top;
5049        top += win.getGivenVisibleInsetsLw().top;
5050        if (mCurBottom > top) {
5051            mCurBottom = top;
5052        }
5053        if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
5054                + mDockBottom + " mContentBottom="
5055                + mContentBottom + " mCurBottom=" + mCurBottom);
5056    }
5057
5058    private void offsetVoiceInputWindowLw(WindowState win) {
5059        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5060        top += win.getGivenContentInsetsLw().top;
5061        if (mVoiceContentBottom > top) {
5062            mVoiceContentBottom = top;
5063        }
5064    }
5065
5066    /** {@inheritDoc} */
5067    @Override
5068    public void finishLayoutLw() {
5069        return;
5070    }
5071
5072    /** {@inheritDoc} */
5073    @Override
5074    public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
5075        mTopFullscreenOpaqueWindowState = null;
5076        mTopFullscreenOpaqueOrDimmingWindowState = null;
5077        mTopDockedOpaqueWindowState = null;
5078        mTopDockedOpaqueOrDimmingWindowState = null;
5079        mAppsToBeHidden.clear();
5080        mAppsThatDismissKeyguard.clear();
5081        mForceStatusBar = false;
5082        mForceStatusBarFromKeyguard = false;
5083        mForceStatusBarTransparent = false;
5084        mForcingShowNavBar = false;
5085        mForcingShowNavBarLayer = -1;
5086
5087        mHideLockScreen = false;
5088        mAllowLockscreenWhenOn = false;
5089        mDismissKeyguard = DISMISS_KEYGUARD_NONE;
5090        mShowingLockscreen = false;
5091        mShowingDream = false;
5092        mWinShowWhenLocked = null;
5093        mKeyguardSecure = isKeyguardSecure(mCurrentUserId);
5094        mKeyguardSecureIncludingHidden = mKeyguardSecure
5095                && (mKeyguardDelegate != null && mKeyguardDelegate.isShowing());
5096    }
5097
5098    /** {@inheritDoc} */
5099    @Override
5100    public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
5101            WindowState attached) {
5102        if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
5103                + win.isVisibleOrBehindKeyguardLw());
5104        final int fl = PolicyControl.getWindowFlags(win, attrs);
5105        if (mTopFullscreenOpaqueWindowState == null
5106                && win.isVisibleLw() && attrs.type == TYPE_INPUT_METHOD) {
5107            mForcingShowNavBar = true;
5108            mForcingShowNavBarLayer = win.getSurfaceLayer();
5109        }
5110        if (attrs.type == TYPE_STATUS_BAR) {
5111            if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
5112                mForceStatusBarFromKeyguard = true;
5113                mShowingLockscreen = true;
5114            }
5115            if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
5116                mForceStatusBarTransparent = true;
5117            }
5118        }
5119
5120        boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
5121                && attrs.type < FIRST_SYSTEM_WINDOW;
5122        final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0;
5123        final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0;
5124        final int stackId = win.getStackId();
5125        if (mTopFullscreenOpaqueWindowState == null &&
5126                win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
5127            if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
5128                if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
5129                    mForceStatusBarFromKeyguard = true;
5130                } else {
5131                    mForceStatusBar = true;
5132                }
5133            }
5134            if (attrs.type == TYPE_DREAM) {
5135                // If the lockscreen was showing when the dream started then wait
5136                // for the dream to draw before hiding the lockscreen.
5137                if (!mDreamingLockscreen
5138                        || (win.isVisibleLw() && win.hasDrawnLw())) {
5139                    mShowingDream = true;
5140                    appWindow = true;
5141                }
5142            }
5143
5144            final IApplicationToken appToken = win.getAppToken();
5145
5146            // For app windows that are not attached, we decide if all windows in the app they
5147            // represent should be hidden or if we should hide the lockscreen. For attached app
5148            // windows we defer the decision to the window it is attached to.
5149            if (appWindow && attached == null) {
5150                if (showWhenLocked) {
5151                    // Remove any previous windows with the same appToken.
5152                    mAppsToBeHidden.remove(appToken);
5153                    mAppsThatDismissKeyguard.remove(appToken);
5154                    if (mAppsToBeHidden.isEmpty()) {
5155                        if (dismissKeyguard && !mKeyguardSecure) {
5156                            mAppsThatDismissKeyguard.add(appToken);
5157                        } else if (win.isDrawnLw() || win.hasAppShownWindows()) {
5158                            mWinShowWhenLocked = win;
5159                            mHideLockScreen = true;
5160                            mForceStatusBarFromKeyguard = false;
5161                        }
5162                    }
5163                } else if (dismissKeyguard) {
5164                    if (mKeyguardSecure) {
5165                        mAppsToBeHidden.add(appToken);
5166                    } else {
5167                        mAppsToBeHidden.remove(appToken);
5168                    }
5169                    mAppsThatDismissKeyguard.add(appToken);
5170                } else {
5171                    mAppsToBeHidden.add(appToken);
5172                }
5173                if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
5174                    if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
5175                    mTopFullscreenOpaqueWindowState = win;
5176                    if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5177                        mTopFullscreenOpaqueOrDimmingWindowState = win;
5178                    }
5179                    if (!mAppsThatDismissKeyguard.isEmpty() &&
5180                            mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
5181                        if (DEBUG_LAYOUT) Slog.v(TAG,
5182                                "Setting mDismissKeyguard true by win " + win);
5183                        mDismissKeyguard = (mWinDismissingKeyguard == win
5184                                && mSecureDismissingKeyguard == mKeyguardSecure)
5185                                ? DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
5186                        mWinDismissingKeyguard = win;
5187                        mSecureDismissingKeyguard = mKeyguardSecure;
5188                        mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure;
5189                    } else if (mAppsToBeHidden.isEmpty() && showWhenLocked
5190                            && (win.isDrawnLw() || win.hasAppShownWindows())) {
5191                        if (DEBUG_LAYOUT) Slog.v(TAG,
5192                                "Setting mHideLockScreen to true by win " + win);
5193                        mHideLockScreen = true;
5194                        mForceStatusBarFromKeyguard = false;
5195                    }
5196                    if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
5197                        mAllowLockscreenWhenOn = true;
5198                    }
5199                }
5200
5201                if (!mKeyguardHidden && mWinShowWhenLocked != null &&
5202                        mWinShowWhenLocked.getAppToken() != win.getAppToken() &&
5203                        (attrs.flags & FLAG_SHOW_WHEN_LOCKED) == 0) {
5204                    win.hideLw(false);
5205                }
5206            }
5207        } else if (mTopFullscreenOpaqueWindowState == null && mWinShowWhenLocked == null) {
5208            // No TopFullscreenOpaqueWindow is showing, but we found a SHOW_WHEN_LOCKED window
5209            // that is being hidden in an animation - keep the
5210            // keyguard hidden until the new window shows up and
5211            // we know whether to show the keyguard or not.
5212            if (win.isAnimatingLw() && appWindow && showWhenLocked && mKeyguardHidden) {
5213                mHideLockScreen = true;
5214                mWinShowWhenLocked = win;
5215            }
5216        }
5217
5218        final boolean reallyVisible = win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw();
5219
5220        // Voice interaction overrides both top fullscreen and top docked.
5221        if (reallyVisible && win.getAttrs().type == TYPE_VOICE_INTERACTION) {
5222            if (mTopFullscreenOpaqueWindowState == null) {
5223                mTopFullscreenOpaqueWindowState = win;
5224                if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5225                    mTopFullscreenOpaqueOrDimmingWindowState = win;
5226                }
5227            }
5228            if (mTopDockedOpaqueWindowState == null) {
5229                mTopDockedOpaqueWindowState = win;
5230                if (mTopDockedOpaqueOrDimmingWindowState == null) {
5231                    mTopDockedOpaqueOrDimmingWindowState = win;
5232                }
5233            }
5234        }
5235
5236        // Keep track of the window if it's dimming but not necessarily fullscreen.
5237        if (mTopFullscreenOpaqueOrDimmingWindowState == null && reallyVisible
5238                && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
5239            mTopFullscreenOpaqueOrDimmingWindowState = win;
5240        }
5241
5242        // We need to keep track of the top "fullscreen" opaque window for the docked stack
5243        // separately, because both the "real fullscreen" opaque window and the one for the docked
5244        // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
5245        if (mTopDockedOpaqueWindowState == null && reallyVisible && appWindow && attached == null
5246                && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
5247            mTopDockedOpaqueWindowState = win;
5248            if (mTopDockedOpaqueOrDimmingWindowState == null) {
5249                mTopDockedOpaqueOrDimmingWindowState = win;
5250            }
5251        }
5252
5253        // Also keep track of any windows that are dimming but not necessarily fullscreen in the
5254        // docked stack.
5255        if (mTopDockedOpaqueOrDimmingWindowState == null && reallyVisible && win.isDimming()
5256                && stackId == DOCKED_STACK_ID) {
5257            mTopDockedOpaqueOrDimmingWindowState = win;
5258        }
5259    }
5260
5261    private boolean isFullscreen(WindowManager.LayoutParams attrs) {
5262        return attrs.x == 0 && attrs.y == 0
5263                && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
5264                && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
5265    }
5266
5267    /** {@inheritDoc} */
5268    @Override
5269    public int finishPostLayoutPolicyLw() {
5270        if (mWinShowWhenLocked != null && mTopFullscreenOpaqueWindowState != null &&
5271                mWinShowWhenLocked.getAppToken() != mTopFullscreenOpaqueWindowState.getAppToken()
5272                && isKeyguardLocked()) {
5273            // A dialog is dismissing the keyguard. Put the wallpaper behind it and hide the
5274            // fullscreen window.
5275            // TODO: Make sure FLAG_SHOW_WALLPAPER is restored when dialog is dismissed. Or not.
5276            mWinShowWhenLocked.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5277            mTopFullscreenOpaqueWindowState.hideLw(false);
5278            mTopFullscreenOpaqueWindowState = mWinShowWhenLocked;
5279        }
5280
5281        int changes = 0;
5282        boolean topIsFullscreen = false;
5283
5284        final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
5285                ? mTopFullscreenOpaqueWindowState.getAttrs()
5286                : null;
5287
5288        // If we are not currently showing a dream then remember the current
5289        // lockscreen state.  We will use this to determine whether the dream
5290        // started while the lockscreen was showing and remember this state
5291        // while the dream is showing.
5292        if (!mShowingDream) {
5293            mDreamingLockscreen = mShowingLockscreen;
5294            if (mDreamingSleepTokenNeeded) {
5295                mDreamingSleepTokenNeeded = false;
5296                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
5297            }
5298        } else {
5299            if (!mDreamingSleepTokenNeeded) {
5300                mDreamingSleepTokenNeeded = true;
5301                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget();
5302            }
5303        }
5304
5305        if (mStatusBar != null) {
5306            if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
5307                    + " forcefkg=" + mForceStatusBarFromKeyguard
5308                    + " top=" + mTopFullscreenOpaqueWindowState);
5309            boolean shouldBeTransparent = mForceStatusBarTransparent
5310                    && !mForceStatusBar
5311                    && !mForceStatusBarFromKeyguard;
5312            if (!shouldBeTransparent) {
5313                mStatusBarController.setShowTransparent(false /* transparent */);
5314            } else if (!mStatusBar.isVisibleLw()) {
5315                mStatusBarController.setShowTransparent(true /* transparent */);
5316            }
5317
5318            WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs();
5319            boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT
5320                    && statusBarAttrs.width == MATCH_PARENT;
5321            if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
5322                    || statusBarExpanded) {
5323                if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
5324                if (mStatusBarController.setBarShowingLw(true)) {
5325                    changes |= FINISH_LAYOUT_REDO_LAYOUT;
5326                }
5327                // Maintain fullscreen layout until incoming animation is complete.
5328                topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
5329                // Transient status bar on the lockscreen is not allowed
5330                if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) {
5331                    mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
5332                            mLastSystemUiFlags, mLastSystemUiFlags);
5333                }
5334                if (statusBarExpanded && mNavigationBar != null) {
5335                    if (mNavigationBarController.setBarShowingLw(true)) {
5336                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5337                    }
5338                }
5339            } else if (mTopFullscreenOpaqueWindowState != null) {
5340                final int fl = PolicyControl.getWindowFlags(null, lp);
5341                if (localLOGV) {
5342                    Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
5343                            + " shown position: "
5344                            + mTopFullscreenOpaqueWindowState.getShownPositionLw());
5345                    Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
5346                            + " lp.flags=0x" + Integer.toHexString(fl));
5347                }
5348                topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
5349                        || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
5350                // The subtle difference between the window for mTopFullscreenOpaqueWindowState
5351                // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
5352                // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
5353                // case though.
5354                if (mStatusBarController.isTransientShowing()) {
5355                    if (mStatusBarController.setBarShowingLw(true)) {
5356                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5357                    }
5358                } else if (topIsFullscreen
5359                        && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)
5360                        && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) {
5361                    if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
5362                    if (mStatusBarController.setBarShowingLw(false)) {
5363                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5364                    } else {
5365                        if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
5366                    }
5367                } else {
5368                    if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
5369                    if (mStatusBarController.setBarShowingLw(true)) {
5370                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5371                    }
5372                }
5373            }
5374        }
5375
5376        if (mTopIsFullscreen != topIsFullscreen) {
5377            if (!topIsFullscreen) {
5378                // Force another layout when status bar becomes fully shown.
5379                changes |= FINISH_LAYOUT_REDO_LAYOUT;
5380            }
5381            mTopIsFullscreen = topIsFullscreen;
5382        }
5383
5384        // Hide the key guard if a visible window explicitly specifies that it wants to be
5385        // displayed when the screen is locked.
5386        if (mKeyguardDelegate != null && mStatusBar != null) {
5387            if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
5388                    + mHideLockScreen);
5389            if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardSecure) {
5390                mKeyguardHidden = true;
5391                if (setKeyguardOccludedLw(true)) {
5392                    changes |= FINISH_LAYOUT_REDO_LAYOUT
5393                            | FINISH_LAYOUT_REDO_CONFIG
5394                            | FINISH_LAYOUT_REDO_WALLPAPER;
5395                }
5396                if (mKeyguardDelegate.isShowing()) {
5397                    mHandler.post(new Runnable() {
5398                        @Override
5399                        public void run() {
5400                            mKeyguardDelegate.keyguardDone(false, false);
5401                        }
5402                    });
5403                }
5404            } else if (mHideLockScreen) {
5405                mKeyguardHidden = true;
5406                mWinDismissingKeyguard = null;
5407                if (setKeyguardOccludedLw(true)) {
5408                    changes |= FINISH_LAYOUT_REDO_LAYOUT
5409                            | FINISH_LAYOUT_REDO_CONFIG
5410                            | FINISH_LAYOUT_REDO_WALLPAPER;
5411                }
5412            } else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) {
5413                mKeyguardHidden = false;
5414                final boolean trusted = mKeyguardDelegate.isTrusted();
5415                if (trusted) {
5416                    // No need to un-occlude keyguard - we'll dimiss it right away anyways.
5417                } else if (setKeyguardOccludedLw(false)) {
5418                    changes |= FINISH_LAYOUT_REDO_LAYOUT
5419                            | FINISH_LAYOUT_REDO_CONFIG
5420                            | FINISH_LAYOUT_REDO_WALLPAPER;
5421                }
5422                if (mDismissKeyguard == DISMISS_KEYGUARD_START) {
5423                    // Only launch the next keyguard unlock window once per window.
5424                    mHandler.post(new Runnable() {
5425                        @Override
5426                        public void run() {
5427                            mKeyguardDelegate.dismiss(trusted /* allowWhileOccluded */);
5428                        }
5429                    });
5430                }
5431            } else {
5432                mWinDismissingKeyguard = null;
5433                mSecureDismissingKeyguard = false;
5434                mKeyguardHidden = false;
5435                if (setKeyguardOccludedLw(false)) {
5436                    changes |= FINISH_LAYOUT_REDO_LAYOUT
5437                            | FINISH_LAYOUT_REDO_CONFIG
5438                            | FINISH_LAYOUT_REDO_WALLPAPER;
5439                }
5440            }
5441        }
5442
5443        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5444            // If the navigation bar has been hidden or shown, we need to do another
5445            // layout pass to update that window.
5446            changes |= FINISH_LAYOUT_REDO_LAYOUT;
5447        }
5448
5449        // update since mAllowLockscreenWhenOn might have changed
5450        updateLockScreenTimeout();
5451        return changes;
5452    }
5453
5454    /**
5455     * Updates the occluded state of the Keyguard.
5456     *
5457     * @return Whether the flags have changed and we have to redo the layout.
5458     */
5459    private boolean setKeyguardOccludedLw(boolean isOccluded) {
5460        boolean wasOccluded = mKeyguardOccluded;
5461        boolean showing = mKeyguardDelegate.isShowing();
5462        if (wasOccluded && !isOccluded && showing) {
5463            mKeyguardOccluded = false;
5464            mKeyguardDelegate.setOccluded(false, true /* animate */);
5465            mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
5466            if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
5467                mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5468            }
5469            Animation anim = AnimationUtils.loadAnimation(mContext,
5470                    com.android.internal.R.anim.wallpaper_open_exit);
5471            mWindowManagerFuncs.overridePlayingAppAnimationsLw(anim);
5472            return true;
5473        } else if (!wasOccluded && isOccluded && showing) {
5474            mKeyguardOccluded = true;
5475            mKeyguardDelegate.setOccluded(true, false /* animate */);
5476            mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
5477            mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
5478            return true;
5479        } else {
5480            return false;
5481        }
5482    }
5483
5484    private boolean isStatusBarKeyguard() {
5485        return mStatusBar != null
5486                && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
5487    }
5488
5489    @Override
5490    public boolean allowAppAnimationsLw() {
5491        if (isStatusBarKeyguard() || mShowingDream) {
5492            // If keyguard or dreams is currently visible, no reason to animate behind it.
5493            return false;
5494        }
5495        return true;
5496    }
5497
5498    @Override
5499    public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
5500        mFocusedWindow = newFocus;
5501        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5502            // If the navigation bar has been hidden or shown, we need to do another
5503            // layout pass to update that window.
5504            return FINISH_LAYOUT_REDO_LAYOUT;
5505        }
5506        return 0;
5507    }
5508
5509    /** {@inheritDoc} */
5510    @Override
5511    public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
5512        // lid changed state
5513        final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
5514        if (newLidState == mLidState) {
5515            return;
5516        }
5517
5518        mLidState = newLidState;
5519        applyLidSwitchState();
5520        updateRotation(true);
5521
5522        if (lidOpen) {
5523            wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
5524                    "android.policy:LID");
5525        } else if (!mLidControlsSleep) {
5526            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
5527        }
5528    }
5529
5530    @Override
5531    public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
5532        int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
5533        if (mCameraLensCoverState == lensCoverState) {
5534            return;
5535        }
5536        if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
5537                lensCoverState == CAMERA_LENS_UNCOVERED) {
5538            Intent intent;
5539            final boolean keyguardActive = mKeyguardDelegate == null ? false :
5540                    mKeyguardDelegate.isShowing();
5541            if (keyguardActive) {
5542                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
5543            } else {
5544                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
5545            }
5546            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
5547                    "android.policy:CAMERA_COVER");
5548            startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
5549        }
5550        mCameraLensCoverState = lensCoverState;
5551    }
5552
5553    void setHdmiPlugged(boolean plugged) {
5554        if (mHdmiPlugged != plugged) {
5555            mHdmiPlugged = plugged;
5556            updateRotation(true, true);
5557            Intent intent = new Intent(ACTION_HDMI_PLUGGED);
5558            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
5559            intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
5560            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
5561        }
5562    }
5563
5564    void initializeHdmiState() {
5565        boolean plugged = false;
5566        // watch for HDMI plug messages if the hdmi switch exists
5567        if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
5568            mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
5569
5570            final String filename = "/sys/class/switch/hdmi/state";
5571            FileReader reader = null;
5572            try {
5573                reader = new FileReader(filename);
5574                char[] buf = new char[15];
5575                int n = reader.read(buf);
5576                if (n > 1) {
5577                    plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
5578                }
5579            } catch (IOException ex) {
5580                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5581            } catch (NumberFormatException ex) {
5582                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5583            } finally {
5584                if (reader != null) {
5585                    try {
5586                        reader.close();
5587                    } catch (IOException ex) {
5588                    }
5589                }
5590            }
5591        }
5592        // This dance forces the code in setHdmiPlugged to run.
5593        // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
5594        mHdmiPlugged = !plugged;
5595        setHdmiPlugged(!mHdmiPlugged);
5596    }
5597
5598    final Object mScreenshotLock = new Object();
5599    ServiceConnection mScreenshotConnection = null;
5600
5601    final Runnable mScreenshotTimeout = new Runnable() {
5602        @Override public void run() {
5603            synchronized (mScreenshotLock) {
5604                if (mScreenshotConnection != null) {
5605                    mContext.unbindService(mScreenshotConnection);
5606                    mScreenshotConnection = null;
5607                    notifyScreenshotError();
5608                }
5609            }
5610        }
5611    };
5612
5613    // Assume this is called from the Handler thread.
5614    private void takeScreenshot(final int screenshotType) {
5615        synchronized (mScreenshotLock) {
5616            if (mScreenshotConnection != null) {
5617                return;
5618            }
5619            final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
5620                    SYSUI_SCREENSHOT_SERVICE);
5621            final Intent serviceIntent = new Intent();
5622            serviceIntent.setComponent(serviceComponent);
5623            ServiceConnection conn = new ServiceConnection() {
5624                @Override
5625                public void onServiceConnected(ComponentName name, IBinder service) {
5626                    synchronized (mScreenshotLock) {
5627                        if (mScreenshotConnection != this) {
5628                            return;
5629                        }
5630                        Messenger messenger = new Messenger(service);
5631                        Message msg = Message.obtain(null, screenshotType);
5632                        final ServiceConnection myConn = this;
5633                        Handler h = new Handler(mHandler.getLooper()) {
5634                            @Override
5635                            public void handleMessage(Message msg) {
5636                                synchronized (mScreenshotLock) {
5637                                    if (mScreenshotConnection == myConn) {
5638                                        mContext.unbindService(mScreenshotConnection);
5639                                        mScreenshotConnection = null;
5640                                        mHandler.removeCallbacks(mScreenshotTimeout);
5641                                    }
5642                                }
5643                            }
5644                        };
5645                        msg.replyTo = new Messenger(h);
5646                        msg.arg1 = msg.arg2 = 0;
5647                        if (mStatusBar != null && mStatusBar.isVisibleLw())
5648                            msg.arg1 = 1;
5649                        if (mNavigationBar != null && mNavigationBar.isVisibleLw())
5650                            msg.arg2 = 1;
5651                        try {
5652                            messenger.send(msg);
5653                        } catch (RemoteException e) {
5654                        }
5655                    }
5656                }
5657
5658                @Override
5659                public void onServiceDisconnected(ComponentName name) {
5660                    synchronized (mScreenshotLock) {
5661                        if (mScreenshotConnection != null) {
5662                            mContext.unbindService(mScreenshotConnection);
5663                            mScreenshotConnection = null;
5664                            mHandler.removeCallbacks(mScreenshotTimeout);
5665                            notifyScreenshotError();
5666                        }
5667                    }
5668                }
5669            };
5670            if (mContext.bindServiceAsUser(serviceIntent, conn,
5671                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
5672                    UserHandle.CURRENT)) {
5673                mScreenshotConnection = conn;
5674                mHandler.postDelayed(mScreenshotTimeout, 10000);
5675            }
5676        }
5677    }
5678
5679    /**
5680     * Notifies the screenshot service to show an error.
5681     */
5682    private void notifyScreenshotError() {
5683        // If the service process is killed, then ask it to clean up after itself
5684        final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
5685                SYSUI_SCREENSHOT_ERROR_RECEIVER);
5686        Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
5687        errorIntent.setComponent(errorComponent);
5688        errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
5689                Intent.FLAG_RECEIVER_FOREGROUND);
5690        mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT);
5691    }
5692
5693    /** {@inheritDoc} */
5694    @Override
5695    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
5696        if (!mSystemBooted) {
5697            // If we have not yet booted, don't let key events do anything.
5698            return 0;
5699        }
5700
5701        final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
5702        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
5703        final boolean canceled = event.isCanceled();
5704        final int keyCode = event.getKeyCode();
5705
5706        final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
5707
5708        // If screen is off then we treat the case where the keyguard is open but hidden
5709        // the same as if it were open and in front.
5710        // This will prevent any keys other than the power button from waking the screen
5711        // when the keyguard is hidden by another activity.
5712        final boolean keyguardActive = (mKeyguardDelegate == null ? false :
5713                                            (interactive ?
5714                                                isKeyguardShowingAndNotOccluded() :
5715                                                mKeyguardDelegate.isShowing()));
5716
5717        if (DEBUG_INPUT) {
5718            Log.d(TAG, "interceptKeyTq keycode=" + keyCode
5719                    + " interactive=" + interactive + " keyguardActive=" + keyguardActive
5720                    + " policyFlags=" + Integer.toHexString(policyFlags));
5721        }
5722
5723        // Basic policy based on interactive state.
5724        int result;
5725        boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
5726                || event.isWakeKey();
5727        if (interactive || (isInjected && !isWakeKey)) {
5728            // When the device is interactive or the key is injected pass the
5729            // key to the application.
5730            result = ACTION_PASS_TO_USER;
5731            isWakeKey = false;
5732
5733            if (interactive) {
5734                // If the screen is awake, but the button pressed was the one that woke the device
5735                // then don't pass it to the application
5736                if (keyCode == mPendingWakeKey && !down) {
5737                    result = 0;
5738                }
5739                // Reset the pending key
5740                mPendingWakeKey = PENDING_KEY_NULL;
5741            }
5742        } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
5743            // If we're currently dozing with the screen on and the keyguard showing, pass the key
5744            // to the application but preserve its wake key status to make sure we still move
5745            // from dozing to fully interactive if we would normally go from off to fully
5746            // interactive.
5747            result = ACTION_PASS_TO_USER;
5748            // Since we're dispatching the input, reset the pending key
5749            mPendingWakeKey = PENDING_KEY_NULL;
5750        } else {
5751            // When the screen is off and the key is not injected, determine whether
5752            // to wake the device but don't pass the key to the application.
5753            result = 0;
5754            if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
5755                isWakeKey = false;
5756            }
5757            // Cache the wake key on down event so we can also avoid sending the up event to the app
5758            if (isWakeKey && down) {
5759                mPendingWakeKey = keyCode;
5760            }
5761        }
5762
5763        // If the key would be handled globally, just return the result, don't worry about special
5764        // key processing.
5765        if (isValidGlobalKey(keyCode)
5766                && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
5767            if (isWakeKey) {
5768                wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5769            }
5770            return result;
5771        }
5772
5773        boolean useHapticFeedback = down
5774                && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
5775                && event.getRepeatCount() == 0;
5776
5777        // Handle special keys.
5778        switch (keyCode) {
5779            case KeyEvent.KEYCODE_BACK: {
5780                if (down) {
5781                    interceptBackKeyDown();
5782                } else {
5783                    boolean handled = interceptBackKeyUp(event);
5784
5785                    // Don't pass back press to app if we've already handled it via long press
5786                    if (handled) {
5787                        result &= ~ACTION_PASS_TO_USER;
5788                    }
5789                }
5790                break;
5791            }
5792
5793            case KeyEvent.KEYCODE_VOLUME_DOWN:
5794            case KeyEvent.KEYCODE_VOLUME_UP:
5795            case KeyEvent.KEYCODE_VOLUME_MUTE: {
5796                if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
5797                    if (down) {
5798                        if (interactive && !mScreenshotChordVolumeDownKeyTriggered
5799                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5800                            mScreenshotChordVolumeDownKeyTriggered = true;
5801                            mScreenshotChordVolumeDownKeyTime = event.getDownTime();
5802                            mScreenshotChordVolumeDownKeyConsumed = false;
5803                            cancelPendingPowerKeyAction();
5804                            interceptScreenshotChord();
5805                        }
5806                    } else {
5807                        mScreenshotChordVolumeDownKeyTriggered = false;
5808                        cancelPendingScreenshotChordAction();
5809                    }
5810                } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
5811                    if (down) {
5812                        if (interactive && !mScreenshotChordVolumeUpKeyTriggered
5813                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5814                            mScreenshotChordVolumeUpKeyTriggered = true;
5815                            cancelPendingPowerKeyAction();
5816                            cancelPendingScreenshotChordAction();
5817                        }
5818                    } else {
5819                        mScreenshotChordVolumeUpKeyTriggered = false;
5820                        cancelPendingScreenshotChordAction();
5821                    }
5822                }
5823                if (down) {
5824                    TelecomManager telecomManager = getTelecommService();
5825                    if (telecomManager != null) {
5826                        if (telecomManager.isRinging()) {
5827                            // If an incoming call is ringing, either VOLUME key means
5828                            // "silence ringer".  We handle these keys here, rather than
5829                            // in the InCallScreen, to make sure we'll respond to them
5830                            // even if the InCallScreen hasn't come to the foreground yet.
5831                            // Look for the DOWN event here, to agree with the "fallback"
5832                            // behavior in the InCallScreen.
5833                            Log.i(TAG, "interceptKeyBeforeQueueing:"
5834                                  + " VOLUME key-down while ringing: Silence ringer!");
5835
5836                            // Silence the ringer.  (It's safe to call this
5837                            // even if the ringer has already been silenced.)
5838                            telecomManager.silenceRinger();
5839
5840                            // And *don't* pass this key thru to the current activity
5841                            // (which is probably the InCallScreen.)
5842                            result &= ~ACTION_PASS_TO_USER;
5843                            break;
5844                        }
5845                        if (telecomManager.isInCall()
5846                                && (result & ACTION_PASS_TO_USER) == 0) {
5847                            // If we are in call but we decided not to pass the key to
5848                            // the application, just pass it to the session service.
5849
5850                            MediaSessionLegacyHelper.getHelper(mContext)
5851                                    .sendVolumeKeyEvent(event, false);
5852                            break;
5853                        }
5854                    }
5855                }
5856                if (mUseTvRouting) {
5857                    // On TVs, defer special key handlings to
5858                    // {@link interceptKeyBeforeDispatching()}.
5859                    result |= ACTION_PASS_TO_USER;
5860                } else if ((result & ACTION_PASS_TO_USER) == 0) {
5861                    // If we aren't passing to the user and no one else
5862                    // handled it send it to the session manager to
5863                    // figure out.
5864                    MediaSessionLegacyHelper.getHelper(mContext)
5865                            .sendVolumeKeyEvent(event, true);
5866                }
5867                break;
5868            }
5869
5870            case KeyEvent.KEYCODE_ENDCALL: {
5871                result &= ~ACTION_PASS_TO_USER;
5872                if (down) {
5873                    TelecomManager telecomManager = getTelecommService();
5874                    boolean hungUp = false;
5875                    if (telecomManager != null) {
5876                        hungUp = telecomManager.endCall();
5877                    }
5878                    if (interactive && !hungUp) {
5879                        mEndCallKeyHandled = false;
5880                        mHandler.postDelayed(mEndCallLongPress,
5881                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
5882                    } else {
5883                        mEndCallKeyHandled = true;
5884                    }
5885                } else {
5886                    if (!mEndCallKeyHandled) {
5887                        mHandler.removeCallbacks(mEndCallLongPress);
5888                        if (!canceled) {
5889                            if ((mEndcallBehavior
5890                                    & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
5891                                if (goHome()) {
5892                                    break;
5893                                }
5894                            }
5895                            if ((mEndcallBehavior
5896                                    & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
5897                                mPowerManager.goToSleep(event.getEventTime(),
5898                                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
5899                                isWakeKey = false;
5900                            }
5901                        }
5902                    }
5903                }
5904                break;
5905            }
5906
5907            case KeyEvent.KEYCODE_POWER: {
5908                result &= ~ACTION_PASS_TO_USER;
5909                isWakeKey = false; // wake-up will be handled separately
5910                if (down) {
5911                    interceptPowerKeyDown(event, interactive);
5912                } else {
5913                    interceptPowerKeyUp(event, interactive, canceled);
5914                }
5915                break;
5916            }
5917
5918            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
5919                // fall through
5920            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
5921                // fall through
5922            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
5923                // fall through
5924            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
5925                result &= ~ACTION_PASS_TO_USER;
5926                interceptSystemNavigationKey(event);
5927                break;
5928            }
5929
5930            case KeyEvent.KEYCODE_SLEEP: {
5931                result &= ~ACTION_PASS_TO_USER;
5932                isWakeKey = false;
5933                if (!mPowerManager.isInteractive()) {
5934                    useHapticFeedback = false; // suppress feedback if already non-interactive
5935                }
5936                if (down) {
5937                    sleepPress(event.getEventTime());
5938                } else {
5939                    sleepRelease(event.getEventTime());
5940                }
5941                break;
5942            }
5943
5944            case KeyEvent.KEYCODE_SOFT_SLEEP: {
5945                result &= ~ACTION_PASS_TO_USER;
5946                isWakeKey = false;
5947                if (!down) {
5948                    mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
5949                }
5950                break;
5951            }
5952
5953            case KeyEvent.KEYCODE_WAKEUP: {
5954                result &= ~ACTION_PASS_TO_USER;
5955                isWakeKey = true;
5956                break;
5957            }
5958
5959            case KeyEvent.KEYCODE_MEDIA_PLAY:
5960            case KeyEvent.KEYCODE_MEDIA_PAUSE:
5961            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
5962            case KeyEvent.KEYCODE_HEADSETHOOK:
5963            case KeyEvent.KEYCODE_MUTE:
5964            case KeyEvent.KEYCODE_MEDIA_STOP:
5965            case KeyEvent.KEYCODE_MEDIA_NEXT:
5966            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
5967            case KeyEvent.KEYCODE_MEDIA_REWIND:
5968            case KeyEvent.KEYCODE_MEDIA_RECORD:
5969            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
5970            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
5971                if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
5972                    // If the global session is active pass all media keys to it
5973                    // instead of the active window.
5974                    result &= ~ACTION_PASS_TO_USER;
5975                }
5976                if ((result & ACTION_PASS_TO_USER) == 0) {
5977                    // Only do this if we would otherwise not pass it to the user. In that
5978                    // case, the PhoneWindow class will do the same thing, except it will
5979                    // only do it if the showing app doesn't process the key on its own.
5980                    // Note that we need to make a copy of the key event here because the
5981                    // original key event will be recycled when we return.
5982                    mBroadcastWakeLock.acquire();
5983                    Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
5984                            new KeyEvent(event));
5985                    msg.setAsynchronous(true);
5986                    msg.sendToTarget();
5987                }
5988                break;
5989            }
5990
5991            case KeyEvent.KEYCODE_CALL: {
5992                if (down) {
5993                    TelecomManager telecomManager = getTelecommService();
5994                    if (telecomManager != null) {
5995                        if (telecomManager.isRinging()) {
5996                            Log.i(TAG, "interceptKeyBeforeQueueing:"
5997                                  + " CALL key-down while ringing: Answer the call!");
5998                            telecomManager.acceptRingingCall();
5999
6000                            // And *don't* pass this key thru to the current activity
6001                            // (which is presumably the InCallScreen.)
6002                            result &= ~ACTION_PASS_TO_USER;
6003                        }
6004                    }
6005                }
6006                break;
6007            }
6008            case KeyEvent.KEYCODE_VOICE_ASSIST: {
6009                // Only do this if we would otherwise not pass it to the user. In that case,
6010                // interceptKeyBeforeDispatching would apply a similar but different policy in
6011                // order to invoke voice assist actions. Note that we need to make a copy of the
6012                // key event here because the original key event will be recycled when we return.
6013                if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
6014                    mBroadcastWakeLock.acquire();
6015                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
6016                            keyguardActive ? 1 : 0, 0);
6017                    msg.setAsynchronous(true);
6018                    msg.sendToTarget();
6019                }
6020                break;
6021            }
6022            case KeyEvent.KEYCODE_WINDOW: {
6023                if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
6024                    if (mTvPictureInPictureVisible) {
6025                        // Consumes the key only if picture-in-picture is visible
6026                        // to show picture-in-picture control menu.
6027                        // This gives a chance to the foreground activity
6028                        // to customize PIP key behavior.
6029                        if (!down) {
6030                            showTvPictureInPictureMenu(event);
6031                        }
6032                        result &= ~ACTION_PASS_TO_USER;
6033                    }
6034                }
6035                break;
6036            }
6037        }
6038
6039        if (useHapticFeedback) {
6040            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
6041        }
6042
6043        if (isWakeKey) {
6044            wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
6045        }
6046
6047        return result;
6048    }
6049
6050    /**
6051     * Handle statusbar expansion events.
6052     * @param event
6053     */
6054    private void interceptSystemNavigationKey(KeyEvent event) {
6055        if (event.getAction() == KeyEvent.ACTION_UP && areSystemNavigationKeysEnabled()) {
6056            IStatusBarService sbar = getStatusBarService();
6057            if (sbar != null) {
6058                try {
6059                    sbar.handleSystemNavigationKey(event.getKeyCode());
6060                } catch (RemoteException e1) {
6061                    // oops, no statusbar. Ignore event.
6062                }
6063            }
6064        }
6065    }
6066
6067    /**
6068     * Returns true if the key can have global actions attached to it.
6069     * We reserve all power management keys for the system since they require
6070     * very careful handling.
6071     */
6072    private static boolean isValidGlobalKey(int keyCode) {
6073        switch (keyCode) {
6074            case KeyEvent.KEYCODE_POWER:
6075            case KeyEvent.KEYCODE_WAKEUP:
6076            case KeyEvent.KEYCODE_SLEEP:
6077                return false;
6078            default:
6079                return true;
6080        }
6081    }
6082
6083    /**
6084     * When the screen is off we ignore some keys that might otherwise typically
6085     * be considered wake keys.  We filter them out here.
6086     *
6087     * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
6088     * is always considered a wake key.
6089     */
6090    private boolean isWakeKeyWhenScreenOff(int keyCode) {
6091        switch (keyCode) {
6092            // ignore volume keys unless docked
6093            case KeyEvent.KEYCODE_VOLUME_UP:
6094            case KeyEvent.KEYCODE_VOLUME_DOWN:
6095            case KeyEvent.KEYCODE_VOLUME_MUTE:
6096                return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
6097
6098            // ignore media and camera keys
6099            case KeyEvent.KEYCODE_MUTE:
6100            case KeyEvent.KEYCODE_HEADSETHOOK:
6101            case KeyEvent.KEYCODE_MEDIA_PLAY:
6102            case KeyEvent.KEYCODE_MEDIA_PAUSE:
6103            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6104            case KeyEvent.KEYCODE_MEDIA_STOP:
6105            case KeyEvent.KEYCODE_MEDIA_NEXT:
6106            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6107            case KeyEvent.KEYCODE_MEDIA_REWIND:
6108            case KeyEvent.KEYCODE_MEDIA_RECORD:
6109            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6110            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
6111            case KeyEvent.KEYCODE_CAMERA:
6112                return false;
6113        }
6114        return true;
6115    }
6116
6117
6118    /** {@inheritDoc} */
6119    @Override
6120    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
6121        if ((policyFlags & FLAG_WAKE) != 0) {
6122            if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
6123                    "android.policy:MOTION")) {
6124                return 0;
6125            }
6126        }
6127
6128        if (shouldDispatchInputWhenNonInteractive(null)) {
6129            return ACTION_PASS_TO_USER;
6130        }
6131
6132        // If we have not passed the action up and we are in theater mode without dreaming,
6133        // there will be no dream to intercept the touch and wake into ambient.  The device should
6134        // wake up in this case.
6135        if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
6136            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
6137                    "android.policy:MOTION");
6138        }
6139
6140        return 0;
6141    }
6142
6143    private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
6144        final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
6145
6146        if (displayOff && !mHasFeatureWatch) {
6147            return false;
6148        }
6149
6150        // Send events to keyguard while the screen is on and it's showing.
6151        if (isKeyguardShowingAndNotOccluded() && !displayOff) {
6152            return true;
6153        }
6154
6155        // Watches handle BACK specially
6156        if (mHasFeatureWatch
6157                && event != null
6158                && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
6159                        || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
6160            return false;
6161        }
6162
6163        // Send events to a dozing dream even if the screen is off since the dream
6164        // is in control of the state of the screen.
6165        IDreamManager dreamManager = getDreamManager();
6166
6167        try {
6168            if (dreamManager != null && dreamManager.isDreaming()) {
6169                return true;
6170            }
6171        } catch (RemoteException e) {
6172            Slog.e(TAG, "RemoteException when checking if dreaming", e);
6173        }
6174
6175        // Otherwise, consume events since the user can't see what is being
6176        // interacted with.
6177        return false;
6178    }
6179
6180    private void dispatchDirectAudioEvent(KeyEvent event) {
6181        if (event.getAction() != KeyEvent.ACTION_DOWN) {
6182            return;
6183        }
6184        int keyCode = event.getKeyCode();
6185        int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
6186                | AudioManager.FLAG_FROM_KEY;
6187        String pkgName = mContext.getOpPackageName();
6188        switch (keyCode) {
6189            case KeyEvent.KEYCODE_VOLUME_UP:
6190                try {
6191                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
6192                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6193                } catch (RemoteException e) {
6194                    Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
6195                }
6196                break;
6197            case KeyEvent.KEYCODE_VOLUME_DOWN:
6198                try {
6199                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
6200                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6201                } catch (RemoteException e) {
6202                    Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
6203                }
6204                break;
6205            case KeyEvent.KEYCODE_VOLUME_MUTE:
6206                try {
6207                    if (event.getRepeatCount() == 0) {
6208                        getAudioService().adjustSuggestedStreamVolume(
6209                                AudioManager.ADJUST_TOGGLE_MUTE,
6210                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6211                    }
6212                } catch (RemoteException e) {
6213                    Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
6214                }
6215                break;
6216        }
6217    }
6218
6219    void dispatchMediaKeyWithWakeLock(KeyEvent event) {
6220        if (DEBUG_INPUT) {
6221            Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
6222        }
6223
6224        if (mHavePendingMediaKeyRepeatWithWakeLock) {
6225            if (DEBUG_INPUT) {
6226                Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
6227            }
6228
6229            mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
6230            mHavePendingMediaKeyRepeatWithWakeLock = false;
6231            mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
6232        }
6233
6234        dispatchMediaKeyWithWakeLockToAudioService(event);
6235
6236        if (event.getAction() == KeyEvent.ACTION_DOWN
6237                && event.getRepeatCount() == 0) {
6238            mHavePendingMediaKeyRepeatWithWakeLock = true;
6239
6240            Message msg = mHandler.obtainMessage(
6241                    MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
6242            msg.setAsynchronous(true);
6243            mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
6244        } else {
6245            mBroadcastWakeLock.release();
6246        }
6247    }
6248
6249    void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
6250        mHavePendingMediaKeyRepeatWithWakeLock = false;
6251
6252        KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
6253                SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6254        if (DEBUG_INPUT) {
6255            Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
6256        }
6257
6258        dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
6259        mBroadcastWakeLock.release();
6260    }
6261
6262    void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
6263        if (ActivityManagerNative.isSystemReady()) {
6264            MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
6265        }
6266    }
6267
6268    void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
6269        IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
6270                ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
6271        if (dic != null) {
6272            try {
6273                dic.exitIdle("voice-search");
6274            } catch (RemoteException e) {
6275            }
6276        }
6277        Intent voiceIntent =
6278            new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
6279        voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
6280        startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
6281        mBroadcastWakeLock.release();
6282    }
6283
6284    BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
6285        @Override
6286        public void onReceive(Context context, Intent intent) {
6287            if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
6288                mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6289                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
6290            } else {
6291                try {
6292                    IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
6293                            ServiceManager.getService(Context.UI_MODE_SERVICE));
6294                    mUiMode = uiModeService.getCurrentModeType();
6295                } catch (RemoteException e) {
6296                }
6297            }
6298            updateRotation(true);
6299            synchronized (mLock) {
6300                updateOrientationListenerLp();
6301            }
6302        }
6303    };
6304
6305    BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
6306        @Override
6307        public void onReceive(Context context, Intent intent) {
6308            if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
6309                if (mKeyguardDelegate != null) {
6310                    mKeyguardDelegate.onDreamingStarted();
6311                }
6312            } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
6313                if (mKeyguardDelegate != null) {
6314                    mKeyguardDelegate.onDreamingStopped();
6315                }
6316            }
6317        }
6318    };
6319
6320    BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
6321        @Override
6322        public void onReceive(Context context, Intent intent) {
6323            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
6324                // tickle the settings observer: this first ensures that we're
6325                // observing the relevant settings for the newly-active user,
6326                // and then updates our own bookkeeping based on the now-
6327                // current user.
6328                mSettingsObserver.onChange(false);
6329
6330                // force a re-application of focused window sysui visibility.
6331                // the window may never have been shown for this user
6332                // e.g. the keyguard when going through the new-user setup flow
6333                synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6334                    mLastSystemUiFlags = 0;
6335                    updateSystemUiVisibilityLw();
6336                }
6337            }
6338        }
6339    };
6340
6341    private final Runnable mHiddenNavPanic = new Runnable() {
6342        @Override
6343        public void run() {
6344            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6345                if (!isUserSetupComplete()) {
6346                    // Swipe-up for navigation bar is disabled during setup
6347                    return;
6348                }
6349                mPendingPanicGestureUptime = SystemClock.uptimeMillis();
6350                if (!isNavBarEmpty(mLastSystemUiFlags)) {
6351                    mNavigationBarController.showTransient();
6352                }
6353            }
6354        }
6355    };
6356
6357    private void requestTransientBars(WindowState swipeTarget) {
6358        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6359            if (!isUserSetupComplete()) {
6360                // Swipe-up for navigation bar is disabled during setup
6361                return;
6362            }
6363            boolean sb = mStatusBarController.checkShowTransientBarLw();
6364            boolean nb = mNavigationBarController.checkShowTransientBarLw()
6365                    && !isNavBarEmpty(mLastSystemUiFlags);
6366            if (sb || nb) {
6367                // Don't show status bar when swiping on already visible navigation bar
6368                if (!nb && swipeTarget == mNavigationBar) {
6369                    if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
6370                    return;
6371                }
6372                if (sb) mStatusBarController.showTransient();
6373                if (nb) mNavigationBarController.showTransient();
6374                mImmersiveModeConfirmation.confirmCurrentPrompt();
6375                updateSystemUiVisibilityLw();
6376            }
6377        }
6378    }
6379
6380    // Called on the PowerManager's Notifier thread.
6381    @Override
6382    public void startedGoingToSleep(int why) {
6383        if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
6384        mCameraGestureTriggeredDuringGoingToSleep = false;
6385        mGoingToSleep = true;
6386        if (mKeyguardDelegate != null) {
6387            mKeyguardDelegate.onStartedGoingToSleep(why);
6388        }
6389    }
6390
6391    // Called on the PowerManager's Notifier thread.
6392    @Override
6393    public void finishedGoingToSleep(int why) {
6394        EventLog.writeEvent(70000, 0);
6395        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
6396        MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
6397
6398        mGoingToSleep = false;
6399
6400        // We must get this work done here because the power manager will drop
6401        // the wake lock and let the system suspend once this function returns.
6402        synchronized (mLock) {
6403            mAwake = false;
6404            updateWakeGestureListenerLp();
6405            updateOrientationListenerLp();
6406            updateLockScreenTimeout();
6407        }
6408        if (mKeyguardDelegate != null) {
6409            mKeyguardDelegate.onFinishedGoingToSleep(why,
6410                    mCameraGestureTriggeredDuringGoingToSleep);
6411        }
6412        mCameraGestureTriggeredDuringGoingToSleep = false;
6413    }
6414
6415    // Called on the PowerManager's Notifier thread.
6416    @Override
6417    public void startedWakingUp() {
6418        EventLog.writeEvent(70000, 1);
6419        if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
6420
6421        // Since goToSleep performs these functions synchronously, we must
6422        // do the same here.  We cannot post this work to a handler because
6423        // that might cause it to become reordered with respect to what
6424        // may happen in a future call to goToSleep.
6425        synchronized (mLock) {
6426            mAwake = true;
6427
6428            updateWakeGestureListenerLp();
6429            updateOrientationListenerLp();
6430            updateLockScreenTimeout();
6431        }
6432
6433        if (mKeyguardDelegate != null) {
6434            mKeyguardDelegate.onStartedWakingUp();
6435        }
6436    }
6437
6438    // Called on the PowerManager's Notifier thread.
6439    @Override
6440    public void finishedWakingUp() {
6441        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
6442    }
6443
6444    private void wakeUpFromPowerKey(long eventTime) {
6445        wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
6446    }
6447
6448    private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
6449        final boolean theaterModeEnabled = isTheaterModeEnabled();
6450        if (!wakeInTheaterMode && theaterModeEnabled) {
6451            return false;
6452        }
6453
6454        if (theaterModeEnabled) {
6455            Settings.Global.putInt(mContext.getContentResolver(),
6456                    Settings.Global.THEATER_MODE_ON, 0);
6457        }
6458
6459        mPowerManager.wakeUp(wakeTime, reason);
6460        return true;
6461    }
6462
6463    private void finishKeyguardDrawn() {
6464        synchronized (mLock) {
6465            if (!mScreenOnEarly || mKeyguardDrawComplete) {
6466                return; // We are not awake yet or we have already informed of this event.
6467            }
6468
6469            mKeyguardDrawComplete = true;
6470            if (mKeyguardDelegate != null) {
6471                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6472            }
6473            mWindowManagerDrawComplete = false;
6474        }
6475
6476        // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
6477        // as well as enabling the orientation change logic/sensor.
6478        mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
6479                WAITING_FOR_DRAWN_TIMEOUT);
6480    }
6481
6482    // Called on the DisplayManager's DisplayPowerController thread.
6483    @Override
6484    public void screenTurnedOff() {
6485        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
6486
6487        updateScreenOffSleepToken(true);
6488        synchronized (mLock) {
6489            mScreenOnEarly = false;
6490            mScreenOnFully = false;
6491            mKeyguardDrawComplete = false;
6492            mWindowManagerDrawComplete = false;
6493            mScreenOnListener = null;
6494            updateOrientationListenerLp();
6495
6496            if (mKeyguardDelegate != null) {
6497                mKeyguardDelegate.onScreenTurnedOff();
6498            }
6499        }
6500    }
6501
6502    // Called on the DisplayManager's DisplayPowerController thread.
6503    @Override
6504    public void screenTurningOn(final ScreenOnListener screenOnListener) {
6505        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
6506
6507        updateScreenOffSleepToken(false);
6508        synchronized (mLock) {
6509            mScreenOnEarly = true;
6510            mScreenOnFully = false;
6511            mKeyguardDrawComplete = false;
6512            mWindowManagerDrawComplete = false;
6513            mScreenOnListener = screenOnListener;
6514
6515            if (mKeyguardDelegate != null) {
6516                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6517                mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
6518                mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
6519            } else {
6520                if (DEBUG_WAKEUP) Slog.d(TAG,
6521                        "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
6522                finishKeyguardDrawn();
6523            }
6524        }
6525    }
6526
6527    // Called on the DisplayManager's DisplayPowerController thread.
6528    @Override
6529    public void screenTurnedOn() {
6530        synchronized (mLock) {
6531            if (mKeyguardDelegate != null) {
6532                mKeyguardDelegate.onScreenTurnedOn();
6533            }
6534        }
6535    }
6536
6537    private void finishWindowsDrawn() {
6538        synchronized (mLock) {
6539            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
6540                return; // Screen is not turned on or we did already handle this case earlier.
6541            }
6542
6543            mWindowManagerDrawComplete = true;
6544        }
6545
6546        finishScreenTurningOn();
6547    }
6548
6549    private void finishScreenTurningOn() {
6550        synchronized (mLock) {
6551            // We have just finished drawing screen content. Since the orientation listener
6552            // gets only installed when all windows are drawn, we try to install it again.
6553            updateOrientationListenerLp();
6554        }
6555        final ScreenOnListener listener;
6556        final boolean enableScreen;
6557        synchronized (mLock) {
6558            if (DEBUG_WAKEUP) Slog.d(TAG,
6559                    "finishScreenTurningOn: mAwake=" + mAwake
6560                            + ", mScreenOnEarly=" + mScreenOnEarly
6561                            + ", mScreenOnFully=" + mScreenOnFully
6562                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
6563                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
6564
6565            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
6566                    || (mAwake && !mKeyguardDrawComplete)) {
6567                return; // spurious or not ready yet
6568            }
6569
6570            if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
6571            listener = mScreenOnListener;
6572            mScreenOnListener = null;
6573            mScreenOnFully = true;
6574
6575            // Remember the first time we draw the keyguard so we know when we're done with
6576            // the main part of booting and can enable the screen and hide boot messages.
6577            if (!mKeyguardDrawnOnce && mAwake) {
6578                mKeyguardDrawnOnce = true;
6579                enableScreen = true;
6580                if (mBootMessageNeedsHiding) {
6581                    mBootMessageNeedsHiding = false;
6582                    hideBootMessages();
6583                }
6584            } else {
6585                enableScreen = false;
6586            }
6587        }
6588
6589        if (listener != null) {
6590            listener.onScreenOn();
6591        }
6592
6593        if (enableScreen) {
6594            try {
6595                mWindowManager.enableScreenIfNeeded();
6596            } catch (RemoteException unhandled) {
6597            }
6598        }
6599    }
6600
6601    private void handleHideBootMessage() {
6602        synchronized (mLock) {
6603            if (!mKeyguardDrawnOnce) {
6604                mBootMessageNeedsHiding = true;
6605                return; // keyguard hasn't drawn the first time yet, not done booting
6606            }
6607        }
6608
6609        if (mBootMsgDialog != null) {
6610            if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
6611            mBootMsgDialog.dismiss();
6612            mBootMsgDialog = null;
6613        }
6614    }
6615
6616    @Override
6617    public boolean isScreenOn() {
6618        return mScreenOnFully;
6619    }
6620
6621    /** {@inheritDoc} */
6622    @Override
6623    public void enableKeyguard(boolean enabled) {
6624        if (mKeyguardDelegate != null) {
6625            mKeyguardDelegate.setKeyguardEnabled(enabled);
6626        }
6627    }
6628
6629    /** {@inheritDoc} */
6630    @Override
6631    public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
6632        if (mKeyguardDelegate != null) {
6633            mKeyguardDelegate.verifyUnlock(callback);
6634        }
6635    }
6636
6637    @Override
6638    public boolean isKeyguardShowingAndNotOccluded() {
6639        if (mKeyguardDelegate == null) return false;
6640        return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
6641    }
6642
6643    /** {@inheritDoc} */
6644    @Override
6645    public boolean isKeyguardLocked() {
6646        return keyguardOn();
6647    }
6648
6649    /** {@inheritDoc} */
6650    @Override
6651    public boolean isKeyguardSecure(int userId) {
6652        if (mKeyguardDelegate == null) return false;
6653        return mKeyguardDelegate.isSecure(userId);
6654    }
6655
6656    /** {@inheritDoc} */
6657    @Override
6658    public boolean isKeyguardShowingOrOccluded() {
6659        return mKeyguardDelegate == null ? false : mKeyguardDelegate.isShowing();
6660    }
6661
6662    /** {@inheritDoc} */
6663    @Override
6664    public boolean inKeyguardRestrictedKeyInputMode() {
6665        if (mKeyguardDelegate == null) return false;
6666        return mKeyguardDelegate.isInputRestricted();
6667    }
6668
6669    @Override
6670    public void dismissKeyguardLw() {
6671        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
6672            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
6673            mHandler.post(new Runnable() {
6674                @Override
6675                public void run() {
6676                    // ask the keyguard to prompt the user to authenticate if necessary
6677                    mKeyguardDelegate.dismiss(false /* allowWhileOccluded */);
6678                }
6679            });
6680        }
6681    }
6682
6683    @Override
6684    public void notifyActivityDrawnForKeyguardLw() {
6685        if (mKeyguardDelegate != null) {
6686            mHandler.post(new Runnable() {
6687                @Override
6688                public void run() {
6689                    mKeyguardDelegate.onActivityDrawn();
6690                }
6691            });
6692        }
6693    }
6694
6695    @Override
6696    public boolean isKeyguardDrawnLw() {
6697        synchronized (mLock) {
6698            return mKeyguardDrawnOnce;
6699        }
6700    }
6701
6702    @Override
6703    public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
6704        if (mKeyguardDelegate != null) {
6705            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
6706            mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
6707        }
6708    }
6709
6710    @Override
6711    public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6712            Rect outInsets) {
6713        outInsets.setEmpty();
6714
6715        // Navigation bar and status bar.
6716        getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
6717        if (mStatusBar != null) {
6718            outInsets.top = mStatusBarHeight;
6719        }
6720    }
6721
6722    @Override
6723    public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6724            Rect outInsets) {
6725        outInsets.setEmpty();
6726
6727        // Only navigation bar
6728        if (mNavigationBar != null) {
6729            int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
6730            if (position == NAV_BAR_BOTTOM) {
6731                outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
6732            } else if (position == NAV_BAR_RIGHT) {
6733                outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
6734            } else if (position == NAV_BAR_LEFT) {
6735                outInsets.left = getNavigationBarWidth(displayRotation, mUiMode);
6736            }
6737        }
6738    }
6739
6740    @Override
6741    public boolean isNavBarForcedShownLw(WindowState windowState) {
6742        return mForceShowSystemBars;
6743    }
6744
6745    @Override
6746    public boolean isDockSideAllowed(int dockSide) {
6747
6748        // We do not allow all dock sides at which the navigation bar touches the docked stack.
6749        if (!mNavigationBarCanMove) {
6750            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT;
6751        } else {
6752            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT;
6753        }
6754    }
6755
6756    void sendCloseSystemWindows() {
6757        PhoneWindow.sendCloseSystemWindows(mContext, null);
6758    }
6759
6760    void sendCloseSystemWindows(String reason) {
6761        PhoneWindow.sendCloseSystemWindows(mContext, reason);
6762    }
6763
6764    @Override
6765    public int rotationForOrientationLw(int orientation, int lastRotation) {
6766        if (false) {
6767            Slog.v(TAG, "rotationForOrientationLw(orient="
6768                        + orientation + ", last=" + lastRotation
6769                        + "); user=" + mUserRotation + " "
6770                        + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
6771                            ? "USER_ROTATION_LOCKED" : "")
6772                        );
6773        }
6774
6775        if (mForceDefaultOrientation) {
6776            return Surface.ROTATION_0;
6777        }
6778
6779        synchronized (mLock) {
6780            int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
6781            if (sensorRotation < 0) {
6782                sensorRotation = lastRotation;
6783            }
6784
6785            final int preferredRotation;
6786            if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
6787                // Ignore sensor when lid switch is open and rotation is forced.
6788                preferredRotation = mLidOpenRotation;
6789            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
6790                    && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
6791                // Ignore sensor when in car dock unless explicitly enabled.
6792                // This case can override the behavior of NOSENSOR, and can also
6793                // enable 180 degree rotation while docked.
6794                preferredRotation = mCarDockEnablesAccelerometer
6795                        ? sensorRotation : mCarDockRotation;
6796            } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
6797                    || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
6798                    || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
6799                    && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
6800                // Ignore sensor when in desk dock unless explicitly enabled.
6801                // This case can override the behavior of NOSENSOR, and can also
6802                // enable 180 degree rotation while docked.
6803                preferredRotation = mDeskDockEnablesAccelerometer
6804                        ? sensorRotation : mDeskDockRotation;
6805            } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
6806                // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
6807                // Note that the dock orientation overrides the HDMI orientation.
6808                preferredRotation = mDemoHdmiRotation;
6809            } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
6810                    && mUndockedHdmiRotation >= 0) {
6811                // Ignore sensor when plugged into HDMI and an undocked orientation has
6812                // been specified in the configuration (only for legacy devices without
6813                // full multi-display support).
6814                // Note that the dock orientation overrides the HDMI orientation.
6815                preferredRotation = mUndockedHdmiRotation;
6816            } else if (mDemoRotationLock) {
6817                // Ignore sensor when demo rotation lock is enabled.
6818                // Note that the dock orientation and HDMI rotation lock override this.
6819                preferredRotation = mDemoRotation;
6820            } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
6821                // Application just wants to remain locked in the last rotation.
6822                preferredRotation = lastRotation;
6823            } else if (!mSupportAutoRotation) {
6824                // If we don't support auto-rotation then bail out here and ignore
6825                // the sensor and any rotation lock settings.
6826                preferredRotation = -1;
6827            } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
6828                            && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
6829                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
6830                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
6831                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
6832                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
6833                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
6834                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6835                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
6836                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
6837                // Otherwise, use sensor only if requested by the application or enabled
6838                // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
6839                if (mAllowAllRotations < 0) {
6840                    // Can't read this during init() because the context doesn't
6841                    // have display metrics at that time so we cannot determine
6842                    // tablet vs. phone then.
6843                    mAllowAllRotations = mContext.getResources().getBoolean(
6844                            com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
6845                }
6846                if (sensorRotation != Surface.ROTATION_180
6847                        || mAllowAllRotations == 1
6848                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6849                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
6850                    preferredRotation = sensorRotation;
6851                } else {
6852                    preferredRotation = lastRotation;
6853                }
6854            } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
6855                    && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
6856                // Apply rotation lock.  Does not apply to NOSENSOR.
6857                // The idea is that the user rotation expresses a weak preference for the direction
6858                // of gravity and as NOSENSOR is never affected by gravity, then neither should
6859                // NOSENSOR be affected by rotation lock (although it will be affected by docks).
6860                preferredRotation = mUserRotation;
6861            } else {
6862                // No overriding preference.
6863                // We will do exactly what the application asked us to do.
6864                preferredRotation = -1;
6865            }
6866
6867            switch (orientation) {
6868                case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6869                    // Return portrait unless overridden.
6870                    if (isAnyPortrait(preferredRotation)) {
6871                        return preferredRotation;
6872                    }
6873                    return mPortraitRotation;
6874
6875                case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6876                    // Return landscape unless overridden.
6877                    if (isLandscapeOrSeascape(preferredRotation)) {
6878                        return preferredRotation;
6879                    }
6880                    return mLandscapeRotation;
6881
6882                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6883                    // Return reverse portrait unless overridden.
6884                    if (isAnyPortrait(preferredRotation)) {
6885                        return preferredRotation;
6886                    }
6887                    return mUpsideDownRotation;
6888
6889                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6890                    // Return seascape unless overridden.
6891                    if (isLandscapeOrSeascape(preferredRotation)) {
6892                        return preferredRotation;
6893                    }
6894                    return mSeascapeRotation;
6895
6896                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6897                case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
6898                    // Return either landscape rotation.
6899                    if (isLandscapeOrSeascape(preferredRotation)) {
6900                        return preferredRotation;
6901                    }
6902                    if (isLandscapeOrSeascape(lastRotation)) {
6903                        return lastRotation;
6904                    }
6905                    return mLandscapeRotation;
6906
6907                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6908                case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
6909                    // Return either portrait rotation.
6910                    if (isAnyPortrait(preferredRotation)) {
6911                        return preferredRotation;
6912                    }
6913                    if (isAnyPortrait(lastRotation)) {
6914                        return lastRotation;
6915                    }
6916                    return mPortraitRotation;
6917
6918                default:
6919                    // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
6920                    // just return the preferred orientation we already calculated.
6921                    if (preferredRotation >= 0) {
6922                        return preferredRotation;
6923                    }
6924                    return Surface.ROTATION_0;
6925            }
6926        }
6927    }
6928
6929    @Override
6930    public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
6931        switch (orientation) {
6932            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6933            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6934            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6935                return isAnyPortrait(rotation);
6936
6937            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6938            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6939            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6940                return isLandscapeOrSeascape(rotation);
6941
6942            default:
6943                return true;
6944        }
6945    }
6946
6947    @Override
6948    public void setRotationLw(int rotation) {
6949        mOrientationListener.setCurrentRotation(rotation);
6950    }
6951
6952    private boolean isLandscapeOrSeascape(int rotation) {
6953        return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
6954    }
6955
6956    private boolean isAnyPortrait(int rotation) {
6957        return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
6958    }
6959
6960    @Override
6961    public int getUserRotationMode() {
6962        return Settings.System.getIntForUser(mContext.getContentResolver(),
6963                Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
6964                        WindowManagerPolicy.USER_ROTATION_FREE :
6965                                WindowManagerPolicy.USER_ROTATION_LOCKED;
6966    }
6967
6968    // User rotation: to be used when all else fails in assigning an orientation to the device
6969    @Override
6970    public void setUserRotationMode(int mode, int rot) {
6971        ContentResolver res = mContext.getContentResolver();
6972
6973        // mUserRotationMode and mUserRotation will be assigned by the content observer
6974        if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
6975            Settings.System.putIntForUser(res,
6976                    Settings.System.USER_ROTATION,
6977                    rot,
6978                    UserHandle.USER_CURRENT);
6979            Settings.System.putIntForUser(res,
6980                    Settings.System.ACCELEROMETER_ROTATION,
6981                    0,
6982                    UserHandle.USER_CURRENT);
6983        } else {
6984            Settings.System.putIntForUser(res,
6985                    Settings.System.ACCELEROMETER_ROTATION,
6986                    1,
6987                    UserHandle.USER_CURRENT);
6988        }
6989    }
6990
6991    @Override
6992    public void setSafeMode(boolean safeMode) {
6993        mSafeMode = safeMode;
6994        performHapticFeedbackLw(null, safeMode
6995                ? HapticFeedbackConstants.SAFE_MODE_ENABLED
6996                : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
6997    }
6998
6999    static long[] getLongIntArray(Resources r, int resid) {
7000        int[] ar = r.getIntArray(resid);
7001        if (ar == null) {
7002            return null;
7003        }
7004        long[] out = new long[ar.length];
7005        for (int i=0; i<ar.length; i++) {
7006            out[i] = ar[i];
7007        }
7008        return out;
7009    }
7010
7011    /** {@inheritDoc} */
7012    @Override
7013    public void systemReady() {
7014        mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
7015        mKeyguardDelegate.onSystemReady();
7016
7017        readCameraLensCoverState();
7018        updateUiMode();
7019        boolean bindKeyguardNow;
7020        synchronized (mLock) {
7021            updateOrientationListenerLp();
7022            mSystemReady = true;
7023            mHandler.post(new Runnable() {
7024                @Override
7025                public void run() {
7026                    updateSettings();
7027                }
7028            });
7029
7030            bindKeyguardNow = mDeferBindKeyguard;
7031            if (bindKeyguardNow) {
7032                // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now.
7033                mDeferBindKeyguard = false;
7034            }
7035        }
7036
7037        if (bindKeyguardNow) {
7038            mKeyguardDelegate.bindService(mContext);
7039            mKeyguardDelegate.onBootCompleted();
7040        }
7041        mSystemGestures.systemReady();
7042        mImmersiveModeConfirmation.systemReady();
7043    }
7044
7045    /** {@inheritDoc} */
7046    @Override
7047    public void systemBooted() {
7048        boolean bindKeyguardNow = false;
7049        synchronized (mLock) {
7050            // Time to bind Keyguard; take care to only bind it once, either here if ready or
7051            // in systemReady if not.
7052            if (mKeyguardDelegate != null) {
7053                bindKeyguardNow = true;
7054            } else {
7055                // Because mKeyguardDelegate is null, we know that the synchronized block in
7056                // systemReady didn't run yet and setting this will actually have an effect.
7057                mDeferBindKeyguard = true;
7058            }
7059        }
7060        if (bindKeyguardNow) {
7061            mKeyguardDelegate.bindService(mContext);
7062            mKeyguardDelegate.onBootCompleted();
7063        }
7064        synchronized (mLock) {
7065            mSystemBooted = true;
7066        }
7067        startedWakingUp();
7068        screenTurningOn(null);
7069        screenTurnedOn();
7070    }
7071
7072    ProgressDialog mBootMsgDialog = null;
7073
7074    /** {@inheritDoc} */
7075    @Override
7076    public void showBootMessage(final CharSequence msg, final boolean always) {
7077        mHandler.post(new Runnable() {
7078            @Override public void run() {
7079                if (mBootMsgDialog == null) {
7080                    int theme;
7081                    if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) {
7082                        theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
7083                    } else {
7084                        theme = 0;
7085                    }
7086
7087                    mBootMsgDialog = new ProgressDialog(mContext, theme) {
7088                        // This dialog will consume all events coming in to
7089                        // it, to avoid it trying to do things too early in boot.
7090                        @Override public boolean dispatchKeyEvent(KeyEvent event) {
7091                            return true;
7092                        }
7093                        @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7094                            return true;
7095                        }
7096                        @Override public boolean dispatchTouchEvent(MotionEvent ev) {
7097                            return true;
7098                        }
7099                        @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
7100                            return true;
7101                        }
7102                        @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
7103                            return true;
7104                        }
7105                        @Override public boolean dispatchPopulateAccessibilityEvent(
7106                                AccessibilityEvent event) {
7107                            return true;
7108                        }
7109                    };
7110                    if (mContext.getPackageManager().isUpgrade()) {
7111                        mBootMsgDialog.setTitle(R.string.android_upgrading_title);
7112                    } else {
7113                        mBootMsgDialog.setTitle(R.string.android_start_title);
7114                    }
7115                    mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
7116                    mBootMsgDialog.setIndeterminate(true);
7117                    mBootMsgDialog.getWindow().setType(
7118                            WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
7119                    mBootMsgDialog.getWindow().addFlags(
7120                            WindowManager.LayoutParams.FLAG_DIM_BEHIND
7121                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
7122                    mBootMsgDialog.getWindow().setDimAmount(1);
7123                    WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
7124                    lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
7125                    mBootMsgDialog.getWindow().setAttributes(lp);
7126                    mBootMsgDialog.setCancelable(false);
7127                    mBootMsgDialog.show();
7128                }
7129                mBootMsgDialog.setMessage(msg);
7130            }
7131        });
7132    }
7133
7134    /** {@inheritDoc} */
7135    @Override
7136    public void hideBootMessages() {
7137        mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
7138    }
7139
7140    /** {@inheritDoc} */
7141    @Override
7142    public void userActivity() {
7143        // ***************************************
7144        // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
7145        // ***************************************
7146        // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
7147        // WITH ITS LOCKS HELD.
7148        //
7149        // This code must be VERY careful about the locks
7150        // it acquires.
7151        // In fact, the current code acquires way too many,
7152        // and probably has lurking deadlocks.
7153
7154        synchronized (mScreenLockTimeout) {
7155            if (mLockScreenTimerActive) {
7156                // reset the timer
7157                mHandler.removeCallbacks(mScreenLockTimeout);
7158                mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7159            }
7160        }
7161    }
7162
7163    class ScreenLockTimeout implements Runnable {
7164        Bundle options;
7165
7166        @Override
7167        public void run() {
7168            synchronized (this) {
7169                if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
7170                if (mKeyguardDelegate != null) {
7171                    mKeyguardDelegate.doKeyguardTimeout(options);
7172                }
7173                mLockScreenTimerActive = false;
7174                options = null;
7175            }
7176        }
7177
7178        public void setLockOptions(Bundle options) {
7179            this.options = options;
7180        }
7181    }
7182
7183    ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
7184
7185    @Override
7186    public void lockNow(Bundle options) {
7187        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
7188        mHandler.removeCallbacks(mScreenLockTimeout);
7189        if (options != null) {
7190            // In case multiple calls are made to lockNow, we don't wipe out the options
7191            // until the runnable actually executes.
7192            mScreenLockTimeout.setLockOptions(options);
7193        }
7194        mHandler.post(mScreenLockTimeout);
7195    }
7196
7197    private void updateLockScreenTimeout() {
7198        synchronized (mScreenLockTimeout) {
7199            boolean enable = (mAllowLockscreenWhenOn && mAwake &&
7200                    mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
7201            if (mLockScreenTimerActive != enable) {
7202                if (enable) {
7203                    if (localLOGV) Log.v(TAG, "setting lockscreen timer");
7204                    mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
7205                    mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7206                } else {
7207                    if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
7208                    mHandler.removeCallbacks(mScreenLockTimeout);
7209                }
7210                mLockScreenTimerActive = enable;
7211            }
7212        }
7213    }
7214
7215    private void updateDreamingSleepToken(boolean acquire) {
7216        if (acquire) {
7217            if (mDreamingSleepToken == null) {
7218                mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream");
7219            }
7220        } else {
7221            if (mDreamingSleepToken != null) {
7222                mDreamingSleepToken.release();
7223                mDreamingSleepToken = null;
7224            }
7225        }
7226    }
7227
7228    private void updateScreenOffSleepToken(boolean acquire) {
7229        if (acquire) {
7230            if (mScreenOffSleepToken == null) {
7231                mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff");
7232            }
7233        } else {
7234            if (mScreenOffSleepToken != null) {
7235                mScreenOffSleepToken.release();
7236                mScreenOffSleepToken = null;
7237            }
7238        }
7239    }
7240
7241    /** {@inheritDoc} */
7242    @Override
7243    public void enableScreenAfterBoot() {
7244        readLidState();
7245        applyLidSwitchState();
7246        updateRotation(true);
7247    }
7248
7249    private void applyLidSwitchState() {
7250        if (mLidState == LID_CLOSED && mLidControlsSleep) {
7251            mPowerManager.goToSleep(SystemClock.uptimeMillis(),
7252                    PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
7253                    PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
7254        } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
7255            mWindowManagerFuncs.lockDeviceNow();
7256        }
7257
7258        synchronized (mLock) {
7259            updateWakeGestureListenerLp();
7260        }
7261    }
7262
7263    void updateUiMode() {
7264        if (mUiModeManager == null) {
7265            mUiModeManager = IUiModeManager.Stub.asInterface(
7266                    ServiceManager.getService(Context.UI_MODE_SERVICE));
7267        }
7268        try {
7269            mUiMode = mUiModeManager.getCurrentModeType();
7270        } catch (RemoteException e) {
7271        }
7272    }
7273
7274    void updateRotation(boolean alwaysSendConfiguration) {
7275        try {
7276            //set orientation on WindowManager
7277            mWindowManager.updateRotation(alwaysSendConfiguration, false);
7278        } catch (RemoteException e) {
7279            // Ignore
7280        }
7281    }
7282
7283    void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
7284        try {
7285            //set orientation on WindowManager
7286            mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
7287        } catch (RemoteException e) {
7288            // Ignore
7289        }
7290    }
7291
7292    /**
7293     * Return an Intent to launch the currently active dock app as home.  Returns
7294     * null if the standard home should be launched, which is the case if any of the following is
7295     * true:
7296     * <ul>
7297     *  <li>The device is not in either car mode or desk mode
7298     *  <li>The device is in car mode but mEnableCarDockHomeCapture is false
7299     *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
7300     *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
7301     *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
7302     * </ul>
7303     * @return A dock intent.
7304     */
7305    Intent createHomeDockIntent() {
7306        Intent intent = null;
7307
7308        // What home does is based on the mode, not the dock state.  That
7309        // is, when in car mode you should be taken to car home regardless
7310        // of whether we are actually in a car dock.
7311        if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
7312            if (mEnableCarDockHomeCapture) {
7313                intent = mCarDockIntent;
7314            }
7315        } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
7316            if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
7317                intent = mDeskDockIntent;
7318            }
7319        } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
7320                && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7321                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
7322                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
7323            // Always launch dock home from home when watch is docked, if it exists.
7324            intent = mDeskDockIntent;
7325        }
7326
7327        if (intent == null) {
7328            return null;
7329        }
7330
7331        ActivityInfo ai = null;
7332        ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
7333                intent,
7334                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
7335                mCurrentUserId);
7336        if (info != null) {
7337            ai = info.activityInfo;
7338        }
7339        if (ai != null
7340                && ai.metaData != null
7341                && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
7342            intent = new Intent(intent);
7343            intent.setClassName(ai.packageName, ai.name);
7344            return intent;
7345        }
7346
7347        return null;
7348    }
7349
7350    void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
7351        if (awakenFromDreams) {
7352            awakenDreams();
7353        }
7354
7355        Intent dock = createHomeDockIntent();
7356        if (dock != null) {
7357            try {
7358                if (fromHomeKey) {
7359                    dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7360                }
7361                startActivityAsUser(dock, UserHandle.CURRENT);
7362                return;
7363            } catch (ActivityNotFoundException e) {
7364            }
7365        }
7366
7367        Intent intent;
7368
7369        if (fromHomeKey) {
7370            intent = new Intent(mHomeIntent);
7371            intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7372        } else {
7373            intent = mHomeIntent;
7374        }
7375
7376        startActivityAsUser(intent, UserHandle.CURRENT);
7377    }
7378
7379    /**
7380     * goes to the home screen
7381     * @return whether it did anything
7382     */
7383    boolean goHome() {
7384        if (!isUserSetupComplete()) {
7385            Slog.i(TAG, "Not going home because user setup is in progress.");
7386            return false;
7387        }
7388        if (false) {
7389            // This code always brings home to the front.
7390            try {
7391                ActivityManagerNative.getDefault().stopAppSwitches();
7392            } catch (RemoteException e) {
7393            }
7394            sendCloseSystemWindows();
7395            startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
7396        } else {
7397            // This code brings home to the front or, if it is already
7398            // at the front, puts the device to sleep.
7399            try {
7400                if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
7401                    /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
7402                    Log.d(TAG, "UTS-TEST-MODE");
7403                } else {
7404                    ActivityManagerNative.getDefault().stopAppSwitches();
7405                    sendCloseSystemWindows();
7406                    Intent dock = createHomeDockIntent();
7407                    if (dock != null) {
7408                        int result = ActivityManagerNative.getDefault()
7409                                .startActivityAsUser(null, null, dock,
7410                                        dock.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                    }
7418                }
7419                int result = ActivityManagerNative.getDefault()
7420                        .startActivityAsUser(null, null, mHomeIntent,
7421                                mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
7422                                null, null, 0,
7423                                ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7424                                null, null, UserHandle.USER_CURRENT);
7425                if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7426                    return false;
7427                }
7428            } catch (RemoteException ex) {
7429                // bummer, the activity manager, which is in this process, is dead
7430            }
7431        }
7432        return true;
7433    }
7434
7435    @Override
7436    public void setCurrentOrientationLw(int newOrientation) {
7437        synchronized (mLock) {
7438            if (newOrientation != mCurrentAppOrientation) {
7439                mCurrentAppOrientation = newOrientation;
7440                updateOrientationListenerLp();
7441            }
7442        }
7443    }
7444
7445    private void performAuditoryFeedbackForAccessibilityIfNeed() {
7446        if (!isGlobalAccessibilityGestureEnabled()) {
7447            return;
7448        }
7449        AudioManager audioManager = (AudioManager) mContext.getSystemService(
7450                Context.AUDIO_SERVICE);
7451        if (audioManager.isSilentMode()) {
7452            return;
7453        }
7454        Ringtone ringTone = RingtoneManager.getRingtone(mContext,
7455                Settings.System.DEFAULT_NOTIFICATION_URI);
7456        ringTone.setStreamType(AudioManager.STREAM_MUSIC);
7457        ringTone.play();
7458    }
7459
7460    private boolean isTheaterModeEnabled() {
7461        return Settings.Global.getInt(mContext.getContentResolver(),
7462                Settings.Global.THEATER_MODE_ON, 0) == 1;
7463    }
7464
7465    private boolean isGlobalAccessibilityGestureEnabled() {
7466        return Settings.Global.getInt(mContext.getContentResolver(),
7467                Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1;
7468    }
7469
7470    private boolean areSystemNavigationKeysEnabled() {
7471        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
7472                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
7473    }
7474
7475    @Override
7476    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
7477        if (!mVibrator.hasVibrator()) {
7478            return false;
7479        }
7480        final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
7481                Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
7482        if (hapticsDisabled && !always) {
7483            return false;
7484        }
7485        long[] pattern = null;
7486        switch (effectId) {
7487            case HapticFeedbackConstants.LONG_PRESS:
7488                pattern = mLongPressVibePattern;
7489                break;
7490            case HapticFeedbackConstants.VIRTUAL_KEY:
7491                pattern = mVirtualKeyVibePattern;
7492                break;
7493            case HapticFeedbackConstants.KEYBOARD_TAP:
7494                pattern = mKeyboardTapVibePattern;
7495                break;
7496            case HapticFeedbackConstants.CLOCK_TICK:
7497                pattern = mClockTickVibePattern;
7498                break;
7499            case HapticFeedbackConstants.CALENDAR_DATE:
7500                pattern = mCalendarDateVibePattern;
7501                break;
7502            case HapticFeedbackConstants.SAFE_MODE_DISABLED:
7503                pattern = mSafeModeDisabledVibePattern;
7504                break;
7505            case HapticFeedbackConstants.SAFE_MODE_ENABLED:
7506                pattern = mSafeModeEnabledVibePattern;
7507                break;
7508            case HapticFeedbackConstants.CONTEXT_CLICK:
7509                pattern = mContextClickVibePattern;
7510                break;
7511            default:
7512                return false;
7513        }
7514        int owningUid;
7515        String owningPackage;
7516        if (win != null) {
7517            owningUid = win.getOwningUid();
7518            owningPackage = win.getOwningPackage();
7519        } else {
7520            owningUid = android.os.Process.myUid();
7521            owningPackage = mContext.getOpPackageName();
7522        }
7523        if (pattern.length == 1) {
7524            // One-shot vibration
7525            mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES);
7526        } else {
7527            // Pattern vibration
7528            mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES);
7529        }
7530        return true;
7531    }
7532
7533    @Override
7534    public void keepScreenOnStartedLw() {
7535    }
7536
7537    @Override
7538    public void keepScreenOnStoppedLw() {
7539        if (isKeyguardShowingAndNotOccluded()) {
7540            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
7541        }
7542    }
7543
7544    private int updateSystemUiVisibilityLw() {
7545        // If there is no window focused, there will be nobody to handle the events
7546        // anyway, so just hang on in whatever state we're in until things settle down.
7547        WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
7548                : mTopFullscreenOpaqueWindowState;
7549        if (winCandidate == null) {
7550            return 0;
7551        }
7552        if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
7553            // The immersive mode confirmation should never affect the system bar visibility,
7554            // otherwise it will unhide the navigation bar and hide itself.
7555            winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState;
7556            if (winCandidate == null) {
7557                return 0;
7558            }
7559        }
7560        final WindowState win = winCandidate;
7561        if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) {
7562            // We are updating at a point where the keyguard has gotten
7563            // focus, but we were last in a state where the top window is
7564            // hiding it.  This is probably because the keyguard as been
7565            // shown while the top window was displayed, so we want to ignore
7566            // it here because this is just a very transient change and it
7567            // will quickly lose focus once it correctly gets hidden.
7568            return 0;
7569        }
7570
7571        int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
7572                & ~mResettingSystemUiFlags
7573                & ~mForceClearedSystemUiFlags;
7574        if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
7575            tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
7576        }
7577
7578        final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
7579                mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
7580        final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
7581                mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
7582        mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);
7583        mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);
7584        final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
7585        final int diff = visibility ^ mLastSystemUiFlags;
7586        final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
7587        final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
7588        final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
7589        if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
7590                && mFocusedApp == win.getAppToken()
7591                && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
7592                && mLastDockedStackBounds.equals(mDockedStackBounds)) {
7593            return 0;
7594        }
7595        mLastSystemUiFlags = visibility;
7596        mLastFullscreenStackSysUiFlags = fullscreenVisibility;
7597        mLastDockedStackSysUiFlags = dockedVisibility;
7598        mLastFocusNeedsMenu = needsMenu;
7599        mFocusedApp = win.getAppToken();
7600        final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
7601        final Rect dockedStackBounds = new Rect(mDockedStackBounds);
7602        mHandler.post(new Runnable() {
7603                @Override
7604                public void run() {
7605                    StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
7606                    if (statusbar != null) {
7607                        statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
7608                                dockedVisibility, 0xffffffff, fullscreenStackBounds,
7609                                dockedStackBounds, win.toString());
7610                        statusbar.topAppWindowChanged(needsMenu);
7611                    }
7612                }
7613            });
7614        return diff;
7615    }
7616
7617    private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
7618        WindowState statusColorWin = isStatusBarKeyguard() && !mHideLockScreen
7619                ? mStatusBar
7620                : opaqueOrDimming;
7621
7622        if (statusColorWin != null) {
7623            if (statusColorWin == opaque) {
7624                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7625                // its light flag.
7626                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7627                vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
7628                        & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7629            } else if (statusColorWin != null && statusColorWin.isDimming()) {
7630                // Otherwise if it's dimming, clear the light flag.
7631                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7632            }
7633        }
7634        return vis;
7635    }
7636
7637    private boolean drawsSystemBarBackground(WindowState win) {
7638        return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
7639    }
7640
7641    private boolean forcesDrawStatusBarBackground(WindowState win) {
7642        return win == null || (win.getAttrs().privateFlags
7643                & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
7644    }
7645
7646    private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
7647        final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
7648        final boolean freeformStackVisible =
7649                mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
7650        final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
7651
7652        // We need to force system bars when the docked stack is visible, when the freeform stack
7653        // is visible but also when we are resizing for the transitions when docked stack
7654        // visibility changes.
7655        mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
7656        final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
7657
7658        // apply translucent bar vis flags
7659        WindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen
7660                ? mStatusBar
7661                : mTopFullscreenOpaqueWindowState;
7662        vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7663        vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7664        final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
7665                mTopDockedOpaqueWindowState, 0, 0);
7666
7667        final boolean fullscreenDrawsStatusBarBackground =
7668                (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
7669                        && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
7670                || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
7671        final boolean dockedDrawsStatusBarBackground =
7672                (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
7673                        && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
7674                || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
7675
7676        // prevent status bar interaction from clearing certain flags
7677        int type = win.getAttrs().type;
7678        boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
7679        if (statusBarHasFocus && !isStatusBarKeyguard()) {
7680            int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
7681                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
7682                    | View.SYSTEM_UI_FLAG_IMMERSIVE
7683                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
7684                    | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7685            if (mHideLockScreen) {
7686                flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
7687            }
7688            vis = (vis & ~flags) | (oldVis & flags);
7689        }
7690
7691        if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
7692            vis |= View.STATUS_BAR_TRANSPARENT;
7693            vis &= ~View.STATUS_BAR_TRANSLUCENT;
7694        } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
7695                || forceOpaqueStatusBar) {
7696            vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
7697        }
7698
7699        vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
7700
7701        // update status bar
7702        boolean immersiveSticky =
7703                (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7704        final boolean hideStatusBarWM =
7705                mTopFullscreenOpaqueWindowState != null
7706                && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
7707                        & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
7708        final boolean hideStatusBarSysui =
7709                (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
7710        final boolean hideNavBarSysui =
7711                (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
7712
7713        final boolean transientStatusBarAllowed = mStatusBar != null
7714                && (statusBarHasFocus || (!mForceShowSystemBars
7715                        && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
7716
7717        final boolean transientNavBarAllowed = mNavigationBar != null
7718                && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
7719
7720        final long now = SystemClock.uptimeMillis();
7721        final boolean pendingPanic = mPendingPanicGestureUptime != 0
7722                && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
7723        if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
7724            // The user performed the panic gesture recently, we're about to hide the bars,
7725            // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
7726            mPendingPanicGestureUptime = 0;
7727            mStatusBarController.showTransient();
7728            if (!isNavBarEmpty(vis)) {
7729                mNavigationBarController.showTransient();
7730            }
7731        }
7732
7733        final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
7734                && !transientStatusBarAllowed && hideStatusBarSysui;
7735        final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
7736                && !transientNavBarAllowed;
7737        if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
7738            // clear the clearable flags instead
7739            clearClearableFlagsLw();
7740            vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
7741        }
7742
7743        final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
7744        immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7745        final boolean navAllowedHidden = immersive || immersiveSticky;
7746
7747        if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType())
7748                > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) {
7749            // We can't hide the navbar from this window otherwise the input consumer would not get
7750            // the input events.
7751            vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
7752        }
7753
7754        vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
7755
7756        // update navigation bar
7757        boolean oldImmersiveMode = isImmersiveMode(oldVis);
7758        boolean newImmersiveMode = isImmersiveMode(vis);
7759        if (win != null && oldImmersiveMode != newImmersiveMode) {
7760            final String pkg = win.getOwningPackage();
7761            mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
7762                    isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility()));
7763        }
7764
7765        vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
7766
7767        return vis;
7768    }
7769
7770    /**
7771     * @return the current visibility flags with the nav-bar opacity related flags toggled based
7772     *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
7773     */
7774    private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
7775            boolean freeformStackVisible, boolean isDockedDividerResizing) {
7776        if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
7777            if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
7778                visibility = setNavBarOpaqueFlag(visibility);
7779            }
7780        } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
7781            if (isDockedDividerResizing) {
7782                visibility = setNavBarOpaqueFlag(visibility);
7783            } else if (freeformStackVisible) {
7784                visibility = setNavBarTranslucentFlag(visibility);
7785            } else {
7786                visibility = setNavBarOpaqueFlag(visibility);
7787            }
7788        }
7789
7790        if (!areTranslucentBarsAllowed()) {
7791            visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
7792        }
7793        return visibility;
7794    }
7795
7796    private int setNavBarOpaqueFlag(int visibility) {
7797        return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
7798    }
7799
7800    private int setNavBarTranslucentFlag(int visibility) {
7801        visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
7802        return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
7803    }
7804
7805    private void clearClearableFlagsLw() {
7806        int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
7807        if (newVal != mResettingSystemUiFlags) {
7808            mResettingSystemUiFlags = newVal;
7809            mWindowManagerFuncs.reevaluateStatusBarVisibility();
7810        }
7811    }
7812
7813    private boolean isImmersiveMode(int vis) {
7814        final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
7815        return mNavigationBar != null
7816                && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
7817                && (vis & flags) != 0
7818                && canHideNavigationBar();
7819    }
7820
7821    private static boolean isNavBarEmpty(int systemUiFlags) {
7822        final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
7823                | View.STATUS_BAR_DISABLE_BACK
7824                | View.STATUS_BAR_DISABLE_RECENT);
7825
7826        return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
7827    }
7828
7829    /**
7830     * @return whether the navigation or status bar can be made translucent
7831     *
7832     * This should return true unless touch exploration is not enabled or
7833     * R.boolean.config_enableTranslucentDecor is false.
7834     */
7835    private boolean areTranslucentBarsAllowed() {
7836        return mTranslucentDecorEnabled;
7837    }
7838
7839    // Use this instead of checking config_showNavigationBar so that it can be consistently
7840    // overridden by qemu.hw.mainkeys in the emulator.
7841    @Override
7842    public boolean hasNavigationBar() {
7843        return mHasNavigationBar;
7844    }
7845
7846    @Override
7847    public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
7848        mLastInputMethodWindow = ime;
7849        mLastInputMethodTargetWindow = target;
7850    }
7851
7852    @Override
7853    public int getInputMethodWindowVisibleHeightLw() {
7854        return mDockBottom - mCurBottom;
7855    }
7856
7857    @Override
7858    public void setCurrentUserLw(int newUserId) {
7859        mCurrentUserId = newUserId;
7860        if (mKeyguardDelegate != null) {
7861            mKeyguardDelegate.setCurrentUser(newUserId);
7862        }
7863        StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
7864        if (statusBar != null) {
7865            statusBar.setCurrentUser(newUserId);
7866        }
7867        setLastInputMethodWindowLw(null, null);
7868    }
7869
7870    @Override
7871    public void setSwitchingUser(boolean switching) {
7872        mKeyguardDelegate.setSwitchingUser(switching);
7873    }
7874
7875    @Override
7876    public boolean canMagnifyWindow(int windowType) {
7877        switch (windowType) {
7878            case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
7879            case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
7880            case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
7881            case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
7882                return false;
7883            }
7884        }
7885        return true;
7886    }
7887
7888    @Override
7889    public boolean isTopLevelWindow(int windowType) {
7890        if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
7891                && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
7892            return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
7893        }
7894        return true;
7895    }
7896
7897    @Override
7898    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
7899        // For the upside down rotation we don't rotate seamlessly as the navigation
7900        // bar moves position.
7901        // Note most apps (using orientation:sensor or user as opposed to fullSensor)
7902        // will not enter the reverse portrait orientation, so actually the
7903        // orientation won't change at all.
7904        if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
7905            return false;
7906        }
7907        int delta = newRotation - oldRotation;
7908        if (delta < 0) delta += 4;
7909        // Likewise we don't rotate seamlessly for 180 degree rotations
7910        // in this case the surfaces never resize, and our logic to
7911        // revert the transformations on size change will fail. We could
7912        // fix this in the future with the "tagged" frames idea.
7913        if (delta == Surface.ROTATION_180) {
7914            return false;
7915        }
7916
7917        final WindowState w = mTopFullscreenOpaqueWindowState;
7918        if (w != mFocusedWindow) {
7919            return false;
7920        }
7921
7922        // We only enable seamless rotation if the top window has requested
7923        // it and is in the fullscreen opaque state. Seamless rotation
7924        // requires freezing various Surface states and won't work well
7925        // with animations, so we disable it in the animation case for now.
7926        if (w != null && !w.isAnimatingLw() &&
7927                ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) ||
7928                        (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) {
7929            return true;
7930        }
7931        return false;
7932    }
7933
7934    @Override
7935    public void dump(String prefix, PrintWriter pw, String[] args) {
7936        pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
7937                pw.print(" mSystemReady="); pw.print(mSystemReady);
7938                pw.print(" mSystemBooted="); pw.println(mSystemBooted);
7939        pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
7940                pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
7941                pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
7942                pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
7943        if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
7944                || mForceClearedSystemUiFlags != 0) {
7945            pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
7946                    pw.print(Integer.toHexString(mLastSystemUiFlags));
7947                    pw.print(" mResettingSystemUiFlags=0x");
7948                    pw.print(Integer.toHexString(mResettingSystemUiFlags));
7949                    pw.print(" mForceClearedSystemUiFlags=0x");
7950                    pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
7951        }
7952        if (mLastFocusNeedsMenu) {
7953            pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
7954                    pw.println(mLastFocusNeedsMenu);
7955        }
7956        pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
7957                pw.println(mWakeGestureEnabledSetting);
7958
7959        pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
7960        pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
7961                pw.print(" mDockMode="); pw.print(mDockMode);
7962                pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
7963                pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
7964                pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
7965        pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
7966                pw.print(" mUserRotation="); pw.print(mUserRotation);
7967                pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
7968        pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
7969        pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
7970                pw.print(mCarDockEnablesAccelerometer);
7971                pw.print(" mDeskDockEnablesAccelerometer=");
7972                pw.println(mDeskDockEnablesAccelerometer);
7973        pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
7974                pw.print(mLidKeyboardAccessibility);
7975                pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
7976                pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
7977                pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
7978        pw.print(prefix);
7979                pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
7980        pw.print(prefix);
7981                pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
7982                pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
7983        pw.print(prefix);
7984                pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
7985                pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
7986        pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
7987        pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
7988        pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
7989                pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
7990        pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
7991                pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
7992        pw.print(prefix); pw.print("mOrientationSensorEnabled=");
7993                pw.println(mOrientationSensorEnabled);
7994        pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
7995                pw.print(","); pw.print(mOverscanScreenTop);
7996                pw.print(") "); pw.print(mOverscanScreenWidth);
7997                pw.print("x"); pw.println(mOverscanScreenHeight);
7998        if (mOverscanLeft != 0 || mOverscanTop != 0
7999                || mOverscanRight != 0 || mOverscanBottom != 0) {
8000            pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
8001                    pw.print(" top="); pw.print(mOverscanTop);
8002                    pw.print(" right="); pw.print(mOverscanRight);
8003                    pw.print(" bottom="); pw.println(mOverscanBottom);
8004        }
8005        pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
8006                pw.print(mRestrictedOverscanScreenLeft);
8007                pw.print(","); pw.print(mRestrictedOverscanScreenTop);
8008                pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
8009                pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
8010        pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
8011                pw.print(","); pw.print(mUnrestrictedScreenTop);
8012                pw.print(") "); pw.print(mUnrestrictedScreenWidth);
8013                pw.print("x"); pw.println(mUnrestrictedScreenHeight);
8014        pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
8015                pw.print(","); pw.print(mRestrictedScreenTop);
8016                pw.print(") "); pw.print(mRestrictedScreenWidth);
8017                pw.print("x"); pw.println(mRestrictedScreenHeight);
8018        pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
8019                pw.print(","); pw.print(mStableFullscreenTop);
8020                pw.print(")-("); pw.print(mStableFullscreenRight);
8021                pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
8022        pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
8023                pw.print(","); pw.print(mStableTop);
8024                pw.print(")-("); pw.print(mStableRight);
8025                pw.print(","); pw.print(mStableBottom); pw.println(")");
8026        pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
8027                pw.print(","); pw.print(mSystemTop);
8028                pw.print(")-("); pw.print(mSystemRight);
8029                pw.print(","); pw.print(mSystemBottom); pw.println(")");
8030        pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
8031                pw.print(","); pw.print(mCurTop);
8032                pw.print(")-("); pw.print(mCurRight);
8033                pw.print(","); pw.print(mCurBottom); pw.println(")");
8034        pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
8035                pw.print(","); pw.print(mContentTop);
8036                pw.print(")-("); pw.print(mContentRight);
8037                pw.print(","); pw.print(mContentBottom); pw.println(")");
8038        pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft);
8039                pw.print(","); pw.print(mVoiceContentTop);
8040                pw.print(")-("); pw.print(mVoiceContentRight);
8041                pw.print(","); pw.print(mVoiceContentBottom); pw.println(")");
8042        pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
8043                pw.print(","); pw.print(mDockTop);
8044                pw.print(")-("); pw.print(mDockRight);
8045                pw.print(","); pw.print(mDockBottom); pw.println(")");
8046        pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
8047                pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
8048        pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen);
8049                pw.print(" mShowingDream="); pw.print(mShowingDream);
8050                pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
8051                pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
8052        if (mLastInputMethodWindow != null) {
8053            pw.print(prefix); pw.print("mLastInputMethodWindow=");
8054                    pw.println(mLastInputMethodWindow);
8055        }
8056        if (mLastInputMethodTargetWindow != null) {
8057            pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
8058                    pw.println(mLastInputMethodTargetWindow);
8059        }
8060        if (mStatusBar != null) {
8061            pw.print(prefix); pw.print("mStatusBar=");
8062                    pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
8063                    pw.println(isStatusBarKeyguard());
8064        }
8065        if (mNavigationBar != null) {
8066            pw.print(prefix); pw.print("mNavigationBar=");
8067                    pw.println(mNavigationBar);
8068        }
8069        if (mFocusedWindow != null) {
8070            pw.print(prefix); pw.print("mFocusedWindow=");
8071                    pw.println(mFocusedWindow);
8072        }
8073        if (mFocusedApp != null) {
8074            pw.print(prefix); pw.print("mFocusedApp=");
8075                    pw.println(mFocusedApp);
8076        }
8077        if (mWinDismissingKeyguard != null) {
8078            pw.print(prefix); pw.print("mWinDismissingKeyguard=");
8079                    pw.println(mWinDismissingKeyguard);
8080        }
8081        if (mTopFullscreenOpaqueWindowState != null) {
8082            pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
8083                    pw.println(mTopFullscreenOpaqueWindowState);
8084        }
8085        if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
8086            pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
8087                    pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
8088        }
8089        if (mForcingShowNavBar) {
8090            pw.print(prefix); pw.print("mForcingShowNavBar=");
8091                    pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
8092                    pw.println(mForcingShowNavBarLayer);
8093        }
8094        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
8095                pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
8096        pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
8097                pw.print(" mForceStatusBarFromKeyguard=");
8098                pw.println(mForceStatusBarFromKeyguard);
8099        pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
8100                pw.print(" mWinDismissingKeyguard="); pw.print(mWinDismissingKeyguard);
8101                pw.print(" mHomePressed="); pw.println(mHomePressed);
8102        pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
8103                pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
8104                pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
8105        pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
8106                pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
8107                pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior);
8108                pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
8109        pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
8110                pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
8111        pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
8112                pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
8113        pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
8114                pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
8115        pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
8116
8117        mGlobalKeyManager.dump(prefix, pw);
8118        mStatusBarController.dump(pw, prefix);
8119        mNavigationBarController.dump(pw, prefix);
8120        PolicyControl.dump(prefix, pw);
8121
8122        if (mWakeGestureListener != null) {
8123            mWakeGestureListener.dump(pw, prefix);
8124        }
8125        if (mOrientationListener != null) {
8126            mOrientationListener.dump(pw, prefix);
8127        }
8128        if (mBurnInProtectionHelper != null) {
8129            mBurnInProtectionHelper.dump(prefix, pw);
8130        }
8131        if (mKeyguardDelegate != null) {
8132            mKeyguardDelegate.dump(prefix, pw);
8133        }
8134    }
8135}
8136