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