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