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