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