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