PhoneWindowManager.java revision 7d76682bb3a3aaf0d6adec10014a18bebbd4a061
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        applyLidSwitchState();
2275
2276        if (config.keyboard == Configuration.KEYBOARD_NOKEYS
2277                || (keyboardPresence == PRESENCE_INTERNAL
2278                        && isHidden(mLidKeyboardAccessibility))) {
2279            config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
2280            if (!mHasSoftInput) {
2281                config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
2282            }
2283        }
2284
2285        if (config.navigation == Configuration.NAVIGATION_NONAV
2286                || (navigationPresence == PRESENCE_INTERNAL
2287                        && isHidden(mLidNavigationAccessibility))) {
2288            config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
2289        }
2290    }
2291
2292    @Override
2293    public void onConfigurationChanged() {
2294        final Resources res = mContext.getResources();
2295
2296        mStatusBarHeight =
2297                res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
2298
2299        // Height of the navigation bar when presented horizontally at bottom
2300        mNavigationBarHeightForRotationDefault[mPortraitRotation] =
2301        mNavigationBarHeightForRotationDefault[mUpsideDownRotation] =
2302                res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
2303        mNavigationBarHeightForRotationDefault[mLandscapeRotation] =
2304        mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize(
2305                com.android.internal.R.dimen.navigation_bar_height_landscape);
2306
2307        // Width of the navigation bar when presented vertically along one side
2308        mNavigationBarWidthForRotationDefault[mPortraitRotation] =
2309        mNavigationBarWidthForRotationDefault[mUpsideDownRotation] =
2310        mNavigationBarWidthForRotationDefault[mLandscapeRotation] =
2311        mNavigationBarWidthForRotationDefault[mSeascapeRotation] =
2312                res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
2313
2314        // Height of the navigation bar when presented horizontally at bottom
2315        mNavigationBarHeightForRotationInCarMode[mPortraitRotation] =
2316        mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] =
2317                res.getDimensionPixelSize(
2318                        com.android.internal.R.dimen.navigation_bar_height_car_mode);
2319        mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] =
2320        mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize(
2321                com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode);
2322
2323        // Width of the navigation bar when presented vertically along one side
2324        mNavigationBarWidthForRotationInCarMode[mPortraitRotation] =
2325        mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] =
2326        mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] =
2327        mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] =
2328                res.getDimensionPixelSize(
2329                        com.android.internal.R.dimen.navigation_bar_width_car_mode);
2330    }
2331
2332    /** {@inheritDoc} */
2333    @Override
2334    public int windowTypeToLayerLw(int type) {
2335        if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
2336            return 2;
2337        }
2338        switch (type) {
2339        case TYPE_PRIVATE_PRESENTATION:
2340            return 2;
2341        case TYPE_WALLPAPER:
2342            // wallpaper is at the bottom, though the window manager may move it.
2343            return 2;
2344        case TYPE_DOCK_DIVIDER:
2345            return 2;
2346        case TYPE_QS_DIALOG:
2347            return 2;
2348        case TYPE_PHONE:
2349            return 3;
2350        case TYPE_SEARCH_BAR:
2351        case TYPE_VOICE_INTERACTION_STARTING:
2352            return 4;
2353        case TYPE_VOICE_INTERACTION:
2354            // voice interaction layer is almost immediately above apps.
2355            return 5;
2356        case TYPE_INPUT_CONSUMER:
2357            return 6;
2358        case TYPE_SYSTEM_DIALOG:
2359            return 7;
2360        case TYPE_TOAST:
2361            // toasts and the plugged-in battery thing
2362            return 8;
2363        case TYPE_PRIORITY_PHONE:
2364            // SIM errors and unlock.  Not sure if this really should be in a high layer.
2365            return 9;
2366        case TYPE_DREAM:
2367            // used for Dreams (screensavers with TYPE_DREAM windows)
2368            return 10;
2369        case TYPE_SYSTEM_ALERT:
2370            // like the ANR / app crashed dialogs
2371            return 11;
2372        case TYPE_INPUT_METHOD:
2373            // on-screen keyboards and other such input method user interfaces go here.
2374            return 12;
2375        case TYPE_INPUT_METHOD_DIALOG:
2376            // on-screen keyboards and other such input method user interfaces go here.
2377            return 13;
2378        case TYPE_KEYGUARD_SCRIM:
2379            // the safety window that shows behind keyguard while keyguard is starting
2380            return 14;
2381        case TYPE_STATUS_BAR_SUB_PANEL:
2382            return 15;
2383        case TYPE_STATUS_BAR:
2384            return 16;
2385        case TYPE_STATUS_BAR_PANEL:
2386            return 17;
2387        case TYPE_KEYGUARD_DIALOG:
2388            return 18;
2389        case TYPE_VOLUME_OVERLAY:
2390            // the on-screen volume indicator and controller shown when the user
2391            // changes the device volume
2392            return 19;
2393        case TYPE_SYSTEM_OVERLAY:
2394            // the on-screen volume indicator and controller shown when the user
2395            // changes the device volume
2396            return 20;
2397        case TYPE_NAVIGATION_BAR:
2398            // the navigation bar, if available, shows atop most things
2399            return 21;
2400        case TYPE_NAVIGATION_BAR_PANEL:
2401            // some panels (e.g. search) need to show on top of the navigation bar
2402            return 22;
2403        case TYPE_SCREENSHOT:
2404            // screenshot selection layer shouldn't go above system error, but it should cover
2405            // navigation bars at the very least.
2406            return 23;
2407        case TYPE_SYSTEM_ERROR:
2408            // system-level error dialogs
2409            return 24;
2410        case TYPE_MAGNIFICATION_OVERLAY:
2411            // used to highlight the magnified portion of a display
2412            return 25;
2413        case TYPE_DISPLAY_OVERLAY:
2414            // used to simulate secondary display devices
2415            return 26;
2416        case TYPE_DRAG:
2417            // the drag layer: input for drag-and-drop is associated with this window,
2418            // which sits above all other focusable windows
2419            return 27;
2420        case TYPE_ACCESSIBILITY_OVERLAY:
2421            // overlay put by accessibility services to intercept user interaction
2422            return 28;
2423        case TYPE_SECURE_SYSTEM_OVERLAY:
2424            return 29;
2425        case TYPE_BOOT_PROGRESS:
2426            return 30;
2427        case TYPE_POINTER:
2428            // the (mouse) pointer layer
2429            return 31;
2430        }
2431        Log.e(TAG, "Unknown window type: " + type);
2432        return 2;
2433    }
2434
2435    /** {@inheritDoc} */
2436    @Override
2437    public int subWindowTypeToLayerLw(int type) {
2438        switch (type) {
2439        case TYPE_APPLICATION_PANEL:
2440        case TYPE_APPLICATION_ATTACHED_DIALOG:
2441            return APPLICATION_PANEL_SUBLAYER;
2442        case TYPE_APPLICATION_MEDIA:
2443            return APPLICATION_MEDIA_SUBLAYER;
2444        case TYPE_APPLICATION_MEDIA_OVERLAY:
2445            return APPLICATION_MEDIA_OVERLAY_SUBLAYER;
2446        case TYPE_APPLICATION_SUB_PANEL:
2447            return APPLICATION_SUB_PANEL_SUBLAYER;
2448        case TYPE_APPLICATION_ABOVE_SUB_PANEL:
2449            return APPLICATION_ABOVE_SUB_PANEL_SUBLAYER;
2450        }
2451        Log.e(TAG, "Unknown sub-window type: " + type);
2452        return 0;
2453    }
2454
2455    @Override
2456    public int getMaxWallpaperLayer() {
2457        return windowTypeToLayerLw(TYPE_STATUS_BAR);
2458    }
2459
2460    private int getNavigationBarWidth(int rotation, int uiMode) {
2461        if ((uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2462            return mNavigationBarWidthForRotationInCarMode[rotation];
2463        } else {
2464            return mNavigationBarWidthForRotationDefault[rotation];
2465        }
2466    }
2467
2468    @Override
2469    public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation,
2470            int uiMode) {
2471        if (mHasNavigationBar) {
2472            // For a basic navigation bar, when we are in landscape mode we place
2473            // the navigation bar to the side.
2474            if (mNavigationBarCanMove && fullWidth > fullHeight) {
2475                return fullWidth - getNavigationBarWidth(rotation, uiMode);
2476            }
2477        }
2478        return fullWidth;
2479    }
2480
2481    private int getNavigationBarHeight(int rotation, int uiMode) {
2482        if ((uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2483            return mNavigationBarHeightForRotationInCarMode[rotation];
2484        } else {
2485            return mNavigationBarHeightForRotationDefault[rotation];
2486        }
2487    }
2488
2489    @Override
2490    public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation,
2491            int uiMode) {
2492        if (mHasNavigationBar) {
2493            // For a basic navigation bar, when we are in portrait mode we place
2494            // the navigation bar to the bottom.
2495            if (!mNavigationBarCanMove || fullWidth < fullHeight) {
2496                return fullHeight - getNavigationBarHeight(rotation, uiMode);
2497            }
2498        }
2499        return fullHeight;
2500    }
2501
2502    @Override
2503    public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode) {
2504        return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode);
2505    }
2506
2507    @Override
2508    public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode) {
2509        // There is a separate status bar at the top of the display.  We don't count that as part
2510        // of the fixed decor, since it can hide; however, for purposes of configurations,
2511        // we do want to exclude it since applications can't generally use that part
2512        // of the screen.
2513        return getNonDecorDisplayHeight(
2514                fullWidth, fullHeight, rotation, uiMode) - mStatusBarHeight;
2515    }
2516
2517    @Override
2518    public boolean isForceHiding(WindowManager.LayoutParams attrs) {
2519        return (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
2520                (isKeyguardHostWindow(attrs) &&
2521                        (mKeyguardDelegate != null && mKeyguardDelegate.isShowing())) ||
2522                (attrs.type == TYPE_KEYGUARD_SCRIM);
2523    }
2524
2525    @Override
2526    public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) {
2527        return attrs.type == TYPE_STATUS_BAR;
2528    }
2529
2530    @Override
2531    public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
2532        switch (attrs.type) {
2533            case TYPE_STATUS_BAR:
2534            case TYPE_NAVIGATION_BAR:
2535            case TYPE_WALLPAPER:
2536            case TYPE_DREAM:
2537            case TYPE_KEYGUARD_SCRIM:
2538                return false;
2539            default:
2540                // Hide only windows below the keyguard host window.
2541                return windowTypeToLayerLw(win.getBaseType())
2542                        < windowTypeToLayerLw(TYPE_STATUS_BAR);
2543        }
2544    }
2545
2546    @Override
2547    public WindowState getWinShowWhenLockedLw() {
2548        return mWinShowWhenLocked;
2549    }
2550
2551    /** {@inheritDoc} */
2552    @Override
2553    public View addStartingWindow(IBinder appToken, String packageName, int theme,
2554            CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
2555            int icon, int logo, int windowFlags, Configuration overrideConfig) {
2556        if (!SHOW_STARTING_ANIMATIONS) {
2557            return null;
2558        }
2559        if (packageName == null) {
2560            return null;
2561        }
2562
2563        WindowManager wm = null;
2564        View view = null;
2565
2566        try {
2567            Context context = mContext;
2568            if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow " + packageName
2569                    + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
2570                    + Integer.toHexString(theme));
2571            if (theme != context.getThemeResId() || labelRes != 0) {
2572                try {
2573                    context = context.createPackageContext(packageName, 0);
2574                    context.setTheme(theme);
2575                } catch (PackageManager.NameNotFoundException e) {
2576                    // Ignore
2577                }
2578            }
2579
2580            if (overrideConfig != null && overrideConfig != EMPTY) {
2581                if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: creating context based"
2582                        + " on overrideConfig" + overrideConfig + " for starting window");
2583                final Context overrideContext = context.createConfigurationContext(overrideConfig);
2584                overrideContext.setTheme(theme);
2585                final TypedArray typedArray = overrideContext.obtainStyledAttributes(
2586                        com.android.internal.R.styleable.Window);
2587                final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
2588                if (resId != 0 && overrideContext.getDrawable(resId) != null) {
2589                    // We want to use the windowBackground for the override context if it is
2590                    // available, otherwise we use the default one to make sure a themed starting
2591                    // window is displayed for the app.
2592                    if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: apply overrideConfig"
2593                            + overrideConfig + " to starting window resId=" + resId);
2594                    context = overrideContext;
2595                }
2596            }
2597
2598            final PhoneWindow win = new PhoneWindow(context);
2599            win.setIsStartingWindow(true);
2600
2601            final Resources r = context.getResources();
2602            win.setTitle(r.getText(labelRes, nonLocalizedLabel));
2603
2604            win.setType(
2605                WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
2606
2607            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
2608                // Assumes it's safe to show starting windows of launched apps while
2609                // the keyguard is being hidden. This is okay because starting windows never show
2610                // secret information.
2611                if (mKeyguardHidden) {
2612                    windowFlags |= FLAG_SHOW_WHEN_LOCKED;
2613                }
2614            }
2615
2616            // Force the window flags: this is a fake window, so it is not really
2617            // touchable or focusable by the user.  We also add in the ALT_FOCUSABLE_IM
2618            // flag because we do know that the next window will take input
2619            // focus, so we want to get the IME window up on top of us right away.
2620            win.setFlags(
2621                windowFlags|
2622                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2623                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2624                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
2625                windowFlags|
2626                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2627                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2628                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
2629
2630            win.setDefaultIcon(icon);
2631            win.setDefaultLogo(logo);
2632
2633            win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
2634                    WindowManager.LayoutParams.MATCH_PARENT);
2635
2636            final WindowManager.LayoutParams params = win.getAttributes();
2637            params.token = appToken;
2638            params.packageName = packageName;
2639            params.windowAnimations = win.getWindowStyle().getResourceId(
2640                    com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
2641            params.privateFlags |=
2642                    WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
2643            params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
2644
2645            if (!compatInfo.supportsScreen()) {
2646                params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
2647            }
2648
2649            params.setTitle("Starting " + packageName);
2650
2651            wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
2652            view = win.getDecorView();
2653
2654            if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Adding starting window for "
2655                + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null));
2656
2657            wm.addView(view, params);
2658
2659            // Only return the view if it was successfully added to the
2660            // window manager... which we can tell by it having a parent.
2661            return view.getParent() != null ? view : null;
2662        } catch (WindowManager.BadTokenException e) {
2663            // ignore
2664            Log.w(TAG, appToken + " already running, starting window not displayed. " +
2665                    e.getMessage());
2666        } catch (RuntimeException e) {
2667            // don't crash if something else bad happens, for example a
2668            // failure loading resources because we are loading from an app
2669            // on external storage that has been unmounted.
2670            Log.w(TAG, appToken + " failed creating starting window", e);
2671        } finally {
2672            if (view != null && view.getParent() == null) {
2673                Log.w(TAG, "view not successfully added to wm, removing view");
2674                wm.removeViewImmediate(view);
2675            }
2676        }
2677
2678        return null;
2679    }
2680
2681    /** {@inheritDoc} */
2682    @Override
2683    public void removeStartingWindow(IBinder appToken, View window) {
2684        if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Removing starting window for " + appToken + ": "
2685                + window + " Callers=" + Debug.getCallers(4));
2686
2687        if (window != null) {
2688            WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
2689            wm.removeView(window);
2690        }
2691    }
2692
2693    /**
2694     * Preflight adding a window to the system.
2695     *
2696     * Currently enforces that three window types are singletons:
2697     * <ul>
2698     * <li>STATUS_BAR_TYPE</li>
2699     * <li>KEYGUARD_TYPE</li>
2700     * </ul>
2701     *
2702     * @param win The window to be added
2703     * @param attrs Information about the window to be added
2704     *
2705     * @return If ok, WindowManagerImpl.ADD_OKAY.  If too many singletons,
2706     * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
2707     */
2708    @Override
2709    public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
2710        switch (attrs.type) {
2711            case TYPE_STATUS_BAR:
2712                mContext.enforceCallingOrSelfPermission(
2713                        android.Manifest.permission.STATUS_BAR_SERVICE,
2714                        "PhoneWindowManager");
2715                if (mStatusBar != null) {
2716                    if (mStatusBar.isAlive()) {
2717                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2718                    }
2719                }
2720                mStatusBar = win;
2721                mStatusBarController.setWindow(win);
2722                break;
2723            case TYPE_NAVIGATION_BAR:
2724                mContext.enforceCallingOrSelfPermission(
2725                        android.Manifest.permission.STATUS_BAR_SERVICE,
2726                        "PhoneWindowManager");
2727                if (mNavigationBar != null) {
2728                    if (mNavigationBar.isAlive()) {
2729                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2730                    }
2731                }
2732                mNavigationBar = win;
2733                mNavigationBarController.setWindow(win);
2734                if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
2735                break;
2736            case TYPE_NAVIGATION_BAR_PANEL:
2737            case TYPE_STATUS_BAR_PANEL:
2738            case TYPE_STATUS_BAR_SUB_PANEL:
2739            case TYPE_VOICE_INTERACTION_STARTING:
2740                mContext.enforceCallingOrSelfPermission(
2741                        android.Manifest.permission.STATUS_BAR_SERVICE,
2742                        "PhoneWindowManager");
2743                break;
2744            case TYPE_KEYGUARD_SCRIM:
2745                if (mKeyguardScrim != null) {
2746                    return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2747                }
2748                mKeyguardScrim = win;
2749                break;
2750        }
2751        return WindowManagerGlobal.ADD_OKAY;
2752    }
2753
2754    /** {@inheritDoc} */
2755    @Override
2756    public void removeWindowLw(WindowState win) {
2757        if (mStatusBar == win) {
2758            mStatusBar = null;
2759            mStatusBarController.setWindow(null);
2760            mKeyguardDelegate.showScrim();
2761        } else if (mKeyguardScrim == win) {
2762            Log.v(TAG, "Removing keyguard scrim");
2763            mKeyguardScrim = null;
2764        } if (mNavigationBar == win) {
2765            mNavigationBar = null;
2766            mNavigationBarController.setWindow(null);
2767        }
2768    }
2769
2770    static final boolean PRINT_ANIM = false;
2771
2772    /** {@inheritDoc} */
2773    @Override
2774    public int selectAnimationLw(WindowState win, int transit) {
2775        if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
2776              + ": transit=" + transit);
2777        if (win == mStatusBar) {
2778            boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
2779            if (transit == TRANSIT_EXIT
2780                    || transit == TRANSIT_HIDE) {
2781                return isKeyguard ? -1 : R.anim.dock_top_exit;
2782            } else if (transit == TRANSIT_ENTER
2783                    || transit == TRANSIT_SHOW) {
2784                return isKeyguard ? -1 : R.anim.dock_top_enter;
2785            }
2786        } else if (win == mNavigationBar) {
2787            if (win.getAttrs().windowAnimations != 0) {
2788                return 0;
2789            }
2790            // This can be on either the bottom or the right or the left.
2791            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
2792                if (transit == TRANSIT_EXIT
2793                        || transit == TRANSIT_HIDE) {
2794                    return R.anim.dock_bottom_exit;
2795                } else if (transit == TRANSIT_ENTER
2796                        || transit == TRANSIT_SHOW) {
2797                    return R.anim.dock_bottom_enter;
2798                }
2799            } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
2800                if (transit == TRANSIT_EXIT
2801                        || transit == TRANSIT_HIDE) {
2802                    return R.anim.dock_right_exit;
2803                } else if (transit == TRANSIT_ENTER
2804                        || transit == TRANSIT_SHOW) {
2805                    return R.anim.dock_right_enter;
2806                }
2807            } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
2808                if (transit == TRANSIT_EXIT
2809                        || transit == TRANSIT_HIDE) {
2810                    return R.anim.dock_left_exit;
2811                } else if (transit == TRANSIT_ENTER
2812                        || transit == TRANSIT_SHOW) {
2813                    return R.anim.dock_left_enter;
2814                }
2815            }
2816        } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) {
2817            return selectDockedDividerAnimationLw(win, transit);
2818        }
2819
2820        if (transit == TRANSIT_PREVIEW_DONE) {
2821            if (win.hasAppShownWindows()) {
2822                if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
2823                return com.android.internal.R.anim.app_starting_exit;
2824            }
2825        } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
2826                && transit == TRANSIT_ENTER) {
2827            // Special case: we are animating in a dream, while the keyguard
2828            // is shown.  We don't want an animation on the dream, because
2829            // we need it shown immediately with the keyguard animating away
2830            // to reveal it.
2831            return -1;
2832        }
2833
2834        return 0;
2835    }
2836
2837    private int selectDockedDividerAnimationLw(WindowState win, int transit) {
2838        int insets = mWindowManagerFuncs.getDockedDividerInsetsLw();
2839
2840        // If the divider is behind the navigation bar, don't animate.
2841        final Rect frame = win.getFrameLw();
2842        final boolean behindNavBar = mNavigationBar != null
2843                && ((mNavigationBarPosition == NAV_BAR_BOTTOM
2844                        && frame.top + insets >= mNavigationBar.getFrameLw().top)
2845                || (mNavigationBarPosition == NAV_BAR_RIGHT
2846                        && frame.left + insets >= mNavigationBar.getFrameLw().left)
2847                || (mNavigationBarPosition == NAV_BAR_LEFT
2848                        && frame.right - insets <= mNavigationBar.getFrameLw().right));
2849        final boolean landscape = frame.height() > frame.width();
2850        final boolean offscreenLandscape = landscape && (frame.right - insets <= 0
2851                || frame.left + insets >= win.getDisplayFrameLw().right);
2852        final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0
2853                || frame.bottom + insets >= win.getDisplayFrameLw().bottom);
2854        final boolean offscreen = offscreenLandscape || offscreenPortrait;
2855        if (behindNavBar || offscreen) {
2856            return 0;
2857        }
2858        if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
2859            return R.anim.fade_in;
2860        } else if (transit == TRANSIT_EXIT) {
2861            return R.anim.fade_out;
2862        } else {
2863            return 0;
2864        }
2865    }
2866
2867    @Override
2868    public void selectRotationAnimationLw(int anim[]) {
2869        if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
2870                + mTopFullscreenOpaqueWindowState + " rotationAnimation="
2871                + (mTopFullscreenOpaqueWindowState == null ?
2872                        "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation));
2873        if (mTopFullscreenOpaqueWindowState != null && mTopIsFullscreen) {
2874            switch (mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation) {
2875                case ROTATION_ANIMATION_CROSSFADE:
2876                    anim[0] = R.anim.rotation_animation_xfade_exit;
2877                    anim[1] = R.anim.rotation_animation_enter;
2878                    break;
2879                case ROTATION_ANIMATION_JUMPCUT:
2880                    anim[0] = R.anim.rotation_animation_jump_exit;
2881                    anim[1] = R.anim.rotation_animation_enter;
2882                    break;
2883                case ROTATION_ANIMATION_ROTATE:
2884                default:
2885                    anim[0] = anim[1] = 0;
2886                    break;
2887            }
2888        } else {
2889            anim[0] = anim[1] = 0;
2890        }
2891    }
2892
2893    @Override
2894    public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId,
2895            boolean forceDefault) {
2896        switch (exitAnimId) {
2897            case R.anim.rotation_animation_xfade_exit:
2898            case R.anim.rotation_animation_jump_exit:
2899                // These are the only cases that matter.
2900                if (forceDefault) {
2901                    return false;
2902                }
2903                int anim[] = new int[2];
2904                selectRotationAnimationLw(anim);
2905                return (exitAnimId == anim[0] && enterAnimId == anim[1]);
2906            default:
2907                return true;
2908        }
2909    }
2910
2911    @Override
2912    public Animation createForceHideEnterAnimation(boolean onWallpaper,
2913            boolean goingToNotificationShade) {
2914        if (goingToNotificationShade) {
2915            return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
2916        }
2917
2918        AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ?
2919                    R.anim.lock_screen_behind_enter_wallpaper :
2920                    R.anim.lock_screen_behind_enter);
2921
2922        // TODO: Use XML interpolators when we have log interpolators available in XML.
2923        final List<Animation> animations = set.getAnimations();
2924        for (int i = animations.size() - 1; i >= 0; --i) {
2925            animations.get(i).setInterpolator(mLogDecelerateInterpolator);
2926        }
2927
2928        return set;
2929    }
2930
2931
2932    @Override
2933    public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade) {
2934        if (goingToNotificationShade) {
2935            return null;
2936        } else {
2937            return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
2938        }
2939    }
2940
2941    private static void awakenDreams() {
2942        IDreamManager dreamManager = getDreamManager();
2943        if (dreamManager != null) {
2944            try {
2945                dreamManager.awaken();
2946            } catch (RemoteException e) {
2947                // fine, stay asleep then
2948            }
2949        }
2950    }
2951
2952    static IDreamManager getDreamManager() {
2953        return IDreamManager.Stub.asInterface(
2954                ServiceManager.checkService(DreamService.DREAM_SERVICE));
2955    }
2956
2957    TelecomManager getTelecommService() {
2958        return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
2959    }
2960
2961    static IAudioService getAudioService() {
2962        IAudioService audioService = IAudioService.Stub.asInterface(
2963                ServiceManager.checkService(Context.AUDIO_SERVICE));
2964        if (audioService == null) {
2965            Log.w(TAG, "Unable to find IAudioService interface.");
2966        }
2967        return audioService;
2968    }
2969
2970    boolean keyguardOn() {
2971        return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode();
2972    }
2973
2974    private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
2975            WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
2976            WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
2977        };
2978
2979    /** {@inheritDoc} */
2980    @Override
2981    public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
2982        final boolean keyguardOn = keyguardOn();
2983        final int keyCode = event.getKeyCode();
2984        final int repeatCount = event.getRepeatCount();
2985        final int metaState = event.getMetaState();
2986        final int flags = event.getFlags();
2987        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
2988        final boolean canceled = event.isCanceled();
2989
2990        if (DEBUG_INPUT) {
2991            Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
2992                    + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
2993                    + " canceled=" + canceled);
2994        }
2995
2996        // If we think we might have a volume down & power key chord on the way
2997        // but we're not sure, then tell the dispatcher to wait a little while and
2998        // try again later before dispatching.
2999        if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
3000            if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
3001                final long now = SystemClock.uptimeMillis();
3002                final long timeoutTime = mScreenshotChordVolumeDownKeyTime
3003                        + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
3004                if (now < timeoutTime) {
3005                    return timeoutTime - now;
3006                }
3007            }
3008            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3009                    && mScreenshotChordVolumeDownKeyConsumed) {
3010                if (!down) {
3011                    mScreenshotChordVolumeDownKeyConsumed = false;
3012                }
3013                return -1;
3014            }
3015        }
3016
3017        // Cancel any pending meta actions if we see any other keys being pressed between the down
3018        // of the meta key and its corresponding up.
3019        if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
3020            mPendingMetaAction = false;
3021        }
3022        // Any key that is not Alt or Meta cancels Caps Lock combo tracking.
3023        if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) {
3024            mPendingCapsLockToggle = false;
3025        }
3026
3027        // First we always handle the home key here, so applications
3028        // can never break it, although if keyguard is on, we do let
3029        // it handle it, because that gives us the correct 5 second
3030        // timeout.
3031        if (keyCode == KeyEvent.KEYCODE_HOME) {
3032
3033            // If we have released the home key, and didn't do anything else
3034            // while it was pressed, then it is time to go home!
3035            if (!down) {
3036                cancelPreloadRecentApps();
3037
3038                mHomePressed = false;
3039                if (mHomeConsumed) {
3040                    mHomeConsumed = false;
3041                    return -1;
3042                }
3043
3044                if (canceled) {
3045                    Log.i(TAG, "Ignoring HOME; event canceled.");
3046                    return -1;
3047                }
3048
3049                // If an incoming call is ringing, HOME is totally disabled.
3050                // (The user is already on the InCallUI at this point,
3051                // and his ONLY options are to answer or reject the call.)
3052                TelecomManager telecomManager = getTelecommService();
3053                if (telecomManager != null && telecomManager.isRinging()) {
3054                    Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
3055                    return -1;
3056                }
3057
3058                // Delay handling home if a double-tap is possible.
3059                if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
3060                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
3061                    mHomeDoubleTapPending = true;
3062                    mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
3063                            ViewConfiguration.getDoubleTapTimeout());
3064                    return -1;
3065                }
3066
3067                handleShortPressOnHome();
3068                return -1;
3069            }
3070
3071            // If a system window has focus, then it doesn't make sense
3072            // right now to interact with applications.
3073            WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
3074            if (attrs != null) {
3075                final int type = attrs.type;
3076                if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM
3077                        || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
3078                        || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
3079                    // the "app" is keyguard, so give it the key
3080                    return 0;
3081                }
3082                final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
3083                for (int i=0; i<typeCount; i++) {
3084                    if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
3085                        // don't do anything, but also don't pass it to the app
3086                        return -1;
3087                    }
3088                }
3089            }
3090
3091            // Remember that home is pressed and handle special actions.
3092            if (repeatCount == 0) {
3093                mHomePressed = true;
3094                if (mHomeDoubleTapPending) {
3095                    mHomeDoubleTapPending = false;
3096                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
3097                    handleDoubleTapOnHome();
3098                } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI
3099                        || mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
3100                    preloadRecentApps();
3101                }
3102            } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
3103                if (!keyguardOn) {
3104                    handleLongPressOnHome(event.getDeviceId());
3105                }
3106            }
3107            return -1;
3108        } else if (keyCode == KeyEvent.KEYCODE_MENU) {
3109            // Hijack modified menu keys for debugging features
3110            final int chordBug = KeyEvent.META_SHIFT_ON;
3111
3112            if (down && repeatCount == 0) {
3113                if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
3114                    Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
3115                    mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
3116                            null, null, null, 0, null, null);
3117                    return -1;
3118                } else if (SHOW_PROCESSES_ON_ALT_MENU &&
3119                        (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
3120                    Intent service = new Intent();
3121                    service.setClassName(mContext, "com.android.server.LoadAverageService");
3122                    ContentResolver res = mContext.getContentResolver();
3123                    boolean shown = Settings.Global.getInt(
3124                            res, Settings.Global.SHOW_PROCESSES, 0) != 0;
3125                    if (!shown) {
3126                        mContext.startService(service);
3127                    } else {
3128                        mContext.stopService(service);
3129                    }
3130                    Settings.Global.putInt(
3131                            res, Settings.Global.SHOW_PROCESSES, shown ? 0 : 1);
3132                    return -1;
3133                }
3134            }
3135        } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
3136            if (down) {
3137                if (repeatCount == 0) {
3138                    mSearchKeyShortcutPending = true;
3139                    mConsumeSearchKeyUp = false;
3140                }
3141            } else {
3142                mSearchKeyShortcutPending = false;
3143                if (mConsumeSearchKeyUp) {
3144                    mConsumeSearchKeyUp = false;
3145                    return -1;
3146                }
3147            }
3148            return 0;
3149        } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
3150            if (!keyguardOn) {
3151                if (down && repeatCount == 0) {
3152                    preloadRecentApps();
3153                } else if (!down) {
3154                    toggleRecentApps();
3155                }
3156            }
3157            return -1;
3158        } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) {
3159            if (down) {
3160                IStatusBarService service = getStatusBarService();
3161                if (service != null) {
3162                    try {
3163                        service.expandNotificationsPanel();
3164                    } catch (RemoteException e) {
3165                        // do nothing.
3166                    }
3167                }
3168            }
3169        } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed()
3170                && event.isCtrlPressed()) {
3171            if (down && repeatCount == 0) {
3172                int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION
3173                        : TAKE_SCREENSHOT_FULLSCREEN;
3174                mScreenshotRunnable.setScreenshotType(type);
3175                mHandler.post(mScreenshotRunnable);
3176                return -1;
3177            }
3178        } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
3179            if (down && repeatCount == 0 && !isKeyguardLocked()) {
3180                toggleKeyboardShortcutsMenu(event.getDeviceId());
3181            }
3182        } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
3183            if (down) {
3184                if (repeatCount == 0) {
3185                    mAssistKeyLongPressed = false;
3186                } else if (repeatCount == 1) {
3187                    mAssistKeyLongPressed = true;
3188                    if (!keyguardOn) {
3189                         launchAssistLongPressAction();
3190                    }
3191                }
3192            } else {
3193                if (mAssistKeyLongPressed) {
3194                    mAssistKeyLongPressed = false;
3195                } else {
3196                    if (!keyguardOn) {
3197                        launchAssistAction(null, event.getDeviceId());
3198                    }
3199                }
3200            }
3201            return -1;
3202        } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
3203            if (!down) {
3204                Intent voiceIntent;
3205                if (!keyguardOn) {
3206                    voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
3207                } else {
3208                    IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
3209                            ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
3210                    if (dic != null) {
3211                        try {
3212                            dic.exitIdle("voice-search");
3213                        } catch (RemoteException e) {
3214                        }
3215                    }
3216                    voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
3217                    voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
3218                }
3219                startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
3220            }
3221        } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
3222            if (down && repeatCount == 0) {
3223                mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
3224                mHandler.post(mScreenshotRunnable);
3225            }
3226            return -1;
3227        } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP
3228                || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) {
3229            if (down) {
3230                int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
3231
3232                // Disable autobrightness if it's on
3233                int auto = Settings.System.getIntForUser(
3234                        mContext.getContentResolver(),
3235                        Settings.System.SCREEN_BRIGHTNESS_MODE,
3236                        Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3237                        UserHandle.USER_CURRENT_OR_SELF);
3238                if (auto != 0) {
3239                    Settings.System.putIntForUser(mContext.getContentResolver(),
3240                            Settings.System.SCREEN_BRIGHTNESS_MODE,
3241                            Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3242                            UserHandle.USER_CURRENT_OR_SELF);
3243                }
3244
3245                int min = mPowerManager.getMinimumScreenBrightnessSetting();
3246                int max = mPowerManager.getMaximumScreenBrightnessSetting();
3247                int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction;
3248                int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
3249                        Settings.System.SCREEN_BRIGHTNESS,
3250                        mPowerManager.getDefaultScreenBrightnessSetting(),
3251                        UserHandle.USER_CURRENT_OR_SELF);
3252                brightness += step;
3253                // Make sure we don't go beyond the limits.
3254                brightness = Math.min(max, brightness);
3255                brightness = Math.max(min, brightness);
3256
3257                Settings.System.putIntForUser(mContext.getContentResolver(),
3258                        Settings.System.SCREEN_BRIGHTNESS, brightness,
3259                        UserHandle.USER_CURRENT_OR_SELF);
3260                startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
3261                        UserHandle.CURRENT_OR_SELF);
3262            }
3263            return -1;
3264        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
3265                || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3266                || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
3267            if (mUseTvRouting) {
3268                // On TVs volume keys never go to the foreground app.
3269                dispatchDirectAudioEvent(event);
3270                return -1;
3271            }
3272        }
3273
3274        // Toggle Caps Lock on META-ALT.
3275        boolean actionTriggered = false;
3276        if (KeyEvent.isModifierKey(keyCode)) {
3277            if (!mPendingCapsLockToggle) {
3278                // Start tracking meta state for combo.
3279                mInitialMetaState = mMetaState;
3280                mPendingCapsLockToggle = true;
3281            } else if (event.getAction() == KeyEvent.ACTION_UP) {
3282                int altOnMask = mMetaState & KeyEvent.META_ALT_MASK;
3283                int metaOnMask = mMetaState & KeyEvent.META_META_MASK;
3284
3285                // Check for Caps Lock toggle
3286                if ((metaOnMask != 0) && (altOnMask != 0)) {
3287                    // Check if nothing else is pressed
3288                    if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) {
3289                        // Handle Caps Lock Toggle
3290                        mInputManagerInternal.toggleCapsLock(event.getDeviceId());
3291                        actionTriggered = true;
3292                    }
3293                }
3294
3295                // Always stop tracking when key goes up.
3296                mPendingCapsLockToggle = false;
3297            }
3298        }
3299        // Store current meta state to be able to evaluate it later.
3300        mMetaState = metaState;
3301
3302        if (actionTriggered) {
3303            return -1;
3304        }
3305
3306        if (KeyEvent.isMetaKey(keyCode)) {
3307            if (down) {
3308                mPendingMetaAction = true;
3309            } else if (mPendingMetaAction) {
3310                launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId());
3311            }
3312            return -1;
3313        }
3314
3315        // Shortcuts are invoked through Search+key, so intercept those here
3316        // Any printing key that is chorded with Search should be consumed
3317        // even if no shortcut was invoked.  This prevents text from being
3318        // inadvertently inserted when using a keyboard that has built-in macro
3319        // shortcut keys (that emit Search+x) and some of them are not registered.
3320        if (mSearchKeyShortcutPending) {
3321            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3322            if (kcm.isPrintingKey(keyCode)) {
3323                mConsumeSearchKeyUp = true;
3324                mSearchKeyShortcutPending = false;
3325                if (down && repeatCount == 0 && !keyguardOn) {
3326                    Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
3327                    if (shortcutIntent != null) {
3328                        shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3329                        try {
3330                            startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3331                            dismissKeyboardShortcutsMenu();
3332                        } catch (ActivityNotFoundException ex) {
3333                            Slog.w(TAG, "Dropping shortcut key combination because "
3334                                    + "the activity to which it is registered was not found: "
3335                                    + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);
3336                        }
3337                    } else {
3338                        Slog.i(TAG, "Dropping unregistered shortcut key combination: "
3339                                + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));
3340                    }
3341                }
3342                return -1;
3343            }
3344        }
3345
3346        // Invoke shortcuts using Meta.
3347        if (down && repeatCount == 0 && !keyguardOn
3348                && (metaState & KeyEvent.META_META_ON) != 0) {
3349            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3350            if (kcm.isPrintingKey(keyCode)) {
3351                Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
3352                        metaState & ~(KeyEvent.META_META_ON
3353                                | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
3354                if (shortcutIntent != null) {
3355                    shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3356                    try {
3357                        startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3358                        dismissKeyboardShortcutsMenu();
3359                    } catch (ActivityNotFoundException ex) {
3360                        Slog.w(TAG, "Dropping shortcut key combination because "
3361                                + "the activity to which it is registered was not found: "
3362                                + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
3363                    }
3364                    return -1;
3365                }
3366            }
3367        }
3368
3369        // Handle application launch keys.
3370        if (down && repeatCount == 0 && !keyguardOn) {
3371            String category = sApplicationLaunchKeyCategories.get(keyCode);
3372            if (category != null) {
3373                Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
3374                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3375                try {
3376                    startActivityAsUser(intent, UserHandle.CURRENT);
3377                    dismissKeyboardShortcutsMenu();
3378                } catch (ActivityNotFoundException ex) {
3379                    Slog.w(TAG, "Dropping application launch key because "
3380                            + "the activity to which it is registered was not found: "
3381                            + "keyCode=" + keyCode + ", category=" + category, ex);
3382                }
3383                return -1;
3384            }
3385        }
3386
3387        // Display task switcher for ALT-TAB.
3388        if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
3389            if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
3390                final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
3391                if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
3392                    mRecentAppsHeldModifiers = shiftlessModifiers;
3393                    showRecentApps(true, false);
3394                    return -1;
3395                }
3396            }
3397        } else if (!down && mRecentAppsHeldModifiers != 0
3398                && (metaState & mRecentAppsHeldModifiers) == 0) {
3399            mRecentAppsHeldModifiers = 0;
3400            hideRecentApps(true, false);
3401        }
3402
3403        // Handle input method switching.
3404        if (down && repeatCount == 0
3405                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3406                        || (keyCode == KeyEvent.KEYCODE_SPACE
3407                                && (metaState & KeyEvent.META_META_MASK) != 0))) {
3408            final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0;
3409            mWindowManagerFuncs.switchInputMethod(forwardDirection);
3410            return -1;
3411        }
3412        if (mLanguageSwitchKeyPressed && !down
3413                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3414                        || keyCode == KeyEvent.KEYCODE_SPACE)) {
3415            mLanguageSwitchKeyPressed = false;
3416            return -1;
3417        }
3418
3419        if (isValidGlobalKey(keyCode)
3420                && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
3421            return -1;
3422        }
3423
3424        if (down) {
3425            long shortcutCode = keyCode;
3426            if (event.isCtrlPressed()) {
3427                shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
3428            }
3429
3430            if (event.isAltPressed()) {
3431                shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
3432            }
3433
3434            if (event.isShiftPressed()) {
3435                shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
3436            }
3437
3438            if (event.isMetaPressed()) {
3439                shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE;
3440            }
3441
3442            IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode);
3443            if (shortcutService != null) {
3444                try {
3445                    if (isUserSetupComplete()) {
3446                        shortcutService.notifyShortcutKeyPressed(shortcutCode);
3447                    }
3448                } catch (RemoteException e) {
3449                    mShortcutKeyServices.delete(shortcutCode);
3450                }
3451                return -1;
3452            }
3453        }
3454
3455        // Reserve all the META modifier combos for system behavior
3456        if ((metaState & KeyEvent.META_META_ON) != 0) {
3457            return -1;
3458        }
3459
3460        // Let the application handle the key.
3461        return 0;
3462    }
3463
3464    /** {@inheritDoc} */
3465    @Override
3466    public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
3467        // Note: This method is only called if the initial down was unhandled.
3468        if (DEBUG_INPUT) {
3469            Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
3470                    + ", flags=" + event.getFlags()
3471                    + ", keyCode=" + event.getKeyCode()
3472                    + ", scanCode=" + event.getScanCode()
3473                    + ", metaState=" + event.getMetaState()
3474                    + ", repeatCount=" + event.getRepeatCount()
3475                    + ", policyFlags=" + policyFlags);
3476        }
3477
3478        KeyEvent fallbackEvent = null;
3479        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3480            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3481            final int keyCode = event.getKeyCode();
3482            final int metaState = event.getMetaState();
3483            final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
3484                    && event.getRepeatCount() == 0;
3485
3486            // Check for fallback actions specified by the key character map.
3487            final FallbackAction fallbackAction;
3488            if (initialDown) {
3489                fallbackAction = kcm.getFallbackAction(keyCode, metaState);
3490            } else {
3491                fallbackAction = mFallbackActions.get(keyCode);
3492            }
3493
3494            if (fallbackAction != null) {
3495                if (DEBUG_INPUT) {
3496                    Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode
3497                            + " metaState=" + Integer.toHexString(fallbackAction.metaState));
3498                }
3499
3500                final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
3501                fallbackEvent = KeyEvent.obtain(
3502                        event.getDownTime(), event.getEventTime(),
3503                        event.getAction(), fallbackAction.keyCode,
3504                        event.getRepeatCount(), fallbackAction.metaState,
3505                        event.getDeviceId(), event.getScanCode(),
3506                        flags, event.getSource(), null);
3507
3508                if (!interceptFallback(win, fallbackEvent, policyFlags)) {
3509                    fallbackEvent.recycle();
3510                    fallbackEvent = null;
3511                }
3512
3513                if (initialDown) {
3514                    mFallbackActions.put(keyCode, fallbackAction);
3515                } else if (event.getAction() == KeyEvent.ACTION_UP) {
3516                    mFallbackActions.remove(keyCode);
3517                    fallbackAction.recycle();
3518                }
3519            }
3520        }
3521
3522        if (DEBUG_INPUT) {
3523            if (fallbackEvent == null) {
3524                Slog.d(TAG, "No fallback.");
3525            } else {
3526                Slog.d(TAG, "Performing fallback: " + fallbackEvent);
3527            }
3528        }
3529        return fallbackEvent;
3530    }
3531
3532    private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
3533        int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
3534        if ((actions & ACTION_PASS_TO_USER) != 0) {
3535            long delayMillis = interceptKeyBeforeDispatching(
3536                    win, fallbackEvent, policyFlags);
3537            if (delayMillis == 0) {
3538                return true;
3539            }
3540        }
3541        return false;
3542    }
3543
3544    @Override
3545    public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
3546            throws RemoteException {
3547        synchronized (mLock) {
3548            IShortcutService service = mShortcutKeyServices.get(shortcutCode);
3549            if (service != null && service.asBinder().pingBinder()) {
3550                throw new RemoteException("Key already exists.");
3551            }
3552
3553            mShortcutKeyServices.put(shortcutCode, shortcutService);
3554        }
3555    }
3556
3557    private void launchAssistLongPressAction() {
3558        performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
3559        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
3560
3561        // launch the search activity
3562        Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
3563        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3564        try {
3565            // TODO: This only stops the factory-installed search manager.
3566            // Need to formalize an API to handle others
3567            SearchManager searchManager = getSearchManager();
3568            if (searchManager != null) {
3569                searchManager.stopSearch();
3570            }
3571            startActivityAsUser(intent, UserHandle.CURRENT);
3572        } catch (ActivityNotFoundException e) {
3573            Slog.w(TAG, "No activity to handle assist long press action.", e);
3574        }
3575    }
3576
3577    private void launchAssistAction(String hint, int deviceId) {
3578        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
3579        if (!isUserSetupComplete()) {
3580            // Disable opening assist window during setup
3581            return;
3582        }
3583        Bundle args = null;
3584        if (deviceId > Integer.MIN_VALUE) {
3585            args = new Bundle();
3586            args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
3587        }
3588        if ((mContext.getResources().getConfiguration().uiMode
3589                & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
3590            // On TV, use legacy handling until assistants are implemented in the proper way.
3591            ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
3592                    .launchLegacyAssist(hint, UserHandle.myUserId(), args);
3593        } else {
3594            if (hint != null) {
3595                if (args == null) {
3596                    args = new Bundle();
3597                }
3598                args.putBoolean(hint, true);
3599            }
3600            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3601            if (statusbar != null) {
3602                statusbar.startAssist(args);
3603            }
3604        }
3605    }
3606
3607    private void startActivityAsUser(Intent intent, UserHandle handle) {
3608        if (isUserSetupComplete()) {
3609            mContext.startActivityAsUser(intent, handle);
3610        } else {
3611            Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent);
3612        }
3613    }
3614
3615    private SearchManager getSearchManager() {
3616        if (mSearchManager == null) {
3617            mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
3618        }
3619        return mSearchManager;
3620    }
3621
3622    private void preloadRecentApps() {
3623        mPreloadedRecentApps = true;
3624        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3625        if (statusbar != null) {
3626            statusbar.preloadRecentApps();
3627        }
3628    }
3629
3630    private void cancelPreloadRecentApps() {
3631        if (mPreloadedRecentApps) {
3632            mPreloadedRecentApps = false;
3633            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3634            if (statusbar != null) {
3635                statusbar.cancelPreloadRecentApps();
3636            }
3637        }
3638    }
3639
3640    private void toggleRecentApps() {
3641        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3642        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3643        if (statusbar != null) {
3644            statusbar.toggleRecentApps();
3645        }
3646    }
3647
3648    @Override
3649    public void showRecentApps(boolean fromHome) {
3650        mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
3651        mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget();
3652    }
3653
3654    private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
3655        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3656        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3657        if (statusbar != null) {
3658            statusbar.showRecentApps(triggeredFromAltTab, fromHome);
3659        }
3660    }
3661
3662    private void toggleKeyboardShortcutsMenu(int deviceId) {
3663        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3664        if (statusbar != null) {
3665            statusbar.toggleKeyboardShortcutsMenu(deviceId);
3666        }
3667    }
3668
3669    private void dismissKeyboardShortcutsMenu() {
3670        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3671        if (statusbar != null) {
3672            statusbar.dismissKeyboardShortcutsMenu();
3673        }
3674    }
3675
3676    private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
3677        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3678        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3679        if (statusbar != null) {
3680            statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
3681        }
3682    }
3683
3684    void launchHomeFromHotKey() {
3685        launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/);
3686    }
3687
3688    /**
3689     * A home key -> launch home action was detected.  Take the appropriate action
3690     * given the situation with the keyguard.
3691     */
3692    void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) {
3693        if (respectKeyguard) {
3694            if (isKeyguardShowingAndNotOccluded()) {
3695                // don't launch home if keyguard showing
3696                return;
3697            }
3698
3699            if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) {
3700                // when in keyguard restricted mode, must first verify unlock
3701                // before launching home
3702                mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
3703                    @Override
3704                    public void onKeyguardExitResult(boolean success) {
3705                        if (success) {
3706                            try {
3707                                ActivityManagerNative.getDefault().stopAppSwitches();
3708                            } catch (RemoteException e) {
3709                            }
3710                            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
3711                            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
3712                        }
3713                    }
3714                });
3715                return;
3716            }
3717        }
3718
3719        // no keyguard stuff to worry about, just launch home!
3720        try {
3721            ActivityManagerNative.getDefault().stopAppSwitches();
3722        } catch (RemoteException e) {
3723        }
3724        if (mRecentsVisible) {
3725            // Hide Recents and notify it to launch Home
3726            if (awakenFromDreams) {
3727                awakenDreams();
3728            }
3729            hideRecentApps(false, true);
3730        } else {
3731            // Otherwise, just launch Home
3732            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
3733            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
3734        }
3735    }
3736
3737    private final Runnable mClearHideNavigationFlag = new Runnable() {
3738        @Override
3739        public void run() {
3740            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
3741                // Clear flags.
3742                mForceClearedSystemUiFlags &=
3743                        ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
3744            }
3745            mWindowManagerFuncs.reevaluateStatusBarVisibility();
3746        }
3747    };
3748
3749    /**
3750     * Input handler used while nav bar is hidden.  Captures any touch on the screen,
3751     * to determine when the nav bar should be shown and prevent applications from
3752     * receiving those touches.
3753     */
3754    final class HideNavInputEventReceiver extends InputEventReceiver {
3755        public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
3756            super(inputChannel, looper);
3757        }
3758
3759        @Override
3760        public void onInputEvent(InputEvent event) {
3761            boolean handled = false;
3762            try {
3763                if (event instanceof MotionEvent
3764                        && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
3765                    final MotionEvent motionEvent = (MotionEvent)event;
3766                    if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
3767                        // When the user taps down, we re-show the nav bar.
3768                        boolean changed = false;
3769                        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
3770                            if (mInputConsumer == null) {
3771                                return;
3772                            }
3773                            // Any user activity always causes us to show the
3774                            // navigation controls, if they had been hidden.
3775                            // We also clear the low profile and only content
3776                            // flags so that tapping on the screen will atomically
3777                            // restore all currently hidden screen decorations.
3778                            int newVal = mResettingSystemUiFlags |
3779                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
3780                                    View.SYSTEM_UI_FLAG_LOW_PROFILE |
3781                                    View.SYSTEM_UI_FLAG_FULLSCREEN;
3782                            if (mResettingSystemUiFlags != newVal) {
3783                                mResettingSystemUiFlags = newVal;
3784                                changed = true;
3785                            }
3786                            // We don't allow the system's nav bar to be hidden
3787                            // again for 1 second, to prevent applications from
3788                            // spamming us and keeping it from being shown.
3789                            newVal = mForceClearedSystemUiFlags |
3790                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
3791                            if (mForceClearedSystemUiFlags != newVal) {
3792                                mForceClearedSystemUiFlags = newVal;
3793                                changed = true;
3794                                mHandler.postDelayed(mClearHideNavigationFlag, 1000);
3795                            }
3796                        }
3797                        if (changed) {
3798                            mWindowManagerFuncs.reevaluateStatusBarVisibility();
3799                        }
3800                    }
3801                }
3802            } finally {
3803                finishInputEvent(event, handled);
3804            }
3805        }
3806    }
3807    final InputEventReceiver.Factory mHideNavInputEventReceiverFactory =
3808            new InputEventReceiver.Factory() {
3809        @Override
3810        public InputEventReceiver createInputEventReceiver(
3811                InputChannel inputChannel, Looper looper) {
3812            return new HideNavInputEventReceiver(inputChannel, looper);
3813        }
3814    };
3815
3816    @Override
3817    public int adjustSystemUiVisibilityLw(int visibility) {
3818        mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
3819        mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
3820        mRecentsVisible = (visibility & View.RECENT_APPS_VISIBLE) > 0;
3821        mTvPictureInPictureVisible = (visibility & View.TV_PICTURE_IN_PICTURE_VISIBLE) > 0;
3822
3823        // Reset any bits in mForceClearingStatusBarVisibility that
3824        // are now clear.
3825        mResettingSystemUiFlags &= visibility;
3826        // Clear any bits in the new visibility that are currently being
3827        // force cleared, before reporting it.
3828        return visibility & ~mResettingSystemUiFlags
3829                & ~mForceClearedSystemUiFlags;
3830    }
3831
3832    @Override
3833    public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
3834            int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets,
3835            Rect outStableInsets, Rect outOutsets) {
3836        final int fl = PolicyControl.getWindowFlags(null, attrs);
3837        final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
3838        final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
3839
3840        final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
3841        if (useOutsets) {
3842            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
3843            if (outset > 0) {
3844                if (displayRotation == Surface.ROTATION_0) {
3845                    outOutsets.bottom += outset;
3846                } else if (displayRotation == Surface.ROTATION_90) {
3847                    outOutsets.right += outset;
3848                } else if (displayRotation == Surface.ROTATION_180) {
3849                    outOutsets.top += outset;
3850                } else if (displayRotation == Surface.ROTATION_270) {
3851                    outOutsets.left += outset;
3852                }
3853            }
3854        }
3855
3856        if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
3857                == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
3858            int availRight, availBottom;
3859            if (canHideNavigationBar() &&
3860                    (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
3861                availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
3862                availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
3863            } else {
3864                availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
3865                availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
3866            }
3867            if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
3868                if ((fl & FLAG_FULLSCREEN) != 0) {
3869                    outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop,
3870                            availRight - mStableFullscreenRight,
3871                            availBottom - mStableFullscreenBottom);
3872                } else {
3873                    outContentInsets.set(mStableLeft, mStableTop,
3874                            availRight - mStableRight, availBottom - mStableBottom);
3875                }
3876            } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
3877                outContentInsets.setEmpty();
3878            } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
3879                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
3880                outContentInsets.set(mCurLeft, mCurTop,
3881                        availRight - mCurRight, availBottom - mCurBottom);
3882            } else {
3883                outContentInsets.set(mCurLeft, mCurTop,
3884                        availRight - mCurRight, availBottom - mCurBottom);
3885            }
3886
3887            outStableInsets.set(mStableLeft, mStableTop,
3888                    availRight - mStableRight, availBottom - mStableBottom);
3889            if (taskBounds != null) {
3890                calculateRelevantTaskInsets(taskBounds, outContentInsets,
3891                        displayWidth, displayHeight);
3892                calculateRelevantTaskInsets(taskBounds, outStableInsets,
3893                        displayWidth, displayHeight);
3894            }
3895            return mForceShowSystemBars;
3896        }
3897        outContentInsets.setEmpty();
3898        outStableInsets.setEmpty();
3899        return mForceShowSystemBars;
3900    }
3901
3902    /**
3903     * For any given task bounds, the insets relevant for these bounds given the insets relevant
3904     * for the entire display.
3905     */
3906    private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth,
3907            int displayHeight) {
3908        mTmpRect.set(0, 0, displayWidth, displayHeight);
3909        mTmpRect.inset(inOutInsets);
3910        mTmpRect.intersect(taskBounds);
3911        int leftInset = mTmpRect.left - taskBounds.left;
3912        int topInset = mTmpRect.top - taskBounds.top;
3913        int rightInset = taskBounds.right - mTmpRect.right;
3914        int bottomInset = taskBounds.bottom - mTmpRect.bottom;
3915        inOutInsets.set(leftInset, topInset, rightInset, bottomInset);
3916    }
3917
3918    private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
3919        return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
3920                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
3921    }
3922
3923    /** {@inheritDoc} */
3924    @Override
3925    public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
3926                              int displayRotation, int uiMode) {
3927        mDisplayRotation = displayRotation;
3928        final int overscanLeft, overscanTop, overscanRight, overscanBottom;
3929        if (isDefaultDisplay) {
3930            switch (displayRotation) {
3931                case Surface.ROTATION_90:
3932                    overscanLeft = mOverscanTop;
3933                    overscanTop = mOverscanRight;
3934                    overscanRight = mOverscanBottom;
3935                    overscanBottom = mOverscanLeft;
3936                    break;
3937                case Surface.ROTATION_180:
3938                    overscanLeft = mOverscanRight;
3939                    overscanTop = mOverscanBottom;
3940                    overscanRight = mOverscanLeft;
3941                    overscanBottom = mOverscanTop;
3942                    break;
3943                case Surface.ROTATION_270:
3944                    overscanLeft = mOverscanBottom;
3945                    overscanTop = mOverscanLeft;
3946                    overscanRight = mOverscanTop;
3947                    overscanBottom = mOverscanRight;
3948                    break;
3949                default:
3950                    overscanLeft = mOverscanLeft;
3951                    overscanTop = mOverscanTop;
3952                    overscanRight = mOverscanRight;
3953                    overscanBottom = mOverscanBottom;
3954                    break;
3955            }
3956        } else {
3957            overscanLeft = 0;
3958            overscanTop = 0;
3959            overscanRight = 0;
3960            overscanBottom = 0;
3961        }
3962        mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0;
3963        mOverscanScreenTop = mRestrictedOverscanScreenTop = 0;
3964        mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth;
3965        mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight;
3966        mSystemLeft = 0;
3967        mSystemTop = 0;
3968        mSystemRight = displayWidth;
3969        mSystemBottom = displayHeight;
3970        mUnrestrictedScreenLeft = overscanLeft;
3971        mUnrestrictedScreenTop = overscanTop;
3972        mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight;
3973        mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom;
3974        mRestrictedScreenLeft = mUnrestrictedScreenLeft;
3975        mRestrictedScreenTop = mUnrestrictedScreenTop;
3976        mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth;
3977        mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight;
3978        mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft
3979                = mCurLeft = mUnrestrictedScreenLeft;
3980        mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop
3981                = mCurTop = mUnrestrictedScreenTop;
3982        mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight
3983                = mCurRight = displayWidth - overscanRight;
3984        mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom
3985                = mCurBottom = displayHeight - overscanBottom;
3986        mDockLayer = 0x10000000;
3987        mStatusBarLayer = -1;
3988
3989        // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
3990        final Rect pf = mTmpParentFrame;
3991        final Rect df = mTmpDisplayFrame;
3992        final Rect of = mTmpOverscanFrame;
3993        final Rect vf = mTmpVisibleFrame;
3994        final Rect dcf = mTmpDecorFrame;
3995        pf.left = df.left = of.left = vf.left = mDockLeft;
3996        pf.top = df.top = of.top = vf.top = mDockTop;
3997        pf.right = df.right = of.right = vf.right = mDockRight;
3998        pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom;
3999        dcf.setEmpty();  // Decor frame N/A for system bars.
4000
4001        if (isDefaultDisplay) {
4002            // For purposes of putting out fake window up to steal focus, we will
4003            // drive nav being hidden only by whether it is requested.
4004            final int sysui = mLastSystemUiFlags;
4005            boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
4006            boolean navTranslucent = (sysui
4007                    & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
4008            boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
4009            boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
4010            boolean navAllowedHidden = immersive || immersiveSticky;
4011            navTranslucent &= !immersiveSticky;  // transient trumps translucent
4012            boolean isKeyguardShowing = isStatusBarKeyguard() && !mHideLockScreen;
4013            if (!isKeyguardShowing) {
4014                navTranslucent &= areTranslucentBarsAllowed();
4015            }
4016            boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null
4017                    && mStatusBar.getAttrs().height == MATCH_PARENT
4018                    && mStatusBar.getAttrs().width == MATCH_PARENT;
4019
4020            // When the navigation bar isn't visible, we put up a fake
4021            // input window to catch all touch events.  This way we can
4022            // detect when the user presses anywhere to bring back the nav
4023            // bar and ensure the application doesn't see the event.
4024            if (navVisible || navAllowedHidden) {
4025                if (mInputConsumer != null) {
4026                    mHandler.sendMessage(
4027                            mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
4028                    mInputConsumer = null;
4029                }
4030            } else if (mInputConsumer == null) {
4031                mInputConsumer = mWindowManagerFuncs.addInputConsumer(mHandler.getLooper(),
4032                        mHideNavInputEventReceiverFactory);
4033            }
4034
4035            // For purposes of positioning and showing the nav bar, if we have
4036            // decided that it can't be hidden (because of the screen aspect ratio),
4037            // then take that into account.
4038            navVisible |= !canHideNavigationBar();
4039
4040            boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight,
4041                    displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom, dcf, navVisible, navTranslucent,
4042                    navAllowedHidden, statusBarExpandedNotKeyguard);
4043            if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
4044                    mDockLeft, mDockTop, mDockRight, mDockBottom));
4045            updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing);
4046            if (updateSysUiVisibility) {
4047                updateSystemUiVisibilityLw();
4048            }
4049        }
4050    }
4051
4052    private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui,
4053            boolean isKeyguardShowing) {
4054        // decide where the status bar goes ahead of time
4055        if (mStatusBar != null) {
4056            // apply any navigation bar insets
4057            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4058            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4059            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4060            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
4061                    + mUnrestrictedScreenTop;
4062            vf.left = mStableLeft;
4063            vf.top = mStableTop;
4064            vf.right = mStableRight;
4065            vf.bottom = mStableBottom;
4066
4067            mStatusBarLayer = mStatusBar.getSurfaceLayer();
4068
4069            // Let the status bar determine its size.
4070            mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
4071                    vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
4072                    dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */);
4073
4074            // For layout, the status bar is always at the top with our fixed height.
4075            mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
4076
4077            boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
4078            boolean statusBarTranslucent = (sysui
4079                    & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
4080            if (!isKeyguardShowing) {
4081                statusBarTranslucent &= areTranslucentBarsAllowed();
4082            }
4083
4084            // If the status bar is hidden, we don't want to cause
4085            // windows behind it to scroll.
4086            if (mStatusBar.isVisibleLw() && !statusBarTransient) {
4087                // Status bar may go away, so the screen area it occupies
4088                // is available to apps but just covering them when the
4089                // status bar is visible.
4090                mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
4091
4092                mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4093                mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4094                mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4095                mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4096
4097                if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " +
4098                        String.format(
4099                                "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
4100                                mDockLeft, mDockTop, mDockRight, mDockBottom,
4101                                mContentLeft, mContentTop, mContentRight, mContentBottom,
4102                                mCurLeft, mCurTop, mCurRight, mCurBottom));
4103            }
4104            if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
4105                    && !statusBarTransient && !statusBarTranslucent
4106                    && !mStatusBarController.wasRecentlyTranslucent()) {
4107                // If the opaque status bar is currently requested to be visible,
4108                // and not in the process of animating on or off, then
4109                // we can tell the app that it is covered by it.
4110                mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
4111            }
4112            if (mStatusBarController.checkHiddenLw()) {
4113                return true;
4114            }
4115        }
4116        return false;
4117    }
4118
4119    private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation,
4120            int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf,
4121            boolean navVisible, boolean navTranslucent, boolean navAllowedHidden,
4122            boolean statusBarExpandedNotKeyguard) {
4123        if (mNavigationBar != null) {
4124            boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
4125            // Force the navigation bar to its appropriate place and
4126            // size.  We need to do this directly, instead of relying on
4127            // it to bubble up from the nav bar, because this needs to
4128            // change atomically with screen rotations.
4129            mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight,
4130                    displayRotation);
4131            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
4132                // It's a system nav bar or a portrait screen; nav bar goes on bottom.
4133                int top = displayHeight - overscanBottom
4134                        - getNavigationBarHeight(displayRotation, uiMode);
4135                mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
4136                mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
4137                if (transientNavBarShowing) {
4138                    mNavigationBarController.setBarShowingLw(true);
4139                } else if (navVisible) {
4140                    mNavigationBarController.setBarShowingLw(true);
4141                    mDockBottom = mTmpNavigationFrame.top;
4142                    mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
4143                    mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
4144                } else {
4145                    // We currently want to hide the navigation UI - unless we expanded the status
4146                    // bar.
4147                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4148                }
4149                if (navVisible && !navTranslucent && !navAllowedHidden
4150                        && !mNavigationBar.isAnimatingLw()
4151                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4152                    // If the opaque nav bar is currently requested to be visible,
4153                    // and not in the process of animating on or off, then
4154                    // we can tell the app that it is covered by it.
4155                    mSystemBottom = mTmpNavigationFrame.top;
4156                }
4157            } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4158                // Landscape screen; nav bar goes to the right.
4159                int left = displayWidth - overscanRight
4160                        - getNavigationBarWidth(displayRotation, uiMode);
4161                mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
4162                mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
4163                if (transientNavBarShowing) {
4164                    mNavigationBarController.setBarShowingLw(true);
4165                } else if (navVisible) {
4166                    mNavigationBarController.setBarShowingLw(true);
4167                    mDockRight = mTmpNavigationFrame.left;
4168                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4169                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4170                } else {
4171                    // We currently want to hide the navigation UI - unless we expanded the status
4172                    // bar.
4173                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4174                }
4175                if (navVisible && !navTranslucent && !navAllowedHidden
4176                        && !mNavigationBar.isAnimatingLw()
4177                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4178                    // If the nav bar is currently requested to be visible,
4179                    // and not in the process of animating on or off, then
4180                    // we can tell the app that it is covered by it.
4181                    mSystemRight = mTmpNavigationFrame.left;
4182                }
4183            } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4184                // Seascape screen; nav bar goes to the left.
4185                int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode);
4186                mTmpNavigationFrame.set(overscanLeft, 0, right, displayHeight);
4187                mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right;
4188                if (transientNavBarShowing) {
4189                    mNavigationBarController.setBarShowingLw(true);
4190                } else if (navVisible) {
4191                    mNavigationBarController.setBarShowingLw(true);
4192                    mDockLeft = mTmpNavigationFrame.right;
4193                    // TODO: not so sure about those:
4194                    mRestrictedScreenLeft = mRestrictedOverscanScreenLeft = mDockLeft;
4195                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4196                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4197                } else {
4198                    // We currently want to hide the navigation UI - unless we expanded the status
4199                    // bar.
4200                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4201                }
4202                if (navVisible && !navTranslucent && !navAllowedHidden
4203                        && !mNavigationBar.isAnimatingLw()
4204                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4205                    // If the nav bar is currently requested to be visible,
4206                    // and not in the process of animating on or off, then
4207                    // we can tell the app that it is covered by it.
4208                    mSystemLeft = mTmpNavigationFrame.right;
4209                }
4210            }
4211            // Make sure the content and current rectangles are updated to
4212            // account for the restrictions from the navigation bar.
4213            mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4214            mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4215            mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4216            mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4217            mStatusBarLayer = mNavigationBar.getSurfaceLayer();
4218            // And compute the final frame.
4219            mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
4220                    mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
4221                    mTmpNavigationFrame, mTmpNavigationFrame);
4222            if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
4223            if (mNavigationBarController.checkHiddenLw()) {
4224                return true;
4225            }
4226        }
4227        return false;
4228    }
4229
4230    private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
4231        if (mNavigationBarCanMove && displayWidth > displayHeight) {
4232            if (displayRotation == Surface.ROTATION_270) {
4233                return NAV_BAR_LEFT;
4234            } else {
4235                return NAV_BAR_RIGHT;
4236            }
4237        }
4238        return NAV_BAR_BOTTOM;
4239    }
4240
4241    /** {@inheritDoc} */
4242    @Override
4243    public int getSystemDecorLayerLw() {
4244        if (mStatusBar != null && mStatusBar.isVisibleLw()) {
4245            return mStatusBar.getSurfaceLayer();
4246        }
4247
4248        if (mNavigationBar != null && mNavigationBar.isVisibleLw()) {
4249            return mNavigationBar.getSurfaceLayer();
4250        }
4251
4252        return 0;
4253    }
4254
4255    @Override
4256    public void getContentRectLw(Rect r) {
4257        r.set(mContentLeft, mContentTop, mContentRight, mContentBottom);
4258    }
4259
4260    void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
4261            boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
4262        if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
4263            // Here's a special case: if this attached window is a panel that is
4264            // above the dock window, and the window it is attached to is below
4265            // the dock window, then the frames we computed for the window it is
4266            // attached to can not be used because the dock is effectively part
4267            // of the underlying window and the attached window is floating on top
4268            // of the whole thing.  So, we ignore the attached window and explicitly
4269            // compute the frames that would be appropriate without the dock.
4270            df.left = of.left = cf.left = vf.left = mDockLeft;
4271            df.top = of.top = cf.top = vf.top = mDockTop;
4272            df.right = of.right = cf.right = vf.right = mDockRight;
4273            df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom;
4274        } else {
4275            // The effective display frame of the attached window depends on
4276            // whether it is taking care of insetting its content.  If not,
4277            // we need to use the parent's content frame so that the entire
4278            // window is positioned within that content.  Otherwise we can use
4279            // the overscan frame and let the attached window take care of
4280            // positioning its content appropriately.
4281            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4282                // Set the content frame of the attached window to the parent's decor frame
4283                // (same as content frame when IME isn't present) if specifically requested by
4284                // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
4285                // Otherwise, use the overscan frame.
4286                cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
4287                        ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
4288            } else {
4289                // If the window is resizing, then we want to base the content
4290                // frame on our attached content frame to resize...  however,
4291                // things can be tricky if the attached window is NOT in resize
4292                // mode, in which case its content frame will be larger.
4293                // Ungh.  So to deal with that, make sure the content frame
4294                // we end up using is not covering the IM dock.
4295                cf.set(attached.getContentFrameLw());
4296                if (attached.isVoiceInteraction()) {
4297                    if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft;
4298                    if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop;
4299                    if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight;
4300                    if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom;
4301                } else if (attached.getSurfaceLayer() < mDockLayer) {
4302                    if (cf.left < mContentLeft) cf.left = mContentLeft;
4303                    if (cf.top < mContentTop) cf.top = mContentTop;
4304                    if (cf.right > mContentRight) cf.right = mContentRight;
4305                    if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
4306                }
4307            }
4308            df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
4309            of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
4310            vf.set(attached.getVisibleFrameLw());
4311        }
4312        // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
4313        // window should be positioned relative to its parent or the entire
4314        // screen.
4315        pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
4316                ? attached.getFrameLw() : df);
4317    }
4318
4319    private void applyStableConstraints(int sysui, int fl, Rect r) {
4320        if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4321            // If app is requesting a stable layout, don't let the
4322            // content insets go below the stable values.
4323            if ((fl & FLAG_FULLSCREEN) != 0) {
4324                if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft;
4325                if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop;
4326                if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight;
4327                if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom;
4328            } else {
4329                if (r.left < mStableLeft) r.left = mStableLeft;
4330                if (r.top < mStableTop) r.top = mStableTop;
4331                if (r.right > mStableRight) r.right = mStableRight;
4332                if (r.bottom > mStableBottom) r.bottom = mStableBottom;
4333            }
4334        }
4335    }
4336
4337    private boolean canReceiveInput(WindowState win) {
4338        boolean notFocusable =
4339                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
4340        boolean altFocusableIm =
4341                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
4342        boolean notFocusableForIm = notFocusable ^ altFocusableIm;
4343        return !notFocusableForIm;
4344    }
4345
4346    /** {@inheritDoc} */
4347    @Override
4348    public void layoutWindowLw(WindowState win, WindowState attached) {
4349        // We've already done the navigation bar and status bar. If the status bar can receive
4350        // input, we need to layout it again to accomodate for the IME window.
4351        if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) {
4352            return;
4353        }
4354        final WindowManager.LayoutParams attrs = win.getAttrs();
4355        final boolean isDefaultDisplay = win.isDefaultDisplay();
4356        final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
4357                (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
4358        if (needsToOffsetInputMethodTarget) {
4359            if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
4360            offsetInputMethodWindowLw(mLastInputMethodWindow);
4361        }
4362
4363        final int fl = PolicyControl.getWindowFlags(win, attrs);
4364        final int pfl = attrs.privateFlags;
4365        final int sim = attrs.softInputMode;
4366        final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
4367
4368        final Rect pf = mTmpParentFrame;
4369        final Rect df = mTmpDisplayFrame;
4370        final Rect of = mTmpOverscanFrame;
4371        final Rect cf = mTmpContentFrame;
4372        final Rect vf = mTmpVisibleFrame;
4373        final Rect dcf = mTmpDecorFrame;
4374        final Rect sf = mTmpStableFrame;
4375        Rect osf = null;
4376        dcf.setEmpty();
4377
4378        final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
4379                && mNavigationBar != null && mNavigationBar.isVisibleLw());
4380
4381        final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
4382
4383        if (isDefaultDisplay) {
4384            sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom);
4385        } else {
4386            sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom);
4387        }
4388
4389        if (!isDefaultDisplay) {
4390            if (attached != null) {
4391                // If this window is attached to another, our display
4392                // frame is the same as the one we are attached to.
4393                setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4394            } else {
4395                // Give the window full screen.
4396                pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4397                pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4398                pf.right = df.right = of.right = cf.right
4399                        = mOverscanScreenLeft + mOverscanScreenWidth;
4400                pf.bottom = df.bottom = of.bottom = cf.bottom
4401                        = mOverscanScreenTop + mOverscanScreenHeight;
4402            }
4403        } else if (attrs.type == TYPE_INPUT_METHOD) {
4404            pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
4405            pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
4406            pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
4407            // IM dock windows layout below the nav bar...
4408            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4409            // ...with content insets above the nav bar
4410            cf.bottom = vf.bottom = mStableBottom;
4411            if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
4412                // The status bar forces the navigation bar while it's visible. Make sure the IME
4413                // avoids the navigation bar in that case.
4414                if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4415                    pf.right = df.right = of.right = cf.right = vf.right = mStableRight;
4416                } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4417                    pf.left = df.left = of.left = cf.left = vf.left = mStableLeft;
4418                }
4419            }
4420            // IM dock windows always go to the bottom of the screen.
4421            attrs.gravity = Gravity.BOTTOM;
4422            mDockLayer = win.getSurfaceLayer();
4423        } else if (attrs.type == TYPE_VOICE_INTERACTION) {
4424            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4425            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4426            pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4427            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4428            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4429                cf.left = mDockLeft;
4430                cf.top = mDockTop;
4431                cf.right = mDockRight;
4432                cf.bottom = mDockBottom;
4433            } else {
4434                cf.left = mContentLeft;
4435                cf.top = mContentTop;
4436                cf.right = mContentRight;
4437                cf.bottom = mContentBottom;
4438            }
4439            if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4440                vf.left = mCurLeft;
4441                vf.top = mCurTop;
4442                vf.right = mCurRight;
4443                vf.bottom = mCurBottom;
4444            } else {
4445                vf.set(cf);
4446            }
4447        } else if (attrs.type == TYPE_WALLPAPER) {
4448           layoutWallpaper(win, pf, df, of, cf);
4449        } else if (win == mStatusBar) {
4450            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4451            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4452            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4453            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop;
4454            cf.left = vf.left = mStableLeft;
4455            cf.top = vf.top = mStableTop;
4456            cf.right = vf.right = mStableRight;
4457            vf.bottom = mStableBottom;
4458
4459            if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
4460                cf.bottom = mContentBottom;
4461            } else {
4462                cf.bottom = mDockBottom;
4463                vf.bottom = mContentBottom;
4464            }
4465        } else {
4466
4467            // Default policy decor for the default display
4468            dcf.left = mSystemLeft;
4469            dcf.top = mSystemTop;
4470            dcf.right = mSystemRight;
4471            dcf.bottom = mSystemBottom;
4472            final boolean inheritTranslucentDecor = (attrs.privateFlags
4473                    & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0;
4474            final boolean isAppWindow =
4475                    attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW &&
4476                    attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
4477            final boolean topAtRest =
4478                    win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
4479            if (isAppWindow && !inheritTranslucentDecor && !topAtRest) {
4480                if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
4481                        && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0
4482                        && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
4483                        && (fl & WindowManager.LayoutParams.
4484                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
4485                        && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) {
4486                    // Ensure policy decor includes status bar
4487                    dcf.top = mStableTop;
4488                }
4489                if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0
4490                        && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
4491                        && (fl & WindowManager.LayoutParams.
4492                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
4493                    // Ensure policy decor includes navigation bar
4494                    dcf.bottom = mStableBottom;
4495                    dcf.right = mStableRight;
4496                }
4497            }
4498
4499            if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4500                    == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4501                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
4502                            + "): IN_SCREEN, INSET_DECOR");
4503                // This is the case for a normal activity window: we want it
4504                // to cover all of the screen space, and it can take care of
4505                // moving its contents to account for screen decorations that
4506                // intrude into that space.
4507                if (attached != null) {
4508                    // If this window is attached to another, our display
4509                    // frame is the same as the one we are attached to.
4510                    setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4511                } else {
4512                    if (attrs.type == TYPE_STATUS_BAR_PANEL
4513                            || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
4514                        // Status bar panels are the only windows who can go on top of
4515                        // the status bar.  They are protected by the STATUS_BAR_SERVICE
4516                        // permission, so they have the same privileges as the status
4517                        // bar itself.
4518                        //
4519                        // However, they should still dodge the navigation bar if it exists.
4520
4521                        pf.left = df.left = of.left = hasNavBar
4522                                ? mDockLeft : mUnrestrictedScreenLeft;
4523                        pf.top = df.top = of.top = mUnrestrictedScreenTop;
4524                        pf.right = df.right = of.right = hasNavBar
4525                                ? mRestrictedScreenLeft+mRestrictedScreenWidth
4526                                : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4527                        pf.bottom = df.bottom = of.bottom = hasNavBar
4528                                ? mRestrictedScreenTop+mRestrictedScreenHeight
4529                                : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4530
4531                        if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4532                                        "Laying out status bar window: (%d,%d - %d,%d)",
4533                                        pf.left, pf.top, pf.right, pf.bottom));
4534                    } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4535                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4536                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4537                        // Asking to layout into the overscan region, so give it that pure
4538                        // unrestricted area.
4539                        pf.left = df.left = of.left = mOverscanScreenLeft;
4540                        pf.top = df.top = of.top = mOverscanScreenTop;
4541                        pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth;
4542                        pf.bottom = df.bottom = of.bottom = mOverscanScreenTop
4543                                + mOverscanScreenHeight;
4544                    } else if (canHideNavigationBar()
4545                            && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4546                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4547                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4548                        // Asking for layout as if the nav bar is hidden, lets the
4549                        // application extend into the unrestricted overscan screen area.  We
4550                        // only do this for application windows to ensure no window that
4551                        // can be above the nav bar can do this.
4552                        pf.left = df.left = mOverscanScreenLeft;
4553                        pf.top = df.top = mOverscanScreenTop;
4554                        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
4555                        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
4556                        // We need to tell the app about where the frame inside the overscan
4557                        // is, so it can inset its content by that amount -- it didn't ask
4558                        // to actually extend itself into the overscan region.
4559                        of.left = mUnrestrictedScreenLeft;
4560                        of.top = mUnrestrictedScreenTop;
4561                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4562                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4563                    } else {
4564                        pf.left = df.left = mRestrictedOverscanScreenLeft;
4565                        pf.top = df.top = mRestrictedOverscanScreenTop;
4566                        pf.right = df.right = mRestrictedOverscanScreenLeft
4567                                + mRestrictedOverscanScreenWidth;
4568                        pf.bottom = df.bottom = mRestrictedOverscanScreenTop
4569                                + mRestrictedOverscanScreenHeight;
4570                        // We need to tell the app about where the frame inside the overscan
4571                        // is, so it can inset its content by that amount -- it didn't ask
4572                        // to actually extend itself into the overscan region.
4573                        of.left = mUnrestrictedScreenLeft;
4574                        of.top = mUnrestrictedScreenTop;
4575                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4576                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4577                    }
4578
4579                    if ((fl & FLAG_FULLSCREEN) == 0) {
4580                        if (win.isVoiceInteraction()) {
4581                            cf.left = mVoiceContentLeft;
4582                            cf.top = mVoiceContentTop;
4583                            cf.right = mVoiceContentRight;
4584                            cf.bottom = mVoiceContentBottom;
4585                        } else {
4586                            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4587                                cf.left = mDockLeft;
4588                                cf.top = mDockTop;
4589                                cf.right = mDockRight;
4590                                cf.bottom = mDockBottom;
4591                            } else {
4592                                cf.left = mContentLeft;
4593                                cf.top = mContentTop;
4594                                cf.right = mContentRight;
4595                                cf.bottom = mContentBottom;
4596                            }
4597                        }
4598                    } else {
4599                        // Full screen windows are always given a layout that is as if the
4600                        // status bar and other transient decors are gone.  This is to avoid
4601                        // bad states when moving from a window that is not hding the
4602                        // status bar to one that is.
4603                        cf.left = mRestrictedScreenLeft;
4604                        cf.top = mRestrictedScreenTop;
4605                        cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
4606                        cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4607                    }
4608                    applyStableConstraints(sysUiFl, fl, cf);
4609                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4610                        vf.left = mCurLeft;
4611                        vf.top = mCurTop;
4612                        vf.right = mCurRight;
4613                        vf.bottom = mCurBottom;
4614                    } else {
4615                        vf.set(cf);
4616                    }
4617                }
4618            } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
4619                    & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
4620                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
4621                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4622                        "): IN_SCREEN");
4623                // A window that has requested to fill the entire screen just
4624                // gets everything, period.
4625                if (attrs.type == TYPE_STATUS_BAR_PANEL
4626                        || attrs.type == TYPE_STATUS_BAR_SUB_PANEL
4627                        || attrs.type == TYPE_VOLUME_OVERLAY) {
4628                    pf.left = df.left = of.left = cf.left = hasNavBar
4629                            ? mDockLeft : mUnrestrictedScreenLeft;
4630                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
4631                    pf.right = df.right = of.right = cf.right = hasNavBar
4632                                        ? mRestrictedScreenLeft+mRestrictedScreenWidth
4633                                        : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4634                    pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar
4635                                          ? mRestrictedScreenTop+mRestrictedScreenHeight
4636                                          : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4637                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4638                                    "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
4639                                    pf.left, pf.top, pf.right, pf.bottom));
4640                } else if (attrs.type == TYPE_NAVIGATION_BAR
4641                        || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
4642                    // The navigation bar has Real Ultimate Power.
4643                    pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4644                    pf.top = df.top = of.top = mUnrestrictedScreenTop;
4645                    pf.right = df.right = of.right = mUnrestrictedScreenLeft
4646                            + mUnrestrictedScreenWidth;
4647                    pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop
4648                            + mUnrestrictedScreenHeight;
4649                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4650                                    "Laying out navigation bar window: (%d,%d - %d,%d)",
4651                                    pf.left, pf.top, pf.right, pf.bottom));
4652                } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
4653                                || attrs.type == TYPE_BOOT_PROGRESS
4654                                || attrs.type == TYPE_SCREENSHOT)
4655                        && ((fl & FLAG_FULLSCREEN) != 0)) {
4656                    // Fullscreen secure system overlays get what they ask for. Screenshot region
4657                    // selection overlay should also expand to full screen.
4658                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4659                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4660                    pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
4661                            + mOverscanScreenWidth;
4662                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
4663                            + mOverscanScreenHeight;
4664                } else if (attrs.type == TYPE_BOOT_PROGRESS) {
4665                    // Boot progress screen always covers entire display.
4666                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4667                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4668                    pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
4669                            + mOverscanScreenWidth;
4670                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
4671                            + mOverscanScreenHeight;
4672                } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4673                        && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4674                        && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4675                    // Asking to layout into the overscan region, so give it that pure
4676                    // unrestricted area.
4677                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4678                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4679                    pf.right = df.right = of.right = cf.right
4680                            = mOverscanScreenLeft + mOverscanScreenWidth;
4681                    pf.bottom = df.bottom = of.bottom = cf.bottom
4682                            = mOverscanScreenTop + mOverscanScreenHeight;
4683                } else if (canHideNavigationBar()
4684                        && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4685                        && (attrs.type == TYPE_STATUS_BAR
4686                            || attrs.type == TYPE_TOAST
4687                            || attrs.type == TYPE_DOCK_DIVIDER
4688                            || attrs.type == TYPE_VOICE_INTERACTION_STARTING
4689                            || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4690                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
4691                    // Asking for layout as if the nav bar is hidden, lets the
4692                    // application extend into the unrestricted screen area.  We
4693                    // only do this for application windows (or toasts) to ensure no window that
4694                    // can be above the nav bar can do this.
4695                    // XXX This assumes that an app asking for this will also
4696                    // ask for layout in only content.  We can't currently figure out
4697                    // what the screen would be if only laying out to hide the nav bar.
4698                    pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
4699                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
4700                    pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft
4701                            + mUnrestrictedScreenWidth;
4702                    pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
4703                            + mUnrestrictedScreenHeight;
4704                } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
4705                    pf.left = df.left = of.left = mRestrictedScreenLeft;
4706                    pf.top = df.top = of.top  = mRestrictedScreenTop;
4707                    pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
4708                    pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop
4709                            + mRestrictedScreenHeight;
4710                    if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4711                        cf.left = mDockLeft;
4712                        cf.top = mDockTop;
4713                        cf.right = mDockRight;
4714                        cf.bottom = mDockBottom;
4715                    } else {
4716                        cf.left = mContentLeft;
4717                        cf.top = mContentTop;
4718                        cf.right = mContentRight;
4719                        cf.bottom = mContentBottom;
4720                    }
4721                } else {
4722                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
4723                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
4724                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
4725                            + mRestrictedScreenWidth;
4726                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
4727                            + mRestrictedScreenHeight;
4728                }
4729
4730                applyStableConstraints(sysUiFl, fl, cf);
4731
4732                if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4733                    vf.left = mCurLeft;
4734                    vf.top = mCurTop;
4735                    vf.right = mCurRight;
4736                    vf.bottom = mCurBottom;
4737                } else {
4738                    vf.set(cf);
4739                }
4740            } else if (attached != null) {
4741                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4742                        "): attached to " + attached);
4743                // A child window should be placed inside of the same visible
4744                // frame that its parent had.
4745                setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf);
4746            } else {
4747                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4748                        "): normal window");
4749                // Otherwise, a normal window must be placed inside the content
4750                // of all screen decorations.
4751                if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) {
4752                    // Status bar panels and the volume dialog are the only windows who can go on
4753                    // top of the status bar.  They are protected by the STATUS_BAR_SERVICE
4754                    // permission, so they have the same privileges as the status
4755                    // bar itself.
4756                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
4757                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
4758                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
4759                            + mRestrictedScreenWidth;
4760                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
4761                            + mRestrictedScreenHeight;
4762                } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) {
4763                    // These dialogs are stable to interim decor changes.
4764                    pf.left = df.left = of.left = cf.left = mStableLeft;
4765                    pf.top = df.top = of.top = cf.top = mStableTop;
4766                    pf.right = df.right = of.right = cf.right = mStableRight;
4767                    pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom;
4768                } else {
4769                    pf.left = mContentLeft;
4770                    pf.top = mContentTop;
4771                    pf.right = mContentRight;
4772                    pf.bottom = mContentBottom;
4773                    if (win.isVoiceInteraction()) {
4774                        df.left = of.left = cf.left = mVoiceContentLeft;
4775                        df.top = of.top = cf.top = mVoiceContentTop;
4776                        df.right = of.right = cf.right = mVoiceContentRight;
4777                        df.bottom = of.bottom = cf.bottom = mVoiceContentBottom;
4778                    } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4779                        df.left = of.left = cf.left = mDockLeft;
4780                        df.top = of.top = cf.top = mDockTop;
4781                        df.right = of.right = cf.right = mDockRight;
4782                        df.bottom = of.bottom = cf.bottom = mDockBottom;
4783                    } else {
4784                        df.left = of.left = cf.left = mContentLeft;
4785                        df.top = of.top = cf.top = mContentTop;
4786                        df.right = of.right = cf.right = mContentRight;
4787                        df.bottom = of.bottom = cf.bottom = mContentBottom;
4788                    }
4789                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4790                        vf.left = mCurLeft;
4791                        vf.top = mCurTop;
4792                        vf.right = mCurRight;
4793                        vf.bottom = mCurBottom;
4794                    } else {
4795                        vf.set(cf);
4796                    }
4797                }
4798            }
4799        }
4800
4801        // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
4802        // Also, we don't allow windows in multi-window mode to extend out of the screen.
4803        if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR
4804                && !win.isInMultiWindowMode()) {
4805            df.left = df.top = -10000;
4806            df.right = df.bottom = 10000;
4807            if (attrs.type != TYPE_WALLPAPER) {
4808                of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
4809                of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
4810            }
4811        }
4812
4813        // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we
4814        // need to provide information to the clients that want to pretend that you can draw there.
4815        // We only want to apply outsets to certain types of windows. For example, we never want to
4816        // apply the outsets to floating dialogs, because they wouldn't make sense there.
4817        final boolean useOutsets = shouldUseOutsets(attrs, fl);
4818        if (isDefaultDisplay && useOutsets) {
4819            osf = mTmpOutsetFrame;
4820            osf.set(cf.left, cf.top, cf.right, cf.bottom);
4821            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
4822            if (outset > 0) {
4823                int rotation = mDisplayRotation;
4824                if (rotation == Surface.ROTATION_0) {
4825                    osf.bottom += outset;
4826                } else if (rotation == Surface.ROTATION_90) {
4827                    osf.right += outset;
4828                } else if (rotation == Surface.ROTATION_180) {
4829                    osf.top -= outset;
4830                } else if (rotation == Surface.ROTATION_270) {
4831                    osf.left -= outset;
4832                }
4833                if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset
4834                        + " with rotation " + rotation + ", result: " + osf);
4835            }
4836        }
4837
4838        if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
4839                + ": sim=#" + Integer.toHexString(sim)
4840                + " attach=" + attached + " type=" + attrs.type
4841                + String.format(" flags=0x%08x", fl)
4842                + " pf=" + pf.toShortString() + " df=" + df.toShortString()
4843                + " of=" + of.toShortString()
4844                + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
4845                + " dcf=" + dcf.toShortString()
4846                + " sf=" + sf.toShortString()
4847                + " osf=" + (osf == null ? "null" : osf.toShortString()));
4848
4849        win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf);
4850
4851        // Dock windows carve out the bottom of the screen, so normal windows
4852        // can't appear underneath them.
4853        if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleOrBehindKeyguardLw()
4854                && win.isDisplayedLw() && !win.getGivenInsetsPendingLw()) {
4855            setLastInputMethodWindowLw(null, null);
4856            offsetInputMethodWindowLw(win);
4857        }
4858        if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleOrBehindKeyguardLw()
4859                && !win.getGivenInsetsPendingLw()) {
4860            offsetVoiceInputWindowLw(win);
4861        }
4862    }
4863
4864    private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) {
4865
4866        // The wallpaper also has Real Ultimate Power, but we want to tell
4867        // it about the overscan area.
4868        pf.left = df.left = mOverscanScreenLeft;
4869        pf.top = df.top = mOverscanScreenTop;
4870        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
4871        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
4872        of.left = cf.left = mUnrestrictedScreenLeft;
4873        of.top = cf.top = mUnrestrictedScreenTop;
4874        of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4875        of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4876    }
4877
4878    private void offsetInputMethodWindowLw(WindowState win) {
4879        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
4880        top += win.getGivenContentInsetsLw().top;
4881        if (mContentBottom > top) {
4882            mContentBottom = top;
4883        }
4884        if (mVoiceContentBottom > top) {
4885            mVoiceContentBottom = top;
4886        }
4887        top = win.getVisibleFrameLw().top;
4888        top += win.getGivenVisibleInsetsLw().top;
4889        if (mCurBottom > top) {
4890            mCurBottom = top;
4891        }
4892        if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
4893                + mDockBottom + " mContentBottom="
4894                + mContentBottom + " mCurBottom=" + mCurBottom);
4895    }
4896
4897    private void offsetVoiceInputWindowLw(WindowState win) {
4898        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
4899        top += win.getGivenContentInsetsLw().top;
4900        if (mVoiceContentBottom > top) {
4901            mVoiceContentBottom = top;
4902        }
4903    }
4904
4905    /** {@inheritDoc} */
4906    @Override
4907    public void finishLayoutLw() {
4908        return;
4909    }
4910
4911    /** {@inheritDoc} */
4912    @Override
4913    public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
4914        mTopFullscreenOpaqueWindowState = null;
4915        mTopFullscreenOpaqueOrDimmingWindowState = null;
4916        mTopDockedOpaqueWindowState = null;
4917        mTopDockedOpaqueOrDimmingWindowState = null;
4918        mAppsToBeHidden.clear();
4919        mAppsThatDismissKeyguard.clear();
4920        mForceStatusBar = false;
4921        mForceStatusBarFromKeyguard = false;
4922        mForceStatusBarTransparent = false;
4923        mForcingShowNavBar = false;
4924        mForcingShowNavBarLayer = -1;
4925
4926        mHideLockScreen = false;
4927        mAllowLockscreenWhenOn = false;
4928        mDismissKeyguard = DISMISS_KEYGUARD_NONE;
4929        mShowingLockscreen = false;
4930        mShowingDream = false;
4931        mWinShowWhenLocked = null;
4932        mKeyguardSecure = isKeyguardSecure(mCurrentUserId);
4933        mKeyguardSecureIncludingHidden = mKeyguardSecure
4934                && (mKeyguardDelegate != null && mKeyguardDelegate.isShowing());
4935    }
4936
4937    /** {@inheritDoc} */
4938    @Override
4939    public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
4940            WindowState attached) {
4941        if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
4942                + win.isVisibleOrBehindKeyguardLw());
4943        final int fl = PolicyControl.getWindowFlags(win, attrs);
4944        if (mTopFullscreenOpaqueWindowState == null
4945                && win.isVisibleLw() && attrs.type == TYPE_INPUT_METHOD) {
4946            mForcingShowNavBar = true;
4947            mForcingShowNavBarLayer = win.getSurfaceLayer();
4948        }
4949        if (attrs.type == TYPE_STATUS_BAR) {
4950            if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
4951                mForceStatusBarFromKeyguard = true;
4952                mShowingLockscreen = true;
4953            }
4954            if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
4955                mForceStatusBarTransparent = true;
4956            }
4957        }
4958
4959        boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
4960                && attrs.type < FIRST_SYSTEM_WINDOW;
4961        final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0;
4962        final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0;
4963        final int stackId = win.getStackId();
4964        if (mTopFullscreenOpaqueWindowState == null &&
4965                win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
4966            if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
4967                if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
4968                    mForceStatusBarFromKeyguard = true;
4969                } else {
4970                    mForceStatusBar = true;
4971                }
4972            }
4973            if (attrs.type == TYPE_DREAM) {
4974                // If the lockscreen was showing when the dream started then wait
4975                // for the dream to draw before hiding the lockscreen.
4976                if (!mDreamingLockscreen
4977                        || (win.isVisibleLw() && win.hasDrawnLw())) {
4978                    mShowingDream = true;
4979                    appWindow = true;
4980                }
4981            }
4982
4983            final IApplicationToken appToken = win.getAppToken();
4984
4985            // For app windows that are not attached, we decide if all windows in the app they
4986            // represent should be hidden or if we should hide the lockscreen. For attached app
4987            // windows we defer the decision to the window it is attached to.
4988            if (appWindow && attached == null) {
4989                if (showWhenLocked) {
4990                    // Remove any previous windows with the same appToken.
4991                    mAppsToBeHidden.remove(appToken);
4992                    mAppsThatDismissKeyguard.remove(appToken);
4993                    if (mAppsToBeHidden.isEmpty()) {
4994                        if (dismissKeyguard && !mKeyguardSecure) {
4995                            mAppsThatDismissKeyguard.add(appToken);
4996                        } else if (win.isDrawnLw() || win.hasAppShownWindows()) {
4997                            mWinShowWhenLocked = win;
4998                            mHideLockScreen = true;
4999                            mForceStatusBarFromKeyguard = false;
5000                        }
5001                    }
5002                } else if (dismissKeyguard) {
5003                    if (mKeyguardSecure) {
5004                        mAppsToBeHidden.add(appToken);
5005                    } else {
5006                        mAppsToBeHidden.remove(appToken);
5007                    }
5008                    mAppsThatDismissKeyguard.add(appToken);
5009                } else {
5010                    mAppsToBeHidden.add(appToken);
5011                }
5012                if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
5013                    if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
5014                    mTopFullscreenOpaqueWindowState = win;
5015                    if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5016                        mTopFullscreenOpaqueOrDimmingWindowState = win;
5017                    }
5018                    if (!mAppsThatDismissKeyguard.isEmpty() &&
5019                            mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
5020                        if (DEBUG_LAYOUT) Slog.v(TAG,
5021                                "Setting mDismissKeyguard true by win " + win);
5022                        mDismissKeyguard = (mWinDismissingKeyguard == win
5023                                && mSecureDismissingKeyguard == mKeyguardSecure)
5024                                ? DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
5025                        mWinDismissingKeyguard = win;
5026                        mSecureDismissingKeyguard = mKeyguardSecure;
5027                        mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure;
5028                    } else if (mAppsToBeHidden.isEmpty() && showWhenLocked
5029                            && (win.isDrawnLw() || win.hasAppShownWindows())) {
5030                        if (DEBUG_LAYOUT) Slog.v(TAG,
5031                                "Setting mHideLockScreen to true by win " + win);
5032                        mHideLockScreen = true;
5033                        mForceStatusBarFromKeyguard = false;
5034                    }
5035                    if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
5036                        mAllowLockscreenWhenOn = true;
5037                    }
5038                }
5039
5040                if (!mKeyguardHidden && mWinShowWhenLocked != null &&
5041                        mWinShowWhenLocked.getAppToken() != win.getAppToken() &&
5042                        (attrs.flags & FLAG_SHOW_WHEN_LOCKED) == 0) {
5043                    win.hideLw(false);
5044                }
5045            }
5046        } else if (mTopFullscreenOpaqueWindowState == null && mWinShowWhenLocked == null) {
5047            // No TopFullscreenOpaqueWindow is showing, but we found a SHOW_WHEN_LOCKED window
5048            // that is being hidden in an animation - keep the
5049            // keyguard hidden until the new window shows up and
5050            // we know whether to show the keyguard or not.
5051            if (win.isAnimatingLw() && appWindow && showWhenLocked && mKeyguardHidden) {
5052                mHideLockScreen = true;
5053                mWinShowWhenLocked = win;
5054            }
5055        }
5056
5057        // Keep track of the window if it's dimming but not necessarily fullscreen.
5058        final boolean reallyVisible = win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw();
5059        if (mTopFullscreenOpaqueOrDimmingWindowState == null && reallyVisible
5060                && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
5061            mTopFullscreenOpaqueOrDimmingWindowState = win;
5062        }
5063
5064        // We need to keep track of the top "fullscreen" opaque window for the docked stack
5065        // separately, because both the "real fullscreen" opaque window and the one for the docked
5066        // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
5067        if (mTopDockedOpaqueWindowState == null && reallyVisible && appWindow && attached == null
5068                && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
5069            mTopDockedOpaqueWindowState = win;
5070            if (mTopDockedOpaqueOrDimmingWindowState == null) {
5071                mTopDockedOpaqueOrDimmingWindowState = win;
5072            }
5073        }
5074
5075        // Also keep track of any windows that are dimming but not necessarily fullscreen in the
5076        // docked stack.
5077        if (mTopDockedOpaqueOrDimmingWindowState == null && reallyVisible && win.isDimming()
5078                && stackId == DOCKED_STACK_ID) {
5079            mTopDockedOpaqueOrDimmingWindowState = win;
5080        }
5081    }
5082
5083    private boolean isFullscreen(WindowManager.LayoutParams attrs) {
5084        return attrs.x == 0 && attrs.y == 0
5085                && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
5086                && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
5087    }
5088
5089    /** {@inheritDoc} */
5090    @Override
5091    public int finishPostLayoutPolicyLw() {
5092        if (mWinShowWhenLocked != null && mTopFullscreenOpaqueWindowState != null &&
5093                mWinShowWhenLocked.getAppToken() != mTopFullscreenOpaqueWindowState.getAppToken()
5094                && isKeyguardLocked()) {
5095            // A dialog is dismissing the keyguard. Put the wallpaper behind it and hide the
5096            // fullscreen window.
5097            // TODO: Make sure FLAG_SHOW_WALLPAPER is restored when dialog is dismissed. Or not.
5098            mWinShowWhenLocked.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5099            mTopFullscreenOpaqueWindowState.hideLw(false);
5100            mTopFullscreenOpaqueWindowState = mWinShowWhenLocked;
5101        }
5102
5103        int changes = 0;
5104        boolean topIsFullscreen = false;
5105
5106        final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
5107                ? mTopFullscreenOpaqueWindowState.getAttrs()
5108                : null;
5109
5110        // If we are not currently showing a dream then remember the current
5111        // lockscreen state.  We will use this to determine whether the dream
5112        // started while the lockscreen was showing and remember this state
5113        // while the dream is showing.
5114        if (!mShowingDream) {
5115            mDreamingLockscreen = mShowingLockscreen;
5116            if (mDreamingSleepTokenNeeded) {
5117                mDreamingSleepTokenNeeded = false;
5118                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
5119            }
5120        } else {
5121            if (!mDreamingSleepTokenNeeded) {
5122                mDreamingSleepTokenNeeded = true;
5123                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget();
5124            }
5125        }
5126
5127        if (mStatusBar != null) {
5128            if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
5129                    + " forcefkg=" + mForceStatusBarFromKeyguard
5130                    + " top=" + mTopFullscreenOpaqueWindowState);
5131            boolean shouldBeTransparent = mForceStatusBarTransparent
5132                    && !mForceStatusBar
5133                    && !mForceStatusBarFromKeyguard;
5134            if (!shouldBeTransparent) {
5135                mStatusBarController.setShowTransparent(false /* transparent */);
5136            } else if (!mStatusBar.isVisibleLw()) {
5137                mStatusBarController.setShowTransparent(true /* transparent */);
5138            }
5139
5140            WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs();
5141            boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT
5142                    && statusBarAttrs.width == MATCH_PARENT;
5143            if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
5144                    || statusBarExpanded) {
5145                if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
5146                if (mStatusBarController.setBarShowingLw(true)) {
5147                    changes |= FINISH_LAYOUT_REDO_LAYOUT;
5148                }
5149                // Maintain fullscreen layout until incoming animation is complete.
5150                topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
5151                // Transient status bar on the lockscreen is not allowed
5152                if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) {
5153                    mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
5154                            mLastSystemUiFlags, mLastSystemUiFlags);
5155                }
5156                if (statusBarExpanded && mNavigationBar != null) {
5157                    if (mNavigationBarController.setBarShowingLw(true)) {
5158                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5159                    }
5160                }
5161            } else if (mTopFullscreenOpaqueWindowState != null) {
5162                final int fl = PolicyControl.getWindowFlags(null, lp);
5163                if (localLOGV) {
5164                    Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
5165                            + " shown position: "
5166                            + mTopFullscreenOpaqueWindowState.getShownPositionLw());
5167                    Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
5168                            + " lp.flags=0x" + Integer.toHexString(fl));
5169                }
5170                topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
5171                        || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
5172                // The subtle difference between the window for mTopFullscreenOpaqueWindowState
5173                // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
5174                // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
5175                // case though.
5176                if (mStatusBarController.isTransientShowing()) {
5177                    if (mStatusBarController.setBarShowingLw(true)) {
5178                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5179                    }
5180                } else if (topIsFullscreen
5181                        && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)
5182                        && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) {
5183                    if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
5184                    if (mStatusBarController.setBarShowingLw(false)) {
5185                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5186                    } else {
5187                        if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
5188                    }
5189                } else {
5190                    if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
5191                    if (mStatusBarController.setBarShowingLw(true)) {
5192                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5193                    }
5194                }
5195            }
5196        }
5197
5198        if (mTopIsFullscreen != topIsFullscreen) {
5199            if (!topIsFullscreen) {
5200                // Force another layout when status bar becomes fully shown.
5201                changes |= FINISH_LAYOUT_REDO_LAYOUT;
5202            }
5203            mTopIsFullscreen = topIsFullscreen;
5204        }
5205
5206        // Hide the key guard if a visible window explicitly specifies that it wants to be
5207        // displayed when the screen is locked.
5208        if (mKeyguardDelegate != null && mStatusBar != null) {
5209            if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
5210                    + mHideLockScreen);
5211            if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardSecure) {
5212                mKeyguardHidden = true;
5213                if (setKeyguardOccludedLw(true)) {
5214                    changes |= FINISH_LAYOUT_REDO_LAYOUT
5215                            | FINISH_LAYOUT_REDO_CONFIG
5216                            | FINISH_LAYOUT_REDO_WALLPAPER;
5217                }
5218                if (mKeyguardDelegate.isShowing()) {
5219                    mHandler.post(new Runnable() {
5220                        @Override
5221                        public void run() {
5222                            mKeyguardDelegate.keyguardDone(false, false);
5223                        }
5224                    });
5225                }
5226            } else if (mHideLockScreen) {
5227                mKeyguardHidden = true;
5228                mWinDismissingKeyguard = null;
5229                if (setKeyguardOccludedLw(true)) {
5230                    changes |= FINISH_LAYOUT_REDO_LAYOUT
5231                            | FINISH_LAYOUT_REDO_CONFIG
5232                            | FINISH_LAYOUT_REDO_WALLPAPER;
5233                }
5234            } else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) {
5235                mKeyguardHidden = false;
5236                if (setKeyguardOccludedLw(false)) {
5237                    changes |= FINISH_LAYOUT_REDO_LAYOUT
5238                            | FINISH_LAYOUT_REDO_CONFIG
5239                            | FINISH_LAYOUT_REDO_WALLPAPER;
5240                }
5241                if (mDismissKeyguard == DISMISS_KEYGUARD_START) {
5242                    // Only launch the next keyguard unlock window once per window.
5243                    mHandler.post(new Runnable() {
5244                        @Override
5245                        public void run() {
5246                            mKeyguardDelegate.dismiss();
5247                        }
5248                    });
5249                }
5250            } else {
5251                mWinDismissingKeyguard = null;
5252                mSecureDismissingKeyguard = false;
5253                mKeyguardHidden = false;
5254                if (setKeyguardOccludedLw(false)) {
5255                    changes |= FINISH_LAYOUT_REDO_LAYOUT
5256                            | FINISH_LAYOUT_REDO_CONFIG
5257                            | FINISH_LAYOUT_REDO_WALLPAPER;
5258                }
5259            }
5260        }
5261
5262        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5263            // If the navigation bar has been hidden or shown, we need to do another
5264            // layout pass to update that window.
5265            changes |= FINISH_LAYOUT_REDO_LAYOUT;
5266        }
5267
5268        // update since mAllowLockscreenWhenOn might have changed
5269        updateLockScreenTimeout();
5270        return changes;
5271    }
5272
5273    /**
5274     * Updates the occluded state of the Keyguard.
5275     *
5276     * @return Whether the flags have changed and we have to redo the layout.
5277     */
5278    private boolean setKeyguardOccludedLw(boolean isOccluded) {
5279        boolean wasOccluded = mKeyguardOccluded;
5280        boolean showing = mKeyguardDelegate.isShowing();
5281        if (wasOccluded && !isOccluded && showing) {
5282            mKeyguardOccluded = false;
5283            mKeyguardDelegate.setOccluded(false);
5284            mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
5285            return true;
5286        } else if (!wasOccluded && isOccluded && showing) {
5287            mKeyguardOccluded = true;
5288            mKeyguardDelegate.setOccluded(true);
5289            mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
5290            mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
5291            return true;
5292        } else {
5293            return false;
5294        }
5295    }
5296
5297    private boolean isStatusBarKeyguard() {
5298        return mStatusBar != null
5299                && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
5300    }
5301
5302    @Override
5303    public boolean allowAppAnimationsLw() {
5304        if (isStatusBarKeyguard() || mShowingDream) {
5305            // If keyguard or dreams is currently visible, no reason to animate behind it.
5306            return false;
5307        }
5308        return true;
5309    }
5310
5311    @Override
5312    public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
5313        mFocusedWindow = newFocus;
5314        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5315            // If the navigation bar has been hidden or shown, we need to do another
5316            // layout pass to update that window.
5317            return FINISH_LAYOUT_REDO_LAYOUT;
5318        }
5319        return 0;
5320    }
5321
5322    /** {@inheritDoc} */
5323    @Override
5324    public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
5325        // lid changed state
5326        final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
5327        if (newLidState == mLidState) {
5328            return;
5329        }
5330
5331        mLidState = newLidState;
5332        applyLidSwitchState();
5333        updateRotation(true);
5334
5335        if (lidOpen) {
5336            wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
5337                    "android.policy:LID");
5338        } else if (!mLidControlsSleep) {
5339            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
5340        }
5341    }
5342
5343    @Override
5344    public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
5345        int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
5346        if (mCameraLensCoverState == lensCoverState) {
5347            return;
5348        }
5349        if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
5350                lensCoverState == CAMERA_LENS_UNCOVERED) {
5351            Intent intent;
5352            final boolean keyguardActive = mKeyguardDelegate == null ? false :
5353                    mKeyguardDelegate.isShowing();
5354            if (keyguardActive) {
5355                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
5356            } else {
5357                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
5358            }
5359            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
5360                    "android.policy:CAMERA_COVER");
5361            startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
5362        }
5363        mCameraLensCoverState = lensCoverState;
5364    }
5365
5366    void setHdmiPlugged(boolean plugged) {
5367        if (mHdmiPlugged != plugged) {
5368            mHdmiPlugged = plugged;
5369            updateRotation(true, true);
5370            Intent intent = new Intent(ACTION_HDMI_PLUGGED);
5371            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
5372            intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
5373            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
5374        }
5375    }
5376
5377    void initializeHdmiState() {
5378        boolean plugged = false;
5379        // watch for HDMI plug messages if the hdmi switch exists
5380        if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
5381            mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
5382
5383            final String filename = "/sys/class/switch/hdmi/state";
5384            FileReader reader = null;
5385            try {
5386                reader = new FileReader(filename);
5387                char[] buf = new char[15];
5388                int n = reader.read(buf);
5389                if (n > 1) {
5390                    plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
5391                }
5392            } catch (IOException ex) {
5393                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5394            } catch (NumberFormatException ex) {
5395                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5396            } finally {
5397                if (reader != null) {
5398                    try {
5399                        reader.close();
5400                    } catch (IOException ex) {
5401                    }
5402                }
5403            }
5404        }
5405        // This dance forces the code in setHdmiPlugged to run.
5406        // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
5407        mHdmiPlugged = !plugged;
5408        setHdmiPlugged(!mHdmiPlugged);
5409    }
5410
5411    final Object mScreenshotLock = new Object();
5412    ServiceConnection mScreenshotConnection = null;
5413
5414    final Runnable mScreenshotTimeout = new Runnable() {
5415        @Override public void run() {
5416            synchronized (mScreenshotLock) {
5417                if (mScreenshotConnection != null) {
5418                    mContext.unbindService(mScreenshotConnection);
5419                    mScreenshotConnection = null;
5420                    notifyScreenshotError();
5421                }
5422            }
5423        }
5424    };
5425
5426    // Assume this is called from the Handler thread.
5427    private void takeScreenshot(final int screenshotType) {
5428        synchronized (mScreenshotLock) {
5429            if (mScreenshotConnection != null) {
5430                return;
5431            }
5432            final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
5433                    SYSUI_SCREENSHOT_SERVICE);
5434            final Intent serviceIntent = new Intent();
5435            serviceIntent.setComponent(serviceComponent);
5436            ServiceConnection conn = new ServiceConnection() {
5437                @Override
5438                public void onServiceConnected(ComponentName name, IBinder service) {
5439                    synchronized (mScreenshotLock) {
5440                        if (mScreenshotConnection != this) {
5441                            return;
5442                        }
5443                        Messenger messenger = new Messenger(service);
5444                        Message msg = Message.obtain(null, screenshotType);
5445                        final ServiceConnection myConn = this;
5446                        Handler h = new Handler(mHandler.getLooper()) {
5447                            @Override
5448                            public void handleMessage(Message msg) {
5449                                synchronized (mScreenshotLock) {
5450                                    if (mScreenshotConnection == myConn) {
5451                                        mContext.unbindService(mScreenshotConnection);
5452                                        mScreenshotConnection = null;
5453                                        mHandler.removeCallbacks(mScreenshotTimeout);
5454                                    }
5455                                }
5456                            }
5457                        };
5458                        msg.replyTo = new Messenger(h);
5459                        msg.arg1 = msg.arg2 = 0;
5460                        if (mStatusBar != null && mStatusBar.isVisibleLw())
5461                            msg.arg1 = 1;
5462                        if (mNavigationBar != null && mNavigationBar.isVisibleLw())
5463                            msg.arg2 = 1;
5464                        try {
5465                            messenger.send(msg);
5466                        } catch (RemoteException e) {
5467                        }
5468                    }
5469                }
5470
5471                @Override
5472                public void onServiceDisconnected(ComponentName name) {
5473                    notifyScreenshotError();
5474                }
5475            };
5476            if (mContext.bindServiceAsUser(serviceIntent, conn,
5477                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
5478                    UserHandle.CURRENT)) {
5479                mScreenshotConnection = conn;
5480                mHandler.postDelayed(mScreenshotTimeout, 10000);
5481            }
5482        }
5483    }
5484
5485    /**
5486     * Notifies the screenshot service to show an error.
5487     */
5488    private void notifyScreenshotError() {
5489        // If the service process is killed, then ask it to clean up after itself
5490        final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
5491                SYSUI_SCREENSHOT_ERROR_RECEIVER);
5492        Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
5493        errorIntent.setComponent(errorComponent);
5494        errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
5495                Intent.FLAG_RECEIVER_FOREGROUND);
5496        mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT);
5497    }
5498
5499    /** {@inheritDoc} */
5500    @Override
5501    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
5502        if (!mSystemBooted) {
5503            // If we have not yet booted, don't let key events do anything.
5504            return 0;
5505        }
5506
5507        final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
5508        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
5509        final boolean canceled = event.isCanceled();
5510        final int keyCode = event.getKeyCode();
5511
5512        final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
5513
5514        // If screen is off then we treat the case where the keyguard is open but hidden
5515        // the same as if it were open and in front.
5516        // This will prevent any keys other than the power button from waking the screen
5517        // when the keyguard is hidden by another activity.
5518        final boolean keyguardActive = (mKeyguardDelegate == null ? false :
5519                                            (interactive ?
5520                                                isKeyguardShowingAndNotOccluded() :
5521                                                mKeyguardDelegate.isShowing()));
5522
5523        if (DEBUG_INPUT) {
5524            Log.d(TAG, "interceptKeyTq keycode=" + keyCode
5525                    + " interactive=" + interactive + " keyguardActive=" + keyguardActive
5526                    + " policyFlags=" + Integer.toHexString(policyFlags));
5527        }
5528
5529        // Basic policy based on interactive state.
5530        int result;
5531        boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
5532                || event.isWakeKey();
5533        if (interactive || (isInjected && !isWakeKey)) {
5534            // When the device is interactive or the key is injected pass the
5535            // key to the application.
5536            result = ACTION_PASS_TO_USER;
5537            isWakeKey = false;
5538        } else if (!interactive && shouldDispatchInputWhenNonInteractive()) {
5539            // If we're currently dozing with the screen on and the keyguard showing, pass the key
5540            // to the application but preserve its wake key status to make sure we still move
5541            // from dozing to fully interactive if we would normally go from off to fully
5542            // interactive.
5543            result = ACTION_PASS_TO_USER;
5544        } else {
5545            // When the screen is off and the key is not injected, determine whether
5546            // to wake the device but don't pass the key to the application.
5547            result = 0;
5548            if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
5549                isWakeKey = false;
5550            }
5551        }
5552
5553        // If the key would be handled globally, just return the result, don't worry about special
5554        // key processing.
5555        if (isValidGlobalKey(keyCode)
5556                && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
5557            if (isWakeKey) {
5558                wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5559            }
5560            return result;
5561        }
5562
5563        boolean useHapticFeedback = down
5564                && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
5565                && event.getRepeatCount() == 0;
5566
5567        // Handle special keys.
5568        switch (keyCode) {
5569            case KeyEvent.KEYCODE_BACK: {
5570                if (down) {
5571                    mBackKeyHandled = false;
5572                    if (hasLongPressOnBackBehavior()) {
5573                        Message msg = mHandler.obtainMessage(MSG_BACK_LONG_PRESS);
5574                        msg.setAsynchronous(true);
5575                        mHandler.sendMessageDelayed(msg,
5576                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
5577                    }
5578                } else {
5579                    boolean handled = mBackKeyHandled;
5580
5581                    // Reset back key state
5582                    cancelPendingBackKeyAction();
5583
5584                    // Don't pass back press to app if we've already handled it
5585                    if (handled) {
5586                        result &= ~ACTION_PASS_TO_USER;
5587                    }
5588                }
5589                break;
5590            }
5591
5592            case KeyEvent.KEYCODE_VOLUME_DOWN:
5593            case KeyEvent.KEYCODE_VOLUME_UP:
5594            case KeyEvent.KEYCODE_VOLUME_MUTE: {
5595                if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
5596                    if (down) {
5597                        if (interactive && !mScreenshotChordVolumeDownKeyTriggered
5598                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5599                            mScreenshotChordVolumeDownKeyTriggered = true;
5600                            mScreenshotChordVolumeDownKeyTime = event.getDownTime();
5601                            mScreenshotChordVolumeDownKeyConsumed = false;
5602                            cancelPendingPowerKeyAction();
5603                            interceptScreenshotChord();
5604                        }
5605                    } else {
5606                        mScreenshotChordVolumeDownKeyTriggered = false;
5607                        cancelPendingScreenshotChordAction();
5608                    }
5609                } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
5610                    if (down) {
5611                        if (interactive && !mScreenshotChordVolumeUpKeyTriggered
5612                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5613                            mScreenshotChordVolumeUpKeyTriggered = true;
5614                            cancelPendingPowerKeyAction();
5615                            cancelPendingScreenshotChordAction();
5616                        }
5617                    } else {
5618                        mScreenshotChordVolumeUpKeyTriggered = false;
5619                        cancelPendingScreenshotChordAction();
5620                    }
5621                }
5622                if (down) {
5623                    TelecomManager telecomManager = getTelecommService();
5624                    if (telecomManager != null) {
5625                        if (telecomManager.isRinging()) {
5626                            // If an incoming call is ringing, either VOLUME key means
5627                            // "silence ringer".  We handle these keys here, rather than
5628                            // in the InCallScreen, to make sure we'll respond to them
5629                            // even if the InCallScreen hasn't come to the foreground yet.
5630                            // Look for the DOWN event here, to agree with the "fallback"
5631                            // behavior in the InCallScreen.
5632                            Log.i(TAG, "interceptKeyBeforeQueueing:"
5633                                  + " VOLUME key-down while ringing: Silence ringer!");
5634
5635                            // Silence the ringer.  (It's safe to call this
5636                            // even if the ringer has already been silenced.)
5637                            telecomManager.silenceRinger();
5638
5639                            // And *don't* pass this key thru to the current activity
5640                            // (which is probably the InCallScreen.)
5641                            result &= ~ACTION_PASS_TO_USER;
5642                            break;
5643                        }
5644                        if (telecomManager.isInCall()
5645                                && (result & ACTION_PASS_TO_USER) == 0) {
5646                            // If we are in call but we decided not to pass the key to
5647                            // the application, just pass it to the session service.
5648
5649                            MediaSessionLegacyHelper.getHelper(mContext)
5650                                    .sendVolumeKeyEvent(event, false);
5651                            break;
5652                        }
5653                    }
5654                }
5655                if (mUseTvRouting) {
5656                    // On TVs, defer special key handlings to
5657                    // {@link interceptKeyBeforeDispatching()}.
5658                    result |= ACTION_PASS_TO_USER;
5659                } else if ((result & ACTION_PASS_TO_USER) == 0) {
5660                    // If we aren't passing to the user and no one else
5661                    // handled it send it to the session manager to
5662                    // figure out.
5663                    MediaSessionLegacyHelper.getHelper(mContext)
5664                            .sendVolumeKeyEvent(event, true);
5665                }
5666                break;
5667            }
5668
5669            case KeyEvent.KEYCODE_ENDCALL: {
5670                result &= ~ACTION_PASS_TO_USER;
5671                if (down) {
5672                    TelecomManager telecomManager = getTelecommService();
5673                    boolean hungUp = false;
5674                    if (telecomManager != null) {
5675                        hungUp = telecomManager.endCall();
5676                    }
5677                    if (interactive && !hungUp) {
5678                        mEndCallKeyHandled = false;
5679                        mHandler.postDelayed(mEndCallLongPress,
5680                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
5681                    } else {
5682                        mEndCallKeyHandled = true;
5683                    }
5684                } else {
5685                    if (!mEndCallKeyHandled) {
5686                        mHandler.removeCallbacks(mEndCallLongPress);
5687                        if (!canceled) {
5688                            if ((mEndcallBehavior
5689                                    & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
5690                                if (goHome()) {
5691                                    break;
5692                                }
5693                            }
5694                            if ((mEndcallBehavior
5695                                    & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
5696                                mPowerManager.goToSleep(event.getEventTime(),
5697                                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
5698                                isWakeKey = false;
5699                            }
5700                        }
5701                    }
5702                }
5703                break;
5704            }
5705
5706            case KeyEvent.KEYCODE_POWER: {
5707                result &= ~ACTION_PASS_TO_USER;
5708                isWakeKey = false; // wake-up will be handled separately
5709                if (down) {
5710                    interceptPowerKeyDown(event, interactive);
5711                } else {
5712                    interceptPowerKeyUp(event, interactive, canceled);
5713                }
5714                break;
5715            }
5716
5717            case KeyEvent.KEYCODE_FP_NAV_DOWN:
5718                // fall through
5719            case KeyEvent.KEYCODE_FP_NAV_UP:
5720                // fall through
5721            case KeyEvent.KEYCODE_FP_NAV_LEFT:
5722                // fall through
5723            case KeyEvent.KEYCODE_FP_NAV_RIGHT: {
5724                interceptStatusBarKey(event);
5725                break;
5726            }
5727
5728            case KeyEvent.KEYCODE_SLEEP: {
5729                result &= ~ACTION_PASS_TO_USER;
5730                isWakeKey = false;
5731                if (!mPowerManager.isInteractive()) {
5732                    useHapticFeedback = false; // suppress feedback if already non-interactive
5733                }
5734                if (down) {
5735                    sleepPress(event.getEventTime());
5736                } else {
5737                    sleepRelease(event.getEventTime());
5738                }
5739                break;
5740            }
5741
5742            case KeyEvent.KEYCODE_SOFT_SLEEP: {
5743                result &= ~ACTION_PASS_TO_USER;
5744                isWakeKey = false;
5745                if (!down) {
5746                    mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
5747                }
5748                break;
5749            }
5750
5751            case KeyEvent.KEYCODE_WAKEUP: {
5752                result &= ~ACTION_PASS_TO_USER;
5753                isWakeKey = true;
5754                break;
5755            }
5756
5757            case KeyEvent.KEYCODE_MEDIA_PLAY:
5758            case KeyEvent.KEYCODE_MEDIA_PAUSE:
5759            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
5760            case KeyEvent.KEYCODE_HEADSETHOOK:
5761            case KeyEvent.KEYCODE_MUTE:
5762            case KeyEvent.KEYCODE_MEDIA_STOP:
5763            case KeyEvent.KEYCODE_MEDIA_NEXT:
5764            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
5765            case KeyEvent.KEYCODE_MEDIA_REWIND:
5766            case KeyEvent.KEYCODE_MEDIA_RECORD:
5767            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
5768            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
5769                if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
5770                    // If the global session is active pass all media keys to it
5771                    // instead of the active window.
5772                    result &= ~ACTION_PASS_TO_USER;
5773                }
5774                if ((result & ACTION_PASS_TO_USER) == 0) {
5775                    // Only do this if we would otherwise not pass it to the user. In that
5776                    // case, the PhoneWindow class will do the same thing, except it will
5777                    // only do it if the showing app doesn't process the key on its own.
5778                    // Note that we need to make a copy of the key event here because the
5779                    // original key event will be recycled when we return.
5780                    mBroadcastWakeLock.acquire();
5781                    Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
5782                            new KeyEvent(event));
5783                    msg.setAsynchronous(true);
5784                    msg.sendToTarget();
5785                }
5786                break;
5787            }
5788
5789            case KeyEvent.KEYCODE_CALL: {
5790                if (down) {
5791                    TelecomManager telecomManager = getTelecommService();
5792                    if (telecomManager != null) {
5793                        if (telecomManager.isRinging()) {
5794                            Log.i(TAG, "interceptKeyBeforeQueueing:"
5795                                  + " CALL key-down while ringing: Answer the call!");
5796                            telecomManager.acceptRingingCall();
5797
5798                            // And *don't* pass this key thru to the current activity
5799                            // (which is presumably the InCallScreen.)
5800                            result &= ~ACTION_PASS_TO_USER;
5801                        }
5802                    }
5803                }
5804                break;
5805            }
5806            case KeyEvent.KEYCODE_VOICE_ASSIST: {
5807                // Only do this if we would otherwise not pass it to the user. In that case,
5808                // interceptKeyBeforeDispatching would apply a similar but different policy in
5809                // order to invoke voice assist actions. Note that we need to make a copy of the
5810                // key event here because the original key event will be recycled when we return.
5811                if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
5812                    mBroadcastWakeLock.acquire();
5813                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
5814                            keyguardActive ? 1 : 0, 0);
5815                    msg.setAsynchronous(true);
5816                    msg.sendToTarget();
5817                }
5818                break;
5819            }
5820            case KeyEvent.KEYCODE_WINDOW: {
5821                if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
5822                    if (mTvPictureInPictureVisible) {
5823                        // Consumes the key only if picture-in-picture is visible
5824                        // to show picture-in-picture control menu.
5825                        // This gives a chance to the foreground activity
5826                        // to customize PIP key behavior.
5827                        if (!down) {
5828                            showTvPictureInPictureMenu(event);
5829                        }
5830                        result &= ~ACTION_PASS_TO_USER;
5831                    }
5832                }
5833                break;
5834            }
5835        }
5836
5837        if (useHapticFeedback) {
5838            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
5839        }
5840
5841        if (isWakeKey) {
5842            wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5843        }
5844
5845        return result;
5846    }
5847
5848    /**
5849     * Handle statusbar expansion events.
5850     * @param event
5851     */
5852    private void interceptStatusBarKey(KeyEvent event) {
5853        final int e = event.getKeyCode();
5854        if (event.getAction() == KeyEvent.ACTION_UP) {
5855            boolean doOpen = false;
5856            boolean doClose = false;
5857            doOpen = (e == KeyEvent.KEYCODE_FP_NAV_DOWN);
5858            doClose = (e == KeyEvent.KEYCODE_FP_NAV_UP);
5859            IStatusBarService sbar = getStatusBarService();
5860            if (sbar != null) {
5861                try {
5862                    if (doOpen) {
5863                        sbar.expandNotificationsPanel();
5864                    } else if (doClose) {
5865                        sbar.collapsePanels();
5866                    }
5867                } catch (RemoteException e1) {
5868                    // oops, no statusbar. Ignore event.
5869                }
5870            }
5871        }
5872    }
5873
5874    /**
5875     * Returns true if the key can have global actions attached to it.
5876     * We reserve all power management keys for the system since they require
5877     * very careful handling.
5878     */
5879    private static boolean isValidGlobalKey(int keyCode) {
5880        switch (keyCode) {
5881            case KeyEvent.KEYCODE_POWER:
5882            case KeyEvent.KEYCODE_WAKEUP:
5883            case KeyEvent.KEYCODE_SLEEP:
5884                return false;
5885            default:
5886                return true;
5887        }
5888    }
5889
5890    /**
5891     * When the screen is off we ignore some keys that might otherwise typically
5892     * be considered wake keys.  We filter them out here.
5893     *
5894     * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
5895     * is always considered a wake key.
5896     */
5897    private boolean isWakeKeyWhenScreenOff(int keyCode) {
5898        switch (keyCode) {
5899            // ignore volume keys unless docked
5900            case KeyEvent.KEYCODE_VOLUME_UP:
5901            case KeyEvent.KEYCODE_VOLUME_DOWN:
5902            case KeyEvent.KEYCODE_VOLUME_MUTE:
5903                return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
5904
5905            // ignore media and camera keys
5906            case KeyEvent.KEYCODE_MUTE:
5907            case KeyEvent.KEYCODE_HEADSETHOOK:
5908            case KeyEvent.KEYCODE_MEDIA_PLAY:
5909            case KeyEvent.KEYCODE_MEDIA_PAUSE:
5910            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
5911            case KeyEvent.KEYCODE_MEDIA_STOP:
5912            case KeyEvent.KEYCODE_MEDIA_NEXT:
5913            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
5914            case KeyEvent.KEYCODE_MEDIA_REWIND:
5915            case KeyEvent.KEYCODE_MEDIA_RECORD:
5916            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
5917            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
5918            case KeyEvent.KEYCODE_CAMERA:
5919                return false;
5920        }
5921        return true;
5922    }
5923
5924
5925    /** {@inheritDoc} */
5926    @Override
5927    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
5928        if ((policyFlags & FLAG_WAKE) != 0) {
5929            if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
5930                    "android.policy:MOTION")) {
5931                return 0;
5932            }
5933        }
5934
5935        if (shouldDispatchInputWhenNonInteractive()) {
5936            return ACTION_PASS_TO_USER;
5937        }
5938
5939        // If we have not passed the action up and we are in theater mode without dreaming,
5940        // there will be no dream to intercept the touch and wake into ambient.  The device should
5941        // wake up in this case.
5942        if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
5943            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
5944                    "android.policy:MOTION");
5945        }
5946
5947        return 0;
5948    }
5949
5950    private boolean shouldDispatchInputWhenNonInteractive() {
5951        final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
5952
5953        if (displayOff && !mHasFeatureWatch) {
5954            return false;
5955        }
5956
5957        // Send events to keyguard while the screen is on and it's showing.
5958        if (isKeyguardShowingAndNotOccluded() && !displayOff) {
5959            return true;
5960        }
5961
5962        // Send events to a dozing dream even if the screen is off since the dream
5963        // is in control of the state of the screen.
5964        IDreamManager dreamManager = getDreamManager();
5965
5966        try {
5967            if (dreamManager != null && dreamManager.isDreaming()) {
5968                return true;
5969            }
5970        } catch (RemoteException e) {
5971            Slog.e(TAG, "RemoteException when checking if dreaming", e);
5972        }
5973
5974        // Otherwise, consume events since the user can't see what is being
5975        // interacted with.
5976        return false;
5977    }
5978
5979    private void dispatchDirectAudioEvent(KeyEvent event) {
5980        if (event.getAction() != KeyEvent.ACTION_DOWN) {
5981            return;
5982        }
5983        int keyCode = event.getKeyCode();
5984        int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
5985                | AudioManager.FLAG_FROM_KEY;
5986        String pkgName = mContext.getOpPackageName();
5987        switch (keyCode) {
5988            case KeyEvent.KEYCODE_VOLUME_UP:
5989                try {
5990                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
5991                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
5992                } catch (RemoteException e) {
5993                    Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
5994                }
5995                break;
5996            case KeyEvent.KEYCODE_VOLUME_DOWN:
5997                try {
5998                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
5999                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6000                } catch (RemoteException e) {
6001                    Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
6002                }
6003                break;
6004            case KeyEvent.KEYCODE_VOLUME_MUTE:
6005                try {
6006                    if (event.getRepeatCount() == 0) {
6007                        getAudioService().adjustSuggestedStreamVolume(
6008                                AudioManager.ADJUST_TOGGLE_MUTE,
6009                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6010                    }
6011                } catch (RemoteException e) {
6012                    Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
6013                }
6014                break;
6015        }
6016    }
6017
6018    void dispatchMediaKeyWithWakeLock(KeyEvent event) {
6019        if (DEBUG_INPUT) {
6020            Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
6021        }
6022
6023        if (mHavePendingMediaKeyRepeatWithWakeLock) {
6024            if (DEBUG_INPUT) {
6025                Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
6026            }
6027
6028            mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
6029            mHavePendingMediaKeyRepeatWithWakeLock = false;
6030            mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
6031        }
6032
6033        dispatchMediaKeyWithWakeLockToAudioService(event);
6034
6035        if (event.getAction() == KeyEvent.ACTION_DOWN
6036                && event.getRepeatCount() == 0) {
6037            mHavePendingMediaKeyRepeatWithWakeLock = true;
6038
6039            Message msg = mHandler.obtainMessage(
6040                    MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
6041            msg.setAsynchronous(true);
6042            mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
6043        } else {
6044            mBroadcastWakeLock.release();
6045        }
6046    }
6047
6048    void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
6049        mHavePendingMediaKeyRepeatWithWakeLock = false;
6050
6051        KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
6052                SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6053        if (DEBUG_INPUT) {
6054            Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
6055        }
6056
6057        dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
6058        mBroadcastWakeLock.release();
6059    }
6060
6061    void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
6062        if (ActivityManagerNative.isSystemReady()) {
6063            MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
6064        }
6065    }
6066
6067    void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
6068        IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
6069                ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
6070        if (dic != null) {
6071            try {
6072                dic.exitIdle("voice-search");
6073            } catch (RemoteException e) {
6074            }
6075        }
6076        Intent voiceIntent =
6077            new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
6078        voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
6079        startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
6080        mBroadcastWakeLock.release();
6081    }
6082
6083    BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
6084        @Override
6085        public void onReceive(Context context, Intent intent) {
6086            if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
6087                mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6088                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
6089            } else {
6090                try {
6091                    IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
6092                            ServiceManager.getService(Context.UI_MODE_SERVICE));
6093                    mUiMode = uiModeService.getCurrentModeType();
6094                } catch (RemoteException e) {
6095                }
6096            }
6097            updateRotation(true);
6098            synchronized (mLock) {
6099                updateOrientationListenerLp();
6100            }
6101        }
6102    };
6103
6104    BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
6105        @Override
6106        public void onReceive(Context context, Intent intent) {
6107            if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
6108                if (mKeyguardDelegate != null) {
6109                    mKeyguardDelegate.onDreamingStarted();
6110                }
6111            } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
6112                if (mKeyguardDelegate != null) {
6113                    mKeyguardDelegate.onDreamingStopped();
6114                }
6115            }
6116        }
6117    };
6118
6119    BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
6120        @Override
6121        public void onReceive(Context context, Intent intent) {
6122            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
6123                // tickle the settings observer: this first ensures that we're
6124                // observing the relevant settings for the newly-active user,
6125                // and then updates our own bookkeeping based on the now-
6126                // current user.
6127                mSettingsObserver.onChange(false);
6128
6129                // force a re-application of focused window sysui visibility.
6130                // the window may never have been shown for this user
6131                // e.g. the keyguard when going through the new-user setup flow
6132                synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6133                    mLastSystemUiFlags = 0;
6134                    updateSystemUiVisibilityLw();
6135                }
6136            }
6137        }
6138    };
6139
6140    private final Runnable mHiddenNavPanic = new Runnable() {
6141        @Override
6142        public void run() {
6143            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6144                if (!isUserSetupComplete()) {
6145                    // Swipe-up for navigation bar is disabled during setup
6146                    return;
6147                }
6148                mPendingPanicGestureUptime = SystemClock.uptimeMillis();
6149                mNavigationBarController.showTransient();
6150            }
6151        }
6152    };
6153
6154    private void requestTransientBars(WindowState swipeTarget) {
6155        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6156            if (!isUserSetupComplete()) {
6157                // Swipe-up for navigation bar is disabled during setup
6158                return;
6159            }
6160            boolean sb = mStatusBarController.checkShowTransientBarLw();
6161            boolean nb = mNavigationBarController.checkShowTransientBarLw();
6162            if (sb || nb) {
6163                // Don't show status bar when swiping on already visible navigation bar
6164                if (!nb && swipeTarget == mNavigationBar) {
6165                    if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
6166                    return;
6167                }
6168                if (sb) mStatusBarController.showTransient();
6169                if (nb) mNavigationBarController.showTransient();
6170                mImmersiveModeConfirmation.confirmCurrentPrompt();
6171                updateSystemUiVisibilityLw();
6172            }
6173        }
6174    }
6175
6176    // Called on the PowerManager's Notifier thread.
6177    @Override
6178    public void startedGoingToSleep(int why) {
6179        if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
6180        mCameraGestureTriggeredDuringGoingToSleep = false;
6181        mGoingToSleep = true;
6182        if (mKeyguardDelegate != null) {
6183            mKeyguardDelegate.onStartedGoingToSleep(why);
6184        }
6185    }
6186
6187    // Called on the PowerManager's Notifier thread.
6188    @Override
6189    public void finishedGoingToSleep(int why) {
6190        EventLog.writeEvent(70000, 0);
6191        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
6192        MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
6193
6194        mGoingToSleep = false;
6195
6196        // We must get this work done here because the power manager will drop
6197        // the wake lock and let the system suspend once this function returns.
6198        synchronized (mLock) {
6199            mAwake = false;
6200            updateWakeGestureListenerLp();
6201            updateOrientationListenerLp();
6202            updateLockScreenTimeout();
6203        }
6204        if (mKeyguardDelegate != null) {
6205            mKeyguardDelegate.onFinishedGoingToSleep(why,
6206                    mCameraGestureTriggeredDuringGoingToSleep);
6207        }
6208        mCameraGestureTriggeredDuringGoingToSleep = false;
6209    }
6210
6211    // Called on the PowerManager's Notifier thread.
6212    @Override
6213    public void startedWakingUp() {
6214        EventLog.writeEvent(70000, 1);
6215        if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
6216
6217        // Since goToSleep performs these functions synchronously, we must
6218        // do the same here.  We cannot post this work to a handler because
6219        // that might cause it to become reordered with respect to what
6220        // may happen in a future call to goToSleep.
6221        synchronized (mLock) {
6222            mAwake = true;
6223
6224            updateWakeGestureListenerLp();
6225            updateOrientationListenerLp();
6226            updateLockScreenTimeout();
6227        }
6228
6229        if (mKeyguardDelegate != null) {
6230            mKeyguardDelegate.onStartedWakingUp();
6231        }
6232    }
6233
6234    // Called on the PowerManager's Notifier thread.
6235    @Override
6236    public void finishedWakingUp() {
6237        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
6238    }
6239
6240    private void wakeUpFromPowerKey(long eventTime) {
6241        wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
6242    }
6243
6244    private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
6245        final boolean theaterModeEnabled = isTheaterModeEnabled();
6246        if (!wakeInTheaterMode && theaterModeEnabled) {
6247            return false;
6248        }
6249
6250        if (theaterModeEnabled) {
6251            Settings.Global.putInt(mContext.getContentResolver(),
6252                    Settings.Global.THEATER_MODE_ON, 0);
6253        }
6254
6255        mPowerManager.wakeUp(wakeTime, reason);
6256        return true;
6257    }
6258
6259    private void finishKeyguardDrawn() {
6260        synchronized (mLock) {
6261            if (!mScreenOnEarly || mKeyguardDrawComplete) {
6262                return; // We are not awake yet or we have already informed of this event.
6263            }
6264
6265            mKeyguardDrawComplete = true;
6266            if (mKeyguardDelegate != null) {
6267                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6268            }
6269            mWindowManagerDrawComplete = false;
6270        }
6271
6272        // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
6273        // as well as enabling the orientation change logic/sensor.
6274        mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
6275                WAITING_FOR_DRAWN_TIMEOUT);
6276    }
6277
6278    // Called on the DisplayManager's DisplayPowerController thread.
6279    @Override
6280    public void screenTurnedOff() {
6281        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
6282
6283        updateScreenOffSleepToken(true);
6284        synchronized (mLock) {
6285            mScreenOnEarly = false;
6286            mScreenOnFully = false;
6287            mKeyguardDrawComplete = false;
6288            mWindowManagerDrawComplete = false;
6289            mScreenOnListener = null;
6290            updateOrientationListenerLp();
6291
6292            if (mKeyguardDelegate != null) {
6293                mKeyguardDelegate.onScreenTurnedOff();
6294            }
6295        }
6296    }
6297
6298    // Called on the DisplayManager's DisplayPowerController thread.
6299    @Override
6300    public void screenTurningOn(final ScreenOnListener screenOnListener) {
6301        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
6302
6303        updateScreenOffSleepToken(false);
6304        synchronized (mLock) {
6305            mScreenOnEarly = true;
6306            mScreenOnFully = false;
6307            mKeyguardDrawComplete = false;
6308            mWindowManagerDrawComplete = false;
6309            mScreenOnListener = screenOnListener;
6310
6311            if (mKeyguardDelegate != null) {
6312                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6313                mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
6314                mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
6315            } else {
6316                if (DEBUG_WAKEUP) Slog.d(TAG,
6317                        "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
6318                finishKeyguardDrawn();
6319            }
6320        }
6321    }
6322
6323    // Called on the DisplayManager's DisplayPowerController thread.
6324    @Override
6325    public void screenTurnedOn() {
6326        synchronized (mLock) {
6327            if (mKeyguardDelegate != null) {
6328                mKeyguardDelegate.onScreenTurnedOn();
6329            }
6330        }
6331    }
6332
6333    private void finishWindowsDrawn() {
6334        synchronized (mLock) {
6335            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
6336                return; // Screen is not turned on or we did already handle this case earlier.
6337            }
6338
6339            mWindowManagerDrawComplete = true;
6340        }
6341
6342        finishScreenTurningOn();
6343    }
6344
6345    private void finishScreenTurningOn() {
6346        synchronized (mLock) {
6347            // We have just finished drawing screen content. Since the orientation listener
6348            // gets only installed when all windows are drawn, we try to install it again.
6349            updateOrientationListenerLp();
6350        }
6351        final ScreenOnListener listener;
6352        final boolean enableScreen;
6353        synchronized (mLock) {
6354            if (DEBUG_WAKEUP) Slog.d(TAG,
6355                    "finishScreenTurningOn: mAwake=" + mAwake
6356                            + ", mScreenOnEarly=" + mScreenOnEarly
6357                            + ", mScreenOnFully=" + mScreenOnFully
6358                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
6359                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
6360
6361            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
6362                    || (mAwake && !mKeyguardDrawComplete)) {
6363                return; // spurious or not ready yet
6364            }
6365
6366            if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
6367            listener = mScreenOnListener;
6368            mScreenOnListener = null;
6369            mScreenOnFully = true;
6370
6371            // Remember the first time we draw the keyguard so we know when we're done with
6372            // the main part of booting and can enable the screen and hide boot messages.
6373            if (!mKeyguardDrawnOnce && mAwake) {
6374                mKeyguardDrawnOnce = true;
6375                enableScreen = true;
6376                if (mBootMessageNeedsHiding) {
6377                    mBootMessageNeedsHiding = false;
6378                    hideBootMessages();
6379                }
6380            } else {
6381                enableScreen = false;
6382            }
6383        }
6384
6385        if (listener != null) {
6386            listener.onScreenOn();
6387        }
6388
6389        if (enableScreen) {
6390            try {
6391                mWindowManager.enableScreenIfNeeded();
6392            } catch (RemoteException unhandled) {
6393            }
6394        }
6395    }
6396
6397    private void handleHideBootMessage() {
6398        synchronized (mLock) {
6399            if (!mKeyguardDrawnOnce) {
6400                mBootMessageNeedsHiding = true;
6401                return; // keyguard hasn't drawn the first time yet, not done booting
6402            }
6403        }
6404
6405        if (mBootMsgDialog != null) {
6406            if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
6407            mBootMsgDialog.dismiss();
6408            mBootMsgDialog = null;
6409        }
6410    }
6411
6412    @Override
6413    public boolean isScreenOn() {
6414        return mScreenOnFully;
6415    }
6416
6417    /** {@inheritDoc} */
6418    @Override
6419    public void enableKeyguard(boolean enabled) {
6420        if (mKeyguardDelegate != null) {
6421            mKeyguardDelegate.setKeyguardEnabled(enabled);
6422        }
6423    }
6424
6425    /** {@inheritDoc} */
6426    @Override
6427    public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
6428        if (mKeyguardDelegate != null) {
6429            mKeyguardDelegate.verifyUnlock(callback);
6430        }
6431    }
6432
6433    private boolean isKeyguardShowingAndNotOccluded() {
6434        if (mKeyguardDelegate == null) return false;
6435        return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
6436    }
6437
6438    /** {@inheritDoc} */
6439    @Override
6440    public boolean isKeyguardLocked() {
6441        return keyguardOn();
6442    }
6443
6444    /** {@inheritDoc} */
6445    @Override
6446    public boolean isKeyguardSecure(int userId) {
6447        if (mKeyguardDelegate == null) return false;
6448        return mKeyguardDelegate.isSecure(userId);
6449    }
6450
6451    /** {@inheritDoc} */
6452    @Override
6453    public boolean isKeyguardShowingOrOccluded() {
6454        return mKeyguardDelegate == null ? false : mKeyguardDelegate.isShowing();
6455    }
6456
6457    /** {@inheritDoc} */
6458    @Override
6459    public boolean inKeyguardRestrictedKeyInputMode() {
6460        if (mKeyguardDelegate == null) return false;
6461        return mKeyguardDelegate.isInputRestricted();
6462    }
6463
6464    @Override
6465    public void dismissKeyguardLw() {
6466        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
6467            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
6468            mHandler.post(new Runnable() {
6469                @Override
6470                public void run() {
6471                    // ask the keyguard to prompt the user to authenticate if necessary
6472                    mKeyguardDelegate.dismiss();
6473                }
6474            });
6475        }
6476    }
6477
6478    @Override
6479    public void notifyActivityDrawnForKeyguardLw() {
6480        if (mKeyguardDelegate != null) {
6481            mHandler.post(new Runnable() {
6482                @Override
6483                public void run() {
6484                    mKeyguardDelegate.onActivityDrawn();
6485                }
6486            });
6487        }
6488    }
6489
6490    @Override
6491    public boolean isKeyguardDrawnLw() {
6492        synchronized (mLock) {
6493            return mKeyguardDrawnOnce;
6494        }
6495    }
6496
6497    @Override
6498    public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
6499        if (mKeyguardDelegate != null) {
6500            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
6501            mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
6502        }
6503    }
6504
6505    @Override
6506    public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6507            Rect outInsets) {
6508        outInsets.setEmpty();
6509
6510        // Navigation bar and status bar.
6511        getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
6512        if (mStatusBar != null) {
6513            outInsets.top = mStatusBarHeight;
6514        }
6515    }
6516
6517    @Override
6518    public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6519            Rect outInsets) {
6520        outInsets.setEmpty();
6521
6522        // Only navigation bar
6523        if (mNavigationBar != null) {
6524            int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
6525            if (position == NAV_BAR_BOTTOM) {
6526                outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
6527            } else if (position == NAV_BAR_RIGHT) {
6528                outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
6529            } else if (position == NAV_BAR_LEFT) {
6530                outInsets.left = getNavigationBarWidth(displayRotation, mUiMode);
6531            }
6532        }
6533    }
6534
6535    @Override
6536    public boolean isNavBarForcedShownLw(WindowState windowState) {
6537        return mForceShowSystemBars;
6538    }
6539
6540    @Override
6541    public boolean isDockSideAllowed(int dockSide) {
6542
6543        // We do not allow all dock sides at which the navigation bar touches the docked stack.
6544        if (!mNavigationBarCanMove) {
6545            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT;
6546        } else {
6547            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT;
6548        }
6549    }
6550
6551    void sendCloseSystemWindows() {
6552        PhoneWindow.sendCloseSystemWindows(mContext, null);
6553    }
6554
6555    void sendCloseSystemWindows(String reason) {
6556        PhoneWindow.sendCloseSystemWindows(mContext, reason);
6557    }
6558
6559    @Override
6560    public int rotationForOrientationLw(int orientation, int lastRotation) {
6561        if (false) {
6562            Slog.v(TAG, "rotationForOrientationLw(orient="
6563                        + orientation + ", last=" + lastRotation
6564                        + "); user=" + mUserRotation + " "
6565                        + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
6566                            ? "USER_ROTATION_LOCKED" : "")
6567                        );
6568        }
6569
6570        if (mForceDefaultOrientation) {
6571            return Surface.ROTATION_0;
6572        }
6573
6574        synchronized (mLock) {
6575            int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
6576            if (sensorRotation < 0) {
6577                sensorRotation = lastRotation;
6578            }
6579
6580            final int preferredRotation;
6581            if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
6582                // Ignore sensor when lid switch is open and rotation is forced.
6583                preferredRotation = mLidOpenRotation;
6584            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
6585                    && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
6586                // Ignore sensor when in car dock unless explicitly enabled.
6587                // This case can override the behavior of NOSENSOR, and can also
6588                // enable 180 degree rotation while docked.
6589                preferredRotation = mCarDockEnablesAccelerometer
6590                        ? sensorRotation : mCarDockRotation;
6591            } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
6592                    || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
6593                    || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
6594                    && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
6595                // Ignore sensor when in desk dock unless explicitly enabled.
6596                // This case can override the behavior of NOSENSOR, and can also
6597                // enable 180 degree rotation while docked.
6598                preferredRotation = mDeskDockEnablesAccelerometer
6599                        ? sensorRotation : mDeskDockRotation;
6600            } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
6601                // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
6602                // Note that the dock orientation overrides the HDMI orientation.
6603                preferredRotation = mDemoHdmiRotation;
6604            } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
6605                    && mUndockedHdmiRotation >= 0) {
6606                // Ignore sensor when plugged into HDMI and an undocked orientation has
6607                // been specified in the configuration (only for legacy devices without
6608                // full multi-display support).
6609                // Note that the dock orientation overrides the HDMI orientation.
6610                preferredRotation = mUndockedHdmiRotation;
6611            } else if (mDemoRotationLock) {
6612                // Ignore sensor when demo rotation lock is enabled.
6613                // Note that the dock orientation and HDMI rotation lock override this.
6614                preferredRotation = mDemoRotation;
6615            } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
6616                // Application just wants to remain locked in the last rotation.
6617                preferredRotation = lastRotation;
6618            } else if (!mSupportAutoRotation) {
6619                // If we don't support auto-rotation then bail out here and ignore
6620                // the sensor and any rotation lock settings.
6621                preferredRotation = -1;
6622            } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
6623                            && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
6624                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
6625                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
6626                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
6627                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
6628                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
6629                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6630                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
6631                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
6632                // Otherwise, use sensor only if requested by the application or enabled
6633                // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
6634                if (mAllowAllRotations < 0) {
6635                    // Can't read this during init() because the context doesn't
6636                    // have display metrics at that time so we cannot determine
6637                    // tablet vs. phone then.
6638                    mAllowAllRotations = mContext.getResources().getBoolean(
6639                            com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
6640                }
6641                if (sensorRotation != Surface.ROTATION_180
6642                        || mAllowAllRotations == 1
6643                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6644                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
6645                    preferredRotation = sensorRotation;
6646                } else {
6647                    preferredRotation = lastRotation;
6648                }
6649            } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
6650                    && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
6651                // Apply rotation lock.  Does not apply to NOSENSOR.
6652                // The idea is that the user rotation expresses a weak preference for the direction
6653                // of gravity and as NOSENSOR is never affected by gravity, then neither should
6654                // NOSENSOR be affected by rotation lock (although it will be affected by docks).
6655                preferredRotation = mUserRotation;
6656            } else {
6657                // No overriding preference.
6658                // We will do exactly what the application asked us to do.
6659                preferredRotation = -1;
6660            }
6661
6662            switch (orientation) {
6663                case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6664                    // Return portrait unless overridden.
6665                    if (isAnyPortrait(preferredRotation)) {
6666                        return preferredRotation;
6667                    }
6668                    return mPortraitRotation;
6669
6670                case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6671                    // Return landscape unless overridden.
6672                    if (isLandscapeOrSeascape(preferredRotation)) {
6673                        return preferredRotation;
6674                    }
6675                    return mLandscapeRotation;
6676
6677                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6678                    // Return reverse portrait unless overridden.
6679                    if (isAnyPortrait(preferredRotation)) {
6680                        return preferredRotation;
6681                    }
6682                    return mUpsideDownRotation;
6683
6684                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6685                    // Return seascape unless overridden.
6686                    if (isLandscapeOrSeascape(preferredRotation)) {
6687                        return preferredRotation;
6688                    }
6689                    return mSeascapeRotation;
6690
6691                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6692                case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
6693                    // Return either landscape rotation.
6694                    if (isLandscapeOrSeascape(preferredRotation)) {
6695                        return preferredRotation;
6696                    }
6697                    if (isLandscapeOrSeascape(lastRotation)) {
6698                        return lastRotation;
6699                    }
6700                    return mLandscapeRotation;
6701
6702                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6703                case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
6704                    // Return either portrait rotation.
6705                    if (isAnyPortrait(preferredRotation)) {
6706                        return preferredRotation;
6707                    }
6708                    if (isAnyPortrait(lastRotation)) {
6709                        return lastRotation;
6710                    }
6711                    return mPortraitRotation;
6712
6713                default:
6714                    // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
6715                    // just return the preferred orientation we already calculated.
6716                    if (preferredRotation >= 0) {
6717                        return preferredRotation;
6718                    }
6719                    return Surface.ROTATION_0;
6720            }
6721        }
6722    }
6723
6724    @Override
6725    public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
6726        switch (orientation) {
6727            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6728            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6729            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6730                return isAnyPortrait(rotation);
6731
6732            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6733            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6734            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6735                return isLandscapeOrSeascape(rotation);
6736
6737            default:
6738                return true;
6739        }
6740    }
6741
6742    @Override
6743    public void setRotationLw(int rotation) {
6744        mOrientationListener.setCurrentRotation(rotation);
6745    }
6746
6747    private boolean isLandscapeOrSeascape(int rotation) {
6748        return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
6749    }
6750
6751    private boolean isAnyPortrait(int rotation) {
6752        return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
6753    }
6754
6755    @Override
6756    public int getUserRotationMode() {
6757        return Settings.System.getIntForUser(mContext.getContentResolver(),
6758                Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
6759                        WindowManagerPolicy.USER_ROTATION_FREE :
6760                                WindowManagerPolicy.USER_ROTATION_LOCKED;
6761    }
6762
6763    // User rotation: to be used when all else fails in assigning an orientation to the device
6764    @Override
6765    public void setUserRotationMode(int mode, int rot) {
6766        ContentResolver res = mContext.getContentResolver();
6767
6768        // mUserRotationMode and mUserRotation will be assigned by the content observer
6769        if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
6770            Settings.System.putIntForUser(res,
6771                    Settings.System.USER_ROTATION,
6772                    rot,
6773                    UserHandle.USER_CURRENT);
6774            Settings.System.putIntForUser(res,
6775                    Settings.System.ACCELEROMETER_ROTATION,
6776                    0,
6777                    UserHandle.USER_CURRENT);
6778        } else {
6779            Settings.System.putIntForUser(res,
6780                    Settings.System.ACCELEROMETER_ROTATION,
6781                    1,
6782                    UserHandle.USER_CURRENT);
6783        }
6784    }
6785
6786    @Override
6787    public void setSafeMode(boolean safeMode) {
6788        mSafeMode = safeMode;
6789        performHapticFeedbackLw(null, safeMode
6790                ? HapticFeedbackConstants.SAFE_MODE_ENABLED
6791                : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
6792    }
6793
6794    static long[] getLongIntArray(Resources r, int resid) {
6795        int[] ar = r.getIntArray(resid);
6796        if (ar == null) {
6797            return null;
6798        }
6799        long[] out = new long[ar.length];
6800        for (int i=0; i<ar.length; i++) {
6801            out[i] = ar[i];
6802        }
6803        return out;
6804    }
6805
6806    /** {@inheritDoc} */
6807    @Override
6808    public void systemReady() {
6809        mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
6810        mKeyguardDelegate.onSystemReady();
6811
6812        readCameraLensCoverState();
6813        updateUiMode();
6814        boolean bindKeyguardNow;
6815        synchronized (mLock) {
6816            updateOrientationListenerLp();
6817            mSystemReady = true;
6818            mHandler.post(new Runnable() {
6819                @Override
6820                public void run() {
6821                    updateSettings();
6822                }
6823            });
6824
6825            bindKeyguardNow = mDeferBindKeyguard;
6826            if (bindKeyguardNow) {
6827                // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now.
6828                mDeferBindKeyguard = false;
6829            }
6830        }
6831
6832        if (bindKeyguardNow) {
6833            mKeyguardDelegate.bindService(mContext);
6834            mKeyguardDelegate.onBootCompleted();
6835        }
6836        mSystemGestures.systemReady();
6837        mImmersiveModeConfirmation.systemReady();
6838    }
6839
6840    /** {@inheritDoc} */
6841    @Override
6842    public void systemBooted() {
6843        boolean bindKeyguardNow = false;
6844        synchronized (mLock) {
6845            // Time to bind Keyguard; take care to only bind it once, either here if ready or
6846            // in systemReady if not.
6847            if (mKeyguardDelegate != null) {
6848                bindKeyguardNow = true;
6849            } else {
6850                // Because mKeyguardDelegate is null, we know that the synchronized block in
6851                // systemReady didn't run yet and setting this will actually have an effect.
6852                mDeferBindKeyguard = true;
6853            }
6854        }
6855        if (bindKeyguardNow) {
6856            mKeyguardDelegate.bindService(mContext);
6857            mKeyguardDelegate.onBootCompleted();
6858        }
6859        synchronized (mLock) {
6860            mSystemBooted = true;
6861        }
6862        startedWakingUp();
6863        screenTurningOn(null);
6864        screenTurnedOn();
6865    }
6866
6867    ProgressDialog mBootMsgDialog = null;
6868
6869    /** {@inheritDoc} */
6870    @Override
6871    public void showBootMessage(final CharSequence msg, final boolean always) {
6872        mHandler.post(new Runnable() {
6873            @Override public void run() {
6874                if (mBootMsgDialog == null) {
6875                    int theme;
6876                    if (mHasFeatureWatch) {
6877                        theme = com.android.internal.R.style.Theme_Micro_Dialog_Alert;
6878                    } else if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) {
6879                        theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
6880                    } else {
6881                        theme = 0;
6882                    }
6883
6884                    mBootMsgDialog = new ProgressDialog(mContext, theme) {
6885                        // This dialog will consume all events coming in to
6886                        // it, to avoid it trying to do things too early in boot.
6887                        @Override public boolean dispatchKeyEvent(KeyEvent event) {
6888                            return true;
6889                        }
6890                        @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
6891                            return true;
6892                        }
6893                        @Override public boolean dispatchTouchEvent(MotionEvent ev) {
6894                            return true;
6895                        }
6896                        @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
6897                            return true;
6898                        }
6899                        @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
6900                            return true;
6901                        }
6902                        @Override public boolean dispatchPopulateAccessibilityEvent(
6903                                AccessibilityEvent event) {
6904                            return true;
6905                        }
6906                    };
6907                    if (mContext.getPackageManager().isUpgrade()) {
6908                        mBootMsgDialog.setTitle(R.string.android_upgrading_title);
6909                    } else {
6910                        mBootMsgDialog.setTitle(R.string.android_start_title);
6911                    }
6912                    mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
6913                    mBootMsgDialog.setIndeterminate(true);
6914                    mBootMsgDialog.getWindow().setType(
6915                            WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
6916                    mBootMsgDialog.getWindow().addFlags(
6917                            WindowManager.LayoutParams.FLAG_DIM_BEHIND
6918                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
6919                    mBootMsgDialog.getWindow().setDimAmount(1);
6920                    WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
6921                    lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
6922                    mBootMsgDialog.getWindow().setAttributes(lp);
6923                    mBootMsgDialog.setCancelable(false);
6924                    mBootMsgDialog.show();
6925                }
6926                mBootMsgDialog.setMessage(msg);
6927            }
6928        });
6929    }
6930
6931    /** {@inheritDoc} */
6932    @Override
6933    public void hideBootMessages() {
6934        mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
6935    }
6936
6937    /** {@inheritDoc} */
6938    @Override
6939    public void userActivity() {
6940        // ***************************************
6941        // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
6942        // ***************************************
6943        // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
6944        // WITH ITS LOCKS HELD.
6945        //
6946        // This code must be VERY careful about the locks
6947        // it acquires.
6948        // In fact, the current code acquires way too many,
6949        // and probably has lurking deadlocks.
6950
6951        synchronized (mScreenLockTimeout) {
6952            if (mLockScreenTimerActive) {
6953                // reset the timer
6954                mHandler.removeCallbacks(mScreenLockTimeout);
6955                mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
6956            }
6957        }
6958    }
6959
6960    class ScreenLockTimeout implements Runnable {
6961        Bundle options;
6962
6963        @Override
6964        public void run() {
6965            synchronized (this) {
6966                if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
6967                if (mKeyguardDelegate != null) {
6968                    mKeyguardDelegate.doKeyguardTimeout(options);
6969                }
6970                mLockScreenTimerActive = false;
6971                options = null;
6972            }
6973        }
6974
6975        public void setLockOptions(Bundle options) {
6976            this.options = options;
6977        }
6978    }
6979
6980    ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
6981
6982    @Override
6983    public void lockNow(Bundle options) {
6984        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
6985        mHandler.removeCallbacks(mScreenLockTimeout);
6986        if (options != null) {
6987            // In case multiple calls are made to lockNow, we don't wipe out the options
6988            // until the runnable actually executes.
6989            mScreenLockTimeout.setLockOptions(options);
6990        }
6991        mHandler.post(mScreenLockTimeout);
6992    }
6993
6994    private void updateLockScreenTimeout() {
6995        synchronized (mScreenLockTimeout) {
6996            boolean enable = (mAllowLockscreenWhenOn && mAwake &&
6997                    mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
6998            if (mLockScreenTimerActive != enable) {
6999                if (enable) {
7000                    if (localLOGV) Log.v(TAG, "setting lockscreen timer");
7001                    mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
7002                    mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7003                } else {
7004                    if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
7005                    mHandler.removeCallbacks(mScreenLockTimeout);
7006                }
7007                mLockScreenTimerActive = enable;
7008            }
7009        }
7010    }
7011
7012    private void updateDreamingSleepToken(boolean acquire) {
7013        if (acquire) {
7014            if (mDreamingSleepToken == null) {
7015                mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream");
7016            }
7017        } else {
7018            if (mDreamingSleepToken != null) {
7019                mDreamingSleepToken.release();
7020                mDreamingSleepToken = null;
7021            }
7022        }
7023    }
7024
7025    private void updateScreenOffSleepToken(boolean acquire) {
7026        if (acquire) {
7027            if (mScreenOffSleepToken == null) {
7028                mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff");
7029            }
7030        } else {
7031            if (mScreenOffSleepToken != null) {
7032                mScreenOffSleepToken.release();
7033                mScreenOffSleepToken = null;
7034            }
7035        }
7036    }
7037
7038    /** {@inheritDoc} */
7039    @Override
7040    public void enableScreenAfterBoot() {
7041        readLidState();
7042        applyLidSwitchState();
7043        updateRotation(true);
7044    }
7045
7046    private void applyLidSwitchState() {
7047        if (mLidState == LID_CLOSED && mLidControlsSleep) {
7048            mPowerManager.goToSleep(SystemClock.uptimeMillis(),
7049                    PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
7050                    PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
7051        } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
7052            mWindowManagerFuncs.lockDeviceNow();
7053        }
7054
7055        synchronized (mLock) {
7056            updateWakeGestureListenerLp();
7057        }
7058    }
7059
7060    void updateUiMode() {
7061        if (mUiModeManager == null) {
7062            mUiModeManager = IUiModeManager.Stub.asInterface(
7063                    ServiceManager.getService(Context.UI_MODE_SERVICE));
7064        }
7065        try {
7066            mUiMode = mUiModeManager.getCurrentModeType();
7067        } catch (RemoteException e) {
7068        }
7069    }
7070
7071    void updateRotation(boolean alwaysSendConfiguration) {
7072        try {
7073            //set orientation on WindowManager
7074            mWindowManager.updateRotation(alwaysSendConfiguration, false);
7075        } catch (RemoteException e) {
7076            // Ignore
7077        }
7078    }
7079
7080    void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
7081        try {
7082            //set orientation on WindowManager
7083            mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
7084        } catch (RemoteException e) {
7085            // Ignore
7086        }
7087    }
7088
7089    /**
7090     * Return an Intent to launch the currently active dock app as home.  Returns
7091     * null if the standard home should be launched, which is the case if any of the following is
7092     * true:
7093     * <ul>
7094     *  <li>The device is not in either car mode or desk mode
7095     *  <li>The device is in car mode but mEnableCarDockHomeCapture is false
7096     *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
7097     *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
7098     *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
7099     * </ul>
7100     * @return A dock intent.
7101     */
7102    Intent createHomeDockIntent() {
7103        Intent intent = null;
7104
7105        // What home does is based on the mode, not the dock state.  That
7106        // is, when in car mode you should be taken to car home regardless
7107        // of whether we are actually in a car dock.
7108        if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
7109            if (mEnableCarDockHomeCapture) {
7110                intent = mCarDockIntent;
7111            }
7112        } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
7113            if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
7114                intent = mDeskDockIntent;
7115            }
7116        } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
7117                && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7118                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
7119                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
7120            // Always launch dock home from home when watch is docked, if it exists.
7121            intent = mDeskDockIntent;
7122        }
7123
7124        if (intent == null) {
7125            return null;
7126        }
7127
7128        ActivityInfo ai = null;
7129        ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
7130                intent,
7131                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
7132                mCurrentUserId);
7133        if (info != null) {
7134            ai = info.activityInfo;
7135        }
7136        if (ai != null
7137                && ai.metaData != null
7138                && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
7139            intent = new Intent(intent);
7140            intent.setClassName(ai.packageName, ai.name);
7141            return intent;
7142        }
7143
7144        return null;
7145    }
7146
7147    void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
7148        if (awakenFromDreams) {
7149            awakenDreams();
7150        }
7151
7152        Intent dock = createHomeDockIntent();
7153        if (dock != null) {
7154            try {
7155                if (fromHomeKey) {
7156                    dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7157                }
7158                startActivityAsUser(dock, UserHandle.CURRENT);
7159                return;
7160            } catch (ActivityNotFoundException e) {
7161            }
7162        }
7163
7164        Intent intent;
7165
7166        if (fromHomeKey) {
7167            intent = new Intent(mHomeIntent);
7168            intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7169        } else {
7170            intent = mHomeIntent;
7171        }
7172
7173        startActivityAsUser(intent, UserHandle.CURRENT);
7174    }
7175
7176    /**
7177     * goes to the home screen
7178     * @return whether it did anything
7179     */
7180    boolean goHome() {
7181        if (!isUserSetupComplete()) {
7182            Slog.i(TAG, "Not going home because user setup is in progress.");
7183            return false;
7184        }
7185        if (false) {
7186            // This code always brings home to the front.
7187            try {
7188                ActivityManagerNative.getDefault().stopAppSwitches();
7189            } catch (RemoteException e) {
7190            }
7191            sendCloseSystemWindows();
7192            startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
7193        } else {
7194            // This code brings home to the front or, if it is already
7195            // at the front, puts the device to sleep.
7196            try {
7197                if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
7198                    /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
7199                    Log.d(TAG, "UTS-TEST-MODE");
7200                } else {
7201                    ActivityManagerNative.getDefault().stopAppSwitches();
7202                    sendCloseSystemWindows();
7203                    Intent dock = createHomeDockIntent();
7204                    if (dock != null) {
7205                        int result = ActivityManagerNative.getDefault()
7206                                .startActivityAsUser(null, null, dock,
7207                                        dock.resolveTypeIfNeeded(mContext.getContentResolver()),
7208                                        null, null, 0,
7209                                        ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7210                                        null, null, UserHandle.USER_CURRENT);
7211                        if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7212                            return false;
7213                        }
7214                    }
7215                }
7216                int result = ActivityManagerNative.getDefault()
7217                        .startActivityAsUser(null, null, mHomeIntent,
7218                                mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
7219                                null, null, 0,
7220                                ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7221                                null, null, UserHandle.USER_CURRENT);
7222                if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7223                    return false;
7224                }
7225            } catch (RemoteException ex) {
7226                // bummer, the activity manager, which is in this process, is dead
7227            }
7228        }
7229        return true;
7230    }
7231
7232    @Override
7233    public void setCurrentOrientationLw(int newOrientation) {
7234        synchronized (mLock) {
7235            if (newOrientation != mCurrentAppOrientation) {
7236                mCurrentAppOrientation = newOrientation;
7237                updateOrientationListenerLp();
7238            }
7239        }
7240    }
7241
7242    private void performAuditoryFeedbackForAccessibilityIfNeed() {
7243        if (!isGlobalAccessibilityGestureEnabled()) {
7244            return;
7245        }
7246        AudioManager audioManager = (AudioManager) mContext.getSystemService(
7247                Context.AUDIO_SERVICE);
7248        if (audioManager.isSilentMode()) {
7249            return;
7250        }
7251        Ringtone ringTone = RingtoneManager.getRingtone(mContext,
7252                Settings.System.DEFAULT_NOTIFICATION_URI);
7253        ringTone.setStreamType(AudioManager.STREAM_MUSIC);
7254        ringTone.play();
7255    }
7256
7257    private boolean isTheaterModeEnabled() {
7258        return Settings.Global.getInt(mContext.getContentResolver(),
7259                Settings.Global.THEATER_MODE_ON, 0) == 1;
7260    }
7261
7262    private boolean isGlobalAccessibilityGestureEnabled() {
7263        return Settings.Global.getInt(mContext.getContentResolver(),
7264                Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1;
7265    }
7266
7267    @Override
7268    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
7269        if (!mVibrator.hasVibrator()) {
7270            return false;
7271        }
7272        final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
7273                Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
7274        if (hapticsDisabled && !always) {
7275            return false;
7276        }
7277        long[] pattern = null;
7278        switch (effectId) {
7279            case HapticFeedbackConstants.LONG_PRESS:
7280                pattern = mLongPressVibePattern;
7281                break;
7282            case HapticFeedbackConstants.VIRTUAL_KEY:
7283                pattern = mVirtualKeyVibePattern;
7284                break;
7285            case HapticFeedbackConstants.KEYBOARD_TAP:
7286                pattern = mKeyboardTapVibePattern;
7287                break;
7288            case HapticFeedbackConstants.CLOCK_TICK:
7289                pattern = mClockTickVibePattern;
7290                break;
7291            case HapticFeedbackConstants.CALENDAR_DATE:
7292                pattern = mCalendarDateVibePattern;
7293                break;
7294            case HapticFeedbackConstants.SAFE_MODE_DISABLED:
7295                pattern = mSafeModeDisabledVibePattern;
7296                break;
7297            case HapticFeedbackConstants.SAFE_MODE_ENABLED:
7298                pattern = mSafeModeEnabledVibePattern;
7299                break;
7300            case HapticFeedbackConstants.CONTEXT_CLICK:
7301                pattern = mContextClickVibePattern;
7302                break;
7303            default:
7304                return false;
7305        }
7306        int owningUid;
7307        String owningPackage;
7308        if (win != null) {
7309            owningUid = win.getOwningUid();
7310            owningPackage = win.getOwningPackage();
7311        } else {
7312            owningUid = android.os.Process.myUid();
7313            owningPackage = mContext.getOpPackageName();
7314        }
7315        if (pattern.length == 1) {
7316            // One-shot vibration
7317            mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES);
7318        } else {
7319            // Pattern vibration
7320            mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES);
7321        }
7322        return true;
7323    }
7324
7325    @Override
7326    public void keepScreenOnStartedLw() {
7327    }
7328
7329    @Override
7330    public void keepScreenOnStoppedLw() {
7331        if (isKeyguardShowingAndNotOccluded()) {
7332            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
7333        }
7334    }
7335
7336    private int updateSystemUiVisibilityLw() {
7337        // If there is no window focused, there will be nobody to handle the events
7338        // anyway, so just hang on in whatever state we're in until things settle down.
7339        final WindowState win = mFocusedWindow != null ? mFocusedWindow
7340                : mTopFullscreenOpaqueWindowState;
7341        if (win == null) {
7342            return 0;
7343        }
7344        if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) {
7345            // We are updating at a point where the keyguard has gotten
7346            // focus, but we were last in a state where the top window is
7347            // hiding it.  This is probably because the keyguard as been
7348            // shown while the top window was displayed, so we want to ignore
7349            // it here because this is just a very transient change and it
7350            // will quickly lose focus once it correctly gets hidden.
7351            return 0;
7352        }
7353
7354        int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
7355                & ~mResettingSystemUiFlags
7356                & ~mForceClearedSystemUiFlags;
7357        if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
7358            tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
7359        }
7360
7361        final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
7362                mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
7363        final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
7364                mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
7365        mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);
7366        mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);
7367        final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
7368        final int diff = visibility ^ mLastSystemUiFlags;
7369        final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
7370        final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
7371        final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
7372        if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
7373                && mFocusedApp == win.getAppToken()
7374                && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
7375                && mLastDockedStackBounds.equals(mDockedStackBounds)) {
7376            return 0;
7377        }
7378        mLastSystemUiFlags = visibility;
7379        mLastFullscreenStackSysUiFlags = fullscreenVisibility;
7380        mLastDockedStackSysUiFlags = dockedVisibility;
7381        mLastFocusNeedsMenu = needsMenu;
7382        mFocusedApp = win.getAppToken();
7383        final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
7384        final Rect dockedStackBounds = new Rect(mDockedStackBounds);
7385        mHandler.post(new Runnable() {
7386                @Override
7387                public void run() {
7388                    StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
7389                    if (statusbar != null) {
7390                        statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
7391                                dockedVisibility, 0xffffffff, fullscreenStackBounds,
7392                                dockedStackBounds, win.toString());
7393                        statusbar.topAppWindowChanged(needsMenu);
7394                    }
7395                }
7396            });
7397        return diff;
7398    }
7399
7400    private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
7401        WindowState statusColorWin = isStatusBarKeyguard() && !mHideLockScreen
7402                ? mStatusBar
7403                : opaqueOrDimming;
7404
7405        if (statusColorWin != null) {
7406            if (statusColorWin == opaque) {
7407                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7408                // its light flag.
7409                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7410                vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
7411                        & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7412            } else if (statusColorWin != null && statusColorWin.isDimming()) {
7413                // Otherwise if it's dimming, clear the light flag.
7414                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7415            }
7416        }
7417        return vis;
7418    }
7419
7420    private boolean drawsSystemBarBackground(WindowState win) {
7421        return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
7422    }
7423
7424    private boolean forcesDrawStatusBarBackground(WindowState win) {
7425        return win == null || (win.getAttrs().privateFlags
7426                & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
7427    }
7428
7429    private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
7430        final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
7431        final boolean freeformStackVisible =
7432                mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
7433        final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
7434
7435        // We need to force system bars when the docked stack is visible, when the freeform stack
7436        // is visible but also when we are resizing for the transitions when docked stack
7437        // visibility changes.
7438        mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
7439        final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
7440
7441        // apply translucent bar vis flags
7442        WindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen
7443                ? mStatusBar
7444                : mTopFullscreenOpaqueWindowState;
7445        vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7446        vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7447        final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
7448                mTopDockedOpaqueWindowState, 0, 0);
7449
7450        final boolean fullscreenDrawsStatusBarBackground =
7451                (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
7452                        && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
7453                || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
7454        final boolean dockedDrawsStatusBarBackground =
7455                (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
7456                        && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
7457                || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
7458
7459        // prevent status bar interaction from clearing certain flags
7460        int type = win.getAttrs().type;
7461        boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
7462        if (statusBarHasFocus && !isStatusBarKeyguard()) {
7463            int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
7464                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
7465                    | View.SYSTEM_UI_FLAG_IMMERSIVE
7466                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
7467                    | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7468            if (mHideLockScreen) {
7469                flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
7470            }
7471            vis = (vis & ~flags) | (oldVis & flags);
7472        }
7473
7474        if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
7475            vis |= View.STATUS_BAR_TRANSPARENT;
7476            vis &= ~View.STATUS_BAR_TRANSLUCENT;
7477        } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
7478                || forceOpaqueStatusBar) {
7479            vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
7480        }
7481
7482        vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
7483
7484        // update status bar
7485        boolean immersiveSticky =
7486                (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7487        final boolean hideStatusBarWM =
7488                mTopFullscreenOpaqueWindowState != null
7489                && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
7490                        & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
7491        final boolean hideStatusBarSysui =
7492                (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
7493        final boolean hideNavBarSysui =
7494                (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
7495
7496        final boolean transientStatusBarAllowed = mStatusBar != null
7497                && (statusBarHasFocus || (!mForceShowSystemBars
7498                        && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
7499
7500        final boolean transientNavBarAllowed = mNavigationBar != null
7501                && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
7502
7503        final long now = SystemClock.uptimeMillis();
7504        final boolean pendingPanic = mPendingPanicGestureUptime != 0
7505                && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
7506        if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
7507            // The user performed the panic gesture recently, we're about to hide the bars,
7508            // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
7509            mPendingPanicGestureUptime = 0;
7510            mStatusBarController.showTransient();
7511            mNavigationBarController.showTransient();
7512        }
7513
7514        final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
7515                && !transientStatusBarAllowed && hideStatusBarSysui;
7516        final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
7517                && !transientNavBarAllowed;
7518        if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
7519            // clear the clearable flags instead
7520            clearClearableFlagsLw();
7521            vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
7522        }
7523
7524        final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
7525        immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7526        final boolean navAllowedHidden = immersive || immersiveSticky;
7527
7528        if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType())
7529                > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) {
7530            // We can't hide the navbar from this window otherwise the input consumer would not get
7531            // the input events.
7532            vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
7533        }
7534
7535        vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
7536
7537        // update navigation bar
7538        boolean oldImmersiveMode = isImmersiveMode(oldVis);
7539        boolean newImmersiveMode = isImmersiveMode(vis);
7540        if (win != null && oldImmersiveMode != newImmersiveMode) {
7541            final String pkg = win.getOwningPackage();
7542            mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
7543                    isUserSetupComplete());
7544        }
7545
7546        vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
7547
7548        return vis;
7549    }
7550
7551    /**
7552     * @return the current visibility flags with the nav-bar opacity related flags toggled based
7553     *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
7554     */
7555    private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
7556            boolean freeformStackVisible, boolean isDockedDividerResizing) {
7557        if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
7558            if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
7559                visibility = setNavBarOpaqueFlag(visibility);
7560            }
7561        } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
7562            if (isDockedDividerResizing) {
7563                visibility = setNavBarOpaqueFlag(visibility);
7564            } else if (freeformStackVisible) {
7565                visibility = setNavBarTranslucentFlag(visibility);
7566            } else {
7567                visibility = setNavBarOpaqueFlag(visibility);
7568            }
7569        }
7570
7571        if (!areTranslucentBarsAllowed()) {
7572            visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
7573        }
7574        return visibility;
7575    }
7576
7577    private int setNavBarOpaqueFlag(int visibility) {
7578        return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
7579    }
7580
7581    private int setNavBarTranslucentFlag(int visibility) {
7582        visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
7583        return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
7584    }
7585
7586    private void clearClearableFlagsLw() {
7587        int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
7588        if (newVal != mResettingSystemUiFlags) {
7589            mResettingSystemUiFlags = newVal;
7590            mWindowManagerFuncs.reevaluateStatusBarVisibility();
7591        }
7592    }
7593
7594    private boolean isImmersiveMode(int vis) {
7595        final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
7596        return mNavigationBar != null
7597                && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
7598                && (vis & flags) != 0
7599                && canHideNavigationBar();
7600    }
7601
7602    /**
7603     * @return whether the navigation or status bar can be made translucent
7604     *
7605     * This should return true unless touch exploration is not enabled or
7606     * R.boolean.config_enableTranslucentDecor is false.
7607     */
7608    private boolean areTranslucentBarsAllowed() {
7609        return mTranslucentDecorEnabled;
7610    }
7611
7612    // Use this instead of checking config_showNavigationBar so that it can be consistently
7613    // overridden by qemu.hw.mainkeys in the emulator.
7614    @Override
7615    public boolean hasNavigationBar() {
7616        return mHasNavigationBar;
7617    }
7618
7619    @Override
7620    public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
7621        mLastInputMethodWindow = ime;
7622        mLastInputMethodTargetWindow = target;
7623    }
7624
7625    @Override
7626    public int getInputMethodWindowVisibleHeightLw() {
7627        return mDockBottom - mCurBottom;
7628    }
7629
7630    @Override
7631    public void setCurrentUserLw(int newUserId) {
7632        mCurrentUserId = newUserId;
7633        if (mKeyguardDelegate != null) {
7634            mKeyguardDelegate.setCurrentUser(newUserId);
7635        }
7636        StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
7637        if (statusBar != null) {
7638            statusBar.setCurrentUser(newUserId);
7639        }
7640        setLastInputMethodWindowLw(null, null);
7641    }
7642
7643    @Override
7644    public boolean canMagnifyWindow(int windowType) {
7645        switch (windowType) {
7646            case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
7647            case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
7648            case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
7649            case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
7650                return false;
7651            }
7652        }
7653        return true;
7654    }
7655
7656    @Override
7657    public boolean isTopLevelWindow(int windowType) {
7658        if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
7659                && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
7660            return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
7661        }
7662        return true;
7663    }
7664
7665    @Override
7666    public void dump(String prefix, PrintWriter pw, String[] args) {
7667        pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
7668                pw.print(" mSystemReady="); pw.print(mSystemReady);
7669                pw.print(" mSystemBooted="); pw.println(mSystemBooted);
7670        pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
7671                pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
7672                pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
7673                pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
7674        if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
7675                || mForceClearedSystemUiFlags != 0) {
7676            pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
7677                    pw.print(Integer.toHexString(mLastSystemUiFlags));
7678                    pw.print(" mResettingSystemUiFlags=0x");
7679                    pw.print(Integer.toHexString(mResettingSystemUiFlags));
7680                    pw.print(" mForceClearedSystemUiFlags=0x");
7681                    pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
7682        }
7683        if (mLastFocusNeedsMenu) {
7684            pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
7685                    pw.println(mLastFocusNeedsMenu);
7686        }
7687        pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
7688                pw.println(mWakeGestureEnabledSetting);
7689
7690        pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
7691        pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
7692                pw.print(" mDockMode="); pw.print(mDockMode);
7693                pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
7694                pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
7695                pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
7696        pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
7697                pw.print(" mUserRotation="); pw.print(mUserRotation);
7698                pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
7699        pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
7700        pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
7701                pw.print(mCarDockEnablesAccelerometer);
7702                pw.print(" mDeskDockEnablesAccelerometer=");
7703                pw.println(mDeskDockEnablesAccelerometer);
7704        pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
7705                pw.print(mLidKeyboardAccessibility);
7706                pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
7707                pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
7708                pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
7709        pw.print(prefix);
7710                pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
7711        pw.print(prefix);
7712                pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
7713                pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
7714        pw.print(prefix);
7715                pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
7716                pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
7717        pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
7718        pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
7719        pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
7720                pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
7721        pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
7722                pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
7723        pw.print(prefix); pw.print("mOrientationSensorEnabled=");
7724                pw.println(mOrientationSensorEnabled);
7725        pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
7726                pw.print(","); pw.print(mOverscanScreenTop);
7727                pw.print(") "); pw.print(mOverscanScreenWidth);
7728                pw.print("x"); pw.println(mOverscanScreenHeight);
7729        if (mOverscanLeft != 0 || mOverscanTop != 0
7730                || mOverscanRight != 0 || mOverscanBottom != 0) {
7731            pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
7732                    pw.print(" top="); pw.print(mOverscanTop);
7733                    pw.print(" right="); pw.print(mOverscanRight);
7734                    pw.print(" bottom="); pw.println(mOverscanBottom);
7735        }
7736        pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
7737                pw.print(mRestrictedOverscanScreenLeft);
7738                pw.print(","); pw.print(mRestrictedOverscanScreenTop);
7739                pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
7740                pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
7741        pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
7742                pw.print(","); pw.print(mUnrestrictedScreenTop);
7743                pw.print(") "); pw.print(mUnrestrictedScreenWidth);
7744                pw.print("x"); pw.println(mUnrestrictedScreenHeight);
7745        pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
7746                pw.print(","); pw.print(mRestrictedScreenTop);
7747                pw.print(") "); pw.print(mRestrictedScreenWidth);
7748                pw.print("x"); pw.println(mRestrictedScreenHeight);
7749        pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
7750                pw.print(","); pw.print(mStableFullscreenTop);
7751                pw.print(")-("); pw.print(mStableFullscreenRight);
7752                pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
7753        pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
7754                pw.print(","); pw.print(mStableTop);
7755                pw.print(")-("); pw.print(mStableRight);
7756                pw.print(","); pw.print(mStableBottom); pw.println(")");
7757        pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
7758                pw.print(","); pw.print(mSystemTop);
7759                pw.print(")-("); pw.print(mSystemRight);
7760                pw.print(","); pw.print(mSystemBottom); pw.println(")");
7761        pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
7762                pw.print(","); pw.print(mCurTop);
7763                pw.print(")-("); pw.print(mCurRight);
7764                pw.print(","); pw.print(mCurBottom); pw.println(")");
7765        pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
7766                pw.print(","); pw.print(mContentTop);
7767                pw.print(")-("); pw.print(mContentRight);
7768                pw.print(","); pw.print(mContentBottom); pw.println(")");
7769        pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft);
7770                pw.print(","); pw.print(mVoiceContentTop);
7771                pw.print(")-("); pw.print(mVoiceContentRight);
7772                pw.print(","); pw.print(mVoiceContentBottom); pw.println(")");
7773        pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
7774                pw.print(","); pw.print(mDockTop);
7775                pw.print(")-("); pw.print(mDockRight);
7776                pw.print(","); pw.print(mDockBottom); pw.println(")");
7777        pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
7778                pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
7779        pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen);
7780                pw.print(" mShowingDream="); pw.print(mShowingDream);
7781                pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
7782                pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
7783        if (mLastInputMethodWindow != null) {
7784            pw.print(prefix); pw.print("mLastInputMethodWindow=");
7785                    pw.println(mLastInputMethodWindow);
7786        }
7787        if (mLastInputMethodTargetWindow != null) {
7788            pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
7789                    pw.println(mLastInputMethodTargetWindow);
7790        }
7791        if (mStatusBar != null) {
7792            pw.print(prefix); pw.print("mStatusBar=");
7793                    pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
7794                    pw.println(isStatusBarKeyguard());
7795        }
7796        if (mNavigationBar != null) {
7797            pw.print(prefix); pw.print("mNavigationBar=");
7798                    pw.println(mNavigationBar);
7799        }
7800        if (mFocusedWindow != null) {
7801            pw.print(prefix); pw.print("mFocusedWindow=");
7802                    pw.println(mFocusedWindow);
7803        }
7804        if (mFocusedApp != null) {
7805            pw.print(prefix); pw.print("mFocusedApp=");
7806                    pw.println(mFocusedApp);
7807        }
7808        if (mWinDismissingKeyguard != null) {
7809            pw.print(prefix); pw.print("mWinDismissingKeyguard=");
7810                    pw.println(mWinDismissingKeyguard);
7811        }
7812        if (mTopFullscreenOpaqueWindowState != null) {
7813            pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
7814                    pw.println(mTopFullscreenOpaqueWindowState);
7815        }
7816        if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
7817            pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
7818                    pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
7819        }
7820        if (mForcingShowNavBar) {
7821            pw.print(prefix); pw.print("mForcingShowNavBar=");
7822                    pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
7823                    pw.println(mForcingShowNavBarLayer);
7824        }
7825        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
7826                pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
7827        pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
7828                pw.print(" mForceStatusBarFromKeyguard=");
7829                pw.println(mForceStatusBarFromKeyguard);
7830        pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
7831                pw.print(" mWinDismissingKeyguard="); pw.print(mWinDismissingKeyguard);
7832                pw.print(" mHomePressed="); pw.println(mHomePressed);
7833        pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
7834                pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
7835                pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
7836        pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
7837                pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
7838                pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
7839        pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
7840                pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
7841        pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
7842                pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
7843        pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
7844                pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
7845        pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
7846
7847        mGlobalKeyManager.dump(prefix, pw);
7848        mStatusBarController.dump(pw, prefix);
7849        mNavigationBarController.dump(pw, prefix);
7850        PolicyControl.dump(prefix, pw);
7851
7852        if (mWakeGestureListener != null) {
7853            mWakeGestureListener.dump(pw, prefix);
7854        }
7855        if (mOrientationListener != null) {
7856            mOrientationListener.dump(pw, prefix);
7857        }
7858        if (mBurnInProtectionHelper != null) {
7859            mBurnInProtectionHelper.dump(prefix, pw);
7860        }
7861        if (mKeyguardDelegate != null) {
7862            mKeyguardDelegate.dump(prefix, pw);
7863        }
7864    }
7865}
7866