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