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