PhoneWindowManager.java revision ab216609f1608e61827d955fcc9fd0560bc52e4d
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 void setRecentsVisibilityLw(boolean visible) {
3856        mRecentsVisible = visible;
3857    }
3858
3859    @Override
3860    public void setTvPipVisibilityLw(boolean visible) {
3861        mTvPictureInPictureVisible = visible;
3862    }
3863
3864    @Override
3865    public int adjustSystemUiVisibilityLw(int visibility) {
3866        mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
3867        mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
3868
3869        // Reset any bits in mForceClearingStatusBarVisibility that
3870        // are now clear.
3871        mResettingSystemUiFlags &= visibility;
3872        // Clear any bits in the new visibility that are currently being
3873        // force cleared, before reporting it.
3874        return visibility & ~mResettingSystemUiFlags
3875                & ~mForceClearedSystemUiFlags;
3876    }
3877
3878    @Override
3879    public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
3880            int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets,
3881            Rect outStableInsets, Rect outOutsets) {
3882        final int fl = PolicyControl.getWindowFlags(null, attrs);
3883        final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
3884        final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
3885
3886        final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
3887        if (useOutsets) {
3888            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
3889            if (outset > 0) {
3890                if (displayRotation == Surface.ROTATION_0) {
3891                    outOutsets.bottom += outset;
3892                } else if (displayRotation == Surface.ROTATION_90) {
3893                    outOutsets.right += outset;
3894                } else if (displayRotation == Surface.ROTATION_180) {
3895                    outOutsets.top += outset;
3896                } else if (displayRotation == Surface.ROTATION_270) {
3897                    outOutsets.left += outset;
3898                }
3899            }
3900        }
3901
3902        if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
3903                == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
3904            int availRight, availBottom;
3905            if (canHideNavigationBar() &&
3906                    (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
3907                availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
3908                availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
3909            } else {
3910                availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
3911                availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
3912            }
3913            if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
3914                if ((fl & FLAG_FULLSCREEN) != 0) {
3915                    outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop,
3916                            availRight - mStableFullscreenRight,
3917                            availBottom - mStableFullscreenBottom);
3918                } else {
3919                    outContentInsets.set(mStableLeft, mStableTop,
3920                            availRight - mStableRight, availBottom - mStableBottom);
3921                }
3922            } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
3923                outContentInsets.setEmpty();
3924            } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
3925                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
3926                outContentInsets.set(mCurLeft, mCurTop,
3927                        availRight - mCurRight, availBottom - mCurBottom);
3928            } else {
3929                outContentInsets.set(mCurLeft, mCurTop,
3930                        availRight - mCurRight, availBottom - mCurBottom);
3931            }
3932
3933            outStableInsets.set(mStableLeft, mStableTop,
3934                    availRight - mStableRight, availBottom - mStableBottom);
3935            if (taskBounds != null) {
3936                calculateRelevantTaskInsets(taskBounds, outContentInsets,
3937                        displayWidth, displayHeight);
3938                calculateRelevantTaskInsets(taskBounds, outStableInsets,
3939                        displayWidth, displayHeight);
3940            }
3941            return mForceShowSystemBars;
3942        }
3943        outContentInsets.setEmpty();
3944        outStableInsets.setEmpty();
3945        return mForceShowSystemBars;
3946    }
3947
3948    /**
3949     * For any given task bounds, the insets relevant for these bounds given the insets relevant
3950     * for the entire display.
3951     */
3952    private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth,
3953            int displayHeight) {
3954        mTmpRect.set(0, 0, displayWidth, displayHeight);
3955        mTmpRect.inset(inOutInsets);
3956        mTmpRect.intersect(taskBounds);
3957        int leftInset = mTmpRect.left - taskBounds.left;
3958        int topInset = mTmpRect.top - taskBounds.top;
3959        int rightInset = taskBounds.right - mTmpRect.right;
3960        int bottomInset = taskBounds.bottom - mTmpRect.bottom;
3961        inOutInsets.set(leftInset, topInset, rightInset, bottomInset);
3962    }
3963
3964    private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
3965        return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
3966                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
3967    }
3968
3969    /** {@inheritDoc} */
3970    @Override
3971    public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
3972                              int displayRotation, int uiMode) {
3973        mDisplayRotation = displayRotation;
3974        final int overscanLeft, overscanTop, overscanRight, overscanBottom;
3975        if (isDefaultDisplay) {
3976            switch (displayRotation) {
3977                case Surface.ROTATION_90:
3978                    overscanLeft = mOverscanTop;
3979                    overscanTop = mOverscanRight;
3980                    overscanRight = mOverscanBottom;
3981                    overscanBottom = mOverscanLeft;
3982                    break;
3983                case Surface.ROTATION_180:
3984                    overscanLeft = mOverscanRight;
3985                    overscanTop = mOverscanBottom;
3986                    overscanRight = mOverscanLeft;
3987                    overscanBottom = mOverscanTop;
3988                    break;
3989                case Surface.ROTATION_270:
3990                    overscanLeft = mOverscanBottom;
3991                    overscanTop = mOverscanLeft;
3992                    overscanRight = mOverscanTop;
3993                    overscanBottom = mOverscanRight;
3994                    break;
3995                default:
3996                    overscanLeft = mOverscanLeft;
3997                    overscanTop = mOverscanTop;
3998                    overscanRight = mOverscanRight;
3999                    overscanBottom = mOverscanBottom;
4000                    break;
4001            }
4002        } else {
4003            overscanLeft = 0;
4004            overscanTop = 0;
4005            overscanRight = 0;
4006            overscanBottom = 0;
4007        }
4008        mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0;
4009        mOverscanScreenTop = mRestrictedOverscanScreenTop = 0;
4010        mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth;
4011        mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight;
4012        mSystemLeft = 0;
4013        mSystemTop = 0;
4014        mSystemRight = displayWidth;
4015        mSystemBottom = displayHeight;
4016        mUnrestrictedScreenLeft = overscanLeft;
4017        mUnrestrictedScreenTop = overscanTop;
4018        mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight;
4019        mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom;
4020        mRestrictedScreenLeft = mUnrestrictedScreenLeft;
4021        mRestrictedScreenTop = mUnrestrictedScreenTop;
4022        mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth;
4023        mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight;
4024        mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft
4025                = mCurLeft = mUnrestrictedScreenLeft;
4026        mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop
4027                = mCurTop = mUnrestrictedScreenTop;
4028        mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight
4029                = mCurRight = displayWidth - overscanRight;
4030        mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom
4031                = mCurBottom = displayHeight - overscanBottom;
4032        mDockLayer = 0x10000000;
4033        mStatusBarLayer = -1;
4034
4035        // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
4036        final Rect pf = mTmpParentFrame;
4037        final Rect df = mTmpDisplayFrame;
4038        final Rect of = mTmpOverscanFrame;
4039        final Rect vf = mTmpVisibleFrame;
4040        final Rect dcf = mTmpDecorFrame;
4041        pf.left = df.left = of.left = vf.left = mDockLeft;
4042        pf.top = df.top = of.top = vf.top = mDockTop;
4043        pf.right = df.right = of.right = vf.right = mDockRight;
4044        pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom;
4045        dcf.setEmpty();  // Decor frame N/A for system bars.
4046
4047        if (isDefaultDisplay) {
4048            // For purposes of putting out fake window up to steal focus, we will
4049            // drive nav being hidden only by whether it is requested.
4050            final int sysui = mLastSystemUiFlags;
4051            boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
4052            boolean navTranslucent = (sysui
4053                    & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
4054            boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
4055            boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
4056            boolean navAllowedHidden = immersive || immersiveSticky;
4057            navTranslucent &= !immersiveSticky;  // transient trumps translucent
4058            boolean isKeyguardShowing = isStatusBarKeyguard() && !mHideLockScreen;
4059            if (!isKeyguardShowing) {
4060                navTranslucent &= areTranslucentBarsAllowed();
4061            }
4062            boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null
4063                    && mStatusBar.getAttrs().height == MATCH_PARENT
4064                    && mStatusBar.getAttrs().width == MATCH_PARENT;
4065
4066            // When the navigation bar isn't visible, we put up a fake
4067            // input window to catch all touch events.  This way we can
4068            // detect when the user presses anywhere to bring back the nav
4069            // bar and ensure the application doesn't see the event.
4070            if (navVisible || navAllowedHidden) {
4071                if (mInputConsumer != null) {
4072                    mHandler.sendMessage(
4073                            mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
4074                    mInputConsumer = null;
4075                }
4076            } else if (mInputConsumer == null) {
4077                mInputConsumer = mWindowManagerFuncs.addInputConsumer(mHandler.getLooper(),
4078                        mHideNavInputEventReceiverFactory);
4079            }
4080
4081            // For purposes of positioning and showing the nav bar, if we have
4082            // decided that it can't be hidden (because of the screen aspect ratio),
4083            // then take that into account.
4084            navVisible |= !canHideNavigationBar();
4085
4086            boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight,
4087                    displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom, dcf, navVisible, navTranslucent,
4088                    navAllowedHidden, statusBarExpandedNotKeyguard);
4089            if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
4090                    mDockLeft, mDockTop, mDockRight, mDockBottom));
4091            updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing);
4092            if (updateSysUiVisibility) {
4093                updateSystemUiVisibilityLw();
4094            }
4095        }
4096    }
4097
4098    private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui,
4099            boolean isKeyguardShowing) {
4100        // decide where the status bar goes ahead of time
4101        if (mStatusBar != null) {
4102            // apply any navigation bar insets
4103            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4104            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4105            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4106            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
4107                    + mUnrestrictedScreenTop;
4108            vf.left = mStableLeft;
4109            vf.top = mStableTop;
4110            vf.right = mStableRight;
4111            vf.bottom = mStableBottom;
4112
4113            mStatusBarLayer = mStatusBar.getSurfaceLayer();
4114
4115            // Let the status bar determine its size.
4116            mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
4117                    vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
4118                    dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */);
4119
4120            // For layout, the status bar is always at the top with our fixed height.
4121            mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
4122
4123            boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
4124            boolean statusBarTranslucent = (sysui
4125                    & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
4126            if (!isKeyguardShowing) {
4127                statusBarTranslucent &= areTranslucentBarsAllowed();
4128            }
4129
4130            // If the status bar is hidden, we don't want to cause
4131            // windows behind it to scroll.
4132            if (mStatusBar.isVisibleLw() && !statusBarTransient) {
4133                // Status bar may go away, so the screen area it occupies
4134                // is available to apps but just covering them when the
4135                // status bar is visible.
4136                mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
4137
4138                mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4139                mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4140                mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4141                mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4142
4143                if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " +
4144                        String.format(
4145                                "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
4146                                mDockLeft, mDockTop, mDockRight, mDockBottom,
4147                                mContentLeft, mContentTop, mContentRight, mContentBottom,
4148                                mCurLeft, mCurTop, mCurRight, mCurBottom));
4149            }
4150            if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
4151                    && !statusBarTransient && !statusBarTranslucent
4152                    && !mStatusBarController.wasRecentlyTranslucent()) {
4153                // If the opaque status bar is currently requested to be visible,
4154                // and not in the process of animating on or off, then
4155                // we can tell the app that it is covered by it.
4156                mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
4157            }
4158            if (mStatusBarController.checkHiddenLw()) {
4159                return true;
4160            }
4161        }
4162        return false;
4163    }
4164
4165    private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation,
4166            int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf,
4167            boolean navVisible, boolean navTranslucent, boolean navAllowedHidden,
4168            boolean statusBarExpandedNotKeyguard) {
4169        if (mNavigationBar != null) {
4170            boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
4171            // Force the navigation bar to its appropriate place and
4172            // size.  We need to do this directly, instead of relying on
4173            // it to bubble up from the nav bar, because this needs to
4174            // change atomically with screen rotations.
4175            mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight,
4176                    displayRotation);
4177            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
4178                // It's a system nav bar or a portrait screen; nav bar goes on bottom.
4179                int top = displayHeight - overscanBottom
4180                        - getNavigationBarHeight(displayRotation, uiMode);
4181                mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
4182                mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
4183                if (transientNavBarShowing) {
4184                    mNavigationBarController.setBarShowingLw(true);
4185                } else if (navVisible) {
4186                    mNavigationBarController.setBarShowingLw(true);
4187                    mDockBottom = mTmpNavigationFrame.top;
4188                    mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
4189                    mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
4190                } else {
4191                    // We currently want to hide the navigation UI - unless we expanded the status
4192                    // bar.
4193                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4194                }
4195                if (navVisible && !navTranslucent && !navAllowedHidden
4196                        && !mNavigationBar.isAnimatingLw()
4197                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4198                    // If the opaque nav bar is currently requested to be visible,
4199                    // and not in the process of animating on or off, then
4200                    // we can tell the app that it is covered by it.
4201                    mSystemBottom = mTmpNavigationFrame.top;
4202                }
4203            } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4204                // Landscape screen; nav bar goes to the right.
4205                int left = displayWidth - overscanRight
4206                        - getNavigationBarWidth(displayRotation, uiMode);
4207                mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
4208                mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
4209                if (transientNavBarShowing) {
4210                    mNavigationBarController.setBarShowingLw(true);
4211                } else if (navVisible) {
4212                    mNavigationBarController.setBarShowingLw(true);
4213                    mDockRight = mTmpNavigationFrame.left;
4214                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4215                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4216                } else {
4217                    // We currently want to hide the navigation UI - unless we expanded the status
4218                    // bar.
4219                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4220                }
4221                if (navVisible && !navTranslucent && !navAllowedHidden
4222                        && !mNavigationBar.isAnimatingLw()
4223                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4224                    // If the nav bar is currently requested to be visible,
4225                    // and not in the process of animating on or off, then
4226                    // we can tell the app that it is covered by it.
4227                    mSystemRight = mTmpNavigationFrame.left;
4228                }
4229            } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4230                // Seascape screen; nav bar goes to the left.
4231                int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode);
4232                mTmpNavigationFrame.set(overscanLeft, 0, right, displayHeight);
4233                mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right;
4234                if (transientNavBarShowing) {
4235                    mNavigationBarController.setBarShowingLw(true);
4236                } else if (navVisible) {
4237                    mNavigationBarController.setBarShowingLw(true);
4238                    mDockLeft = mTmpNavigationFrame.right;
4239                    // TODO: not so sure about those:
4240                    mRestrictedScreenLeft = mRestrictedOverscanScreenLeft = mDockLeft;
4241                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4242                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4243                } else {
4244                    // We currently want to hide the navigation UI - unless we expanded the status
4245                    // bar.
4246                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4247                }
4248                if (navVisible && !navTranslucent && !navAllowedHidden
4249                        && !mNavigationBar.isAnimatingLw()
4250                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4251                    // If the nav bar is currently requested to be visible,
4252                    // and not in the process of animating on or off, then
4253                    // we can tell the app that it is covered by it.
4254                    mSystemLeft = mTmpNavigationFrame.right;
4255                }
4256            }
4257            // Make sure the content and current rectangles are updated to
4258            // account for the restrictions from the navigation bar.
4259            mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4260            mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4261            mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4262            mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4263            mStatusBarLayer = mNavigationBar.getSurfaceLayer();
4264            // And compute the final frame.
4265            mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
4266                    mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
4267                    mTmpNavigationFrame, mTmpNavigationFrame);
4268            if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
4269            if (mNavigationBarController.checkHiddenLw()) {
4270                return true;
4271            }
4272        }
4273        return false;
4274    }
4275
4276    private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
4277        if (mNavigationBarCanMove && displayWidth > displayHeight) {
4278            if (displayRotation == Surface.ROTATION_270) {
4279                return NAV_BAR_LEFT;
4280            } else {
4281                return NAV_BAR_RIGHT;
4282            }
4283        }
4284        return NAV_BAR_BOTTOM;
4285    }
4286
4287    /** {@inheritDoc} */
4288    @Override
4289    public int getSystemDecorLayerLw() {
4290        if (mStatusBar != null && mStatusBar.isVisibleLw()) {
4291            return mStatusBar.getSurfaceLayer();
4292        }
4293
4294        if (mNavigationBar != null && mNavigationBar.isVisibleLw()) {
4295            return mNavigationBar.getSurfaceLayer();
4296        }
4297
4298        return 0;
4299    }
4300
4301    @Override
4302    public void getContentRectLw(Rect r) {
4303        r.set(mContentLeft, mContentTop, mContentRight, mContentBottom);
4304    }
4305
4306    void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
4307            boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
4308        if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
4309            // Here's a special case: if this attached window is a panel that is
4310            // above the dock window, and the window it is attached to is below
4311            // the dock window, then the frames we computed for the window it is
4312            // attached to can not be used because the dock is effectively part
4313            // of the underlying window and the attached window is floating on top
4314            // of the whole thing.  So, we ignore the attached window and explicitly
4315            // compute the frames that would be appropriate without the dock.
4316            df.left = of.left = cf.left = vf.left = mDockLeft;
4317            df.top = of.top = cf.top = vf.top = mDockTop;
4318            df.right = of.right = cf.right = vf.right = mDockRight;
4319            df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom;
4320        } else {
4321            // The effective display frame of the attached window depends on
4322            // whether it is taking care of insetting its content.  If not,
4323            // we need to use the parent's content frame so that the entire
4324            // window is positioned within that content.  Otherwise we can use
4325            // the overscan frame and let the attached window take care of
4326            // positioning its content appropriately.
4327            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4328                // Set the content frame of the attached window to the parent's decor frame
4329                // (same as content frame when IME isn't present) if specifically requested by
4330                // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
4331                // Otherwise, use the overscan frame.
4332                cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
4333                        ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
4334            } else {
4335                // If the window is resizing, then we want to base the content
4336                // frame on our attached content frame to resize...  however,
4337                // things can be tricky if the attached window is NOT in resize
4338                // mode, in which case its content frame will be larger.
4339                // Ungh.  So to deal with that, make sure the content frame
4340                // we end up using is not covering the IM dock.
4341                cf.set(attached.getContentFrameLw());
4342                if (attached.isVoiceInteraction()) {
4343                    if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft;
4344                    if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop;
4345                    if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight;
4346                    if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom;
4347                } else if (attached.getSurfaceLayer() < mDockLayer) {
4348                    if (cf.left < mContentLeft) cf.left = mContentLeft;
4349                    if (cf.top < mContentTop) cf.top = mContentTop;
4350                    if (cf.right > mContentRight) cf.right = mContentRight;
4351                    if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
4352                }
4353            }
4354            df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
4355            of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
4356            vf.set(attached.getVisibleFrameLw());
4357        }
4358        // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
4359        // window should be positioned relative to its parent or the entire
4360        // screen.
4361        pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
4362                ? attached.getFrameLw() : df);
4363    }
4364
4365    private void applyStableConstraints(int sysui, int fl, Rect r) {
4366        if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4367            // If app is requesting a stable layout, don't let the
4368            // content insets go below the stable values.
4369            if ((fl & FLAG_FULLSCREEN) != 0) {
4370                if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft;
4371                if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop;
4372                if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight;
4373                if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom;
4374            } else {
4375                if (r.left < mStableLeft) r.left = mStableLeft;
4376                if (r.top < mStableTop) r.top = mStableTop;
4377                if (r.right > mStableRight) r.right = mStableRight;
4378                if (r.bottom > mStableBottom) r.bottom = mStableBottom;
4379            }
4380        }
4381    }
4382
4383    private boolean canReceiveInput(WindowState win) {
4384        boolean notFocusable =
4385                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
4386        boolean altFocusableIm =
4387                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
4388        boolean notFocusableForIm = notFocusable ^ altFocusableIm;
4389        return !notFocusableForIm;
4390    }
4391
4392    /** {@inheritDoc} */
4393    @Override
4394    public void layoutWindowLw(WindowState win, WindowState attached) {
4395        // We've already done the navigation bar and status bar. If the status bar can receive
4396        // input, we need to layout it again to accomodate for the IME window.
4397        if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) {
4398            return;
4399        }
4400        final WindowManager.LayoutParams attrs = win.getAttrs();
4401        final boolean isDefaultDisplay = win.isDefaultDisplay();
4402        final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
4403                (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
4404        if (needsToOffsetInputMethodTarget) {
4405            if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
4406            offsetInputMethodWindowLw(mLastInputMethodWindow);
4407        }
4408
4409        final int fl = PolicyControl.getWindowFlags(win, attrs);
4410        final int pfl = attrs.privateFlags;
4411        final int sim = attrs.softInputMode;
4412        final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
4413
4414        final Rect pf = mTmpParentFrame;
4415        final Rect df = mTmpDisplayFrame;
4416        final Rect of = mTmpOverscanFrame;
4417        final Rect cf = mTmpContentFrame;
4418        final Rect vf = mTmpVisibleFrame;
4419        final Rect dcf = mTmpDecorFrame;
4420        final Rect sf = mTmpStableFrame;
4421        Rect osf = null;
4422        dcf.setEmpty();
4423
4424        final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
4425                && mNavigationBar != null && mNavigationBar.isVisibleLw());
4426
4427        final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
4428
4429        if (isDefaultDisplay) {
4430            sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom);
4431        } else {
4432            sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom);
4433        }
4434
4435        if (!isDefaultDisplay) {
4436            if (attached != null) {
4437                // If this window is attached to another, our display
4438                // frame is the same as the one we are attached to.
4439                setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4440            } else {
4441                // Give the window full screen.
4442                pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4443                pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4444                pf.right = df.right = of.right = cf.right
4445                        = mOverscanScreenLeft + mOverscanScreenWidth;
4446                pf.bottom = df.bottom = of.bottom = cf.bottom
4447                        = mOverscanScreenTop + mOverscanScreenHeight;
4448            }
4449        } else if (attrs.type == TYPE_INPUT_METHOD) {
4450            pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
4451            pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
4452            pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
4453            // IM dock windows layout below the nav bar...
4454            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4455            // ...with content insets above the nav bar
4456            cf.bottom = vf.bottom = mStableBottom;
4457            if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
4458                // The status bar forces the navigation bar while it's visible. Make sure the IME
4459                // avoids the navigation bar in that case.
4460                if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4461                    pf.right = df.right = of.right = cf.right = vf.right = mStableRight;
4462                } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4463                    pf.left = df.left = of.left = cf.left = vf.left = mStableLeft;
4464                }
4465            }
4466            // IM dock windows always go to the bottom of the screen.
4467            attrs.gravity = Gravity.BOTTOM;
4468            mDockLayer = win.getSurfaceLayer();
4469        } else if (attrs.type == TYPE_VOICE_INTERACTION) {
4470            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4471            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4472            pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4473            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4474            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4475                cf.left = mDockLeft;
4476                cf.top = mDockTop;
4477                cf.right = mDockRight;
4478                cf.bottom = mDockBottom;
4479            } else {
4480                cf.left = mContentLeft;
4481                cf.top = mContentTop;
4482                cf.right = mContentRight;
4483                cf.bottom = mContentBottom;
4484            }
4485            if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4486                vf.left = mCurLeft;
4487                vf.top = mCurTop;
4488                vf.right = mCurRight;
4489                vf.bottom = mCurBottom;
4490            } else {
4491                vf.set(cf);
4492            }
4493        } else if (attrs.type == TYPE_WALLPAPER) {
4494           layoutWallpaper(win, pf, df, of, cf);
4495        } else if (win == mStatusBar) {
4496            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4497            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4498            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4499            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop;
4500            cf.left = vf.left = mStableLeft;
4501            cf.top = vf.top = mStableTop;
4502            cf.right = vf.right = mStableRight;
4503            vf.bottom = mStableBottom;
4504
4505            if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
4506                cf.bottom = mContentBottom;
4507            } else {
4508                cf.bottom = mDockBottom;
4509                vf.bottom = mContentBottom;
4510            }
4511        } else {
4512
4513            // Default policy decor for the default display
4514            dcf.left = mSystemLeft;
4515            dcf.top = mSystemTop;
4516            dcf.right = mSystemRight;
4517            dcf.bottom = mSystemBottom;
4518            final boolean inheritTranslucentDecor = (attrs.privateFlags
4519                    & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0;
4520            final boolean isAppWindow =
4521                    attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW &&
4522                    attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
4523            final boolean topAtRest =
4524                    win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
4525            if (isAppWindow && !inheritTranslucentDecor && !topAtRest) {
4526                if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
4527                        && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0
4528                        && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
4529                        && (fl & WindowManager.LayoutParams.
4530                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
4531                        && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) {
4532                    // Ensure policy decor includes status bar
4533                    dcf.top = mStableTop;
4534                }
4535                if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0
4536                        && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
4537                        && (fl & WindowManager.LayoutParams.
4538                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
4539                    // Ensure policy decor includes navigation bar
4540                    dcf.bottom = mStableBottom;
4541                    dcf.right = mStableRight;
4542                }
4543            }
4544
4545            if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4546                    == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4547                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
4548                            + "): IN_SCREEN, INSET_DECOR");
4549                // This is the case for a normal activity window: we want it
4550                // to cover all of the screen space, and it can take care of
4551                // moving its contents to account for screen decorations that
4552                // intrude into that space.
4553                if (attached != null) {
4554                    // If this window is attached to another, our display
4555                    // frame is the same as the one we are attached to.
4556                    setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4557                } else {
4558                    if (attrs.type == TYPE_STATUS_BAR_PANEL
4559                            || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
4560                        // Status bar panels are the only windows who can go on top of
4561                        // the status bar.  They are protected by the STATUS_BAR_SERVICE
4562                        // permission, so they have the same privileges as the status
4563                        // bar itself.
4564                        //
4565                        // However, they should still dodge the navigation bar if it exists.
4566
4567                        pf.left = df.left = of.left = hasNavBar
4568                                ? mDockLeft : mUnrestrictedScreenLeft;
4569                        pf.top = df.top = of.top = mUnrestrictedScreenTop;
4570                        pf.right = df.right = of.right = hasNavBar
4571                                ? mRestrictedScreenLeft+mRestrictedScreenWidth
4572                                : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4573                        pf.bottom = df.bottom = of.bottom = hasNavBar
4574                                ? mRestrictedScreenTop+mRestrictedScreenHeight
4575                                : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4576
4577                        if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4578                                        "Laying out status bar window: (%d,%d - %d,%d)",
4579                                        pf.left, pf.top, pf.right, pf.bottom));
4580                    } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4581                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4582                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4583                        // Asking to layout into the overscan region, so give it that pure
4584                        // unrestricted area.
4585                        pf.left = df.left = of.left = mOverscanScreenLeft;
4586                        pf.top = df.top = of.top = mOverscanScreenTop;
4587                        pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth;
4588                        pf.bottom = df.bottom = of.bottom = mOverscanScreenTop
4589                                + mOverscanScreenHeight;
4590                    } else if (canHideNavigationBar()
4591                            && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4592                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4593                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4594                        // Asking for layout as if the nav bar is hidden, lets the
4595                        // application extend into the unrestricted overscan screen area.  We
4596                        // only do this for application windows to ensure no window that
4597                        // can be above the nav bar can do this.
4598                        pf.left = df.left = mOverscanScreenLeft;
4599                        pf.top = df.top = mOverscanScreenTop;
4600                        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
4601                        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
4602                        // We need to tell the app about where the frame inside the overscan
4603                        // is, so it can inset its content by that amount -- it didn't ask
4604                        // to actually extend itself into the overscan region.
4605                        of.left = mUnrestrictedScreenLeft;
4606                        of.top = mUnrestrictedScreenTop;
4607                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4608                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4609                    } else {
4610                        pf.left = df.left = mRestrictedOverscanScreenLeft;
4611                        pf.top = df.top = mRestrictedOverscanScreenTop;
4612                        pf.right = df.right = mRestrictedOverscanScreenLeft
4613                                + mRestrictedOverscanScreenWidth;
4614                        pf.bottom = df.bottom = mRestrictedOverscanScreenTop
4615                                + mRestrictedOverscanScreenHeight;
4616                        // We need to tell the app about where the frame inside the overscan
4617                        // is, so it can inset its content by that amount -- it didn't ask
4618                        // to actually extend itself into the overscan region.
4619                        of.left = mUnrestrictedScreenLeft;
4620                        of.top = mUnrestrictedScreenTop;
4621                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4622                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4623                    }
4624
4625                    if ((fl & FLAG_FULLSCREEN) == 0) {
4626                        if (win.isVoiceInteraction()) {
4627                            cf.left = mVoiceContentLeft;
4628                            cf.top = mVoiceContentTop;
4629                            cf.right = mVoiceContentRight;
4630                            cf.bottom = mVoiceContentBottom;
4631                        } else {
4632                            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4633                                cf.left = mDockLeft;
4634                                cf.top = mDockTop;
4635                                cf.right = mDockRight;
4636                                cf.bottom = mDockBottom;
4637                            } else {
4638                                cf.left = mContentLeft;
4639                                cf.top = mContentTop;
4640                                cf.right = mContentRight;
4641                                cf.bottom = mContentBottom;
4642                            }
4643                        }
4644                    } else {
4645                        // Full screen windows are always given a layout that is as if the
4646                        // status bar and other transient decors are gone.  This is to avoid
4647                        // bad states when moving from a window that is not hding the
4648                        // status bar to one that is.
4649                        cf.left = mRestrictedScreenLeft;
4650                        cf.top = mRestrictedScreenTop;
4651                        cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
4652                        cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4653                    }
4654                    applyStableConstraints(sysUiFl, fl, cf);
4655                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4656                        vf.left = mCurLeft;
4657                        vf.top = mCurTop;
4658                        vf.right = mCurRight;
4659                        vf.bottom = mCurBottom;
4660                    } else {
4661                        vf.set(cf);
4662                    }
4663                }
4664            } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
4665                    & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
4666                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
4667                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4668                        "): IN_SCREEN");
4669                // A window that has requested to fill the entire screen just
4670                // gets everything, period.
4671                if (attrs.type == TYPE_STATUS_BAR_PANEL
4672                        || attrs.type == TYPE_STATUS_BAR_SUB_PANEL
4673                        || attrs.type == TYPE_VOLUME_OVERLAY) {
4674                    pf.left = df.left = of.left = cf.left = hasNavBar
4675                            ? mDockLeft : mUnrestrictedScreenLeft;
4676                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
4677                    pf.right = df.right = of.right = cf.right = hasNavBar
4678                                        ? mRestrictedScreenLeft+mRestrictedScreenWidth
4679                                        : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4680                    pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar
4681                                          ? mRestrictedScreenTop+mRestrictedScreenHeight
4682                                          : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4683                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4684                                    "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
4685                                    pf.left, pf.top, pf.right, pf.bottom));
4686                } else if (attrs.type == TYPE_NAVIGATION_BAR
4687                        || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
4688                    // The navigation bar has Real Ultimate Power.
4689                    pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4690                    pf.top = df.top = of.top = mUnrestrictedScreenTop;
4691                    pf.right = df.right = of.right = mUnrestrictedScreenLeft
4692                            + mUnrestrictedScreenWidth;
4693                    pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop
4694                            + mUnrestrictedScreenHeight;
4695                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4696                                    "Laying out navigation bar window: (%d,%d - %d,%d)",
4697                                    pf.left, pf.top, pf.right, pf.bottom));
4698                } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
4699                                || attrs.type == TYPE_BOOT_PROGRESS
4700                                || attrs.type == TYPE_SCREENSHOT)
4701                        && ((fl & FLAG_FULLSCREEN) != 0)) {
4702                    // Fullscreen secure system overlays get what they ask for. Screenshot region
4703                    // selection overlay should also expand to full screen.
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 (attrs.type == TYPE_BOOT_PROGRESS) {
4711                    // Boot progress screen always covers entire display.
4712                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4713                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4714                    pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
4715                            + mOverscanScreenWidth;
4716                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
4717                            + mOverscanScreenHeight;
4718                } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4719                        && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4720                        && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4721                    // Asking to layout into the overscan region, so give it that pure
4722                    // unrestricted area.
4723                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4724                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4725                    pf.right = df.right = of.right = cf.right
4726                            = mOverscanScreenLeft + mOverscanScreenWidth;
4727                    pf.bottom = df.bottom = of.bottom = cf.bottom
4728                            = mOverscanScreenTop + mOverscanScreenHeight;
4729                } else if (canHideNavigationBar()
4730                        && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4731                        && (attrs.type == TYPE_STATUS_BAR
4732                            || attrs.type == TYPE_TOAST
4733                            || attrs.type == TYPE_DOCK_DIVIDER
4734                            || attrs.type == TYPE_VOICE_INTERACTION_STARTING
4735                            || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4736                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
4737                    // Asking for layout as if the nav bar is hidden, lets the
4738                    // application extend into the unrestricted screen area.  We
4739                    // only do this for application windows (or toasts) to ensure no window that
4740                    // can be above the nav bar can do this.
4741                    // XXX This assumes that an app asking for this will also
4742                    // ask for layout in only content.  We can't currently figure out
4743                    // what the screen would be if only laying out to hide the nav bar.
4744                    pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
4745                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
4746                    pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft
4747                            + mUnrestrictedScreenWidth;
4748                    pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
4749                            + mUnrestrictedScreenHeight;
4750                } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
4751                    pf.left = df.left = of.left = mRestrictedScreenLeft;
4752                    pf.top = df.top = of.top  = mRestrictedScreenTop;
4753                    pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
4754                    pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop
4755                            + mRestrictedScreenHeight;
4756                    if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4757                        cf.left = mDockLeft;
4758                        cf.top = mDockTop;
4759                        cf.right = mDockRight;
4760                        cf.bottom = mDockBottom;
4761                    } else {
4762                        cf.left = mContentLeft;
4763                        cf.top = mContentTop;
4764                        cf.right = mContentRight;
4765                        cf.bottom = mContentBottom;
4766                    }
4767                } else {
4768                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
4769                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
4770                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
4771                            + mRestrictedScreenWidth;
4772                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
4773                            + mRestrictedScreenHeight;
4774                }
4775
4776                applyStableConstraints(sysUiFl, fl, cf);
4777
4778                if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4779                    vf.left = mCurLeft;
4780                    vf.top = mCurTop;
4781                    vf.right = mCurRight;
4782                    vf.bottom = mCurBottom;
4783                } else {
4784                    vf.set(cf);
4785                }
4786            } else if (attached != null) {
4787                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4788                        "): attached to " + attached);
4789                // A child window should be placed inside of the same visible
4790                // frame that its parent had.
4791                setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf);
4792            } else {
4793                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4794                        "): normal window");
4795                // Otherwise, a normal window must be placed inside the content
4796                // of all screen decorations.
4797                if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) {
4798                    // Status bar panels and the volume dialog are the only windows who can go on
4799                    // top of the status bar.  They are protected by the STATUS_BAR_SERVICE
4800                    // permission, so they have the same privileges as the status
4801                    // bar itself.
4802                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
4803                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
4804                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
4805                            + mRestrictedScreenWidth;
4806                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
4807                            + mRestrictedScreenHeight;
4808                } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) {
4809                    // These dialogs are stable to interim decor changes.
4810                    pf.left = df.left = of.left = cf.left = mStableLeft;
4811                    pf.top = df.top = of.top = cf.top = mStableTop;
4812                    pf.right = df.right = of.right = cf.right = mStableRight;
4813                    pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom;
4814                } else {
4815                    pf.left = mContentLeft;
4816                    pf.top = mContentTop;
4817                    pf.right = mContentRight;
4818                    pf.bottom = mContentBottom;
4819                    if (win.isVoiceInteraction()) {
4820                        df.left = of.left = cf.left = mVoiceContentLeft;
4821                        df.top = of.top = cf.top = mVoiceContentTop;
4822                        df.right = of.right = cf.right = mVoiceContentRight;
4823                        df.bottom = of.bottom = cf.bottom = mVoiceContentBottom;
4824                    } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4825                        df.left = of.left = cf.left = mDockLeft;
4826                        df.top = of.top = cf.top = mDockTop;
4827                        df.right = of.right = cf.right = mDockRight;
4828                        df.bottom = of.bottom = cf.bottom = mDockBottom;
4829                    } else {
4830                        df.left = of.left = cf.left = mContentLeft;
4831                        df.top = of.top = cf.top = mContentTop;
4832                        df.right = of.right = cf.right = mContentRight;
4833                        df.bottom = of.bottom = cf.bottom = mContentBottom;
4834                    }
4835                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4836                        vf.left = mCurLeft;
4837                        vf.top = mCurTop;
4838                        vf.right = mCurRight;
4839                        vf.bottom = mCurBottom;
4840                    } else {
4841                        vf.set(cf);
4842                    }
4843                }
4844            }
4845        }
4846
4847        // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
4848        // Also, we don't allow windows in multi-window mode to extend out of the screen.
4849        if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR
4850                && !win.isInMultiWindowMode()) {
4851            df.left = df.top = -10000;
4852            df.right = df.bottom = 10000;
4853            if (attrs.type != TYPE_WALLPAPER) {
4854                of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
4855                of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
4856            }
4857        }
4858
4859        // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we
4860        // need to provide information to the clients that want to pretend that you can draw there.
4861        // We only want to apply outsets to certain types of windows. For example, we never want to
4862        // apply the outsets to floating dialogs, because they wouldn't make sense there.
4863        final boolean useOutsets = shouldUseOutsets(attrs, fl);
4864        if (isDefaultDisplay && useOutsets) {
4865            osf = mTmpOutsetFrame;
4866            osf.set(cf.left, cf.top, cf.right, cf.bottom);
4867            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
4868            if (outset > 0) {
4869                int rotation = mDisplayRotation;
4870                if (rotation == Surface.ROTATION_0) {
4871                    osf.bottom += outset;
4872                } else if (rotation == Surface.ROTATION_90) {
4873                    osf.right += outset;
4874                } else if (rotation == Surface.ROTATION_180) {
4875                    osf.top -= outset;
4876                } else if (rotation == Surface.ROTATION_270) {
4877                    osf.left -= outset;
4878                }
4879                if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset
4880                        + " with rotation " + rotation + ", result: " + osf);
4881            }
4882        }
4883
4884        if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
4885                + ": sim=#" + Integer.toHexString(sim)
4886                + " attach=" + attached + " type=" + attrs.type
4887                + String.format(" flags=0x%08x", fl)
4888                + " pf=" + pf.toShortString() + " df=" + df.toShortString()
4889                + " of=" + of.toShortString()
4890                + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
4891                + " dcf=" + dcf.toShortString()
4892                + " sf=" + sf.toShortString()
4893                + " osf=" + (osf == null ? "null" : osf.toShortString()));
4894
4895        win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf);
4896
4897        // Dock windows carve out the bottom of the screen, so normal windows
4898        // can't appear underneath them.
4899        if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleOrBehindKeyguardLw()
4900                && win.isDisplayedLw() && !win.getGivenInsetsPendingLw()) {
4901            setLastInputMethodWindowLw(null, null);
4902            offsetInputMethodWindowLw(win);
4903        }
4904        if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleOrBehindKeyguardLw()
4905                && !win.getGivenInsetsPendingLw()) {
4906            offsetVoiceInputWindowLw(win);
4907        }
4908    }
4909
4910    private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) {
4911
4912        // The wallpaper also has Real Ultimate Power, but we want to tell
4913        // it about the overscan area.
4914        pf.left = df.left = mOverscanScreenLeft;
4915        pf.top = df.top = mOverscanScreenTop;
4916        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
4917        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
4918        of.left = cf.left = mUnrestrictedScreenLeft;
4919        of.top = cf.top = mUnrestrictedScreenTop;
4920        of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4921        of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4922    }
4923
4924    private void offsetInputMethodWindowLw(WindowState win) {
4925        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
4926        top += win.getGivenContentInsetsLw().top;
4927        if (mContentBottom > top) {
4928            mContentBottom = top;
4929        }
4930        if (mVoiceContentBottom > top) {
4931            mVoiceContentBottom = top;
4932        }
4933        top = win.getVisibleFrameLw().top;
4934        top += win.getGivenVisibleInsetsLw().top;
4935        if (mCurBottom > top) {
4936            mCurBottom = top;
4937        }
4938        if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
4939                + mDockBottom + " mContentBottom="
4940                + mContentBottom + " mCurBottom=" + mCurBottom);
4941    }
4942
4943    private void offsetVoiceInputWindowLw(WindowState win) {
4944        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
4945        top += win.getGivenContentInsetsLw().top;
4946        if (mVoiceContentBottom > top) {
4947            mVoiceContentBottom = top;
4948        }
4949    }
4950
4951    /** {@inheritDoc} */
4952    @Override
4953    public void finishLayoutLw() {
4954        return;
4955    }
4956
4957    /** {@inheritDoc} */
4958    @Override
4959    public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
4960        mTopFullscreenOpaqueWindowState = null;
4961        mTopFullscreenOpaqueOrDimmingWindowState = null;
4962        mTopDockedOpaqueWindowState = null;
4963        mTopDockedOpaqueOrDimmingWindowState = null;
4964        mAppsToBeHidden.clear();
4965        mAppsThatDismissKeyguard.clear();
4966        mForceStatusBar = false;
4967        mForceStatusBarFromKeyguard = false;
4968        mForceStatusBarTransparent = false;
4969        mForcingShowNavBar = false;
4970        mForcingShowNavBarLayer = -1;
4971
4972        mHideLockScreen = false;
4973        mAllowLockscreenWhenOn = false;
4974        mDismissKeyguard = DISMISS_KEYGUARD_NONE;
4975        mShowingLockscreen = false;
4976        mShowingDream = false;
4977        mWinShowWhenLocked = null;
4978        mKeyguardSecure = isKeyguardSecure(mCurrentUserId);
4979        mKeyguardSecureIncludingHidden = mKeyguardSecure
4980                && (mKeyguardDelegate != null && mKeyguardDelegate.isShowing());
4981    }
4982
4983    /** {@inheritDoc} */
4984    @Override
4985    public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
4986            WindowState attached) {
4987        if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
4988                + win.isVisibleOrBehindKeyguardLw());
4989        final int fl = PolicyControl.getWindowFlags(win, attrs);
4990        if (mTopFullscreenOpaqueWindowState == null
4991                && win.isVisibleLw() && attrs.type == TYPE_INPUT_METHOD) {
4992            mForcingShowNavBar = true;
4993            mForcingShowNavBarLayer = win.getSurfaceLayer();
4994        }
4995        if (attrs.type == TYPE_STATUS_BAR) {
4996            if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
4997                mForceStatusBarFromKeyguard = true;
4998                mShowingLockscreen = true;
4999            }
5000            if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
5001                mForceStatusBarTransparent = true;
5002            }
5003        }
5004
5005        boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
5006                && attrs.type < FIRST_SYSTEM_WINDOW;
5007        final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0;
5008        final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0;
5009        final int stackId = win.getStackId();
5010        if (mTopFullscreenOpaqueWindowState == null &&
5011                win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
5012            if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
5013                if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
5014                    mForceStatusBarFromKeyguard = true;
5015                } else {
5016                    mForceStatusBar = true;
5017                }
5018            }
5019            if (attrs.type == TYPE_DREAM) {
5020                // If the lockscreen was showing when the dream started then wait
5021                // for the dream to draw before hiding the lockscreen.
5022                if (!mDreamingLockscreen
5023                        || (win.isVisibleLw() && win.hasDrawnLw())) {
5024                    mShowingDream = true;
5025                    appWindow = true;
5026                }
5027            }
5028
5029            final IApplicationToken appToken = win.getAppToken();
5030
5031            // For app windows that are not attached, we decide if all windows in the app they
5032            // represent should be hidden or if we should hide the lockscreen. For attached app
5033            // windows we defer the decision to the window it is attached to.
5034            if (appWindow && attached == null) {
5035                if (showWhenLocked) {
5036                    // Remove any previous windows with the same appToken.
5037                    mAppsToBeHidden.remove(appToken);
5038                    mAppsThatDismissKeyguard.remove(appToken);
5039                    if (mAppsToBeHidden.isEmpty()) {
5040                        if (dismissKeyguard && !mKeyguardSecure) {
5041                            mAppsThatDismissKeyguard.add(appToken);
5042                        } else if (win.isDrawnLw() || win.hasAppShownWindows()) {
5043                            mWinShowWhenLocked = win;
5044                            mHideLockScreen = true;
5045                            mForceStatusBarFromKeyguard = false;
5046                        }
5047                    }
5048                } else if (dismissKeyguard) {
5049                    if (mKeyguardSecure) {
5050                        mAppsToBeHidden.add(appToken);
5051                    } else {
5052                        mAppsToBeHidden.remove(appToken);
5053                    }
5054                    mAppsThatDismissKeyguard.add(appToken);
5055                } else {
5056                    mAppsToBeHidden.add(appToken);
5057                }
5058                if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
5059                    if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
5060                    mTopFullscreenOpaqueWindowState = win;
5061                    if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5062                        mTopFullscreenOpaqueOrDimmingWindowState = win;
5063                    }
5064                    if (!mAppsThatDismissKeyguard.isEmpty() &&
5065                            mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
5066                        if (DEBUG_LAYOUT) Slog.v(TAG,
5067                                "Setting mDismissKeyguard true by win " + win);
5068                        mDismissKeyguard = (mWinDismissingKeyguard == win
5069                                && mSecureDismissingKeyguard == mKeyguardSecure)
5070                                ? DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
5071                        mWinDismissingKeyguard = win;
5072                        mSecureDismissingKeyguard = mKeyguardSecure;
5073                        mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure;
5074                    } else if (mAppsToBeHidden.isEmpty() && showWhenLocked
5075                            && (win.isDrawnLw() || win.hasAppShownWindows())) {
5076                        if (DEBUG_LAYOUT) Slog.v(TAG,
5077                                "Setting mHideLockScreen to true by win " + win);
5078                        mHideLockScreen = true;
5079                        mForceStatusBarFromKeyguard = false;
5080                    }
5081                    if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
5082                        mAllowLockscreenWhenOn = true;
5083                    }
5084                }
5085
5086                if (!mKeyguardHidden && mWinShowWhenLocked != null &&
5087                        mWinShowWhenLocked.getAppToken() != win.getAppToken() &&
5088                        (attrs.flags & FLAG_SHOW_WHEN_LOCKED) == 0) {
5089                    win.hideLw(false);
5090                }
5091            }
5092        } else if (mTopFullscreenOpaqueWindowState == null && mWinShowWhenLocked == null) {
5093            // No TopFullscreenOpaqueWindow is showing, but we found a SHOW_WHEN_LOCKED window
5094            // that is being hidden in an animation - keep the
5095            // keyguard hidden until the new window shows up and
5096            // we know whether to show the keyguard or not.
5097            if (win.isAnimatingLw() && appWindow && showWhenLocked && mKeyguardHidden) {
5098                mHideLockScreen = true;
5099                mWinShowWhenLocked = win;
5100            }
5101        }
5102
5103        final boolean reallyVisible = win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw();
5104
5105        // Voice interaction overrides both top fullscreen and top docked.
5106        if (reallyVisible && win.getAttrs().type == TYPE_VOICE_INTERACTION) {
5107            if (mTopFullscreenOpaqueWindowState == null) {
5108                mTopFullscreenOpaqueWindowState = win;
5109                if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5110                    mTopFullscreenOpaqueOrDimmingWindowState = win;
5111                }
5112            }
5113            if (mTopDockedOpaqueWindowState == null) {
5114                mTopDockedOpaqueWindowState = win;
5115                if (mTopDockedOpaqueOrDimmingWindowState == null) {
5116                    mTopDockedOpaqueOrDimmingWindowState = win;
5117                }
5118            }
5119        }
5120
5121        // Keep track of the window if it's dimming but not necessarily fullscreen.
5122        if (mTopFullscreenOpaqueOrDimmingWindowState == null && reallyVisible
5123                && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
5124            mTopFullscreenOpaqueOrDimmingWindowState = win;
5125        }
5126
5127        // We need to keep track of the top "fullscreen" opaque window for the docked stack
5128        // separately, because both the "real fullscreen" opaque window and the one for the docked
5129        // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
5130        if (mTopDockedOpaqueWindowState == null && reallyVisible && appWindow && attached == null
5131                && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
5132            mTopDockedOpaqueWindowState = win;
5133            if (mTopDockedOpaqueOrDimmingWindowState == null) {
5134                mTopDockedOpaqueOrDimmingWindowState = win;
5135            }
5136        }
5137
5138        // Also keep track of any windows that are dimming but not necessarily fullscreen in the
5139        // docked stack.
5140        if (mTopDockedOpaqueOrDimmingWindowState == null && reallyVisible && win.isDimming()
5141                && stackId == DOCKED_STACK_ID) {
5142            mTopDockedOpaqueOrDimmingWindowState = win;
5143        }
5144    }
5145
5146    private boolean isFullscreen(WindowManager.LayoutParams attrs) {
5147        return attrs.x == 0 && attrs.y == 0
5148                && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
5149                && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
5150    }
5151
5152    /** {@inheritDoc} */
5153    @Override
5154    public int finishPostLayoutPolicyLw() {
5155        if (mWinShowWhenLocked != null && mTopFullscreenOpaqueWindowState != null &&
5156                mWinShowWhenLocked.getAppToken() != mTopFullscreenOpaqueWindowState.getAppToken()
5157                && isKeyguardLocked()) {
5158            // A dialog is dismissing the keyguard. Put the wallpaper behind it and hide the
5159            // fullscreen window.
5160            // TODO: Make sure FLAG_SHOW_WALLPAPER is restored when dialog is dismissed. Or not.
5161            mWinShowWhenLocked.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5162            mTopFullscreenOpaqueWindowState.hideLw(false);
5163            mTopFullscreenOpaqueWindowState = mWinShowWhenLocked;
5164        }
5165
5166        int changes = 0;
5167        boolean topIsFullscreen = false;
5168
5169        final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
5170                ? mTopFullscreenOpaqueWindowState.getAttrs()
5171                : null;
5172
5173        // If we are not currently showing a dream then remember the current
5174        // lockscreen state.  We will use this to determine whether the dream
5175        // started while the lockscreen was showing and remember this state
5176        // while the dream is showing.
5177        if (!mShowingDream) {
5178            mDreamingLockscreen = mShowingLockscreen;
5179            if (mDreamingSleepTokenNeeded) {
5180                mDreamingSleepTokenNeeded = false;
5181                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
5182            }
5183        } else {
5184            if (!mDreamingSleepTokenNeeded) {
5185                mDreamingSleepTokenNeeded = true;
5186                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget();
5187            }
5188        }
5189
5190        if (mStatusBar != null) {
5191            if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
5192                    + " forcefkg=" + mForceStatusBarFromKeyguard
5193                    + " top=" + mTopFullscreenOpaqueWindowState);
5194            boolean shouldBeTransparent = mForceStatusBarTransparent
5195                    && !mForceStatusBar
5196                    && !mForceStatusBarFromKeyguard;
5197            if (!shouldBeTransparent) {
5198                mStatusBarController.setShowTransparent(false /* transparent */);
5199            } else if (!mStatusBar.isVisibleLw()) {
5200                mStatusBarController.setShowTransparent(true /* transparent */);
5201            }
5202
5203            WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs();
5204            boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT
5205                    && statusBarAttrs.width == MATCH_PARENT;
5206            if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
5207                    || statusBarExpanded) {
5208                if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
5209                if (mStatusBarController.setBarShowingLw(true)) {
5210                    changes |= FINISH_LAYOUT_REDO_LAYOUT;
5211                }
5212                // Maintain fullscreen layout until incoming animation is complete.
5213                topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
5214                // Transient status bar on the lockscreen is not allowed
5215                if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) {
5216                    mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
5217                            mLastSystemUiFlags, mLastSystemUiFlags);
5218                }
5219                if (statusBarExpanded && mNavigationBar != null) {
5220                    if (mNavigationBarController.setBarShowingLw(true)) {
5221                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5222                    }
5223                }
5224            } else if (mTopFullscreenOpaqueWindowState != null) {
5225                final int fl = PolicyControl.getWindowFlags(null, lp);
5226                if (localLOGV) {
5227                    Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
5228                            + " shown position: "
5229                            + mTopFullscreenOpaqueWindowState.getShownPositionLw());
5230                    Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
5231                            + " lp.flags=0x" + Integer.toHexString(fl));
5232                }
5233                topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
5234                        || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
5235                // The subtle difference between the window for mTopFullscreenOpaqueWindowState
5236                // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
5237                // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
5238                // case though.
5239                if (mStatusBarController.isTransientShowing()) {
5240                    if (mStatusBarController.setBarShowingLw(true)) {
5241                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5242                    }
5243                } else if (topIsFullscreen
5244                        && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)
5245                        && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) {
5246                    if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
5247                    if (mStatusBarController.setBarShowingLw(false)) {
5248                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5249                    } else {
5250                        if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
5251                    }
5252                } else {
5253                    if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
5254                    if (mStatusBarController.setBarShowingLw(true)) {
5255                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5256                    }
5257                }
5258            }
5259        }
5260
5261        if (mTopIsFullscreen != topIsFullscreen) {
5262            if (!topIsFullscreen) {
5263                // Force another layout when status bar becomes fully shown.
5264                changes |= FINISH_LAYOUT_REDO_LAYOUT;
5265            }
5266            mTopIsFullscreen = topIsFullscreen;
5267        }
5268
5269        // Hide the key guard if a visible window explicitly specifies that it wants to be
5270        // displayed when the screen is locked.
5271        if (mKeyguardDelegate != null && mStatusBar != null) {
5272            if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
5273                    + mHideLockScreen);
5274            if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardSecure) {
5275                mKeyguardHidden = true;
5276                if (setKeyguardOccludedLw(true)) {
5277                    changes |= FINISH_LAYOUT_REDO_LAYOUT
5278                            | FINISH_LAYOUT_REDO_CONFIG
5279                            | FINISH_LAYOUT_REDO_WALLPAPER;
5280                }
5281                if (mKeyguardDelegate.isShowing()) {
5282                    mHandler.post(new Runnable() {
5283                        @Override
5284                        public void run() {
5285                            mKeyguardDelegate.keyguardDone(false, false);
5286                        }
5287                    });
5288                }
5289            } else if (mHideLockScreen) {
5290                mKeyguardHidden = true;
5291                mWinDismissingKeyguard = null;
5292                if (setKeyguardOccludedLw(true)) {
5293                    changes |= FINISH_LAYOUT_REDO_LAYOUT
5294                            | FINISH_LAYOUT_REDO_CONFIG
5295                            | FINISH_LAYOUT_REDO_WALLPAPER;
5296                }
5297            } else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) {
5298                mKeyguardHidden = false;
5299                final boolean trusted = mKeyguardDelegate.isTrusted();
5300                if (trusted) {
5301                    // No need to un-occlude keyguard - we'll dimiss it right away anyways.
5302                } else if (setKeyguardOccludedLw(false)) {
5303                    changes |= FINISH_LAYOUT_REDO_LAYOUT
5304                            | FINISH_LAYOUT_REDO_CONFIG
5305                            | FINISH_LAYOUT_REDO_WALLPAPER;
5306                }
5307                if (mDismissKeyguard == DISMISS_KEYGUARD_START) {
5308                    // Only launch the next keyguard unlock window once per window.
5309                    mHandler.post(new Runnable() {
5310                        @Override
5311                        public void run() {
5312                            mKeyguardDelegate.dismiss(trusted /* allowWhileOccluded */);
5313                        }
5314                    });
5315                }
5316            } else {
5317                mWinDismissingKeyguard = null;
5318                mSecureDismissingKeyguard = false;
5319                mKeyguardHidden = false;
5320                if (setKeyguardOccludedLw(false)) {
5321                    changes |= FINISH_LAYOUT_REDO_LAYOUT
5322                            | FINISH_LAYOUT_REDO_CONFIG
5323                            | FINISH_LAYOUT_REDO_WALLPAPER;
5324                }
5325            }
5326        }
5327
5328        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5329            // If the navigation bar has been hidden or shown, we need to do another
5330            // layout pass to update that window.
5331            changes |= FINISH_LAYOUT_REDO_LAYOUT;
5332        }
5333
5334        // update since mAllowLockscreenWhenOn might have changed
5335        updateLockScreenTimeout();
5336        return changes;
5337    }
5338
5339    /**
5340     * Updates the occluded state of the Keyguard.
5341     *
5342     * @return Whether the flags have changed and we have to redo the layout.
5343     */
5344    private boolean setKeyguardOccludedLw(boolean isOccluded) {
5345        boolean wasOccluded = mKeyguardOccluded;
5346        boolean showing = mKeyguardDelegate.isShowing();
5347        if (wasOccluded && !isOccluded && showing) {
5348            mKeyguardOccluded = false;
5349            mKeyguardDelegate.setOccluded(false, true /* animate */);
5350            mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
5351            if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
5352                mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5353            }
5354            Animation anim = AnimationUtils.loadAnimation(mContext,
5355                    com.android.internal.R.anim.wallpaper_open_exit);
5356            mWindowManagerFuncs.overridePlayingAppAnimationsLw(anim);
5357            return true;
5358        } else if (!wasOccluded && isOccluded && showing) {
5359            mKeyguardOccluded = true;
5360            mKeyguardDelegate.setOccluded(true, false /* animate */);
5361            mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
5362            mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
5363            return true;
5364        } else {
5365            return false;
5366        }
5367    }
5368
5369    private boolean isStatusBarKeyguard() {
5370        return mStatusBar != null
5371                && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
5372    }
5373
5374    @Override
5375    public boolean allowAppAnimationsLw() {
5376        if (isStatusBarKeyguard() || mShowingDream) {
5377            // If keyguard or dreams is currently visible, no reason to animate behind it.
5378            return false;
5379        }
5380        return true;
5381    }
5382
5383    @Override
5384    public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
5385        mFocusedWindow = newFocus;
5386        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5387            // If the navigation bar has been hidden or shown, we need to do another
5388            // layout pass to update that window.
5389            return FINISH_LAYOUT_REDO_LAYOUT;
5390        }
5391        return 0;
5392    }
5393
5394    /** {@inheritDoc} */
5395    @Override
5396    public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
5397        // lid changed state
5398        final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
5399        if (newLidState == mLidState) {
5400            return;
5401        }
5402
5403        mLidState = newLidState;
5404        applyLidSwitchState();
5405        updateRotation(true);
5406
5407        if (lidOpen) {
5408            wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
5409                    "android.policy:LID");
5410        } else if (!mLidControlsSleep) {
5411            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
5412        }
5413    }
5414
5415    @Override
5416    public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
5417        int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
5418        if (mCameraLensCoverState == lensCoverState) {
5419            return;
5420        }
5421        if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
5422                lensCoverState == CAMERA_LENS_UNCOVERED) {
5423            Intent intent;
5424            final boolean keyguardActive = mKeyguardDelegate == null ? false :
5425                    mKeyguardDelegate.isShowing();
5426            if (keyguardActive) {
5427                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
5428            } else {
5429                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
5430            }
5431            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
5432                    "android.policy:CAMERA_COVER");
5433            startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
5434        }
5435        mCameraLensCoverState = lensCoverState;
5436    }
5437
5438    void setHdmiPlugged(boolean plugged) {
5439        if (mHdmiPlugged != plugged) {
5440            mHdmiPlugged = plugged;
5441            updateRotation(true, true);
5442            Intent intent = new Intent(ACTION_HDMI_PLUGGED);
5443            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
5444            intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
5445            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
5446        }
5447    }
5448
5449    void initializeHdmiState() {
5450        boolean plugged = false;
5451        // watch for HDMI plug messages if the hdmi switch exists
5452        if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
5453            mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
5454
5455            final String filename = "/sys/class/switch/hdmi/state";
5456            FileReader reader = null;
5457            try {
5458                reader = new FileReader(filename);
5459                char[] buf = new char[15];
5460                int n = reader.read(buf);
5461                if (n > 1) {
5462                    plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
5463                }
5464            } catch (IOException ex) {
5465                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5466            } catch (NumberFormatException ex) {
5467                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5468            } finally {
5469                if (reader != null) {
5470                    try {
5471                        reader.close();
5472                    } catch (IOException ex) {
5473                    }
5474                }
5475            }
5476        }
5477        // This dance forces the code in setHdmiPlugged to run.
5478        // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
5479        mHdmiPlugged = !plugged;
5480        setHdmiPlugged(!mHdmiPlugged);
5481    }
5482
5483    final Object mScreenshotLock = new Object();
5484    ServiceConnection mScreenshotConnection = null;
5485
5486    final Runnable mScreenshotTimeout = new Runnable() {
5487        @Override public void run() {
5488            synchronized (mScreenshotLock) {
5489                if (mScreenshotConnection != null) {
5490                    mContext.unbindService(mScreenshotConnection);
5491                    mScreenshotConnection = null;
5492                    notifyScreenshotError();
5493                }
5494            }
5495        }
5496    };
5497
5498    // Assume this is called from the Handler thread.
5499    private void takeScreenshot(final int screenshotType) {
5500        synchronized (mScreenshotLock) {
5501            if (mScreenshotConnection != null) {
5502                return;
5503            }
5504            final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
5505                    SYSUI_SCREENSHOT_SERVICE);
5506            final Intent serviceIntent = new Intent();
5507            serviceIntent.setComponent(serviceComponent);
5508            ServiceConnection conn = new ServiceConnection() {
5509                @Override
5510                public void onServiceConnected(ComponentName name, IBinder service) {
5511                    synchronized (mScreenshotLock) {
5512                        if (mScreenshotConnection != this) {
5513                            return;
5514                        }
5515                        Messenger messenger = new Messenger(service);
5516                        Message msg = Message.obtain(null, screenshotType);
5517                        final ServiceConnection myConn = this;
5518                        Handler h = new Handler(mHandler.getLooper()) {
5519                            @Override
5520                            public void handleMessage(Message msg) {
5521                                synchronized (mScreenshotLock) {
5522                                    if (mScreenshotConnection == myConn) {
5523                                        mContext.unbindService(mScreenshotConnection);
5524                                        mScreenshotConnection = null;
5525                                        mHandler.removeCallbacks(mScreenshotTimeout);
5526                                    }
5527                                }
5528                            }
5529                        };
5530                        msg.replyTo = new Messenger(h);
5531                        msg.arg1 = msg.arg2 = 0;
5532                        if (mStatusBar != null && mStatusBar.isVisibleLw())
5533                            msg.arg1 = 1;
5534                        if (mNavigationBar != null && mNavigationBar.isVisibleLw())
5535                            msg.arg2 = 1;
5536                        try {
5537                            messenger.send(msg);
5538                        } catch (RemoteException e) {
5539                        }
5540                    }
5541                }
5542
5543                @Override
5544                public void onServiceDisconnected(ComponentName name) {
5545                    synchronized (mScreenshotLock) {
5546                        if (mScreenshotConnection != null) {
5547                            mContext.unbindService(mScreenshotConnection);
5548                            mScreenshotConnection = null;
5549                            mHandler.removeCallbacks(mScreenshotTimeout);
5550                            notifyScreenshotError();
5551                        }
5552                    }
5553                }
5554            };
5555            if (mContext.bindServiceAsUser(serviceIntent, conn,
5556                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
5557                    UserHandle.CURRENT)) {
5558                mScreenshotConnection = conn;
5559                mHandler.postDelayed(mScreenshotTimeout, 10000);
5560            }
5561        }
5562    }
5563
5564    /**
5565     * Notifies the screenshot service to show an error.
5566     */
5567    private void notifyScreenshotError() {
5568        // If the service process is killed, then ask it to clean up after itself
5569        final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
5570                SYSUI_SCREENSHOT_ERROR_RECEIVER);
5571        Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
5572        errorIntent.setComponent(errorComponent);
5573        errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
5574                Intent.FLAG_RECEIVER_FOREGROUND);
5575        mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT);
5576    }
5577
5578    /** {@inheritDoc} */
5579    @Override
5580    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
5581        if (!mSystemBooted) {
5582            // If we have not yet booted, don't let key events do anything.
5583            return 0;
5584        }
5585
5586        final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
5587        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
5588        final boolean canceled = event.isCanceled();
5589        final int keyCode = event.getKeyCode();
5590
5591        final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
5592
5593        // If screen is off then we treat the case where the keyguard is open but hidden
5594        // the same as if it were open and in front.
5595        // This will prevent any keys other than the power button from waking the screen
5596        // when the keyguard is hidden by another activity.
5597        final boolean keyguardActive = (mKeyguardDelegate == null ? false :
5598                                            (interactive ?
5599                                                isKeyguardShowingAndNotOccluded() :
5600                                                mKeyguardDelegate.isShowing()));
5601
5602        if (DEBUG_INPUT) {
5603            Log.d(TAG, "interceptKeyTq keycode=" + keyCode
5604                    + " interactive=" + interactive + " keyguardActive=" + keyguardActive
5605                    + " policyFlags=" + Integer.toHexString(policyFlags));
5606        }
5607
5608        // Basic policy based on interactive state.
5609        int result;
5610        boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
5611                || event.isWakeKey();
5612        if (interactive || (isInjected && !isWakeKey)) {
5613            // When the device is interactive or the key is injected pass the
5614            // key to the application.
5615            result = ACTION_PASS_TO_USER;
5616            isWakeKey = false;
5617
5618            if (interactive) {
5619                // If the screen is awake, but the button pressed was the one that woke the device
5620                // then don't pass it to the application
5621                if (keyCode == mPendingWakeKey && !down) {
5622                    result = 0;
5623                }
5624                // Reset the pending key
5625                mPendingWakeKey = PENDING_KEY_NULL;
5626            }
5627        } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
5628            // If we're currently dozing with the screen on and the keyguard showing, pass the key
5629            // to the application but preserve its wake key status to make sure we still move
5630            // from dozing to fully interactive if we would normally go from off to fully
5631            // interactive.
5632            result = ACTION_PASS_TO_USER;
5633            // Since we're dispatching the input, reset the pending key
5634            mPendingWakeKey = PENDING_KEY_NULL;
5635        } else {
5636            // When the screen is off and the key is not injected, determine whether
5637            // to wake the device but don't pass the key to the application.
5638            result = 0;
5639            if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
5640                isWakeKey = false;
5641            }
5642            // Cache the wake key on down event so we can also avoid sending the up event to the app
5643            if (isWakeKey && down) {
5644                mPendingWakeKey = keyCode;
5645            }
5646        }
5647
5648        // If the key would be handled globally, just return the result, don't worry about special
5649        // key processing.
5650        if (isValidGlobalKey(keyCode)
5651                && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
5652            if (isWakeKey) {
5653                wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5654            }
5655            return result;
5656        }
5657
5658        boolean useHapticFeedback = down
5659                && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
5660                && event.getRepeatCount() == 0;
5661
5662        // Handle special keys.
5663        switch (keyCode) {
5664            case KeyEvent.KEYCODE_BACK: {
5665                if (down) {
5666                    mBackKeyHandled = false;
5667                    if (hasLongPressOnBackBehavior()) {
5668                        Message msg = mHandler.obtainMessage(MSG_BACK_LONG_PRESS);
5669                        msg.setAsynchronous(true);
5670                        mHandler.sendMessageDelayed(msg,
5671                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
5672                    }
5673                } else {
5674                    boolean handled = mBackKeyHandled;
5675
5676                    // Reset back key state
5677                    cancelPendingBackKeyAction();
5678
5679                    // Don't pass back press to app if we've already handled it
5680                    if (handled) {
5681                        result &= ~ACTION_PASS_TO_USER;
5682                    }
5683                }
5684                break;
5685            }
5686
5687            case KeyEvent.KEYCODE_VOLUME_DOWN:
5688            case KeyEvent.KEYCODE_VOLUME_UP:
5689            case KeyEvent.KEYCODE_VOLUME_MUTE: {
5690                if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
5691                    if (down) {
5692                        if (interactive && !mScreenshotChordVolumeDownKeyTriggered
5693                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5694                            mScreenshotChordVolumeDownKeyTriggered = true;
5695                            mScreenshotChordVolumeDownKeyTime = event.getDownTime();
5696                            mScreenshotChordVolumeDownKeyConsumed = false;
5697                            cancelPendingPowerKeyAction();
5698                            interceptScreenshotChord();
5699                        }
5700                    } else {
5701                        mScreenshotChordVolumeDownKeyTriggered = false;
5702                        cancelPendingScreenshotChordAction();
5703                    }
5704                } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
5705                    if (down) {
5706                        if (interactive && !mScreenshotChordVolumeUpKeyTriggered
5707                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5708                            mScreenshotChordVolumeUpKeyTriggered = true;
5709                            cancelPendingPowerKeyAction();
5710                            cancelPendingScreenshotChordAction();
5711                        }
5712                    } else {
5713                        mScreenshotChordVolumeUpKeyTriggered = false;
5714                        cancelPendingScreenshotChordAction();
5715                    }
5716                }
5717                if (down) {
5718                    TelecomManager telecomManager = getTelecommService();
5719                    if (telecomManager != null) {
5720                        if (telecomManager.isRinging()) {
5721                            // If an incoming call is ringing, either VOLUME key means
5722                            // "silence ringer".  We handle these keys here, rather than
5723                            // in the InCallScreen, to make sure we'll respond to them
5724                            // even if the InCallScreen hasn't come to the foreground yet.
5725                            // Look for the DOWN event here, to agree with the "fallback"
5726                            // behavior in the InCallScreen.
5727                            Log.i(TAG, "interceptKeyBeforeQueueing:"
5728                                  + " VOLUME key-down while ringing: Silence ringer!");
5729
5730                            // Silence the ringer.  (It's safe to call this
5731                            // even if the ringer has already been silenced.)
5732                            telecomManager.silenceRinger();
5733
5734                            // And *don't* pass this key thru to the current activity
5735                            // (which is probably the InCallScreen.)
5736                            result &= ~ACTION_PASS_TO_USER;
5737                            break;
5738                        }
5739                        if (telecomManager.isInCall()
5740                                && (result & ACTION_PASS_TO_USER) == 0) {
5741                            // If we are in call but we decided not to pass the key to
5742                            // the application, just pass it to the session service.
5743
5744                            MediaSessionLegacyHelper.getHelper(mContext)
5745                                    .sendVolumeKeyEvent(event, false);
5746                            break;
5747                        }
5748                    }
5749                }
5750                if (mUseTvRouting) {
5751                    // On TVs, defer special key handlings to
5752                    // {@link interceptKeyBeforeDispatching()}.
5753                    result |= ACTION_PASS_TO_USER;
5754                } else if ((result & ACTION_PASS_TO_USER) == 0) {
5755                    // If we aren't passing to the user and no one else
5756                    // handled it send it to the session manager to
5757                    // figure out.
5758                    MediaSessionLegacyHelper.getHelper(mContext)
5759                            .sendVolumeKeyEvent(event, true);
5760                }
5761                break;
5762            }
5763
5764            case KeyEvent.KEYCODE_ENDCALL: {
5765                result &= ~ACTION_PASS_TO_USER;
5766                if (down) {
5767                    TelecomManager telecomManager = getTelecommService();
5768                    boolean hungUp = false;
5769                    if (telecomManager != null) {
5770                        hungUp = telecomManager.endCall();
5771                    }
5772                    if (interactive && !hungUp) {
5773                        mEndCallKeyHandled = false;
5774                        mHandler.postDelayed(mEndCallLongPress,
5775                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
5776                    } else {
5777                        mEndCallKeyHandled = true;
5778                    }
5779                } else {
5780                    if (!mEndCallKeyHandled) {
5781                        mHandler.removeCallbacks(mEndCallLongPress);
5782                        if (!canceled) {
5783                            if ((mEndcallBehavior
5784                                    & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
5785                                if (goHome()) {
5786                                    break;
5787                                }
5788                            }
5789                            if ((mEndcallBehavior
5790                                    & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
5791                                mPowerManager.goToSleep(event.getEventTime(),
5792                                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
5793                                isWakeKey = false;
5794                            }
5795                        }
5796                    }
5797                }
5798                break;
5799            }
5800
5801            case KeyEvent.KEYCODE_POWER: {
5802                result &= ~ACTION_PASS_TO_USER;
5803                isWakeKey = false; // wake-up will be handled separately
5804                if (down) {
5805                    interceptPowerKeyDown(event, interactive);
5806                } else {
5807                    interceptPowerKeyUp(event, interactive, canceled);
5808                }
5809                break;
5810            }
5811
5812            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
5813                // fall through
5814            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
5815                // fall through
5816            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
5817                // fall through
5818            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
5819                result &= ~ACTION_PASS_TO_USER;
5820                interceptSystemNavigationKey(event);
5821                break;
5822            }
5823
5824            case KeyEvent.KEYCODE_SLEEP: {
5825                result &= ~ACTION_PASS_TO_USER;
5826                isWakeKey = false;
5827                if (!mPowerManager.isInteractive()) {
5828                    useHapticFeedback = false; // suppress feedback if already non-interactive
5829                }
5830                if (down) {
5831                    sleepPress(event.getEventTime());
5832                } else {
5833                    sleepRelease(event.getEventTime());
5834                }
5835                break;
5836            }
5837
5838            case KeyEvent.KEYCODE_SOFT_SLEEP: {
5839                result &= ~ACTION_PASS_TO_USER;
5840                isWakeKey = false;
5841                if (!down) {
5842                    mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
5843                }
5844                break;
5845            }
5846
5847            case KeyEvent.KEYCODE_WAKEUP: {
5848                result &= ~ACTION_PASS_TO_USER;
5849                isWakeKey = true;
5850                break;
5851            }
5852
5853            case KeyEvent.KEYCODE_MEDIA_PLAY:
5854            case KeyEvent.KEYCODE_MEDIA_PAUSE:
5855            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
5856            case KeyEvent.KEYCODE_HEADSETHOOK:
5857            case KeyEvent.KEYCODE_MUTE:
5858            case KeyEvent.KEYCODE_MEDIA_STOP:
5859            case KeyEvent.KEYCODE_MEDIA_NEXT:
5860            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
5861            case KeyEvent.KEYCODE_MEDIA_REWIND:
5862            case KeyEvent.KEYCODE_MEDIA_RECORD:
5863            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
5864            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
5865                if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
5866                    // If the global session is active pass all media keys to it
5867                    // instead of the active window.
5868                    result &= ~ACTION_PASS_TO_USER;
5869                }
5870                if ((result & ACTION_PASS_TO_USER) == 0) {
5871                    // Only do this if we would otherwise not pass it to the user. In that
5872                    // case, the PhoneWindow class will do the same thing, except it will
5873                    // only do it if the showing app doesn't process the key on its own.
5874                    // Note that we need to make a copy of the key event here because the
5875                    // original key event will be recycled when we return.
5876                    mBroadcastWakeLock.acquire();
5877                    Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
5878                            new KeyEvent(event));
5879                    msg.setAsynchronous(true);
5880                    msg.sendToTarget();
5881                }
5882                break;
5883            }
5884
5885            case KeyEvent.KEYCODE_CALL: {
5886                if (down) {
5887                    TelecomManager telecomManager = getTelecommService();
5888                    if (telecomManager != null) {
5889                        if (telecomManager.isRinging()) {
5890                            Log.i(TAG, "interceptKeyBeforeQueueing:"
5891                                  + " CALL key-down while ringing: Answer the call!");
5892                            telecomManager.acceptRingingCall();
5893
5894                            // And *don't* pass this key thru to the current activity
5895                            // (which is presumably the InCallScreen.)
5896                            result &= ~ACTION_PASS_TO_USER;
5897                        }
5898                    }
5899                }
5900                break;
5901            }
5902            case KeyEvent.KEYCODE_VOICE_ASSIST: {
5903                // Only do this if we would otherwise not pass it to the user. In that case,
5904                // interceptKeyBeforeDispatching would apply a similar but different policy in
5905                // order to invoke voice assist actions. Note that we need to make a copy of the
5906                // key event here because the original key event will be recycled when we return.
5907                if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
5908                    mBroadcastWakeLock.acquire();
5909                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
5910                            keyguardActive ? 1 : 0, 0);
5911                    msg.setAsynchronous(true);
5912                    msg.sendToTarget();
5913                }
5914                break;
5915            }
5916            case KeyEvent.KEYCODE_WINDOW: {
5917                if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
5918                    if (mTvPictureInPictureVisible) {
5919                        // Consumes the key only if picture-in-picture is visible
5920                        // to show picture-in-picture control menu.
5921                        // This gives a chance to the foreground activity
5922                        // to customize PIP key behavior.
5923                        if (!down) {
5924                            showTvPictureInPictureMenu(event);
5925                        }
5926                        result &= ~ACTION_PASS_TO_USER;
5927                    }
5928                }
5929                break;
5930            }
5931        }
5932
5933        if (useHapticFeedback) {
5934            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
5935        }
5936
5937        if (isWakeKey) {
5938            wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5939        }
5940
5941        return result;
5942    }
5943
5944    /**
5945     * Handle statusbar expansion events.
5946     * @param event
5947     */
5948    private void interceptSystemNavigationKey(KeyEvent event) {
5949        if (event.getAction() == KeyEvent.ACTION_UP && areSystemNavigationKeysEnabled()) {
5950            IStatusBarService sbar = getStatusBarService();
5951            if (sbar != null) {
5952                try {
5953                    sbar.handleSystemNavigationKey(event.getKeyCode());
5954                } catch (RemoteException e1) {
5955                    // oops, no statusbar. Ignore event.
5956                }
5957            }
5958        }
5959    }
5960
5961    /**
5962     * Returns true if the key can have global actions attached to it.
5963     * We reserve all power management keys for the system since they require
5964     * very careful handling.
5965     */
5966    private static boolean isValidGlobalKey(int keyCode) {
5967        switch (keyCode) {
5968            case KeyEvent.KEYCODE_POWER:
5969            case KeyEvent.KEYCODE_WAKEUP:
5970            case KeyEvent.KEYCODE_SLEEP:
5971                return false;
5972            default:
5973                return true;
5974        }
5975    }
5976
5977    /**
5978     * When the screen is off we ignore some keys that might otherwise typically
5979     * be considered wake keys.  We filter them out here.
5980     *
5981     * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
5982     * is always considered a wake key.
5983     */
5984    private boolean isWakeKeyWhenScreenOff(int keyCode) {
5985        switch (keyCode) {
5986            // ignore volume keys unless docked
5987            case KeyEvent.KEYCODE_VOLUME_UP:
5988            case KeyEvent.KEYCODE_VOLUME_DOWN:
5989            case KeyEvent.KEYCODE_VOLUME_MUTE:
5990                return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
5991
5992            // ignore media and camera keys
5993            case KeyEvent.KEYCODE_MUTE:
5994            case KeyEvent.KEYCODE_HEADSETHOOK:
5995            case KeyEvent.KEYCODE_MEDIA_PLAY:
5996            case KeyEvent.KEYCODE_MEDIA_PAUSE:
5997            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
5998            case KeyEvent.KEYCODE_MEDIA_STOP:
5999            case KeyEvent.KEYCODE_MEDIA_NEXT:
6000            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6001            case KeyEvent.KEYCODE_MEDIA_REWIND:
6002            case KeyEvent.KEYCODE_MEDIA_RECORD:
6003            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6004            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
6005            case KeyEvent.KEYCODE_CAMERA:
6006                return false;
6007        }
6008        return true;
6009    }
6010
6011
6012    /** {@inheritDoc} */
6013    @Override
6014    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
6015        if ((policyFlags & FLAG_WAKE) != 0) {
6016            if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
6017                    "android.policy:MOTION")) {
6018                return 0;
6019            }
6020        }
6021
6022        if (shouldDispatchInputWhenNonInteractive(null)) {
6023            return ACTION_PASS_TO_USER;
6024        }
6025
6026        // If we have not passed the action up and we are in theater mode without dreaming,
6027        // there will be no dream to intercept the touch and wake into ambient.  The device should
6028        // wake up in this case.
6029        if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
6030            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
6031                    "android.policy:MOTION");
6032        }
6033
6034        return 0;
6035    }
6036
6037    private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
6038        final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
6039
6040        if (displayOff && !mHasFeatureWatch) {
6041            return false;
6042        }
6043
6044        // Send events to keyguard while the screen is on and it's showing.
6045        if (isKeyguardShowingAndNotOccluded() && !displayOff) {
6046            return true;
6047        }
6048
6049        // Watches handle BACK specially
6050        if (mHasFeatureWatch
6051                && event != null
6052                && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
6053                        || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
6054            return false;
6055        }
6056
6057        // Send events to a dozing dream even if the screen is off since the dream
6058        // is in control of the state of the screen.
6059        IDreamManager dreamManager = getDreamManager();
6060
6061        try {
6062            if (dreamManager != null && dreamManager.isDreaming()) {
6063                return true;
6064            }
6065        } catch (RemoteException e) {
6066            Slog.e(TAG, "RemoteException when checking if dreaming", e);
6067        }
6068
6069        // Otherwise, consume events since the user can't see what is being
6070        // interacted with.
6071        return false;
6072    }
6073
6074    private void dispatchDirectAudioEvent(KeyEvent event) {
6075        if (event.getAction() != KeyEvent.ACTION_DOWN) {
6076            return;
6077        }
6078        int keyCode = event.getKeyCode();
6079        int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
6080                | AudioManager.FLAG_FROM_KEY;
6081        String pkgName = mContext.getOpPackageName();
6082        switch (keyCode) {
6083            case KeyEvent.KEYCODE_VOLUME_UP:
6084                try {
6085                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
6086                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6087                } catch (RemoteException e) {
6088                    Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
6089                }
6090                break;
6091            case KeyEvent.KEYCODE_VOLUME_DOWN:
6092                try {
6093                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
6094                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6095                } catch (RemoteException e) {
6096                    Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
6097                }
6098                break;
6099            case KeyEvent.KEYCODE_VOLUME_MUTE:
6100                try {
6101                    if (event.getRepeatCount() == 0) {
6102                        getAudioService().adjustSuggestedStreamVolume(
6103                                AudioManager.ADJUST_TOGGLE_MUTE,
6104                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6105                    }
6106                } catch (RemoteException e) {
6107                    Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
6108                }
6109                break;
6110        }
6111    }
6112
6113    void dispatchMediaKeyWithWakeLock(KeyEvent event) {
6114        if (DEBUG_INPUT) {
6115            Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
6116        }
6117
6118        if (mHavePendingMediaKeyRepeatWithWakeLock) {
6119            if (DEBUG_INPUT) {
6120                Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
6121            }
6122
6123            mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
6124            mHavePendingMediaKeyRepeatWithWakeLock = false;
6125            mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
6126        }
6127
6128        dispatchMediaKeyWithWakeLockToAudioService(event);
6129
6130        if (event.getAction() == KeyEvent.ACTION_DOWN
6131                && event.getRepeatCount() == 0) {
6132            mHavePendingMediaKeyRepeatWithWakeLock = true;
6133
6134            Message msg = mHandler.obtainMessage(
6135                    MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
6136            msg.setAsynchronous(true);
6137            mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
6138        } else {
6139            mBroadcastWakeLock.release();
6140        }
6141    }
6142
6143    void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
6144        mHavePendingMediaKeyRepeatWithWakeLock = false;
6145
6146        KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
6147                SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6148        if (DEBUG_INPUT) {
6149            Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
6150        }
6151
6152        dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
6153        mBroadcastWakeLock.release();
6154    }
6155
6156    void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
6157        if (ActivityManagerNative.isSystemReady()) {
6158            MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
6159        }
6160    }
6161
6162    void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
6163        IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
6164                ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
6165        if (dic != null) {
6166            try {
6167                dic.exitIdle("voice-search");
6168            } catch (RemoteException e) {
6169            }
6170        }
6171        Intent voiceIntent =
6172            new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
6173        voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
6174        startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
6175        mBroadcastWakeLock.release();
6176    }
6177
6178    BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
6179        @Override
6180        public void onReceive(Context context, Intent intent) {
6181            if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
6182                mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6183                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
6184            } else {
6185                try {
6186                    IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
6187                            ServiceManager.getService(Context.UI_MODE_SERVICE));
6188                    mUiMode = uiModeService.getCurrentModeType();
6189                } catch (RemoteException e) {
6190                }
6191            }
6192            updateRotation(true);
6193            synchronized (mLock) {
6194                updateOrientationListenerLp();
6195            }
6196        }
6197    };
6198
6199    BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
6200        @Override
6201        public void onReceive(Context context, Intent intent) {
6202            if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
6203                if (mKeyguardDelegate != null) {
6204                    mKeyguardDelegate.onDreamingStarted();
6205                }
6206            } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
6207                if (mKeyguardDelegate != null) {
6208                    mKeyguardDelegate.onDreamingStopped();
6209                }
6210            }
6211        }
6212    };
6213
6214    BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
6215        @Override
6216        public void onReceive(Context context, Intent intent) {
6217            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
6218                // tickle the settings observer: this first ensures that we're
6219                // observing the relevant settings for the newly-active user,
6220                // and then updates our own bookkeeping based on the now-
6221                // current user.
6222                mSettingsObserver.onChange(false);
6223
6224                // force a re-application of focused window sysui visibility.
6225                // the window may never have been shown for this user
6226                // e.g. the keyguard when going through the new-user setup flow
6227                synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6228                    mLastSystemUiFlags = 0;
6229                    updateSystemUiVisibilityLw();
6230                }
6231            }
6232        }
6233    };
6234
6235    private final Runnable mHiddenNavPanic = new Runnable() {
6236        @Override
6237        public void run() {
6238            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6239                if (!isUserSetupComplete()) {
6240                    // Swipe-up for navigation bar is disabled during setup
6241                    return;
6242                }
6243                mPendingPanicGestureUptime = SystemClock.uptimeMillis();
6244                if (!isNavBarEmpty(mLastSystemUiFlags)) {
6245                    mNavigationBarController.showTransient();
6246                }
6247            }
6248        }
6249    };
6250
6251    private void requestTransientBars(WindowState swipeTarget) {
6252        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6253            if (!isUserSetupComplete()) {
6254                // Swipe-up for navigation bar is disabled during setup
6255                return;
6256            }
6257            boolean sb = mStatusBarController.checkShowTransientBarLw();
6258            boolean nb = mNavigationBarController.checkShowTransientBarLw()
6259                    && !isNavBarEmpty(mLastSystemUiFlags);
6260            if (sb || nb) {
6261                // Don't show status bar when swiping on already visible navigation bar
6262                if (!nb && swipeTarget == mNavigationBar) {
6263                    if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
6264                    return;
6265                }
6266                if (sb) mStatusBarController.showTransient();
6267                if (nb) mNavigationBarController.showTransient();
6268                mImmersiveModeConfirmation.confirmCurrentPrompt();
6269                updateSystemUiVisibilityLw();
6270            }
6271        }
6272    }
6273
6274    // Called on the PowerManager's Notifier thread.
6275    @Override
6276    public void startedGoingToSleep(int why) {
6277        if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
6278        mCameraGestureTriggeredDuringGoingToSleep = false;
6279        mGoingToSleep = true;
6280        if (mKeyguardDelegate != null) {
6281            mKeyguardDelegate.onStartedGoingToSleep(why);
6282        }
6283    }
6284
6285    // Called on the PowerManager's Notifier thread.
6286    @Override
6287    public void finishedGoingToSleep(int why) {
6288        EventLog.writeEvent(70000, 0);
6289        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
6290        MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
6291
6292        mGoingToSleep = false;
6293
6294        // We must get this work done here because the power manager will drop
6295        // the wake lock and let the system suspend once this function returns.
6296        synchronized (mLock) {
6297            mAwake = false;
6298            updateWakeGestureListenerLp();
6299            updateOrientationListenerLp();
6300            updateLockScreenTimeout();
6301        }
6302        if (mKeyguardDelegate != null) {
6303            mKeyguardDelegate.onFinishedGoingToSleep(why,
6304                    mCameraGestureTriggeredDuringGoingToSleep);
6305        }
6306        mCameraGestureTriggeredDuringGoingToSleep = false;
6307    }
6308
6309    // Called on the PowerManager's Notifier thread.
6310    @Override
6311    public void startedWakingUp() {
6312        EventLog.writeEvent(70000, 1);
6313        if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
6314
6315        // Since goToSleep performs these functions synchronously, we must
6316        // do the same here.  We cannot post this work to a handler because
6317        // that might cause it to become reordered with respect to what
6318        // may happen in a future call to goToSleep.
6319        synchronized (mLock) {
6320            mAwake = true;
6321
6322            updateWakeGestureListenerLp();
6323            updateOrientationListenerLp();
6324            updateLockScreenTimeout();
6325        }
6326
6327        if (mKeyguardDelegate != null) {
6328            mKeyguardDelegate.onStartedWakingUp();
6329        }
6330    }
6331
6332    // Called on the PowerManager's Notifier thread.
6333    @Override
6334    public void finishedWakingUp() {
6335        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
6336    }
6337
6338    private void wakeUpFromPowerKey(long eventTime) {
6339        wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
6340    }
6341
6342    private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
6343        final boolean theaterModeEnabled = isTheaterModeEnabled();
6344        if (!wakeInTheaterMode && theaterModeEnabled) {
6345            return false;
6346        }
6347
6348        if (theaterModeEnabled) {
6349            Settings.Global.putInt(mContext.getContentResolver(),
6350                    Settings.Global.THEATER_MODE_ON, 0);
6351        }
6352
6353        mPowerManager.wakeUp(wakeTime, reason);
6354        return true;
6355    }
6356
6357    private void finishKeyguardDrawn() {
6358        synchronized (mLock) {
6359            if (!mScreenOnEarly || mKeyguardDrawComplete) {
6360                return; // We are not awake yet or we have already informed of this event.
6361            }
6362
6363            mKeyguardDrawComplete = true;
6364            if (mKeyguardDelegate != null) {
6365                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6366            }
6367            mWindowManagerDrawComplete = false;
6368        }
6369
6370        // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
6371        // as well as enabling the orientation change logic/sensor.
6372        mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
6373                WAITING_FOR_DRAWN_TIMEOUT);
6374    }
6375
6376    // Called on the DisplayManager's DisplayPowerController thread.
6377    @Override
6378    public void screenTurnedOff() {
6379        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
6380
6381        updateScreenOffSleepToken(true);
6382        synchronized (mLock) {
6383            mScreenOnEarly = false;
6384            mScreenOnFully = false;
6385            mKeyguardDrawComplete = false;
6386            mWindowManagerDrawComplete = false;
6387            mScreenOnListener = null;
6388            updateOrientationListenerLp();
6389
6390            if (mKeyguardDelegate != null) {
6391                mKeyguardDelegate.onScreenTurnedOff();
6392            }
6393        }
6394    }
6395
6396    // Called on the DisplayManager's DisplayPowerController thread.
6397    @Override
6398    public void screenTurningOn(final ScreenOnListener screenOnListener) {
6399        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
6400
6401        updateScreenOffSleepToken(false);
6402        synchronized (mLock) {
6403            mScreenOnEarly = true;
6404            mScreenOnFully = false;
6405            mKeyguardDrawComplete = false;
6406            mWindowManagerDrawComplete = false;
6407            mScreenOnListener = screenOnListener;
6408
6409            if (mKeyguardDelegate != null) {
6410                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6411                mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
6412                mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
6413            } else {
6414                if (DEBUG_WAKEUP) Slog.d(TAG,
6415                        "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
6416                finishKeyguardDrawn();
6417            }
6418        }
6419    }
6420
6421    // Called on the DisplayManager's DisplayPowerController thread.
6422    @Override
6423    public void screenTurnedOn() {
6424        synchronized (mLock) {
6425            if (mKeyguardDelegate != null) {
6426                mKeyguardDelegate.onScreenTurnedOn();
6427            }
6428        }
6429    }
6430
6431    private void finishWindowsDrawn() {
6432        synchronized (mLock) {
6433            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
6434                return; // Screen is not turned on or we did already handle this case earlier.
6435            }
6436
6437            mWindowManagerDrawComplete = true;
6438        }
6439
6440        finishScreenTurningOn();
6441    }
6442
6443    private void finishScreenTurningOn() {
6444        synchronized (mLock) {
6445            // We have just finished drawing screen content. Since the orientation listener
6446            // gets only installed when all windows are drawn, we try to install it again.
6447            updateOrientationListenerLp();
6448        }
6449        final ScreenOnListener listener;
6450        final boolean enableScreen;
6451        synchronized (mLock) {
6452            if (DEBUG_WAKEUP) Slog.d(TAG,
6453                    "finishScreenTurningOn: mAwake=" + mAwake
6454                            + ", mScreenOnEarly=" + mScreenOnEarly
6455                            + ", mScreenOnFully=" + mScreenOnFully
6456                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
6457                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
6458
6459            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
6460                    || (mAwake && !mKeyguardDrawComplete)) {
6461                return; // spurious or not ready yet
6462            }
6463
6464            if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
6465            listener = mScreenOnListener;
6466            mScreenOnListener = null;
6467            mScreenOnFully = true;
6468
6469            // Remember the first time we draw the keyguard so we know when we're done with
6470            // the main part of booting and can enable the screen and hide boot messages.
6471            if (!mKeyguardDrawnOnce && mAwake) {
6472                mKeyguardDrawnOnce = true;
6473                enableScreen = true;
6474                if (mBootMessageNeedsHiding) {
6475                    mBootMessageNeedsHiding = false;
6476                    hideBootMessages();
6477                }
6478            } else {
6479                enableScreen = false;
6480            }
6481        }
6482
6483        if (listener != null) {
6484            listener.onScreenOn();
6485        }
6486
6487        if (enableScreen) {
6488            try {
6489                mWindowManager.enableScreenIfNeeded();
6490            } catch (RemoteException unhandled) {
6491            }
6492        }
6493    }
6494
6495    private void handleHideBootMessage() {
6496        synchronized (mLock) {
6497            if (!mKeyguardDrawnOnce) {
6498                mBootMessageNeedsHiding = true;
6499                return; // keyguard hasn't drawn the first time yet, not done booting
6500            }
6501        }
6502
6503        if (mBootMsgDialog != null) {
6504            if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
6505            mBootMsgDialog.dismiss();
6506            mBootMsgDialog = null;
6507        }
6508    }
6509
6510    @Override
6511    public boolean isScreenOn() {
6512        return mScreenOnFully;
6513    }
6514
6515    /** {@inheritDoc} */
6516    @Override
6517    public void enableKeyguard(boolean enabled) {
6518        if (mKeyguardDelegate != null) {
6519            mKeyguardDelegate.setKeyguardEnabled(enabled);
6520        }
6521    }
6522
6523    /** {@inheritDoc} */
6524    @Override
6525    public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
6526        if (mKeyguardDelegate != null) {
6527            mKeyguardDelegate.verifyUnlock(callback);
6528        }
6529    }
6530
6531    private boolean isKeyguardShowingAndNotOccluded() {
6532        if (mKeyguardDelegate == null) return false;
6533        return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
6534    }
6535
6536    /** {@inheritDoc} */
6537    @Override
6538    public boolean isKeyguardLocked() {
6539        return keyguardOn();
6540    }
6541
6542    /** {@inheritDoc} */
6543    @Override
6544    public boolean isKeyguardSecure(int userId) {
6545        if (mKeyguardDelegate == null) return false;
6546        return mKeyguardDelegate.isSecure(userId);
6547    }
6548
6549    /** {@inheritDoc} */
6550    @Override
6551    public boolean isKeyguardShowingOrOccluded() {
6552        return mKeyguardDelegate == null ? false : mKeyguardDelegate.isShowing();
6553    }
6554
6555    /** {@inheritDoc} */
6556    @Override
6557    public boolean inKeyguardRestrictedKeyInputMode() {
6558        if (mKeyguardDelegate == null) return false;
6559        return mKeyguardDelegate.isInputRestricted();
6560    }
6561
6562    @Override
6563    public void dismissKeyguardLw() {
6564        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
6565            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
6566            mHandler.post(new Runnable() {
6567                @Override
6568                public void run() {
6569                    // ask the keyguard to prompt the user to authenticate if necessary
6570                    mKeyguardDelegate.dismiss(false /* allowWhileOccluded */);
6571                }
6572            });
6573        }
6574    }
6575
6576    @Override
6577    public void notifyActivityDrawnForKeyguardLw() {
6578        if (mKeyguardDelegate != null) {
6579            mHandler.post(new Runnable() {
6580                @Override
6581                public void run() {
6582                    mKeyguardDelegate.onActivityDrawn();
6583                }
6584            });
6585        }
6586    }
6587
6588    @Override
6589    public boolean isKeyguardDrawnLw() {
6590        synchronized (mLock) {
6591            return mKeyguardDrawnOnce;
6592        }
6593    }
6594
6595    @Override
6596    public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
6597        if (mKeyguardDelegate != null) {
6598            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
6599            mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
6600        }
6601    }
6602
6603    @Override
6604    public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6605            Rect outInsets) {
6606        outInsets.setEmpty();
6607
6608        // Navigation bar and status bar.
6609        getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
6610        if (mStatusBar != null) {
6611            outInsets.top = mStatusBarHeight;
6612        }
6613    }
6614
6615    @Override
6616    public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6617            Rect outInsets) {
6618        outInsets.setEmpty();
6619
6620        // Only navigation bar
6621        if (mNavigationBar != null) {
6622            int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
6623            if (position == NAV_BAR_BOTTOM) {
6624                outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
6625            } else if (position == NAV_BAR_RIGHT) {
6626                outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
6627            } else if (position == NAV_BAR_LEFT) {
6628                outInsets.left = getNavigationBarWidth(displayRotation, mUiMode);
6629            }
6630        }
6631    }
6632
6633    @Override
6634    public boolean isNavBarForcedShownLw(WindowState windowState) {
6635        return mForceShowSystemBars;
6636    }
6637
6638    @Override
6639    public boolean isDockSideAllowed(int dockSide) {
6640
6641        // We do not allow all dock sides at which the navigation bar touches the docked stack.
6642        if (!mNavigationBarCanMove) {
6643            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT;
6644        } else {
6645            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT;
6646        }
6647    }
6648
6649    void sendCloseSystemWindows() {
6650        PhoneWindow.sendCloseSystemWindows(mContext, null);
6651    }
6652
6653    void sendCloseSystemWindows(String reason) {
6654        PhoneWindow.sendCloseSystemWindows(mContext, reason);
6655    }
6656
6657    @Override
6658    public int rotationForOrientationLw(int orientation, int lastRotation) {
6659        if (false) {
6660            Slog.v(TAG, "rotationForOrientationLw(orient="
6661                        + orientation + ", last=" + lastRotation
6662                        + "); user=" + mUserRotation + " "
6663                        + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
6664                            ? "USER_ROTATION_LOCKED" : "")
6665                        );
6666        }
6667
6668        if (mForceDefaultOrientation) {
6669            return Surface.ROTATION_0;
6670        }
6671
6672        synchronized (mLock) {
6673            int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
6674            if (sensorRotation < 0) {
6675                sensorRotation = lastRotation;
6676            }
6677
6678            final int preferredRotation;
6679            if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
6680                // Ignore sensor when lid switch is open and rotation is forced.
6681                preferredRotation = mLidOpenRotation;
6682            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
6683                    && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
6684                // Ignore sensor when in car dock unless explicitly enabled.
6685                // This case can override the behavior of NOSENSOR, and can also
6686                // enable 180 degree rotation while docked.
6687                preferredRotation = mCarDockEnablesAccelerometer
6688                        ? sensorRotation : mCarDockRotation;
6689            } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
6690                    || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
6691                    || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
6692                    && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
6693                // Ignore sensor when in desk dock unless explicitly enabled.
6694                // This case can override the behavior of NOSENSOR, and can also
6695                // enable 180 degree rotation while docked.
6696                preferredRotation = mDeskDockEnablesAccelerometer
6697                        ? sensorRotation : mDeskDockRotation;
6698            } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
6699                // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
6700                // Note that the dock orientation overrides the HDMI orientation.
6701                preferredRotation = mDemoHdmiRotation;
6702            } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
6703                    && mUndockedHdmiRotation >= 0) {
6704                // Ignore sensor when plugged into HDMI and an undocked orientation has
6705                // been specified in the configuration (only for legacy devices without
6706                // full multi-display support).
6707                // Note that the dock orientation overrides the HDMI orientation.
6708                preferredRotation = mUndockedHdmiRotation;
6709            } else if (mDemoRotationLock) {
6710                // Ignore sensor when demo rotation lock is enabled.
6711                // Note that the dock orientation and HDMI rotation lock override this.
6712                preferredRotation = mDemoRotation;
6713            } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
6714                // Application just wants to remain locked in the last rotation.
6715                preferredRotation = lastRotation;
6716            } else if (!mSupportAutoRotation) {
6717                // If we don't support auto-rotation then bail out here and ignore
6718                // the sensor and any rotation lock settings.
6719                preferredRotation = -1;
6720            } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
6721                            && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
6722                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
6723                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
6724                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
6725                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
6726                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
6727                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6728                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
6729                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
6730                // Otherwise, use sensor only if requested by the application or enabled
6731                // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
6732                if (mAllowAllRotations < 0) {
6733                    // Can't read this during init() because the context doesn't
6734                    // have display metrics at that time so we cannot determine
6735                    // tablet vs. phone then.
6736                    mAllowAllRotations = mContext.getResources().getBoolean(
6737                            com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
6738                }
6739                if (sensorRotation != Surface.ROTATION_180
6740                        || mAllowAllRotations == 1
6741                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6742                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
6743                    preferredRotation = sensorRotation;
6744                } else {
6745                    preferredRotation = lastRotation;
6746                }
6747            } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
6748                    && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
6749                // Apply rotation lock.  Does not apply to NOSENSOR.
6750                // The idea is that the user rotation expresses a weak preference for the direction
6751                // of gravity and as NOSENSOR is never affected by gravity, then neither should
6752                // NOSENSOR be affected by rotation lock (although it will be affected by docks).
6753                preferredRotation = mUserRotation;
6754            } else {
6755                // No overriding preference.
6756                // We will do exactly what the application asked us to do.
6757                preferredRotation = -1;
6758            }
6759
6760            switch (orientation) {
6761                case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6762                    // Return portrait unless overridden.
6763                    if (isAnyPortrait(preferredRotation)) {
6764                        return preferredRotation;
6765                    }
6766                    return mPortraitRotation;
6767
6768                case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6769                    // Return landscape unless overridden.
6770                    if (isLandscapeOrSeascape(preferredRotation)) {
6771                        return preferredRotation;
6772                    }
6773                    return mLandscapeRotation;
6774
6775                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6776                    // Return reverse portrait unless overridden.
6777                    if (isAnyPortrait(preferredRotation)) {
6778                        return preferredRotation;
6779                    }
6780                    return mUpsideDownRotation;
6781
6782                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6783                    // Return seascape unless overridden.
6784                    if (isLandscapeOrSeascape(preferredRotation)) {
6785                        return preferredRotation;
6786                    }
6787                    return mSeascapeRotation;
6788
6789                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6790                case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
6791                    // Return either landscape rotation.
6792                    if (isLandscapeOrSeascape(preferredRotation)) {
6793                        return preferredRotation;
6794                    }
6795                    if (isLandscapeOrSeascape(lastRotation)) {
6796                        return lastRotation;
6797                    }
6798                    return mLandscapeRotation;
6799
6800                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6801                case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
6802                    // Return either portrait rotation.
6803                    if (isAnyPortrait(preferredRotation)) {
6804                        return preferredRotation;
6805                    }
6806                    if (isAnyPortrait(lastRotation)) {
6807                        return lastRotation;
6808                    }
6809                    return mPortraitRotation;
6810
6811                default:
6812                    // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
6813                    // just return the preferred orientation we already calculated.
6814                    if (preferredRotation >= 0) {
6815                        return preferredRotation;
6816                    }
6817                    return Surface.ROTATION_0;
6818            }
6819        }
6820    }
6821
6822    @Override
6823    public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
6824        switch (orientation) {
6825            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6826            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6827            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6828                return isAnyPortrait(rotation);
6829
6830            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6831            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6832            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6833                return isLandscapeOrSeascape(rotation);
6834
6835            default:
6836                return true;
6837        }
6838    }
6839
6840    @Override
6841    public void setRotationLw(int rotation) {
6842        mOrientationListener.setCurrentRotation(rotation);
6843    }
6844
6845    private boolean isLandscapeOrSeascape(int rotation) {
6846        return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
6847    }
6848
6849    private boolean isAnyPortrait(int rotation) {
6850        return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
6851    }
6852
6853    @Override
6854    public int getUserRotationMode() {
6855        return Settings.System.getIntForUser(mContext.getContentResolver(),
6856                Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
6857                        WindowManagerPolicy.USER_ROTATION_FREE :
6858                                WindowManagerPolicy.USER_ROTATION_LOCKED;
6859    }
6860
6861    // User rotation: to be used when all else fails in assigning an orientation to the device
6862    @Override
6863    public void setUserRotationMode(int mode, int rot) {
6864        ContentResolver res = mContext.getContentResolver();
6865
6866        // mUserRotationMode and mUserRotation will be assigned by the content observer
6867        if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
6868            Settings.System.putIntForUser(res,
6869                    Settings.System.USER_ROTATION,
6870                    rot,
6871                    UserHandle.USER_CURRENT);
6872            Settings.System.putIntForUser(res,
6873                    Settings.System.ACCELEROMETER_ROTATION,
6874                    0,
6875                    UserHandle.USER_CURRENT);
6876        } else {
6877            Settings.System.putIntForUser(res,
6878                    Settings.System.ACCELEROMETER_ROTATION,
6879                    1,
6880                    UserHandle.USER_CURRENT);
6881        }
6882    }
6883
6884    @Override
6885    public void setSafeMode(boolean safeMode) {
6886        mSafeMode = safeMode;
6887        performHapticFeedbackLw(null, safeMode
6888                ? HapticFeedbackConstants.SAFE_MODE_ENABLED
6889                : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
6890    }
6891
6892    static long[] getLongIntArray(Resources r, int resid) {
6893        int[] ar = r.getIntArray(resid);
6894        if (ar == null) {
6895            return null;
6896        }
6897        long[] out = new long[ar.length];
6898        for (int i=0; i<ar.length; i++) {
6899            out[i] = ar[i];
6900        }
6901        return out;
6902    }
6903
6904    /** {@inheritDoc} */
6905    @Override
6906    public void systemReady() {
6907        mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
6908        mKeyguardDelegate.onSystemReady();
6909
6910        readCameraLensCoverState();
6911        updateUiMode();
6912        boolean bindKeyguardNow;
6913        synchronized (mLock) {
6914            updateOrientationListenerLp();
6915            mSystemReady = true;
6916            mHandler.post(new Runnable() {
6917                @Override
6918                public void run() {
6919                    updateSettings();
6920                }
6921            });
6922
6923            bindKeyguardNow = mDeferBindKeyguard;
6924            if (bindKeyguardNow) {
6925                // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now.
6926                mDeferBindKeyguard = false;
6927            }
6928        }
6929
6930        if (bindKeyguardNow) {
6931            mKeyguardDelegate.bindService(mContext);
6932            mKeyguardDelegate.onBootCompleted();
6933        }
6934        mSystemGestures.systemReady();
6935        mImmersiveModeConfirmation.systemReady();
6936    }
6937
6938    /** {@inheritDoc} */
6939    @Override
6940    public void systemBooted() {
6941        boolean bindKeyguardNow = false;
6942        synchronized (mLock) {
6943            // Time to bind Keyguard; take care to only bind it once, either here if ready or
6944            // in systemReady if not.
6945            if (mKeyguardDelegate != null) {
6946                bindKeyguardNow = true;
6947            } else {
6948                // Because mKeyguardDelegate is null, we know that the synchronized block in
6949                // systemReady didn't run yet and setting this will actually have an effect.
6950                mDeferBindKeyguard = true;
6951            }
6952        }
6953        if (bindKeyguardNow) {
6954            mKeyguardDelegate.bindService(mContext);
6955            mKeyguardDelegate.onBootCompleted();
6956        }
6957        synchronized (mLock) {
6958            mSystemBooted = true;
6959        }
6960        startedWakingUp();
6961        screenTurningOn(null);
6962        screenTurnedOn();
6963    }
6964
6965    ProgressDialog mBootMsgDialog = null;
6966
6967    /** {@inheritDoc} */
6968    @Override
6969    public void showBootMessage(final CharSequence msg, final boolean always) {
6970        mHandler.post(new Runnable() {
6971            @Override public void run() {
6972                if (mBootMsgDialog == null) {
6973                    int theme;
6974                    if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) {
6975                        theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
6976                    } else {
6977                        theme = 0;
6978                    }
6979
6980                    mBootMsgDialog = new ProgressDialog(mContext, theme) {
6981                        // This dialog will consume all events coming in to
6982                        // it, to avoid it trying to do things too early in boot.
6983                        @Override public boolean dispatchKeyEvent(KeyEvent event) {
6984                            return true;
6985                        }
6986                        @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
6987                            return true;
6988                        }
6989                        @Override public boolean dispatchTouchEvent(MotionEvent ev) {
6990                            return true;
6991                        }
6992                        @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
6993                            return true;
6994                        }
6995                        @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
6996                            return true;
6997                        }
6998                        @Override public boolean dispatchPopulateAccessibilityEvent(
6999                                AccessibilityEvent event) {
7000                            return true;
7001                        }
7002                    };
7003                    if (mContext.getPackageManager().isUpgrade()) {
7004                        mBootMsgDialog.setTitle(R.string.android_upgrading_title);
7005                    } else {
7006                        mBootMsgDialog.setTitle(R.string.android_start_title);
7007                    }
7008                    mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
7009                    mBootMsgDialog.setIndeterminate(true);
7010                    mBootMsgDialog.getWindow().setType(
7011                            WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
7012                    mBootMsgDialog.getWindow().addFlags(
7013                            WindowManager.LayoutParams.FLAG_DIM_BEHIND
7014                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
7015                    mBootMsgDialog.getWindow().setDimAmount(1);
7016                    WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
7017                    lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
7018                    mBootMsgDialog.getWindow().setAttributes(lp);
7019                    mBootMsgDialog.setCancelable(false);
7020                    mBootMsgDialog.show();
7021                }
7022                mBootMsgDialog.setMessage(msg);
7023            }
7024        });
7025    }
7026
7027    /** {@inheritDoc} */
7028    @Override
7029    public void hideBootMessages() {
7030        mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
7031    }
7032
7033    /** {@inheritDoc} */
7034    @Override
7035    public void userActivity() {
7036        // ***************************************
7037        // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
7038        // ***************************************
7039        // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
7040        // WITH ITS LOCKS HELD.
7041        //
7042        // This code must be VERY careful about the locks
7043        // it acquires.
7044        // In fact, the current code acquires way too many,
7045        // and probably has lurking deadlocks.
7046
7047        synchronized (mScreenLockTimeout) {
7048            if (mLockScreenTimerActive) {
7049                // reset the timer
7050                mHandler.removeCallbacks(mScreenLockTimeout);
7051                mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7052            }
7053        }
7054    }
7055
7056    class ScreenLockTimeout implements Runnable {
7057        Bundle options;
7058
7059        @Override
7060        public void run() {
7061            synchronized (this) {
7062                if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
7063                if (mKeyguardDelegate != null) {
7064                    mKeyguardDelegate.doKeyguardTimeout(options);
7065                }
7066                mLockScreenTimerActive = false;
7067                options = null;
7068            }
7069        }
7070
7071        public void setLockOptions(Bundle options) {
7072            this.options = options;
7073        }
7074    }
7075
7076    ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
7077
7078    @Override
7079    public void lockNow(Bundle options) {
7080        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
7081        mHandler.removeCallbacks(mScreenLockTimeout);
7082        if (options != null) {
7083            // In case multiple calls are made to lockNow, we don't wipe out the options
7084            // until the runnable actually executes.
7085            mScreenLockTimeout.setLockOptions(options);
7086        }
7087        mHandler.post(mScreenLockTimeout);
7088    }
7089
7090    private void updateLockScreenTimeout() {
7091        synchronized (mScreenLockTimeout) {
7092            boolean enable = (mAllowLockscreenWhenOn && mAwake &&
7093                    mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
7094            if (mLockScreenTimerActive != enable) {
7095                if (enable) {
7096                    if (localLOGV) Log.v(TAG, "setting lockscreen timer");
7097                    mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
7098                    mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7099                } else {
7100                    if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
7101                    mHandler.removeCallbacks(mScreenLockTimeout);
7102                }
7103                mLockScreenTimerActive = enable;
7104            }
7105        }
7106    }
7107
7108    private void updateDreamingSleepToken(boolean acquire) {
7109        if (acquire) {
7110            if (mDreamingSleepToken == null) {
7111                mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream");
7112            }
7113        } else {
7114            if (mDreamingSleepToken != null) {
7115                mDreamingSleepToken.release();
7116                mDreamingSleepToken = null;
7117            }
7118        }
7119    }
7120
7121    private void updateScreenOffSleepToken(boolean acquire) {
7122        if (acquire) {
7123            if (mScreenOffSleepToken == null) {
7124                mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff");
7125            }
7126        } else {
7127            if (mScreenOffSleepToken != null) {
7128                mScreenOffSleepToken.release();
7129                mScreenOffSleepToken = null;
7130            }
7131        }
7132    }
7133
7134    /** {@inheritDoc} */
7135    @Override
7136    public void enableScreenAfterBoot() {
7137        readLidState();
7138        applyLidSwitchState();
7139        updateRotation(true);
7140    }
7141
7142    private void applyLidSwitchState() {
7143        if (mLidState == LID_CLOSED && mLidControlsSleep) {
7144            mPowerManager.goToSleep(SystemClock.uptimeMillis(),
7145                    PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
7146                    PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
7147        } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
7148            mWindowManagerFuncs.lockDeviceNow();
7149        }
7150
7151        synchronized (mLock) {
7152            updateWakeGestureListenerLp();
7153        }
7154    }
7155
7156    void updateUiMode() {
7157        if (mUiModeManager == null) {
7158            mUiModeManager = IUiModeManager.Stub.asInterface(
7159                    ServiceManager.getService(Context.UI_MODE_SERVICE));
7160        }
7161        try {
7162            mUiMode = mUiModeManager.getCurrentModeType();
7163        } catch (RemoteException e) {
7164        }
7165    }
7166
7167    void updateRotation(boolean alwaysSendConfiguration) {
7168        try {
7169            //set orientation on WindowManager
7170            mWindowManager.updateRotation(alwaysSendConfiguration, false);
7171        } catch (RemoteException e) {
7172            // Ignore
7173        }
7174    }
7175
7176    void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
7177        try {
7178            //set orientation on WindowManager
7179            mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
7180        } catch (RemoteException e) {
7181            // Ignore
7182        }
7183    }
7184
7185    /**
7186     * Return an Intent to launch the currently active dock app as home.  Returns
7187     * null if the standard home should be launched, which is the case if any of the following is
7188     * true:
7189     * <ul>
7190     *  <li>The device is not in either car mode or desk mode
7191     *  <li>The device is in car mode but mEnableCarDockHomeCapture is false
7192     *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
7193     *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
7194     *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
7195     * </ul>
7196     * @return A dock intent.
7197     */
7198    Intent createHomeDockIntent() {
7199        Intent intent = null;
7200
7201        // What home does is based on the mode, not the dock state.  That
7202        // is, when in car mode you should be taken to car home regardless
7203        // of whether we are actually in a car dock.
7204        if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
7205            if (mEnableCarDockHomeCapture) {
7206                intent = mCarDockIntent;
7207            }
7208        } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
7209            if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
7210                intent = mDeskDockIntent;
7211            }
7212        } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
7213                && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7214                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
7215                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
7216            // Always launch dock home from home when watch is docked, if it exists.
7217            intent = mDeskDockIntent;
7218        }
7219
7220        if (intent == null) {
7221            return null;
7222        }
7223
7224        ActivityInfo ai = null;
7225        ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
7226                intent,
7227                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
7228                mCurrentUserId);
7229        if (info != null) {
7230            ai = info.activityInfo;
7231        }
7232        if (ai != null
7233                && ai.metaData != null
7234                && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
7235            intent = new Intent(intent);
7236            intent.setClassName(ai.packageName, ai.name);
7237            return intent;
7238        }
7239
7240        return null;
7241    }
7242
7243    void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
7244        if (awakenFromDreams) {
7245            awakenDreams();
7246        }
7247
7248        Intent dock = createHomeDockIntent();
7249        if (dock != null) {
7250            try {
7251                if (fromHomeKey) {
7252                    dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7253                }
7254                startActivityAsUser(dock, UserHandle.CURRENT);
7255                return;
7256            } catch (ActivityNotFoundException e) {
7257            }
7258        }
7259
7260        Intent intent;
7261
7262        if (fromHomeKey) {
7263            intent = new Intent(mHomeIntent);
7264            intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7265        } else {
7266            intent = mHomeIntent;
7267        }
7268
7269        startActivityAsUser(intent, UserHandle.CURRENT);
7270    }
7271
7272    /**
7273     * goes to the home screen
7274     * @return whether it did anything
7275     */
7276    boolean goHome() {
7277        if (!isUserSetupComplete()) {
7278            Slog.i(TAG, "Not going home because user setup is in progress.");
7279            return false;
7280        }
7281        if (false) {
7282            // This code always brings home to the front.
7283            try {
7284                ActivityManagerNative.getDefault().stopAppSwitches();
7285            } catch (RemoteException e) {
7286            }
7287            sendCloseSystemWindows();
7288            startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
7289        } else {
7290            // This code brings home to the front or, if it is already
7291            // at the front, puts the device to sleep.
7292            try {
7293                if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
7294                    /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
7295                    Log.d(TAG, "UTS-TEST-MODE");
7296                } else {
7297                    ActivityManagerNative.getDefault().stopAppSwitches();
7298                    sendCloseSystemWindows();
7299                    Intent dock = createHomeDockIntent();
7300                    if (dock != null) {
7301                        int result = ActivityManagerNative.getDefault()
7302                                .startActivityAsUser(null, null, dock,
7303                                        dock.resolveTypeIfNeeded(mContext.getContentResolver()),
7304                                        null, null, 0,
7305                                        ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7306                                        null, null, UserHandle.USER_CURRENT);
7307                        if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7308                            return false;
7309                        }
7310                    }
7311                }
7312                int result = ActivityManagerNative.getDefault()
7313                        .startActivityAsUser(null, null, mHomeIntent,
7314                                mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
7315                                null, null, 0,
7316                                ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7317                                null, null, UserHandle.USER_CURRENT);
7318                if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7319                    return false;
7320                }
7321            } catch (RemoteException ex) {
7322                // bummer, the activity manager, which is in this process, is dead
7323            }
7324        }
7325        return true;
7326    }
7327
7328    @Override
7329    public void setCurrentOrientationLw(int newOrientation) {
7330        synchronized (mLock) {
7331            if (newOrientation != mCurrentAppOrientation) {
7332                mCurrentAppOrientation = newOrientation;
7333                updateOrientationListenerLp();
7334            }
7335        }
7336    }
7337
7338    private void performAuditoryFeedbackForAccessibilityIfNeed() {
7339        if (!isGlobalAccessibilityGestureEnabled()) {
7340            return;
7341        }
7342        AudioManager audioManager = (AudioManager) mContext.getSystemService(
7343                Context.AUDIO_SERVICE);
7344        if (audioManager.isSilentMode()) {
7345            return;
7346        }
7347        Ringtone ringTone = RingtoneManager.getRingtone(mContext,
7348                Settings.System.DEFAULT_NOTIFICATION_URI);
7349        ringTone.setStreamType(AudioManager.STREAM_MUSIC);
7350        ringTone.play();
7351    }
7352
7353    private boolean isTheaterModeEnabled() {
7354        return Settings.Global.getInt(mContext.getContentResolver(),
7355                Settings.Global.THEATER_MODE_ON, 0) == 1;
7356    }
7357
7358    private boolean isGlobalAccessibilityGestureEnabled() {
7359        return Settings.Global.getInt(mContext.getContentResolver(),
7360                Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1;
7361    }
7362
7363    private boolean areSystemNavigationKeysEnabled() {
7364        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
7365                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
7366    }
7367
7368    @Override
7369    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
7370        if (!mVibrator.hasVibrator()) {
7371            return false;
7372        }
7373        final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
7374                Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
7375        if (hapticsDisabled && !always) {
7376            return false;
7377        }
7378        long[] pattern = null;
7379        switch (effectId) {
7380            case HapticFeedbackConstants.LONG_PRESS:
7381                pattern = mLongPressVibePattern;
7382                break;
7383            case HapticFeedbackConstants.VIRTUAL_KEY:
7384                pattern = mVirtualKeyVibePattern;
7385                break;
7386            case HapticFeedbackConstants.KEYBOARD_TAP:
7387                pattern = mKeyboardTapVibePattern;
7388                break;
7389            case HapticFeedbackConstants.CLOCK_TICK:
7390                pattern = mClockTickVibePattern;
7391                break;
7392            case HapticFeedbackConstants.CALENDAR_DATE:
7393                pattern = mCalendarDateVibePattern;
7394                break;
7395            case HapticFeedbackConstants.SAFE_MODE_DISABLED:
7396                pattern = mSafeModeDisabledVibePattern;
7397                break;
7398            case HapticFeedbackConstants.SAFE_MODE_ENABLED:
7399                pattern = mSafeModeEnabledVibePattern;
7400                break;
7401            case HapticFeedbackConstants.CONTEXT_CLICK:
7402                pattern = mContextClickVibePattern;
7403                break;
7404            default:
7405                return false;
7406        }
7407        int owningUid;
7408        String owningPackage;
7409        if (win != null) {
7410            owningUid = win.getOwningUid();
7411            owningPackage = win.getOwningPackage();
7412        } else {
7413            owningUid = android.os.Process.myUid();
7414            owningPackage = mContext.getOpPackageName();
7415        }
7416        if (pattern.length == 1) {
7417            // One-shot vibration
7418            mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES);
7419        } else {
7420            // Pattern vibration
7421            mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES);
7422        }
7423        return true;
7424    }
7425
7426    @Override
7427    public void keepScreenOnStartedLw() {
7428    }
7429
7430    @Override
7431    public void keepScreenOnStoppedLw() {
7432        if (isKeyguardShowingAndNotOccluded()) {
7433            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
7434        }
7435    }
7436
7437    private int updateSystemUiVisibilityLw() {
7438        // If there is no window focused, there will be nobody to handle the events
7439        // anyway, so just hang on in whatever state we're in until things settle down.
7440        final WindowState win = mFocusedWindow != null ? mFocusedWindow
7441                : mTopFullscreenOpaqueWindowState;
7442        if (win == null) {
7443            return 0;
7444        }
7445        if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) {
7446            // We are updating at a point where the keyguard has gotten
7447            // focus, but we were last in a state where the top window is
7448            // hiding it.  This is probably because the keyguard as been
7449            // shown while the top window was displayed, so we want to ignore
7450            // it here because this is just a very transient change and it
7451            // will quickly lose focus once it correctly gets hidden.
7452            return 0;
7453        }
7454
7455        int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
7456                & ~mResettingSystemUiFlags
7457                & ~mForceClearedSystemUiFlags;
7458        if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
7459            tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
7460        }
7461
7462        final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
7463                mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
7464        final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
7465                mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
7466        mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);
7467        mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);
7468        final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
7469        final int diff = visibility ^ mLastSystemUiFlags;
7470        final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
7471        final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
7472        final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
7473        if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
7474                && mFocusedApp == win.getAppToken()
7475                && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
7476                && mLastDockedStackBounds.equals(mDockedStackBounds)) {
7477            return 0;
7478        }
7479        mLastSystemUiFlags = visibility;
7480        mLastFullscreenStackSysUiFlags = fullscreenVisibility;
7481        mLastDockedStackSysUiFlags = dockedVisibility;
7482        mLastFocusNeedsMenu = needsMenu;
7483        mFocusedApp = win.getAppToken();
7484        final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
7485        final Rect dockedStackBounds = new Rect(mDockedStackBounds);
7486        mHandler.post(new Runnable() {
7487                @Override
7488                public void run() {
7489                    StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
7490                    if (statusbar != null) {
7491                        statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
7492                                dockedVisibility, 0xffffffff, fullscreenStackBounds,
7493                                dockedStackBounds, win.toString());
7494                        statusbar.topAppWindowChanged(needsMenu);
7495                    }
7496                }
7497            });
7498        return diff;
7499    }
7500
7501    private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
7502        WindowState statusColorWin = isStatusBarKeyguard() && !mHideLockScreen
7503                ? mStatusBar
7504                : opaqueOrDimming;
7505
7506        if (statusColorWin != null) {
7507            if (statusColorWin == opaque) {
7508                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7509                // its light flag.
7510                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7511                vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
7512                        & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7513            } else if (statusColorWin != null && statusColorWin.isDimming()) {
7514                // Otherwise if it's dimming, clear the light flag.
7515                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7516            }
7517        }
7518        return vis;
7519    }
7520
7521    private boolean drawsSystemBarBackground(WindowState win) {
7522        return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
7523    }
7524
7525    private boolean forcesDrawStatusBarBackground(WindowState win) {
7526        return win == null || (win.getAttrs().privateFlags
7527                & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
7528    }
7529
7530    private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
7531        final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
7532        final boolean freeformStackVisible =
7533                mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
7534        final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
7535
7536        // We need to force system bars when the docked stack is visible, when the freeform stack
7537        // is visible but also when we are resizing for the transitions when docked stack
7538        // visibility changes.
7539        mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
7540        final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
7541
7542        // apply translucent bar vis flags
7543        WindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen
7544                ? mStatusBar
7545                : mTopFullscreenOpaqueWindowState;
7546        vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7547        vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7548        final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
7549                mTopDockedOpaqueWindowState, 0, 0);
7550
7551        final boolean fullscreenDrawsStatusBarBackground =
7552                (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
7553                        && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
7554                || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
7555        final boolean dockedDrawsStatusBarBackground =
7556                (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
7557                        && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
7558                || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
7559
7560        // prevent status bar interaction from clearing certain flags
7561        int type = win.getAttrs().type;
7562        boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
7563        if (statusBarHasFocus && !isStatusBarKeyguard()) {
7564            int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
7565                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
7566                    | View.SYSTEM_UI_FLAG_IMMERSIVE
7567                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
7568                    | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7569            if (mHideLockScreen) {
7570                flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
7571            }
7572            vis = (vis & ~flags) | (oldVis & flags);
7573        }
7574
7575        if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
7576            vis |= View.STATUS_BAR_TRANSPARENT;
7577            vis &= ~View.STATUS_BAR_TRANSLUCENT;
7578        } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
7579                || forceOpaqueStatusBar) {
7580            vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
7581        }
7582
7583        vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
7584
7585        // update status bar
7586        boolean immersiveSticky =
7587                (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7588        final boolean hideStatusBarWM =
7589                mTopFullscreenOpaqueWindowState != null
7590                && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
7591                        & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
7592        final boolean hideStatusBarSysui =
7593                (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
7594        final boolean hideNavBarSysui =
7595                (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
7596
7597        final boolean transientStatusBarAllowed = mStatusBar != null
7598                && (statusBarHasFocus || (!mForceShowSystemBars
7599                        && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
7600
7601        final boolean transientNavBarAllowed = mNavigationBar != null
7602                && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
7603
7604        final long now = SystemClock.uptimeMillis();
7605        final boolean pendingPanic = mPendingPanicGestureUptime != 0
7606                && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
7607        if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
7608            // The user performed the panic gesture recently, we're about to hide the bars,
7609            // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
7610            mPendingPanicGestureUptime = 0;
7611            mStatusBarController.showTransient();
7612            if (!isNavBarEmpty(vis)) {
7613                mNavigationBarController.showTransient();
7614            }
7615        }
7616
7617        final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
7618                && !transientStatusBarAllowed && hideStatusBarSysui;
7619        final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
7620                && !transientNavBarAllowed;
7621        if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
7622            // clear the clearable flags instead
7623            clearClearableFlagsLw();
7624            vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
7625        }
7626
7627        final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
7628        immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7629        final boolean navAllowedHidden = immersive || immersiveSticky;
7630
7631        if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType())
7632                > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) {
7633            // We can't hide the navbar from this window otherwise the input consumer would not get
7634            // the input events.
7635            vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
7636        }
7637
7638        vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
7639
7640        // update navigation bar
7641        boolean oldImmersiveMode = isImmersiveMode(oldVis);
7642        boolean newImmersiveMode = isImmersiveMode(vis);
7643        if (win != null && oldImmersiveMode != newImmersiveMode) {
7644            final String pkg = win.getOwningPackage();
7645            mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
7646                    isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility()));
7647        }
7648
7649        vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
7650
7651        return vis;
7652    }
7653
7654    /**
7655     * @return the current visibility flags with the nav-bar opacity related flags toggled based
7656     *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
7657     */
7658    private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
7659            boolean freeformStackVisible, boolean isDockedDividerResizing) {
7660        if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
7661            if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
7662                visibility = setNavBarOpaqueFlag(visibility);
7663            }
7664        } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
7665            if (isDockedDividerResizing) {
7666                visibility = setNavBarOpaqueFlag(visibility);
7667            } else if (freeformStackVisible) {
7668                visibility = setNavBarTranslucentFlag(visibility);
7669            } else {
7670                visibility = setNavBarOpaqueFlag(visibility);
7671            }
7672        }
7673
7674        if (!areTranslucentBarsAllowed()) {
7675            visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
7676        }
7677        return visibility;
7678    }
7679
7680    private int setNavBarOpaqueFlag(int visibility) {
7681        return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
7682    }
7683
7684    private int setNavBarTranslucentFlag(int visibility) {
7685        visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
7686        return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
7687    }
7688
7689    private void clearClearableFlagsLw() {
7690        int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
7691        if (newVal != mResettingSystemUiFlags) {
7692            mResettingSystemUiFlags = newVal;
7693            mWindowManagerFuncs.reevaluateStatusBarVisibility();
7694        }
7695    }
7696
7697    private boolean isImmersiveMode(int vis) {
7698        final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
7699        return mNavigationBar != null
7700                && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
7701                && (vis & flags) != 0
7702                && canHideNavigationBar();
7703    }
7704
7705    private static boolean isNavBarEmpty(int systemUiFlags) {
7706        final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
7707                | View.STATUS_BAR_DISABLE_BACK
7708                | View.STATUS_BAR_DISABLE_RECENT);
7709
7710        return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
7711    }
7712
7713    /**
7714     * @return whether the navigation or status bar can be made translucent
7715     *
7716     * This should return true unless touch exploration is not enabled or
7717     * R.boolean.config_enableTranslucentDecor is false.
7718     */
7719    private boolean areTranslucentBarsAllowed() {
7720        return mTranslucentDecorEnabled;
7721    }
7722
7723    // Use this instead of checking config_showNavigationBar so that it can be consistently
7724    // overridden by qemu.hw.mainkeys in the emulator.
7725    @Override
7726    public boolean hasNavigationBar() {
7727        return mHasNavigationBar;
7728    }
7729
7730    @Override
7731    public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
7732        mLastInputMethodWindow = ime;
7733        mLastInputMethodTargetWindow = target;
7734    }
7735
7736    @Override
7737    public int getInputMethodWindowVisibleHeightLw() {
7738        return mDockBottom - mCurBottom;
7739    }
7740
7741    @Override
7742    public void setCurrentUserLw(int newUserId) {
7743        mCurrentUserId = newUserId;
7744        if (mKeyguardDelegate != null) {
7745            mKeyguardDelegate.setCurrentUser(newUserId);
7746        }
7747        StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
7748        if (statusBar != null) {
7749            statusBar.setCurrentUser(newUserId);
7750        }
7751        setLastInputMethodWindowLw(null, null);
7752    }
7753
7754    @Override
7755    public boolean canMagnifyWindow(int windowType) {
7756        switch (windowType) {
7757            case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
7758            case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
7759            case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
7760            case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
7761                return false;
7762            }
7763        }
7764        return true;
7765    }
7766
7767    @Override
7768    public boolean isTopLevelWindow(int windowType) {
7769        if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
7770                && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
7771            return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
7772        }
7773        return true;
7774    }
7775
7776    @Override
7777    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
7778        // For the upside down rotation we don't rotate seamlessly as the navigation
7779        // bar moves position.
7780        // Note most apps (using orientation:sensor or user as opposed to fullSensor)
7781        // will not enter the reverse portrait orientation, so actually the
7782        // orientation won't change at all.
7783        if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
7784            return false;
7785        }
7786        int delta = newRotation - oldRotation;
7787        if (delta < 0) delta += 4;
7788        // Likewise we don't rotate seamlessly for 180 degree rotations
7789        // in this case the surfaces never resize, and our logic to
7790        // revert the transformations on size change will fail. We could
7791        // fix this in the future with the "tagged" frames idea.
7792        if (delta == Surface.ROTATION_180) {
7793            return false;
7794        }
7795
7796        final WindowState w = mTopFullscreenOpaqueWindowState;
7797        if (w != mFocusedWindow) {
7798            return false;
7799        }
7800
7801        // We only enable seamless rotation if the top window has requested
7802        // it and is in the fullscreen opaque state. Seamless rotation
7803        // requires freezing various Surface states and won't work well
7804        // with animations, so we disable it in the animation case for now.
7805        if (w != null && !w.isAnimatingLw() &&
7806                ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) ||
7807                        (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) {
7808            return true;
7809        }
7810        return false;
7811    }
7812
7813    @Override
7814    public void dump(String prefix, PrintWriter pw, String[] args) {
7815        pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
7816                pw.print(" mSystemReady="); pw.print(mSystemReady);
7817                pw.print(" mSystemBooted="); pw.println(mSystemBooted);
7818        pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
7819                pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
7820                pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
7821                pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
7822        if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
7823                || mForceClearedSystemUiFlags != 0) {
7824            pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
7825                    pw.print(Integer.toHexString(mLastSystemUiFlags));
7826                    pw.print(" mResettingSystemUiFlags=0x");
7827                    pw.print(Integer.toHexString(mResettingSystemUiFlags));
7828                    pw.print(" mForceClearedSystemUiFlags=0x");
7829                    pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
7830        }
7831        if (mLastFocusNeedsMenu) {
7832            pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
7833                    pw.println(mLastFocusNeedsMenu);
7834        }
7835        pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
7836                pw.println(mWakeGestureEnabledSetting);
7837
7838        pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
7839        pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
7840                pw.print(" mDockMode="); pw.print(mDockMode);
7841                pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
7842                pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
7843                pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
7844        pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
7845                pw.print(" mUserRotation="); pw.print(mUserRotation);
7846                pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
7847        pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
7848        pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
7849                pw.print(mCarDockEnablesAccelerometer);
7850                pw.print(" mDeskDockEnablesAccelerometer=");
7851                pw.println(mDeskDockEnablesAccelerometer);
7852        pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
7853                pw.print(mLidKeyboardAccessibility);
7854                pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
7855                pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
7856                pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
7857        pw.print(prefix);
7858                pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
7859        pw.print(prefix);
7860                pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
7861                pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
7862        pw.print(prefix);
7863                pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
7864                pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
7865        pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
7866        pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
7867        pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
7868                pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
7869        pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
7870                pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
7871        pw.print(prefix); pw.print("mOrientationSensorEnabled=");
7872                pw.println(mOrientationSensorEnabled);
7873        pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
7874                pw.print(","); pw.print(mOverscanScreenTop);
7875                pw.print(") "); pw.print(mOverscanScreenWidth);
7876                pw.print("x"); pw.println(mOverscanScreenHeight);
7877        if (mOverscanLeft != 0 || mOverscanTop != 0
7878                || mOverscanRight != 0 || mOverscanBottom != 0) {
7879            pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
7880                    pw.print(" top="); pw.print(mOverscanTop);
7881                    pw.print(" right="); pw.print(mOverscanRight);
7882                    pw.print(" bottom="); pw.println(mOverscanBottom);
7883        }
7884        pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
7885                pw.print(mRestrictedOverscanScreenLeft);
7886                pw.print(","); pw.print(mRestrictedOverscanScreenTop);
7887                pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
7888                pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
7889        pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
7890                pw.print(","); pw.print(mUnrestrictedScreenTop);
7891                pw.print(") "); pw.print(mUnrestrictedScreenWidth);
7892                pw.print("x"); pw.println(mUnrestrictedScreenHeight);
7893        pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
7894                pw.print(","); pw.print(mRestrictedScreenTop);
7895                pw.print(") "); pw.print(mRestrictedScreenWidth);
7896                pw.print("x"); pw.println(mRestrictedScreenHeight);
7897        pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
7898                pw.print(","); pw.print(mStableFullscreenTop);
7899                pw.print(")-("); pw.print(mStableFullscreenRight);
7900                pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
7901        pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
7902                pw.print(","); pw.print(mStableTop);
7903                pw.print(")-("); pw.print(mStableRight);
7904                pw.print(","); pw.print(mStableBottom); pw.println(")");
7905        pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
7906                pw.print(","); pw.print(mSystemTop);
7907                pw.print(")-("); pw.print(mSystemRight);
7908                pw.print(","); pw.print(mSystemBottom); pw.println(")");
7909        pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
7910                pw.print(","); pw.print(mCurTop);
7911                pw.print(")-("); pw.print(mCurRight);
7912                pw.print(","); pw.print(mCurBottom); pw.println(")");
7913        pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
7914                pw.print(","); pw.print(mContentTop);
7915                pw.print(")-("); pw.print(mContentRight);
7916                pw.print(","); pw.print(mContentBottom); pw.println(")");
7917        pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft);
7918                pw.print(","); pw.print(mVoiceContentTop);
7919                pw.print(")-("); pw.print(mVoiceContentRight);
7920                pw.print(","); pw.print(mVoiceContentBottom); pw.println(")");
7921        pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
7922                pw.print(","); pw.print(mDockTop);
7923                pw.print(")-("); pw.print(mDockRight);
7924                pw.print(","); pw.print(mDockBottom); pw.println(")");
7925        pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
7926                pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
7927        pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen);
7928                pw.print(" mShowingDream="); pw.print(mShowingDream);
7929                pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
7930                pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
7931        if (mLastInputMethodWindow != null) {
7932            pw.print(prefix); pw.print("mLastInputMethodWindow=");
7933                    pw.println(mLastInputMethodWindow);
7934        }
7935        if (mLastInputMethodTargetWindow != null) {
7936            pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
7937                    pw.println(mLastInputMethodTargetWindow);
7938        }
7939        if (mStatusBar != null) {
7940            pw.print(prefix); pw.print("mStatusBar=");
7941                    pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
7942                    pw.println(isStatusBarKeyguard());
7943        }
7944        if (mNavigationBar != null) {
7945            pw.print(prefix); pw.print("mNavigationBar=");
7946                    pw.println(mNavigationBar);
7947        }
7948        if (mFocusedWindow != null) {
7949            pw.print(prefix); pw.print("mFocusedWindow=");
7950                    pw.println(mFocusedWindow);
7951        }
7952        if (mFocusedApp != null) {
7953            pw.print(prefix); pw.print("mFocusedApp=");
7954                    pw.println(mFocusedApp);
7955        }
7956        if (mWinDismissingKeyguard != null) {
7957            pw.print(prefix); pw.print("mWinDismissingKeyguard=");
7958                    pw.println(mWinDismissingKeyguard);
7959        }
7960        if (mTopFullscreenOpaqueWindowState != null) {
7961            pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
7962                    pw.println(mTopFullscreenOpaqueWindowState);
7963        }
7964        if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
7965            pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
7966                    pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
7967        }
7968        if (mForcingShowNavBar) {
7969            pw.print(prefix); pw.print("mForcingShowNavBar=");
7970                    pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
7971                    pw.println(mForcingShowNavBarLayer);
7972        }
7973        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
7974                pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
7975        pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
7976                pw.print(" mForceStatusBarFromKeyguard=");
7977                pw.println(mForceStatusBarFromKeyguard);
7978        pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
7979                pw.print(" mWinDismissingKeyguard="); pw.print(mWinDismissingKeyguard);
7980                pw.print(" mHomePressed="); pw.println(mHomePressed);
7981        pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
7982                pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
7983                pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
7984        pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
7985                pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
7986                pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
7987        pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
7988                pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
7989        pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
7990                pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
7991        pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
7992                pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
7993        pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
7994
7995        mGlobalKeyManager.dump(prefix, pw);
7996        mStatusBarController.dump(pw, prefix);
7997        mNavigationBarController.dump(pw, prefix);
7998        PolicyControl.dump(prefix, pw);
7999
8000        if (mWakeGestureListener != null) {
8001            mWakeGestureListener.dump(pw, prefix);
8002        }
8003        if (mOrientationListener != null) {
8004            mOrientationListener.dump(pw, prefix);
8005        }
8006        if (mBurnInProtectionHelper != null) {
8007            mBurnInProtectionHelper.dump(prefix, pw);
8008        }
8009        if (mKeyguardDelegate != null) {
8010            mKeyguardDelegate.dump(prefix, pw);
8011        }
8012    }
8013}
8014