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