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