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