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