PhoneWindowManager.java revision 5026936e49540449165fd5881231f8970a29ea91
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                            MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
5808                                    event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
5809                            break;
5810                        }
5811                    }
5812                }
5813                if (mUseTvRouting) {
5814                    // On TVs, defer special key handlings to
5815                    // {@link interceptKeyBeforeDispatching()}.
5816                    result |= ACTION_PASS_TO_USER;
5817                } else if ((result & ACTION_PASS_TO_USER) == 0) {
5818                    // If we aren't passing to the user and no one else
5819                    // handled it send it to the session manager to
5820                    // figure out.
5821                    MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
5822                            event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
5823                }
5824                break;
5825            }
5826
5827            case KeyEvent.KEYCODE_ENDCALL: {
5828                result &= ~ACTION_PASS_TO_USER;
5829                if (down) {
5830                    TelecomManager telecomManager = getTelecommService();
5831                    boolean hungUp = false;
5832                    if (telecomManager != null) {
5833                        hungUp = telecomManager.endCall();
5834                    }
5835                    if (interactive && !hungUp) {
5836                        mEndCallKeyHandled = false;
5837                        mHandler.postDelayed(mEndCallLongPress,
5838                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
5839                    } else {
5840                        mEndCallKeyHandled = true;
5841                    }
5842                } else {
5843                    if (!mEndCallKeyHandled) {
5844                        mHandler.removeCallbacks(mEndCallLongPress);
5845                        if (!canceled) {
5846                            if ((mEndcallBehavior
5847                                    & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
5848                                if (goHome()) {
5849                                    break;
5850                                }
5851                            }
5852                            if ((mEndcallBehavior
5853                                    & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
5854                                mPowerManager.goToSleep(event.getEventTime(),
5855                                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
5856                                isWakeKey = false;
5857                            }
5858                        }
5859                    }
5860                }
5861                break;
5862            }
5863
5864            case KeyEvent.KEYCODE_POWER: {
5865                result &= ~ACTION_PASS_TO_USER;
5866                isWakeKey = false; // wake-up will be handled separately
5867                if (down) {
5868                    interceptPowerKeyDown(event, interactive);
5869                } else {
5870                    interceptPowerKeyUp(event, interactive, canceled);
5871                }
5872                break;
5873            }
5874
5875            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
5876                // fall through
5877            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
5878                // fall through
5879            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
5880                // fall through
5881            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
5882                result &= ~ACTION_PASS_TO_USER;
5883                interceptSystemNavigationKey(event);
5884                break;
5885            }
5886
5887            case KeyEvent.KEYCODE_SLEEP: {
5888                result &= ~ACTION_PASS_TO_USER;
5889                isWakeKey = false;
5890                if (!mPowerManager.isInteractive()) {
5891                    useHapticFeedback = false; // suppress feedback if already non-interactive
5892                }
5893                if (down) {
5894                    sleepPress(event.getEventTime());
5895                } else {
5896                    sleepRelease(event.getEventTime());
5897                }
5898                break;
5899            }
5900
5901            case KeyEvent.KEYCODE_SOFT_SLEEP: {
5902                result &= ~ACTION_PASS_TO_USER;
5903                isWakeKey = false;
5904                if (!down) {
5905                    mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
5906                }
5907                break;
5908            }
5909
5910            case KeyEvent.KEYCODE_WAKEUP: {
5911                result &= ~ACTION_PASS_TO_USER;
5912                isWakeKey = true;
5913                break;
5914            }
5915
5916            case KeyEvent.KEYCODE_MEDIA_PLAY:
5917            case KeyEvent.KEYCODE_MEDIA_PAUSE:
5918            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
5919            case KeyEvent.KEYCODE_HEADSETHOOK:
5920            case KeyEvent.KEYCODE_MUTE:
5921            case KeyEvent.KEYCODE_MEDIA_STOP:
5922            case KeyEvent.KEYCODE_MEDIA_NEXT:
5923            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
5924            case KeyEvent.KEYCODE_MEDIA_REWIND:
5925            case KeyEvent.KEYCODE_MEDIA_RECORD:
5926            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
5927            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
5928                if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
5929                    // If the global session is active pass all media keys to it
5930                    // instead of the active window.
5931                    result &= ~ACTION_PASS_TO_USER;
5932                }
5933                if ((result & ACTION_PASS_TO_USER) == 0) {
5934                    // Only do this if we would otherwise not pass it to the user. In that
5935                    // case, the PhoneWindow class will do the same thing, except it will
5936                    // only do it if the showing app doesn't process the key on its own.
5937                    // Note that we need to make a copy of the key event here because the
5938                    // original key event will be recycled when we return.
5939                    mBroadcastWakeLock.acquire();
5940                    Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
5941                            new KeyEvent(event));
5942                    msg.setAsynchronous(true);
5943                    msg.sendToTarget();
5944                }
5945                break;
5946            }
5947
5948            case KeyEvent.KEYCODE_CALL: {
5949                if (down) {
5950                    TelecomManager telecomManager = getTelecommService();
5951                    if (telecomManager != null) {
5952                        if (telecomManager.isRinging()) {
5953                            Log.i(TAG, "interceptKeyBeforeQueueing:"
5954                                  + " CALL key-down while ringing: Answer the call!");
5955                            telecomManager.acceptRingingCall();
5956
5957                            // And *don't* pass this key thru to the current activity
5958                            // (which is presumably the InCallScreen.)
5959                            result &= ~ACTION_PASS_TO_USER;
5960                        }
5961                    }
5962                }
5963                break;
5964            }
5965            case KeyEvent.KEYCODE_VOICE_ASSIST: {
5966                // Only do this if we would otherwise not pass it to the user. In that case,
5967                // interceptKeyBeforeDispatching would apply a similar but different policy in
5968                // order to invoke voice assist actions. Note that we need to make a copy of the
5969                // key event here because the original key event will be recycled when we return.
5970                if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
5971                    mBroadcastWakeLock.acquire();
5972                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
5973                            keyguardActive ? 1 : 0, 0);
5974                    msg.setAsynchronous(true);
5975                    msg.sendToTarget();
5976                }
5977                break;
5978            }
5979            case KeyEvent.KEYCODE_WINDOW: {
5980                if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
5981                    if (mTvPictureInPictureVisible) {
5982                        // Consumes the key only if picture-in-picture is visible
5983                        // to show picture-in-picture control menu.
5984                        // This gives a chance to the foreground activity
5985                        // to customize PIP key behavior.
5986                        if (!down) {
5987                            showTvPictureInPictureMenu(event);
5988                        }
5989                        result &= ~ACTION_PASS_TO_USER;
5990                    }
5991                }
5992                break;
5993            }
5994        }
5995
5996        if (useHapticFeedback) {
5997            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
5998        }
5999
6000        if (isWakeKey) {
6001            wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
6002        }
6003
6004        return result;
6005    }
6006
6007    /**
6008     * Handle statusbar expansion events.
6009     * @param event
6010     */
6011    private void interceptSystemNavigationKey(KeyEvent event) {
6012        if (event.getAction() == KeyEvent.ACTION_UP && areSystemNavigationKeysEnabled()) {
6013            IStatusBarService sbar = getStatusBarService();
6014            if (sbar != null) {
6015                try {
6016                    sbar.handleSystemNavigationKey(event.getKeyCode());
6017                } catch (RemoteException e1) {
6018                    // oops, no statusbar. Ignore event.
6019                }
6020            }
6021        }
6022    }
6023
6024    /**
6025     * Returns true if the key can have global actions attached to it.
6026     * We reserve all power management keys for the system since they require
6027     * very careful handling.
6028     */
6029    private static boolean isValidGlobalKey(int keyCode) {
6030        switch (keyCode) {
6031            case KeyEvent.KEYCODE_POWER:
6032            case KeyEvent.KEYCODE_WAKEUP:
6033            case KeyEvent.KEYCODE_SLEEP:
6034                return false;
6035            default:
6036                return true;
6037        }
6038    }
6039
6040    /**
6041     * When the screen is off we ignore some keys that might otherwise typically
6042     * be considered wake keys.  We filter them out here.
6043     *
6044     * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
6045     * is always considered a wake key.
6046     */
6047    private boolean isWakeKeyWhenScreenOff(int keyCode) {
6048        switch (keyCode) {
6049            // ignore volume keys unless docked
6050            case KeyEvent.KEYCODE_VOLUME_UP:
6051            case KeyEvent.KEYCODE_VOLUME_DOWN:
6052            case KeyEvent.KEYCODE_VOLUME_MUTE:
6053                return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
6054
6055            // ignore media and camera keys
6056            case KeyEvent.KEYCODE_MUTE:
6057            case KeyEvent.KEYCODE_HEADSETHOOK:
6058            case KeyEvent.KEYCODE_MEDIA_PLAY:
6059            case KeyEvent.KEYCODE_MEDIA_PAUSE:
6060            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6061            case KeyEvent.KEYCODE_MEDIA_STOP:
6062            case KeyEvent.KEYCODE_MEDIA_NEXT:
6063            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6064            case KeyEvent.KEYCODE_MEDIA_REWIND:
6065            case KeyEvent.KEYCODE_MEDIA_RECORD:
6066            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6067            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
6068            case KeyEvent.KEYCODE_CAMERA:
6069                return false;
6070        }
6071        return true;
6072    }
6073
6074
6075    /** {@inheritDoc} */
6076    @Override
6077    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
6078        if ((policyFlags & FLAG_WAKE) != 0) {
6079            if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
6080                    "android.policy:MOTION")) {
6081                return 0;
6082            }
6083        }
6084
6085        if (shouldDispatchInputWhenNonInteractive(null)) {
6086            return ACTION_PASS_TO_USER;
6087        }
6088
6089        // If we have not passed the action up and we are in theater mode without dreaming,
6090        // there will be no dream to intercept the touch and wake into ambient.  The device should
6091        // wake up in this case.
6092        if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
6093            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
6094                    "android.policy:MOTION");
6095        }
6096
6097        return 0;
6098    }
6099
6100    private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
6101        final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
6102
6103        if (displayOff && !mHasFeatureWatch) {
6104            return false;
6105        }
6106
6107        // Send events to keyguard while the screen is on and it's showing.
6108        if (isKeyguardShowingAndNotOccluded() && !displayOff) {
6109            return true;
6110        }
6111
6112        // Watches handle BACK specially
6113        if (mHasFeatureWatch
6114                && event != null
6115                && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
6116                        || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
6117            return false;
6118        }
6119
6120        // Send events to a dozing dream even if the screen is off since the dream
6121        // is in control of the state of the screen.
6122        IDreamManager dreamManager = getDreamManager();
6123
6124        try {
6125            if (dreamManager != null && dreamManager.isDreaming()) {
6126                return true;
6127            }
6128        } catch (RemoteException e) {
6129            Slog.e(TAG, "RemoteException when checking if dreaming", e);
6130        }
6131
6132        // Otherwise, consume events since the user can't see what is being
6133        // interacted with.
6134        return false;
6135    }
6136
6137    private void dispatchDirectAudioEvent(KeyEvent event) {
6138        if (event.getAction() != KeyEvent.ACTION_DOWN) {
6139            return;
6140        }
6141        int keyCode = event.getKeyCode();
6142        int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
6143                | AudioManager.FLAG_FROM_KEY;
6144        String pkgName = mContext.getOpPackageName();
6145        switch (keyCode) {
6146            case KeyEvent.KEYCODE_VOLUME_UP:
6147                try {
6148                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
6149                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6150                } catch (RemoteException e) {
6151                    Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
6152                }
6153                break;
6154            case KeyEvent.KEYCODE_VOLUME_DOWN:
6155                try {
6156                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
6157                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6158                } catch (RemoteException e) {
6159                    Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
6160                }
6161                break;
6162            case KeyEvent.KEYCODE_VOLUME_MUTE:
6163                try {
6164                    if (event.getRepeatCount() == 0) {
6165                        getAudioService().adjustSuggestedStreamVolume(
6166                                AudioManager.ADJUST_TOGGLE_MUTE,
6167                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6168                    }
6169                } catch (RemoteException e) {
6170                    Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
6171                }
6172                break;
6173        }
6174    }
6175
6176    void dispatchMediaKeyWithWakeLock(KeyEvent event) {
6177        if (DEBUG_INPUT) {
6178            Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
6179        }
6180
6181        if (mHavePendingMediaKeyRepeatWithWakeLock) {
6182            if (DEBUG_INPUT) {
6183                Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
6184            }
6185
6186            mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
6187            mHavePendingMediaKeyRepeatWithWakeLock = false;
6188            mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
6189        }
6190
6191        dispatchMediaKeyWithWakeLockToAudioService(event);
6192
6193        if (event.getAction() == KeyEvent.ACTION_DOWN
6194                && event.getRepeatCount() == 0) {
6195            mHavePendingMediaKeyRepeatWithWakeLock = true;
6196
6197            Message msg = mHandler.obtainMessage(
6198                    MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
6199            msg.setAsynchronous(true);
6200            mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
6201        } else {
6202            mBroadcastWakeLock.release();
6203        }
6204    }
6205
6206    void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
6207        mHavePendingMediaKeyRepeatWithWakeLock = false;
6208
6209        KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
6210                SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6211        if (DEBUG_INPUT) {
6212            Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
6213        }
6214
6215        dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
6216        mBroadcastWakeLock.release();
6217    }
6218
6219    void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
6220        if (mActivityManagerInternal.isSystemReady()) {
6221            MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
6222        }
6223    }
6224
6225    void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
6226        IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
6227                ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
6228        if (dic != null) {
6229            try {
6230                dic.exitIdle("voice-search");
6231            } catch (RemoteException e) {
6232            }
6233        }
6234        Intent voiceIntent =
6235            new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
6236        voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
6237        startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
6238        mBroadcastWakeLock.release();
6239    }
6240
6241    BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
6242        @Override
6243        public void onReceive(Context context, Intent intent) {
6244            if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
6245                mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6246                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
6247            } else {
6248                try {
6249                    IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
6250                            ServiceManager.getService(Context.UI_MODE_SERVICE));
6251                    mUiMode = uiModeService.getCurrentModeType();
6252                } catch (RemoteException e) {
6253                }
6254            }
6255            updateRotation(true);
6256            synchronized (mLock) {
6257                updateOrientationListenerLp();
6258            }
6259        }
6260    };
6261
6262    BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
6263        @Override
6264        public void onReceive(Context context, Intent intent) {
6265            if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
6266                if (mKeyguardDelegate != null) {
6267                    mKeyguardDelegate.onDreamingStarted();
6268                }
6269            } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
6270                if (mKeyguardDelegate != null) {
6271                    mKeyguardDelegate.onDreamingStopped();
6272                }
6273            }
6274        }
6275    };
6276
6277    BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
6278        @Override
6279        public void onReceive(Context context, Intent intent) {
6280            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
6281                // tickle the settings observer: this first ensures that we're
6282                // observing the relevant settings for the newly-active user,
6283                // and then updates our own bookkeeping based on the now-
6284                // current user.
6285                mSettingsObserver.onChange(false);
6286
6287                // force a re-application of focused window sysui visibility.
6288                // the window may never have been shown for this user
6289                // e.g. the keyguard when going through the new-user setup flow
6290                synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6291                    mLastSystemUiFlags = 0;
6292                    updateSystemUiVisibilityLw();
6293                }
6294            }
6295        }
6296    };
6297
6298    private final Runnable mHiddenNavPanic = new Runnable() {
6299        @Override
6300        public void run() {
6301            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6302                if (!isUserSetupComplete()) {
6303                    // Swipe-up for navigation bar is disabled during setup
6304                    return;
6305                }
6306                mPendingPanicGestureUptime = SystemClock.uptimeMillis();
6307                if (!isNavBarEmpty(mLastSystemUiFlags)) {
6308                    mNavigationBarController.showTransient();
6309                }
6310            }
6311        }
6312    };
6313
6314    private void requestTransientBars(WindowState swipeTarget) {
6315        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6316            if (!isUserSetupComplete()) {
6317                // Swipe-up for navigation bar is disabled during setup
6318                return;
6319            }
6320            boolean sb = mStatusBarController.checkShowTransientBarLw();
6321            boolean nb = mNavigationBarController.checkShowTransientBarLw()
6322                    && !isNavBarEmpty(mLastSystemUiFlags);
6323            if (sb || nb) {
6324                // Don't show status bar when swiping on already visible navigation bar
6325                if (!nb && swipeTarget == mNavigationBar) {
6326                    if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
6327                    return;
6328                }
6329                if (sb) mStatusBarController.showTransient();
6330                if (nb) mNavigationBarController.showTransient();
6331                mImmersiveModeConfirmation.confirmCurrentPrompt();
6332                updateSystemUiVisibilityLw();
6333            }
6334        }
6335    }
6336
6337    // Called on the PowerManager's Notifier thread.
6338    @Override
6339    public void startedGoingToSleep(int why) {
6340        if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
6341        mCameraGestureTriggeredDuringGoingToSleep = false;
6342        mGoingToSleep = true;
6343        if (mKeyguardDelegate != null) {
6344            mKeyguardDelegate.onStartedGoingToSleep(why);
6345        }
6346    }
6347
6348    // Called on the PowerManager's Notifier thread.
6349    @Override
6350    public void finishedGoingToSleep(int why) {
6351        EventLog.writeEvent(70000, 0);
6352        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
6353        MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
6354
6355        mGoingToSleep = false;
6356
6357        // We must get this work done here because the power manager will drop
6358        // the wake lock and let the system suspend once this function returns.
6359        synchronized (mLock) {
6360            mAwake = false;
6361            updateWakeGestureListenerLp();
6362            updateOrientationListenerLp();
6363            updateLockScreenTimeout();
6364        }
6365        if (mKeyguardDelegate != null) {
6366            mKeyguardDelegate.onFinishedGoingToSleep(why,
6367                    mCameraGestureTriggeredDuringGoingToSleep);
6368        }
6369        mCameraGestureTriggeredDuringGoingToSleep = false;
6370    }
6371
6372    // Called on the PowerManager's Notifier thread.
6373    @Override
6374    public void startedWakingUp() {
6375        EventLog.writeEvent(70000, 1);
6376        if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
6377
6378        // Since goToSleep performs these functions synchronously, we must
6379        // do the same here.  We cannot post this work to a handler because
6380        // that might cause it to become reordered with respect to what
6381        // may happen in a future call to goToSleep.
6382        synchronized (mLock) {
6383            mAwake = true;
6384
6385            updateWakeGestureListenerLp();
6386            updateOrientationListenerLp();
6387            updateLockScreenTimeout();
6388        }
6389
6390        if (mKeyguardDelegate != null) {
6391            mKeyguardDelegate.onStartedWakingUp();
6392        }
6393    }
6394
6395    // Called on the PowerManager's Notifier thread.
6396    @Override
6397    public void finishedWakingUp() {
6398        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
6399    }
6400
6401    private void wakeUpFromPowerKey(long eventTime) {
6402        wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
6403    }
6404
6405    private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
6406        final boolean theaterModeEnabled = isTheaterModeEnabled();
6407        if (!wakeInTheaterMode && theaterModeEnabled) {
6408            return false;
6409        }
6410
6411        if (theaterModeEnabled) {
6412            Settings.Global.putInt(mContext.getContentResolver(),
6413                    Settings.Global.THEATER_MODE_ON, 0);
6414        }
6415
6416        mPowerManager.wakeUp(wakeTime, reason);
6417        return true;
6418    }
6419
6420    private void finishKeyguardDrawn() {
6421        synchronized (mLock) {
6422            if (!mScreenOnEarly || mKeyguardDrawComplete) {
6423                return; // We are not awake yet or we have already informed of this event.
6424            }
6425
6426            mKeyguardDrawComplete = true;
6427            if (mKeyguardDelegate != null) {
6428                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6429            }
6430            mWindowManagerDrawComplete = false;
6431        }
6432
6433        // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
6434        // as well as enabling the orientation change logic/sensor.
6435        mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
6436                WAITING_FOR_DRAWN_TIMEOUT);
6437    }
6438
6439    // Called on the DisplayManager's DisplayPowerController thread.
6440    @Override
6441    public void screenTurnedOff() {
6442        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
6443
6444        updateScreenOffSleepToken(true);
6445        synchronized (mLock) {
6446            mScreenOnEarly = false;
6447            mScreenOnFully = false;
6448            mKeyguardDrawComplete = false;
6449            mWindowManagerDrawComplete = false;
6450            mScreenOnListener = null;
6451            updateOrientationListenerLp();
6452
6453            if (mKeyguardDelegate != null) {
6454                mKeyguardDelegate.onScreenTurnedOff();
6455            }
6456        }
6457        reportScreenStateToVrManager(false);
6458    }
6459
6460    // Called on the DisplayManager's DisplayPowerController thread.
6461    @Override
6462    public void screenTurningOn(final ScreenOnListener screenOnListener) {
6463        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
6464
6465        updateScreenOffSleepToken(false);
6466        synchronized (mLock) {
6467            mScreenOnEarly = true;
6468            mScreenOnFully = false;
6469            mKeyguardDrawComplete = false;
6470            mWindowManagerDrawComplete = false;
6471            mScreenOnListener = screenOnListener;
6472
6473            if (mKeyguardDelegate != null) {
6474                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6475                mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
6476                mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
6477            } else {
6478                if (DEBUG_WAKEUP) Slog.d(TAG,
6479                        "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
6480                finishKeyguardDrawn();
6481            }
6482        }
6483    }
6484
6485    // Called on the DisplayManager's DisplayPowerController thread.
6486    @Override
6487    public void screenTurnedOn() {
6488        synchronized (mLock) {
6489            if (mKeyguardDelegate != null) {
6490                mKeyguardDelegate.onScreenTurnedOn();
6491            }
6492        }
6493        reportScreenStateToVrManager(true);
6494    }
6495
6496    private void reportScreenStateToVrManager(boolean isScreenOn) {
6497        VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
6498        if (vrService == null) {
6499            return;
6500        }
6501        vrService.onScreenStateChanged(isScreenOn);
6502    }
6503
6504    private void finishWindowsDrawn() {
6505        synchronized (mLock) {
6506            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
6507                return; // Screen is not turned on or we did already handle this case earlier.
6508            }
6509
6510            mWindowManagerDrawComplete = true;
6511        }
6512
6513        finishScreenTurningOn();
6514    }
6515
6516    private void finishScreenTurningOn() {
6517        synchronized (mLock) {
6518            // We have just finished drawing screen content. Since the orientation listener
6519            // gets only installed when all windows are drawn, we try to install it again.
6520            updateOrientationListenerLp();
6521        }
6522        final ScreenOnListener listener;
6523        final boolean enableScreen;
6524        synchronized (mLock) {
6525            if (DEBUG_WAKEUP) Slog.d(TAG,
6526                    "finishScreenTurningOn: mAwake=" + mAwake
6527                            + ", mScreenOnEarly=" + mScreenOnEarly
6528                            + ", mScreenOnFully=" + mScreenOnFully
6529                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
6530                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
6531
6532            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
6533                    || (mAwake && !mKeyguardDrawComplete)) {
6534                return; // spurious or not ready yet
6535            }
6536
6537            if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
6538            listener = mScreenOnListener;
6539            mScreenOnListener = null;
6540            mScreenOnFully = true;
6541
6542            // Remember the first time we draw the keyguard so we know when we're done with
6543            // the main part of booting and can enable the screen and hide boot messages.
6544            if (!mKeyguardDrawnOnce && mAwake) {
6545                mKeyguardDrawnOnce = true;
6546                enableScreen = true;
6547                if (mBootMessageNeedsHiding) {
6548                    mBootMessageNeedsHiding = false;
6549                    hideBootMessages();
6550                }
6551            } else {
6552                enableScreen = false;
6553            }
6554        }
6555
6556        if (listener != null) {
6557            listener.onScreenOn();
6558        }
6559
6560        if (enableScreen) {
6561            try {
6562                mWindowManager.enableScreenIfNeeded();
6563            } catch (RemoteException unhandled) {
6564            }
6565        }
6566    }
6567
6568    private void handleHideBootMessage() {
6569        synchronized (mLock) {
6570            if (!mKeyguardDrawnOnce) {
6571                mBootMessageNeedsHiding = true;
6572                return; // keyguard hasn't drawn the first time yet, not done booting
6573            }
6574        }
6575
6576        if (mBootMsgDialog != null) {
6577            if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
6578            mBootMsgDialog.dismiss();
6579            mBootMsgDialog = null;
6580        }
6581    }
6582
6583    @Override
6584    public boolean isScreenOn() {
6585        return mScreenOnFully;
6586    }
6587
6588    /** {@inheritDoc} */
6589    @Override
6590    public void enableKeyguard(boolean enabled) {
6591        if (mKeyguardDelegate != null) {
6592            mKeyguardDelegate.setKeyguardEnabled(enabled);
6593        }
6594    }
6595
6596    /** {@inheritDoc} */
6597    @Override
6598    public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
6599        if (mKeyguardDelegate != null) {
6600            mKeyguardDelegate.verifyUnlock(callback);
6601        }
6602    }
6603
6604    @Override
6605    public boolean isKeyguardShowingAndNotOccluded() {
6606        if (mKeyguardDelegate == null) return false;
6607        return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
6608    }
6609
6610    @Override
6611    public boolean isKeyguardTrustedLw() {
6612        if (mKeyguardDelegate == null) return false;
6613        return mKeyguardDelegate.isTrusted();
6614    }
6615
6616    /** {@inheritDoc} */
6617    @Override
6618    public boolean isKeyguardLocked() {
6619        return keyguardOn();
6620    }
6621
6622    /** {@inheritDoc} */
6623    @Override
6624    public boolean isKeyguardSecure(int userId) {
6625        if (mKeyguardDelegate == null) return false;
6626        return mKeyguardDelegate.isSecure(userId);
6627    }
6628
6629    /** {@inheritDoc} */
6630    @Override
6631    public boolean isKeyguardOccluded() {
6632        if (mKeyguardDelegate == null) return false;
6633        return mKeyguardOccluded;
6634    }
6635
6636    /** {@inheritDoc} */
6637    @Override
6638    public boolean inKeyguardRestrictedKeyInputMode() {
6639        if (mKeyguardDelegate == null) return false;
6640        return mKeyguardDelegate.isInputRestricted();
6641    }
6642
6643    @Override
6644    public void dismissKeyguardLw(IKeyguardDismissCallback callback) {
6645        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
6646            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
6647
6648            // ask the keyguard to prompt the user to authenticate if necessary
6649            mKeyguardDelegate.dismiss(callback);
6650        } else if (callback != null) {
6651            try {
6652                callback.onDismissError();
6653            } catch (RemoteException e) {
6654                Slog.w(TAG, "Failed to call callback", e);
6655            }
6656        }
6657    }
6658
6659    @Override
6660    public boolean isKeyguardDrawnLw() {
6661        synchronized (mLock) {
6662            return mKeyguardDrawnOnce;
6663        }
6664    }
6665
6666    @Override
6667    public boolean isShowingDreamLw() {
6668        return mShowingDream;
6669    }
6670
6671    @Override
6672    public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
6673        if (mKeyguardDelegate != null) {
6674            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
6675            mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
6676        }
6677    }
6678
6679    @Override
6680    public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6681            Rect outInsets) {
6682        outInsets.setEmpty();
6683
6684        // Navigation bar and status bar.
6685        getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
6686        outInsets.top = mStatusBarHeight;
6687    }
6688
6689    @Override
6690    public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6691            Rect outInsets) {
6692        outInsets.setEmpty();
6693
6694        // Only navigation bar
6695        if (mHasNavigationBar) {
6696            int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
6697            if (position == NAV_BAR_BOTTOM) {
6698                outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
6699            } else if (position == NAV_BAR_RIGHT) {
6700                outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
6701            } else if (position == NAV_BAR_LEFT) {
6702                outInsets.left = getNavigationBarWidth(displayRotation, mUiMode);
6703            }
6704        }
6705    }
6706
6707    @Override
6708    public boolean isNavBarForcedShownLw(WindowState windowState) {
6709        return mForceShowSystemBars;
6710    }
6711
6712    @Override
6713    public boolean isDockSideAllowed(int dockSide) {
6714
6715        // We do not allow all dock sides at which the navigation bar touches the docked stack.
6716        if (!mNavigationBarCanMove) {
6717            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT;
6718        } else {
6719            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT;
6720        }
6721    }
6722
6723    void sendCloseSystemWindows() {
6724        PhoneWindow.sendCloseSystemWindows(mContext, null);
6725    }
6726
6727    void sendCloseSystemWindows(String reason) {
6728        PhoneWindow.sendCloseSystemWindows(mContext, reason);
6729    }
6730
6731    @Override
6732    public int rotationForOrientationLw(int orientation, int lastRotation) {
6733        if (false) {
6734            Slog.v(TAG, "rotationForOrientationLw(orient="
6735                        + orientation + ", last=" + lastRotation
6736                        + "); user=" + mUserRotation + " "
6737                        + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
6738                            ? "USER_ROTATION_LOCKED" : "")
6739                        );
6740        }
6741
6742        if (mForceDefaultOrientation) {
6743            return Surface.ROTATION_0;
6744        }
6745
6746        synchronized (mLock) {
6747            int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
6748            if (sensorRotation < 0) {
6749                sensorRotation = lastRotation;
6750            }
6751
6752            final int preferredRotation;
6753            if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
6754                // Ignore sensor when lid switch is open and rotation is forced.
6755                preferredRotation = mLidOpenRotation;
6756            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
6757                    && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
6758                // Ignore sensor when in car dock unless explicitly enabled.
6759                // This case can override the behavior of NOSENSOR, and can also
6760                // enable 180 degree rotation while docked.
6761                preferredRotation = mCarDockEnablesAccelerometer
6762                        ? sensorRotation : mCarDockRotation;
6763            } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
6764                    || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
6765                    || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
6766                    && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
6767                // Ignore sensor when in desk dock unless explicitly enabled.
6768                // This case can override the behavior of NOSENSOR, and can also
6769                // enable 180 degree rotation while docked.
6770                preferredRotation = mDeskDockEnablesAccelerometer
6771                        ? sensorRotation : mDeskDockRotation;
6772            } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
6773                // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
6774                // Note that the dock orientation overrides the HDMI orientation.
6775                preferredRotation = mDemoHdmiRotation;
6776            } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
6777                    && mUndockedHdmiRotation >= 0) {
6778                // Ignore sensor when plugged into HDMI and an undocked orientation has
6779                // been specified in the configuration (only for legacy devices without
6780                // full multi-display support).
6781                // Note that the dock orientation overrides the HDMI orientation.
6782                preferredRotation = mUndockedHdmiRotation;
6783            } else if (mDemoRotationLock) {
6784                // Ignore sensor when demo rotation lock is enabled.
6785                // Note that the dock orientation and HDMI rotation lock override this.
6786                preferredRotation = mDemoRotation;
6787            } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
6788                // Application just wants to remain locked in the last rotation.
6789                preferredRotation = lastRotation;
6790            } else if (!mSupportAutoRotation) {
6791                // If we don't support auto-rotation then bail out here and ignore
6792                // the sensor and any rotation lock settings.
6793                preferredRotation = -1;
6794            } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
6795                            && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
6796                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
6797                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
6798                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
6799                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
6800                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
6801                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6802                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
6803                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
6804                // Otherwise, use sensor only if requested by the application or enabled
6805                // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
6806                if (mAllowAllRotations < 0) {
6807                    // Can't read this during init() because the context doesn't
6808                    // have display metrics at that time so we cannot determine
6809                    // tablet vs. phone then.
6810                    mAllowAllRotations = mContext.getResources().getBoolean(
6811                            com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
6812                }
6813                if (sensorRotation != Surface.ROTATION_180
6814                        || mAllowAllRotations == 1
6815                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6816                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
6817                    preferredRotation = sensorRotation;
6818                } else {
6819                    preferredRotation = lastRotation;
6820                }
6821            } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
6822                    && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
6823                // Apply rotation lock.  Does not apply to NOSENSOR.
6824                // The idea is that the user rotation expresses a weak preference for the direction
6825                // of gravity and as NOSENSOR is never affected by gravity, then neither should
6826                // NOSENSOR be affected by rotation lock (although it will be affected by docks).
6827                preferredRotation = mUserRotation;
6828            } else {
6829                // No overriding preference.
6830                // We will do exactly what the application asked us to do.
6831                preferredRotation = -1;
6832            }
6833
6834            switch (orientation) {
6835                case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6836                    // Return portrait unless overridden.
6837                    if (isAnyPortrait(preferredRotation)) {
6838                        return preferredRotation;
6839                    }
6840                    return mPortraitRotation;
6841
6842                case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6843                    // Return landscape unless overridden.
6844                    if (isLandscapeOrSeascape(preferredRotation)) {
6845                        return preferredRotation;
6846                    }
6847                    return mLandscapeRotation;
6848
6849                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6850                    // Return reverse portrait unless overridden.
6851                    if (isAnyPortrait(preferredRotation)) {
6852                        return preferredRotation;
6853                    }
6854                    return mUpsideDownRotation;
6855
6856                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6857                    // Return seascape unless overridden.
6858                    if (isLandscapeOrSeascape(preferredRotation)) {
6859                        return preferredRotation;
6860                    }
6861                    return mSeascapeRotation;
6862
6863                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6864                case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
6865                    // Return either landscape rotation.
6866                    if (isLandscapeOrSeascape(preferredRotation)) {
6867                        return preferredRotation;
6868                    }
6869                    if (isLandscapeOrSeascape(lastRotation)) {
6870                        return lastRotation;
6871                    }
6872                    return mLandscapeRotation;
6873
6874                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6875                case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
6876                    // Return either portrait rotation.
6877                    if (isAnyPortrait(preferredRotation)) {
6878                        return preferredRotation;
6879                    }
6880                    if (isAnyPortrait(lastRotation)) {
6881                        return lastRotation;
6882                    }
6883                    return mPortraitRotation;
6884
6885                default:
6886                    // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
6887                    // just return the preferred orientation we already calculated.
6888                    if (preferredRotation >= 0) {
6889                        return preferredRotation;
6890                    }
6891                    return Surface.ROTATION_0;
6892            }
6893        }
6894    }
6895
6896    @Override
6897    public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
6898        switch (orientation) {
6899            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6900            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6901            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6902                return isAnyPortrait(rotation);
6903
6904            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6905            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6906            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6907                return isLandscapeOrSeascape(rotation);
6908
6909            default:
6910                return true;
6911        }
6912    }
6913
6914    @Override
6915    public void setRotationLw(int rotation) {
6916        mOrientationListener.setCurrentRotation(rotation);
6917    }
6918
6919    private boolean isLandscapeOrSeascape(int rotation) {
6920        return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
6921    }
6922
6923    private boolean isAnyPortrait(int rotation) {
6924        return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
6925    }
6926
6927    @Override
6928    public int getUserRotationMode() {
6929        return Settings.System.getIntForUser(mContext.getContentResolver(),
6930                Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
6931                        WindowManagerPolicy.USER_ROTATION_FREE :
6932                                WindowManagerPolicy.USER_ROTATION_LOCKED;
6933    }
6934
6935    // User rotation: to be used when all else fails in assigning an orientation to the device
6936    @Override
6937    public void setUserRotationMode(int mode, int rot) {
6938        ContentResolver res = mContext.getContentResolver();
6939
6940        // mUserRotationMode and mUserRotation will be assigned by the content observer
6941        if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
6942            Settings.System.putIntForUser(res,
6943                    Settings.System.USER_ROTATION,
6944                    rot,
6945                    UserHandle.USER_CURRENT);
6946            Settings.System.putIntForUser(res,
6947                    Settings.System.ACCELEROMETER_ROTATION,
6948                    0,
6949                    UserHandle.USER_CURRENT);
6950        } else {
6951            Settings.System.putIntForUser(res,
6952                    Settings.System.ACCELEROMETER_ROTATION,
6953                    1,
6954                    UserHandle.USER_CURRENT);
6955        }
6956    }
6957
6958    @Override
6959    public void setSafeMode(boolean safeMode) {
6960        mSafeMode = safeMode;
6961        performHapticFeedbackLw(null, safeMode
6962                ? HapticFeedbackConstants.SAFE_MODE_ENABLED
6963                : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
6964    }
6965
6966    static long[] getLongIntArray(Resources r, int resid) {
6967        int[] ar = r.getIntArray(resid);
6968        if (ar == null) {
6969            return null;
6970        }
6971        long[] out = new long[ar.length];
6972        for (int i=0; i<ar.length; i++) {
6973            out[i] = ar[i];
6974        }
6975        return out;
6976    }
6977
6978    /** {@inheritDoc} */
6979    @Override
6980    public void systemReady() {
6981        mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
6982                new StateCallback() {
6983                    @Override
6984                    public void onTrustedChanged() {
6985                        mWindowManagerFuncs.notifyKeyguardTrustedChanged();
6986                    }
6987                });
6988        mKeyguardDelegate.onSystemReady();
6989
6990        readCameraLensCoverState();
6991        updateUiMode();
6992        boolean bindKeyguardNow;
6993        synchronized (mLock) {
6994            updateOrientationListenerLp();
6995            mSystemReady = true;
6996            mHandler.post(new Runnable() {
6997                @Override
6998                public void run() {
6999                    updateSettings();
7000                }
7001            });
7002
7003            bindKeyguardNow = mDeferBindKeyguard;
7004            if (bindKeyguardNow) {
7005                // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now.
7006                mDeferBindKeyguard = false;
7007            }
7008        }
7009
7010        if (bindKeyguardNow) {
7011            mKeyguardDelegate.bindService(mContext);
7012            mKeyguardDelegate.onBootCompleted();
7013        }
7014        mSystemGestures.systemReady();
7015        mImmersiveModeConfirmation.systemReady();
7016    }
7017
7018    /** {@inheritDoc} */
7019    @Override
7020    public void systemBooted() {
7021        boolean bindKeyguardNow = false;
7022        synchronized (mLock) {
7023            // Time to bind Keyguard; take care to only bind it once, either here if ready or
7024            // in systemReady if not.
7025            if (mKeyguardDelegate != null) {
7026                bindKeyguardNow = true;
7027            } else {
7028                // Because mKeyguardDelegate is null, we know that the synchronized block in
7029                // systemReady didn't run yet and setting this will actually have an effect.
7030                mDeferBindKeyguard = true;
7031            }
7032        }
7033        if (bindKeyguardNow) {
7034            mKeyguardDelegate.bindService(mContext);
7035            mKeyguardDelegate.onBootCompleted();
7036        }
7037        synchronized (mLock) {
7038            mSystemBooted = true;
7039        }
7040        startedWakingUp();
7041        screenTurningOn(null);
7042        screenTurnedOn();
7043    }
7044
7045    ProgressDialog mBootMsgDialog = null;
7046
7047    /** {@inheritDoc} */
7048    @Override
7049    public void showBootMessage(final CharSequence msg, final boolean always) {
7050        mHandler.post(new Runnable() {
7051            @Override public void run() {
7052                if (mBootMsgDialog == null) {
7053                    int theme;
7054                    if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) {
7055                        theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
7056                    } else {
7057                        theme = 0;
7058                    }
7059
7060                    mBootMsgDialog = new ProgressDialog(mContext, theme) {
7061                        // This dialog will consume all events coming in to
7062                        // it, to avoid it trying to do things too early in boot.
7063                        @Override public boolean dispatchKeyEvent(KeyEvent event) {
7064                            return true;
7065                        }
7066                        @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7067                            return true;
7068                        }
7069                        @Override public boolean dispatchTouchEvent(MotionEvent ev) {
7070                            return true;
7071                        }
7072                        @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
7073                            return true;
7074                        }
7075                        @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
7076                            return true;
7077                        }
7078                        @Override public boolean dispatchPopulateAccessibilityEvent(
7079                                AccessibilityEvent event) {
7080                            return true;
7081                        }
7082                    };
7083                    if (mContext.getPackageManager().isUpgrade()) {
7084                        mBootMsgDialog.setTitle(R.string.android_upgrading_title);
7085                    } else {
7086                        mBootMsgDialog.setTitle(R.string.android_start_title);
7087                    }
7088                    mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
7089                    mBootMsgDialog.setIndeterminate(true);
7090                    mBootMsgDialog.getWindow().setType(
7091                            WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
7092                    mBootMsgDialog.getWindow().addFlags(
7093                            WindowManager.LayoutParams.FLAG_DIM_BEHIND
7094                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
7095                    mBootMsgDialog.getWindow().setDimAmount(1);
7096                    WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
7097                    lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
7098                    mBootMsgDialog.getWindow().setAttributes(lp);
7099                    mBootMsgDialog.setCancelable(false);
7100                    mBootMsgDialog.show();
7101                }
7102                mBootMsgDialog.setMessage(msg);
7103            }
7104        });
7105    }
7106
7107    /** {@inheritDoc} */
7108    @Override
7109    public void hideBootMessages() {
7110        mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
7111    }
7112
7113    /** {@inheritDoc} */
7114    @Override
7115    public void userActivity() {
7116        // ***************************************
7117        // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
7118        // ***************************************
7119        // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
7120        // WITH ITS LOCKS HELD.
7121        //
7122        // This code must be VERY careful about the locks
7123        // it acquires.
7124        // In fact, the current code acquires way too many,
7125        // and probably has lurking deadlocks.
7126
7127        synchronized (mScreenLockTimeout) {
7128            if (mLockScreenTimerActive) {
7129                // reset the timer
7130                mHandler.removeCallbacks(mScreenLockTimeout);
7131                mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7132            }
7133        }
7134    }
7135
7136    class ScreenLockTimeout implements Runnable {
7137        Bundle options;
7138
7139        @Override
7140        public void run() {
7141            synchronized (this) {
7142                if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
7143                if (mKeyguardDelegate != null) {
7144                    mKeyguardDelegate.doKeyguardTimeout(options);
7145                }
7146                mLockScreenTimerActive = false;
7147                options = null;
7148            }
7149        }
7150
7151        public void setLockOptions(Bundle options) {
7152            this.options = options;
7153        }
7154    }
7155
7156    ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
7157
7158    @Override
7159    public void lockNow(Bundle options) {
7160        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
7161        mHandler.removeCallbacks(mScreenLockTimeout);
7162        if (options != null) {
7163            // In case multiple calls are made to lockNow, we don't wipe out the options
7164            // until the runnable actually executes.
7165            mScreenLockTimeout.setLockOptions(options);
7166        }
7167        mHandler.post(mScreenLockTimeout);
7168    }
7169
7170    private void updateLockScreenTimeout() {
7171        synchronized (mScreenLockTimeout) {
7172            boolean enable = (mAllowLockscreenWhenOn && mAwake &&
7173                    mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
7174            if (mLockScreenTimerActive != enable) {
7175                if (enable) {
7176                    if (localLOGV) Log.v(TAG, "setting lockscreen timer");
7177                    mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
7178                    mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7179                } else {
7180                    if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
7181                    mHandler.removeCallbacks(mScreenLockTimeout);
7182                }
7183                mLockScreenTimerActive = enable;
7184            }
7185        }
7186    }
7187
7188    private void updateDreamingSleepToken(boolean acquire) {
7189        if (acquire) {
7190            if (mDreamingSleepToken == null) {
7191                mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream");
7192            }
7193        } else {
7194            if (mDreamingSleepToken != null) {
7195                mDreamingSleepToken.release();
7196                mDreamingSleepToken = null;
7197            }
7198        }
7199    }
7200
7201    private void updateScreenOffSleepToken(boolean acquire) {
7202        if (acquire) {
7203            if (mScreenOffSleepToken == null) {
7204                mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff");
7205            }
7206        } else {
7207            if (mScreenOffSleepToken != null) {
7208                mScreenOffSleepToken.release();
7209                mScreenOffSleepToken = null;
7210            }
7211        }
7212    }
7213
7214    /** {@inheritDoc} */
7215    @Override
7216    public void enableScreenAfterBoot() {
7217        readLidState();
7218        applyLidSwitchState();
7219        updateRotation(true);
7220    }
7221
7222    private void applyLidSwitchState() {
7223        if (mLidState == LID_CLOSED && mLidControlsSleep) {
7224            mPowerManager.goToSleep(SystemClock.uptimeMillis(),
7225                    PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
7226                    PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
7227        } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
7228            mWindowManagerFuncs.lockDeviceNow();
7229        }
7230
7231        synchronized (mLock) {
7232            updateWakeGestureListenerLp();
7233        }
7234    }
7235
7236    void updateUiMode() {
7237        if (mUiModeManager == null) {
7238            mUiModeManager = IUiModeManager.Stub.asInterface(
7239                    ServiceManager.getService(Context.UI_MODE_SERVICE));
7240        }
7241        try {
7242            mUiMode = mUiModeManager.getCurrentModeType();
7243        } catch (RemoteException e) {
7244        }
7245    }
7246
7247    void updateRotation(boolean alwaysSendConfiguration) {
7248        try {
7249            //set orientation on WindowManager
7250            mWindowManager.updateRotation(alwaysSendConfiguration, false);
7251        } catch (RemoteException e) {
7252            // Ignore
7253        }
7254    }
7255
7256    void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
7257        try {
7258            //set orientation on WindowManager
7259            mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
7260        } catch (RemoteException e) {
7261            // Ignore
7262        }
7263    }
7264
7265    /**
7266     * Return an Intent to launch the currently active dock app as home.  Returns
7267     * null if the standard home should be launched, which is the case if any of the following is
7268     * true:
7269     * <ul>
7270     *  <li>The device is not in either car mode or desk mode
7271     *  <li>The device is in car mode but mEnableCarDockHomeCapture is false
7272     *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
7273     *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
7274     *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
7275     * </ul>
7276     * @return A dock intent.
7277     */
7278    Intent createHomeDockIntent() {
7279        Intent intent = null;
7280
7281        // What home does is based on the mode, not the dock state.  That
7282        // is, when in car mode you should be taken to car home regardless
7283        // of whether we are actually in a car dock.
7284        if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
7285            if (mEnableCarDockHomeCapture) {
7286                intent = mCarDockIntent;
7287            }
7288        } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
7289            if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
7290                intent = mDeskDockIntent;
7291            }
7292        } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
7293                && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7294                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
7295                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
7296            // Always launch dock home from home when watch is docked, if it exists.
7297            intent = mDeskDockIntent;
7298        }
7299
7300        if (intent == null) {
7301            return null;
7302        }
7303
7304        ActivityInfo ai = null;
7305        ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
7306                intent,
7307                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
7308                mCurrentUserId);
7309        if (info != null) {
7310            ai = info.activityInfo;
7311        }
7312        if (ai != null
7313                && ai.metaData != null
7314                && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
7315            intent = new Intent(intent);
7316            intent.setClassName(ai.packageName, ai.name);
7317            return intent;
7318        }
7319
7320        return null;
7321    }
7322
7323    void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
7324        if (awakenFromDreams) {
7325            awakenDreams();
7326        }
7327
7328        Intent dock = createHomeDockIntent();
7329        if (dock != null) {
7330            try {
7331                if (fromHomeKey) {
7332                    dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7333                }
7334                startActivityAsUser(dock, UserHandle.CURRENT);
7335                return;
7336            } catch (ActivityNotFoundException e) {
7337            }
7338        }
7339
7340        Intent intent;
7341
7342        if (fromHomeKey) {
7343            intent = new Intent(mHomeIntent);
7344            intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7345        } else {
7346            intent = mHomeIntent;
7347        }
7348
7349        startActivityAsUser(intent, UserHandle.CURRENT);
7350    }
7351
7352    /**
7353     * goes to the home screen
7354     * @return whether it did anything
7355     */
7356    boolean goHome() {
7357        if (!isUserSetupComplete()) {
7358            Slog.i(TAG, "Not going home because user setup is in progress.");
7359            return false;
7360        }
7361        if (false) {
7362            // This code always brings home to the front.
7363            try {
7364                ActivityManager.getService().stopAppSwitches();
7365            } catch (RemoteException e) {
7366            }
7367            sendCloseSystemWindows();
7368            startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
7369        } else {
7370            // This code brings home to the front or, if it is already
7371            // at the front, puts the device to sleep.
7372            try {
7373                if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
7374                    /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
7375                    Log.d(TAG, "UTS-TEST-MODE");
7376                } else {
7377                    ActivityManager.getService().stopAppSwitches();
7378                    sendCloseSystemWindows();
7379                    Intent dock = createHomeDockIntent();
7380                    if (dock != null) {
7381                        int result = ActivityManager.getService()
7382                                .startActivityAsUser(null, null, dock,
7383                                        dock.resolveTypeIfNeeded(mContext.getContentResolver()),
7384                                        null, null, 0,
7385                                        ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7386                                        null, null, UserHandle.USER_CURRENT);
7387                        if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7388                            return false;
7389                        }
7390                    }
7391                }
7392                int result = ActivityManager.getService()
7393                        .startActivityAsUser(null, null, mHomeIntent,
7394                                mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
7395                                null, null, 0,
7396                                ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7397                                null, null, UserHandle.USER_CURRENT);
7398                if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7399                    return false;
7400                }
7401            } catch (RemoteException ex) {
7402                // bummer, the activity manager, which is in this process, is dead
7403            }
7404        }
7405        return true;
7406    }
7407
7408    @Override
7409    public void setCurrentOrientationLw(int newOrientation) {
7410        synchronized (mLock) {
7411            if (newOrientation != mCurrentAppOrientation) {
7412                mCurrentAppOrientation = newOrientation;
7413                updateOrientationListenerLp();
7414            }
7415        }
7416    }
7417
7418    private void performAuditoryFeedbackForAccessibilityIfNeed() {
7419        if (!isGlobalAccessibilityGestureEnabled()) {
7420            return;
7421        }
7422        AudioManager audioManager = (AudioManager) mContext.getSystemService(
7423                Context.AUDIO_SERVICE);
7424        if (audioManager.isSilentMode()) {
7425            return;
7426        }
7427        Ringtone ringTone = RingtoneManager.getRingtone(mContext,
7428                Settings.System.DEFAULT_NOTIFICATION_URI);
7429        ringTone.setStreamType(AudioManager.STREAM_MUSIC);
7430        ringTone.play();
7431    }
7432
7433    private boolean isTheaterModeEnabled() {
7434        return Settings.Global.getInt(mContext.getContentResolver(),
7435                Settings.Global.THEATER_MODE_ON, 0) == 1;
7436    }
7437
7438    private boolean isGlobalAccessibilityGestureEnabled() {
7439        return Settings.Global.getInt(mContext.getContentResolver(),
7440                Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1;
7441    }
7442
7443    private boolean areSystemNavigationKeysEnabled() {
7444        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
7445                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
7446    }
7447
7448    @Override
7449    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
7450        if (!mVibrator.hasVibrator()) {
7451            return false;
7452        }
7453        final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
7454                Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
7455        if (hapticsDisabled && !always) {
7456            return false;
7457        }
7458        long[] pattern = null;
7459        switch (effectId) {
7460            case HapticFeedbackConstants.LONG_PRESS:
7461                pattern = mLongPressVibePattern;
7462                break;
7463            case HapticFeedbackConstants.VIRTUAL_KEY:
7464                pattern = mVirtualKeyVibePattern;
7465                break;
7466            case HapticFeedbackConstants.KEYBOARD_TAP:
7467                pattern = mKeyboardTapVibePattern;
7468                break;
7469            case HapticFeedbackConstants.CLOCK_TICK:
7470                pattern = mClockTickVibePattern;
7471                break;
7472            case HapticFeedbackConstants.CALENDAR_DATE:
7473                pattern = mCalendarDateVibePattern;
7474                break;
7475            case HapticFeedbackConstants.SAFE_MODE_DISABLED:
7476                pattern = mSafeModeDisabledVibePattern;
7477                break;
7478            case HapticFeedbackConstants.SAFE_MODE_ENABLED:
7479                pattern = mSafeModeEnabledVibePattern;
7480                break;
7481            case HapticFeedbackConstants.CONTEXT_CLICK:
7482                pattern = mContextClickVibePattern;
7483                break;
7484            default:
7485                return false;
7486        }
7487        int owningUid;
7488        String owningPackage;
7489        if (win != null) {
7490            owningUid = win.getOwningUid();
7491            owningPackage = win.getOwningPackage();
7492        } else {
7493            owningUid = android.os.Process.myUid();
7494            owningPackage = mContext.getOpPackageName();
7495        }
7496        if (pattern.length == 1) {
7497            // One-shot vibration
7498            mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES);
7499        } else {
7500            // Pattern vibration
7501            mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES);
7502        }
7503        return true;
7504    }
7505
7506    @Override
7507    public void keepScreenOnStartedLw() {
7508    }
7509
7510    @Override
7511    public void keepScreenOnStoppedLw() {
7512        if (isKeyguardShowingAndNotOccluded()) {
7513            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
7514        }
7515    }
7516
7517    private int updateSystemUiVisibilityLw() {
7518        // If there is no window focused, there will be nobody to handle the events
7519        // anyway, so just hang on in whatever state we're in until things settle down.
7520        WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
7521                : mTopFullscreenOpaqueWindowState;
7522        if (winCandidate == null) {
7523            return 0;
7524        }
7525        if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
7526            // The immersive mode confirmation should never affect the system bar visibility,
7527            // otherwise it will unhide the navigation bar and hide itself.
7528            winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState;
7529            if (winCandidate == null) {
7530                return 0;
7531            }
7532        }
7533        final WindowState win = winCandidate;
7534        if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mKeyguardOccluded) {
7535            // We are updating at a point where the keyguard has gotten
7536            // focus, but we were last in a state where the top window is
7537            // hiding it.  This is probably because the keyguard as been
7538            // shown while the top window was displayed, so we want to ignore
7539            // it here because this is just a very transient change and it
7540            // will quickly lose focus once it correctly gets hidden.
7541            return 0;
7542        }
7543
7544        int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
7545                & ~mResettingSystemUiFlags
7546                & ~mForceClearedSystemUiFlags;
7547        if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
7548            tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
7549        }
7550
7551        final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
7552                mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
7553        final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
7554                mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
7555        mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);
7556        mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);
7557        final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
7558        final int diff = visibility ^ mLastSystemUiFlags;
7559        final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
7560        final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
7561        final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
7562        if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
7563                && mFocusedApp == win.getAppToken()
7564                && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
7565                && mLastDockedStackBounds.equals(mDockedStackBounds)) {
7566            return 0;
7567        }
7568        mLastSystemUiFlags = visibility;
7569        mLastFullscreenStackSysUiFlags = fullscreenVisibility;
7570        mLastDockedStackSysUiFlags = dockedVisibility;
7571        mLastFocusNeedsMenu = needsMenu;
7572        mFocusedApp = win.getAppToken();
7573        final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
7574        final Rect dockedStackBounds = new Rect(mDockedStackBounds);
7575        mHandler.post(new Runnable() {
7576                @Override
7577                public void run() {
7578                    StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
7579                    if (statusbar != null) {
7580                        statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
7581                                dockedVisibility, 0xffffffff, fullscreenStackBounds,
7582                                dockedStackBounds, win.toString());
7583                        statusbar.topAppWindowChanged(needsMenu);
7584                    }
7585                }
7586            });
7587        return diff;
7588    }
7589
7590    private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
7591        WindowState statusColorWin = isStatusBarKeyguard() && !mKeyguardOccluded
7592                ? mStatusBar
7593                : opaqueOrDimming;
7594
7595        if (statusColorWin != null) {
7596            if (statusColorWin == opaque) {
7597                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7598                // its light flag.
7599                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7600                vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
7601                        & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7602            } else if (statusColorWin != null && statusColorWin.isDimming()) {
7603                // Otherwise if it's dimming, clear the light flag.
7604                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7605            }
7606        }
7607        return vis;
7608    }
7609
7610    private int updateLightNavigationBarLw(int vis, WindowState opaque,
7611            WindowState opaqueOrDimming) {
7612        final WindowState imeWin = mWindowManagerFuncs.getInputMethodWindowLw();
7613
7614        final WindowState navColorWin;
7615        if (imeWin != null && imeWin.isVisibleLw()) {
7616            navColorWin = imeWin;
7617        } else {
7618            navColorWin = opaqueOrDimming;
7619        }
7620
7621        if (navColorWin != null) {
7622            if (navColorWin == opaque) {
7623                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7624                // its light flag.
7625                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7626                vis |= PolicyControl.getSystemUiVisibility(navColorWin, null)
7627                        & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7628            } else if (navColorWin.isDimming() || navColorWin == imeWin) {
7629                // Otherwise if it's dimming or it's the IME window, clear the light flag.
7630                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
7631            }
7632        }
7633        return vis;
7634    }
7635
7636    private boolean drawsSystemBarBackground(WindowState win) {
7637        return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
7638    }
7639
7640    private boolean forcesDrawStatusBarBackground(WindowState win) {
7641        return win == null || (win.getAttrs().privateFlags
7642                & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
7643    }
7644
7645    private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
7646        final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
7647        final boolean freeformStackVisible =
7648                mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
7649        final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
7650
7651        // We need to force system bars when the docked stack is visible, when the freeform stack
7652        // is visible but also when we are resizing for the transitions when docked stack
7653        // visibility changes.
7654        mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
7655        final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
7656
7657        // apply translucent bar vis flags
7658        WindowState fullscreenTransWin = isStatusBarKeyguard() && !mKeyguardOccluded
7659                ? mStatusBar
7660                : mTopFullscreenOpaqueWindowState;
7661        vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7662        vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7663        final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
7664                mTopDockedOpaqueWindowState, 0, 0);
7665
7666        final boolean fullscreenDrawsStatusBarBackground =
7667                (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
7668                        && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
7669                || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
7670        final boolean dockedDrawsStatusBarBackground =
7671                (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
7672                        && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
7673                || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
7674
7675        // prevent status bar interaction from clearing certain flags
7676        int type = win.getAttrs().type;
7677        boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
7678        if (statusBarHasFocus && !isStatusBarKeyguard()) {
7679            int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
7680                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
7681                    | View.SYSTEM_UI_FLAG_IMMERSIVE
7682                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
7683                    | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7684            if (mKeyguardOccluded) {
7685                flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
7686            }
7687            vis = (vis & ~flags) | (oldVis & flags);
7688        }
7689
7690        if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
7691            vis |= View.STATUS_BAR_TRANSPARENT;
7692            vis &= ~View.STATUS_BAR_TRANSLUCENT;
7693        } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
7694                || forceOpaqueStatusBar) {
7695            vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
7696        }
7697
7698        vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
7699
7700        // update status bar
7701        boolean immersiveSticky =
7702                (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7703        final boolean hideStatusBarWM =
7704                mTopFullscreenOpaqueWindowState != null
7705                && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
7706                        & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
7707        final boolean hideStatusBarSysui =
7708                (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
7709        final boolean hideNavBarSysui =
7710                (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
7711
7712        final boolean transientStatusBarAllowed = mStatusBar != null
7713                && (statusBarHasFocus || (!mForceShowSystemBars
7714                        && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
7715
7716        final boolean transientNavBarAllowed = mNavigationBar != null
7717                && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
7718
7719        final long now = SystemClock.uptimeMillis();
7720        final boolean pendingPanic = mPendingPanicGestureUptime != 0
7721                && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
7722        if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
7723            // The user performed the panic gesture recently, we're about to hide the bars,
7724            // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
7725            mPendingPanicGestureUptime = 0;
7726            mStatusBarController.showTransient();
7727            if (!isNavBarEmpty(vis)) {
7728                mNavigationBarController.showTransient();
7729            }
7730        }
7731
7732        final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
7733                && !transientStatusBarAllowed && hideStatusBarSysui;
7734        final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
7735                && !transientNavBarAllowed;
7736        if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
7737            // clear the clearable flags instead
7738            clearClearableFlagsLw();
7739            vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
7740        }
7741
7742        final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
7743        immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7744        final boolean navAllowedHidden = immersive || immersiveSticky;
7745
7746        if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType())
7747                > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) {
7748            // We can't hide the navbar from this window otherwise the input consumer would not get
7749            // the input events.
7750            vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
7751        }
7752
7753        vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
7754
7755        // update navigation bar
7756        boolean oldImmersiveMode = isImmersiveMode(oldVis);
7757        boolean newImmersiveMode = isImmersiveMode(vis);
7758        if (win != null && oldImmersiveMode != newImmersiveMode) {
7759            final String pkg = win.getOwningPackage();
7760            mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
7761                    isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility()));
7762        }
7763
7764        vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
7765
7766        vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState,
7767                mTopFullscreenOpaqueOrDimmingWindowState);
7768
7769        return vis;
7770    }
7771
7772    /**
7773     * @return the current visibility flags with the nav-bar opacity related flags toggled based
7774     *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
7775     */
7776    private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
7777            boolean freeformStackVisible, boolean isDockedDividerResizing) {
7778        if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
7779            if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
7780                visibility = setNavBarOpaqueFlag(visibility);
7781            }
7782        } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
7783            if (isDockedDividerResizing) {
7784                visibility = setNavBarOpaqueFlag(visibility);
7785            } else if (freeformStackVisible) {
7786                visibility = setNavBarTranslucentFlag(visibility);
7787            } else {
7788                visibility = setNavBarOpaqueFlag(visibility);
7789            }
7790        }
7791
7792        if (!areTranslucentBarsAllowed()) {
7793            visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
7794        }
7795        return visibility;
7796    }
7797
7798    private int setNavBarOpaqueFlag(int visibility) {
7799        return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
7800    }
7801
7802    private int setNavBarTranslucentFlag(int visibility) {
7803        visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
7804        return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
7805    }
7806
7807    private void clearClearableFlagsLw() {
7808        int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
7809        if (newVal != mResettingSystemUiFlags) {
7810            mResettingSystemUiFlags = newVal;
7811            mWindowManagerFuncs.reevaluateStatusBarVisibility();
7812        }
7813    }
7814
7815    private boolean isImmersiveMode(int vis) {
7816        final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
7817        return mNavigationBar != null
7818                && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
7819                && (vis & flags) != 0
7820                && canHideNavigationBar();
7821    }
7822
7823    private static boolean isNavBarEmpty(int systemUiFlags) {
7824        final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
7825                | View.STATUS_BAR_DISABLE_BACK
7826                | View.STATUS_BAR_DISABLE_RECENT);
7827
7828        return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
7829    }
7830
7831    /**
7832     * @return whether the navigation or status bar can be made translucent
7833     *
7834     * This should return true unless touch exploration is not enabled or
7835     * R.boolean.config_enableTranslucentDecor is false.
7836     */
7837    private boolean areTranslucentBarsAllowed() {
7838        return mTranslucentDecorEnabled;
7839    }
7840
7841    // Use this instead of checking config_showNavigationBar so that it can be consistently
7842    // overridden by qemu.hw.mainkeys in the emulator.
7843    @Override
7844    public boolean hasNavigationBar() {
7845        return mHasNavigationBar;
7846    }
7847
7848    @Override
7849    public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
7850        mLastInputMethodWindow = ime;
7851        mLastInputMethodTargetWindow = target;
7852    }
7853
7854    @Override
7855    public int getInputMethodWindowVisibleHeightLw() {
7856        return mDockBottom - mCurBottom;
7857    }
7858
7859    @Override
7860    public void setCurrentUserLw(int newUserId) {
7861        mCurrentUserId = newUserId;
7862        if (mKeyguardDelegate != null) {
7863            mKeyguardDelegate.setCurrentUser(newUserId);
7864        }
7865        StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
7866        if (statusBar != null) {
7867            statusBar.setCurrentUser(newUserId);
7868        }
7869        setLastInputMethodWindowLw(null, null);
7870    }
7871
7872    @Override
7873    public void setSwitchingUser(boolean switching) {
7874        mKeyguardDelegate.setSwitchingUser(switching);
7875    }
7876
7877    @Override
7878    public boolean canMagnifyWindow(int windowType) {
7879        switch (windowType) {
7880            case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
7881            case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
7882            case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
7883            case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
7884                return false;
7885            }
7886        }
7887        return true;
7888    }
7889
7890    @Override
7891    public boolean isTopLevelWindow(int windowType) {
7892        if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
7893                && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
7894            return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
7895        }
7896        return true;
7897    }
7898
7899    @Override
7900    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
7901        // For the upside down rotation we don't rotate seamlessly as the navigation
7902        // bar moves position.
7903        // Note most apps (using orientation:sensor or user as opposed to fullSensor)
7904        // will not enter the reverse portrait orientation, so actually the
7905        // orientation won't change at all.
7906        if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
7907            return false;
7908        }
7909        // If the navigation bar can't change sides, then it will
7910        // jump when we change orientations and we don't rotate
7911        // seamlessly.
7912        if (!mNavigationBarCanMove) {
7913            return false;
7914        }
7915        int delta = newRotation - oldRotation;
7916        if (delta < 0) delta += 4;
7917        // Likewise we don't rotate seamlessly for 180 degree rotations
7918        // in this case the surfaces never resize, and our logic to
7919        // revert the transformations on size change will fail. We could
7920        // fix this in the future with the "tagged" frames idea.
7921        if (delta == Surface.ROTATION_180) {
7922            return false;
7923        }
7924
7925        final WindowState w = mTopFullscreenOpaqueWindowState;
7926        if (w != mFocusedWindow) {
7927            return false;
7928        }
7929
7930        // We only enable seamless rotation if the top window has requested
7931        // it and is in the fullscreen opaque state. Seamless rotation
7932        // requires freezing various Surface states and won't work well
7933        // with animations, so we disable it in the animation case for now.
7934        if (w != null && !w.isAnimatingLw() &&
7935                ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) ||
7936                        (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) {
7937            return true;
7938        }
7939        return false;
7940    }
7941
7942    @Override
7943    public void dump(String prefix, PrintWriter pw, String[] args) {
7944        pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
7945                pw.print(" mSystemReady="); pw.print(mSystemReady);
7946                pw.print(" mSystemBooted="); pw.println(mSystemBooted);
7947        pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
7948                pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
7949                pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
7950                pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
7951        if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
7952                || mForceClearedSystemUiFlags != 0) {
7953            pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
7954                    pw.print(Integer.toHexString(mLastSystemUiFlags));
7955                    pw.print(" mResettingSystemUiFlags=0x");
7956                    pw.print(Integer.toHexString(mResettingSystemUiFlags));
7957                    pw.print(" mForceClearedSystemUiFlags=0x");
7958                    pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
7959        }
7960        if (mLastFocusNeedsMenu) {
7961            pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
7962                    pw.println(mLastFocusNeedsMenu);
7963        }
7964        pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
7965                pw.println(mWakeGestureEnabledSetting);
7966
7967        pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
7968        pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
7969                pw.print(" mDockMode="); pw.print(mDockMode);
7970                pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
7971                pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
7972                pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
7973        pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
7974                pw.print(" mUserRotation="); pw.print(mUserRotation);
7975                pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
7976        pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
7977        pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
7978                pw.print(mCarDockEnablesAccelerometer);
7979                pw.print(" mDeskDockEnablesAccelerometer=");
7980                pw.println(mDeskDockEnablesAccelerometer);
7981        pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
7982                pw.print(mLidKeyboardAccessibility);
7983                pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
7984                pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
7985                pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
7986        pw.print(prefix);
7987                pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
7988        pw.print(prefix);
7989                pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
7990                pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
7991        pw.print(prefix);
7992                pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
7993                pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
7994        pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
7995        pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
7996        pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
7997                pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
7998        pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
7999                pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
8000        pw.print(prefix); pw.print("mOrientationSensorEnabled=");
8001                pw.println(mOrientationSensorEnabled);
8002        pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
8003                pw.print(","); pw.print(mOverscanScreenTop);
8004                pw.print(") "); pw.print(mOverscanScreenWidth);
8005                pw.print("x"); pw.println(mOverscanScreenHeight);
8006        if (mOverscanLeft != 0 || mOverscanTop != 0
8007                || mOverscanRight != 0 || mOverscanBottom != 0) {
8008            pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
8009                    pw.print(" top="); pw.print(mOverscanTop);
8010                    pw.print(" right="); pw.print(mOverscanRight);
8011                    pw.print(" bottom="); pw.println(mOverscanBottom);
8012        }
8013        pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
8014                pw.print(mRestrictedOverscanScreenLeft);
8015                pw.print(","); pw.print(mRestrictedOverscanScreenTop);
8016                pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
8017                pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
8018        pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
8019                pw.print(","); pw.print(mUnrestrictedScreenTop);
8020                pw.print(") "); pw.print(mUnrestrictedScreenWidth);
8021                pw.print("x"); pw.println(mUnrestrictedScreenHeight);
8022        pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
8023                pw.print(","); pw.print(mRestrictedScreenTop);
8024                pw.print(") "); pw.print(mRestrictedScreenWidth);
8025                pw.print("x"); pw.println(mRestrictedScreenHeight);
8026        pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
8027                pw.print(","); pw.print(mStableFullscreenTop);
8028                pw.print(")-("); pw.print(mStableFullscreenRight);
8029                pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
8030        pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
8031                pw.print(","); pw.print(mStableTop);
8032                pw.print(")-("); pw.print(mStableRight);
8033                pw.print(","); pw.print(mStableBottom); pw.println(")");
8034        pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
8035                pw.print(","); pw.print(mSystemTop);
8036                pw.print(")-("); pw.print(mSystemRight);
8037                pw.print(","); pw.print(mSystemBottom); pw.println(")");
8038        pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
8039                pw.print(","); pw.print(mCurTop);
8040                pw.print(")-("); pw.print(mCurRight);
8041                pw.print(","); pw.print(mCurBottom); pw.println(")");
8042        pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
8043                pw.print(","); pw.print(mContentTop);
8044                pw.print(")-("); pw.print(mContentRight);
8045                pw.print(","); pw.print(mContentBottom); pw.println(")");
8046        pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft);
8047                pw.print(","); pw.print(mVoiceContentTop);
8048                pw.print(")-("); pw.print(mVoiceContentRight);
8049                pw.print(","); pw.print(mVoiceContentBottom); pw.println(")");
8050        pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
8051                pw.print(","); pw.print(mDockTop);
8052                pw.print(")-("); pw.print(mDockRight);
8053                pw.print(","); pw.print(mDockBottom); pw.println(")");
8054        pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
8055                pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
8056        pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
8057                pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
8058                pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
8059        if (mLastInputMethodWindow != null) {
8060            pw.print(prefix); pw.print("mLastInputMethodWindow=");
8061                    pw.println(mLastInputMethodWindow);
8062        }
8063        if (mLastInputMethodTargetWindow != null) {
8064            pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
8065                    pw.println(mLastInputMethodTargetWindow);
8066        }
8067        if (mStatusBar != null) {
8068            pw.print(prefix); pw.print("mStatusBar=");
8069                    pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
8070                    pw.println(isStatusBarKeyguard());
8071        }
8072        if (mNavigationBar != null) {
8073            pw.print(prefix); pw.print("mNavigationBar=");
8074                    pw.println(mNavigationBar);
8075        }
8076        if (mFocusedWindow != null) {
8077            pw.print(prefix); pw.print("mFocusedWindow=");
8078                    pw.println(mFocusedWindow);
8079        }
8080        if (mFocusedApp != null) {
8081            pw.print(prefix); pw.print("mFocusedApp=");
8082                    pw.println(mFocusedApp);
8083        }
8084        if (mTopFullscreenOpaqueWindowState != null) {
8085            pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
8086                    pw.println(mTopFullscreenOpaqueWindowState);
8087        }
8088        if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
8089            pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
8090                    pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
8091        }
8092        if (mForcingShowNavBar) {
8093            pw.print(prefix); pw.print("mForcingShowNavBar=");
8094                    pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
8095                    pw.println(mForcingShowNavBarLayer);
8096        }
8097        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
8098                pw.print(" mKeyguardOccluded="); pw.println(mKeyguardOccluded);
8099                pw.print(" mKeyguardOccludedChanged="); pw.println(mKeyguardOccludedChanged);
8100                pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded);
8101        pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
8102                pw.print(" mForceStatusBarFromKeyguard=");
8103                pw.println(mForceStatusBarFromKeyguard);
8104        pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
8105        pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
8106                pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
8107                pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
8108        pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
8109                pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
8110                pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior);
8111                pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
8112        pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
8113                pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
8114        pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
8115                pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
8116        pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
8117                pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
8118        pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
8119
8120        mGlobalKeyManager.dump(prefix, pw);
8121        mStatusBarController.dump(pw, prefix);
8122        mNavigationBarController.dump(pw, prefix);
8123        PolicyControl.dump(prefix, pw);
8124
8125        if (mWakeGestureListener != null) {
8126            mWakeGestureListener.dump(pw, prefix);
8127        }
8128        if (mOrientationListener != null) {
8129            mOrientationListener.dump(pw, prefix);
8130        }
8131        if (mBurnInProtectionHelper != null) {
8132            mBurnInProtectionHelper.dump(prefix, pw);
8133        }
8134        if (mKeyguardDelegate != null) {
8135            mKeyguardDelegate.dump(prefix, pw);
8136        }
8137    }
8138}
8139