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