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