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