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