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