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