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