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