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