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