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