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