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