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