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