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