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