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