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