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