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