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