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