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