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