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