PhoneWindowManager.java revision fc46e9b643881b7b2ab76854f3a0ac077e9def8d
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.policy;
18
19import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
20import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
21import static android.app.ActivityManager.StackId.HOME_STACK_ID;
22import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
23import static android.content.pm.PackageManager.FEATURE_TELEVISION;
24import static android.content.pm.PackageManager.FEATURE_WATCH;
25import static android.content.res.Configuration.EMPTY;
26import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
27import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
28import static android.view.WindowManager.DOCKED_LEFT;
29import static android.view.WindowManager.DOCKED_RIGHT;
30import static android.view.WindowManager.DOCKED_TOP;
31import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
32import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
33import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
34import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
35import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
36import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
37import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
38import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
39import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR;
40import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
41import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN;
42import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
43import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
44import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
45import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
46import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
47import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
48import static android.view.WindowManager.LayoutParams.LAST_SYSTEM_WINDOW;
49import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
50import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
51import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
52import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
53import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
54import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
55import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
56import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
57import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
58import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
59import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
60import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
61import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
62import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
63import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL;
64import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
65import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
66import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
67import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
68import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
69import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
70import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
71import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
72import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
73import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
74import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
75import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
76import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
77import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
78import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
79import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
80import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
81import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
82import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
83import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
84import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
85import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
86import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
87import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
88import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
89import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR;
90import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
91import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
92import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
93import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
94import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
95import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
96import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
97import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
98import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
99import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
100import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING;
101import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
102import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
103import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
104import static android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION;
105import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
106import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
107import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
108import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
109import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
110import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
111
112import android.annotation.Nullable;
113import android.app.ActivityManager;
114import android.app.ActivityManager.StackId;
115import android.app.ActivityManagerInternal;
116import android.app.ActivityManagerInternal.SleepToken;
117import android.app.ActivityManagerNative;
118import android.app.AppOpsManager;
119import android.app.IUiModeManager;
120import android.app.ProgressDialog;
121import android.app.SearchManager;
122import android.app.StatusBarManager;
123import android.app.UiModeManager;
124import android.content.ActivityNotFoundException;
125import android.content.BroadcastReceiver;
126import android.content.ComponentName;
127import android.content.ContentResolver;
128import android.content.Context;
129import android.content.Intent;
130import android.content.IntentFilter;
131import android.content.ServiceConnection;
132import android.content.pm.ActivityInfo;
133import android.content.pm.ApplicationInfo;
134import android.content.pm.PackageManager;
135import android.content.pm.ResolveInfo;
136import android.content.res.CompatibilityInfo;
137import android.content.res.Configuration;
138import android.content.res.Resources;
139import android.content.res.TypedArray;
140import android.database.ContentObserver;
141import android.graphics.PixelFormat;
142import android.graphics.Rect;
143import android.hardware.hdmi.HdmiControlManager;
144import android.hardware.hdmi.HdmiPlaybackClient;
145import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback;
146import android.hardware.input.InputManagerInternal;
147import android.hardware.power.V1_0.PowerHint;
148import android.media.AudioAttributes;
149import android.media.AudioManager;
150import android.media.AudioSystem;
151import android.media.IAudioService;
152import android.media.Ringtone;
153import android.media.RingtoneManager;
154import android.media.session.MediaSessionLegacyHelper;
155import android.os.Binder;
156import android.os.Build;
157import android.os.Bundle;
158import android.os.Debug;
159import android.os.FactoryTest;
160import android.os.Handler;
161import android.os.IBinder;
162import android.os.IDeviceIdleController;
163import android.os.Looper;
164import android.os.Message;
165import android.os.Messenger;
166import android.os.PowerManager;
167import android.os.PowerManagerInternal;
168import android.os.Process;
169import android.os.RemoteException;
170import android.os.ServiceManager;
171import android.os.SystemClock;
172import android.os.SystemProperties;
173import android.os.UEventObserver;
174import android.os.UserHandle;
175import android.os.Vibrator;
176import android.provider.MediaStore;
177import android.provider.Settings;
178import android.service.dreams.DreamManagerInternal;
179import android.service.dreams.DreamService;
180import android.service.dreams.IDreamManager;
181import android.speech.RecognizerIntent;
182import android.telecom.TelecomManager;
183import android.util.DisplayMetrics;
184import android.util.EventLog;
185import android.util.Log;
186import android.util.LongSparseArray;
187import android.util.MutableBoolean;
188import android.util.Slog;
189import android.util.SparseArray;
190import android.view.Display;
191import android.view.Gravity;
192import android.view.HapticFeedbackConstants;
193import android.view.IApplicationToken;
194import android.view.IWindowManager;
195import android.view.InputChannel;
196import android.view.InputDevice;
197import android.view.InputEvent;
198import android.view.InputEventReceiver;
199import android.view.KeyCharacterMap;
200import android.view.KeyCharacterMap.FallbackAction;
201import android.view.KeyEvent;
202import android.view.MotionEvent;
203import android.view.Surface;
204import android.view.View;
205import android.view.ViewConfiguration;
206import android.view.WindowManager;
207import android.view.WindowManager.LayoutParams;
208import android.view.WindowManagerGlobal;
209import android.view.WindowManagerInternal;
210import android.view.WindowManagerInternal.AppTransitionListener;
211import android.view.WindowManagerPolicy;
212import android.view.accessibility.AccessibilityEvent;
213import android.view.accessibility.AccessibilityManager;
214import android.view.animation.Animation;
215import android.view.animation.AnimationSet;
216import android.view.animation.AnimationUtils;
217
218import com.android.internal.R;
219import com.android.internal.logging.MetricsLogger;
220import com.android.internal.policy.IShortcutService;
221import com.android.internal.policy.PhoneWindow;
222import com.android.internal.statusbar.IStatusBarService;
223import com.android.internal.util.ScreenShapeHelper;
224import com.android.internal.widget.PointerLocationView;
225import com.android.server.GestureLauncherService;
226import com.android.server.LocalServices;
227import com.android.server.policy.keyguard.KeyguardServiceDelegate;
228import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener;
229import com.android.server.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,
2681            int uiMode) {
2682        if (mHasNavigationBar) {
2683            // For a basic navigation bar, when we are in landscape mode we place
2684            // the navigation bar to the side.
2685            if (mNavigationBarCanMove && fullWidth > fullHeight) {
2686                return fullWidth - getNavigationBarWidth(rotation, uiMode);
2687            }
2688        }
2689        return fullWidth;
2690    }
2691
2692    private int getNavigationBarHeight(int rotation, int uiMode) {
2693        if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
2694            return mNavigationBarHeightForRotationInCarMode[rotation];
2695        } else {
2696            return mNavigationBarHeightForRotationDefault[rotation];
2697        }
2698    }
2699
2700    @Override
2701    public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation,
2702            int uiMode) {
2703        if (mHasNavigationBar) {
2704            // For a basic navigation bar, when we are in portrait mode we place
2705            // the navigation bar to the bottom.
2706            if (!mNavigationBarCanMove || fullWidth < fullHeight) {
2707                return fullHeight - getNavigationBarHeight(rotation, uiMode);
2708            }
2709        }
2710        return fullHeight;
2711    }
2712
2713    @Override
2714    public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode) {
2715        return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode);
2716    }
2717
2718    @Override
2719    public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode) {
2720        // There is a separate status bar at the top of the display.  We don't count that as part
2721        // of the fixed decor, since it can hide; however, for purposes of configurations,
2722        // we do want to exclude it since applications can't generally use that part
2723        // of the screen.
2724        return getNonDecorDisplayHeight(
2725                fullWidth, fullHeight, rotation, uiMode) - mStatusBarHeight;
2726    }
2727
2728    @Override
2729    public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) {
2730        return attrs.type == TYPE_STATUS_BAR;
2731    }
2732
2733    @Override
2734    public boolean canBeHiddenByKeyguardLw(WindowState win) {
2735        switch (win.getAttrs().type) {
2736            case TYPE_STATUS_BAR:
2737            case TYPE_NAVIGATION_BAR:
2738            case TYPE_WALLPAPER:
2739            case TYPE_DREAM:
2740                return false;
2741            default:
2742                // Hide only windows below the keyguard host window.
2743                return windowTypeToLayerLw(win.getBaseType())
2744                        < windowTypeToLayerLw(TYPE_STATUS_BAR);
2745        }
2746    }
2747
2748    private boolean shouldBeHiddenByKeyguard(WindowState win, WindowState imeTarget) {
2749
2750        // Keyguard visibility of window from activities are determined over activity visibility.
2751        if (win.getAppToken() != null) {
2752            return false;
2753        }
2754
2755        final LayoutParams attrs = win.getAttrs();
2756        final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleLw() &&
2757                ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0
2758                        || !canBeHiddenByKeyguardLw(imeTarget));
2759
2760        // Show IME over the keyguard if the target allows it
2761        boolean allowWhenLocked = (win.isInputMethodWindow() || imeTarget == this)
2762                && showImeOverKeyguard;;
2763
2764        if (isKeyguardLocked() && isKeyguardOccluded()) {
2765            // Show SHOW_WHEN_LOCKED windows if Keyguard is occluded.
2766            allowWhenLocked |= (attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
2767                    // Show error dialogs over apps that are shown on lockscreen
2768                    || (attrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
2769        }
2770
2771        boolean keyguardLocked = isKeyguardLocked();
2772        boolean hideDockDivider = attrs.type == TYPE_DOCK_DIVIDER
2773                && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
2774        return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == Display.DEFAULT_DISPLAY)
2775                || hideDockDivider;
2776    }
2777
2778    /** {@inheritDoc} */
2779    @Override
2780    public View addStartingWindow(IBinder appToken, String packageName, int theme,
2781            CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
2782            int icon, int logo, int windowFlags, Configuration overrideConfig) {
2783        if (!SHOW_STARTING_ANIMATIONS) {
2784            return null;
2785        }
2786        if (packageName == null) {
2787            return null;
2788        }
2789
2790        WindowManager wm = null;
2791        View view = null;
2792
2793        try {
2794            Context context = mContext;
2795            if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow " + packageName
2796                    + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
2797                    + Integer.toHexString(theme));
2798            if (theme != context.getThemeResId() || labelRes != 0) {
2799                try {
2800                    context = context.createPackageContext(packageName, 0);
2801                    context.setTheme(theme);
2802                } catch (PackageManager.NameNotFoundException e) {
2803                    // Ignore
2804                }
2805            }
2806
2807            if (overrideConfig != null && !overrideConfig.equals(EMPTY)) {
2808                if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: creating context based"
2809                        + " on overrideConfig" + overrideConfig + " for starting window");
2810                final Context overrideContext = context.createConfigurationContext(overrideConfig);
2811                overrideContext.setTheme(theme);
2812                final TypedArray typedArray = overrideContext.obtainStyledAttributes(
2813                        com.android.internal.R.styleable.Window);
2814                final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
2815                if (resId != 0 && overrideContext.getDrawable(resId) != null) {
2816                    // We want to use the windowBackground for the override context if it is
2817                    // available, otherwise we use the default one to make sure a themed starting
2818                    // window is displayed for the app.
2819                    if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: apply overrideConfig"
2820                            + overrideConfig + " to starting window resId=" + resId);
2821                    context = overrideContext;
2822                }
2823            }
2824
2825            final PhoneWindow win = new PhoneWindow(context);
2826            win.setIsStartingWindow(true);
2827
2828            CharSequence label = context.getResources().getText(labelRes, null);
2829            // Only change the accessibility title if the label is localized
2830            if (label != null) {
2831                win.setTitle(label, true);
2832            } else {
2833                win.setTitle(nonLocalizedLabel, false);
2834            }
2835
2836            win.setType(
2837                WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
2838
2839            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
2840                // Assumes it's safe to show starting windows of launched apps while
2841                // the keyguard is being hidden. This is okay because starting windows never show
2842                // secret information.
2843                if (mKeyguardOccluded) {
2844                    windowFlags |= FLAG_SHOW_WHEN_LOCKED;
2845                }
2846            }
2847
2848            // Force the window flags: this is a fake window, so it is not really
2849            // touchable or focusable by the user.  We also add in the ALT_FOCUSABLE_IM
2850            // flag because we do know that the next window will take input
2851            // focus, so we want to get the IME window up on top of us right away.
2852            win.setFlags(
2853                windowFlags|
2854                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2855                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2856                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
2857                windowFlags|
2858                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
2859                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
2860                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
2861
2862            win.setDefaultIcon(icon);
2863            win.setDefaultLogo(logo);
2864
2865            win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
2866                    WindowManager.LayoutParams.MATCH_PARENT);
2867
2868            final WindowManager.LayoutParams params = win.getAttributes();
2869            params.token = appToken;
2870            params.packageName = packageName;
2871            params.windowAnimations = win.getWindowStyle().getResourceId(
2872                    com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
2873            params.privateFlags |=
2874                    WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
2875            params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
2876
2877            if (!compatInfo.supportsScreen()) {
2878                params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
2879            }
2880
2881            params.setTitle("Starting " + packageName);
2882
2883            wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
2884            view = win.getDecorView();
2885
2886            if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Adding starting window for "
2887                + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null));
2888
2889            wm.addView(view, params);
2890
2891            // Only return the view if it was successfully added to the
2892            // window manager... which we can tell by it having a parent.
2893            return view.getParent() != null ? view : null;
2894        } catch (WindowManager.BadTokenException e) {
2895            // ignore
2896            Log.w(TAG, appToken + " already running, starting window not displayed. " +
2897                    e.getMessage());
2898        } catch (RuntimeException e) {
2899            // don't crash if something else bad happens, for example a
2900            // failure loading resources because we are loading from an app
2901            // on external storage that has been unmounted.
2902            Log.w(TAG, appToken + " failed creating starting window", e);
2903        } finally {
2904            if (view != null && view.getParent() == null) {
2905                Log.w(TAG, "view not successfully added to wm, removing view");
2906                wm.removeViewImmediate(view);
2907            }
2908        }
2909
2910        return null;
2911    }
2912
2913    /** {@inheritDoc} */
2914    @Override
2915    public void removeStartingWindow(IBinder appToken, View window) {
2916        if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Removing starting window for " + appToken + ": "
2917                + window + " Callers=" + Debug.getCallers(4));
2918
2919        if (window != null) {
2920            WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
2921            wm.removeView(window);
2922        }
2923    }
2924
2925    /**
2926     * Preflight adding a window to the system.
2927     *
2928     * Currently enforces that three window types are singletons:
2929     * <ul>
2930     * <li>STATUS_BAR_TYPE</li>
2931     * <li>KEYGUARD_TYPE</li>
2932     * </ul>
2933     *
2934     * @param win The window to be added
2935     * @param attrs Information about the window to be added
2936     *
2937     * @return If ok, WindowManagerImpl.ADD_OKAY.  If too many singletons,
2938     * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
2939     */
2940    @Override
2941    public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
2942        switch (attrs.type) {
2943            case TYPE_STATUS_BAR:
2944                mContext.enforceCallingOrSelfPermission(
2945                        android.Manifest.permission.STATUS_BAR_SERVICE,
2946                        "PhoneWindowManager");
2947                if (mStatusBar != null) {
2948                    if (mStatusBar.isAlive()) {
2949                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2950                    }
2951                }
2952                mStatusBar = win;
2953                mStatusBarController.setWindow(win);
2954                break;
2955            case TYPE_NAVIGATION_BAR:
2956                mContext.enforceCallingOrSelfPermission(
2957                        android.Manifest.permission.STATUS_BAR_SERVICE,
2958                        "PhoneWindowManager");
2959                if (mNavigationBar != null) {
2960                    if (mNavigationBar.isAlive()) {
2961                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
2962                    }
2963                }
2964                mNavigationBar = win;
2965                mNavigationBarController.setWindow(win);
2966                if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
2967                break;
2968            case TYPE_NAVIGATION_BAR_PANEL:
2969            case TYPE_STATUS_BAR_PANEL:
2970            case TYPE_STATUS_BAR_SUB_PANEL:
2971            case TYPE_VOICE_INTERACTION_STARTING:
2972                mContext.enforceCallingOrSelfPermission(
2973                        android.Manifest.permission.STATUS_BAR_SERVICE,
2974                        "PhoneWindowManager");
2975                break;
2976        }
2977        return WindowManagerGlobal.ADD_OKAY;
2978    }
2979
2980    /** {@inheritDoc} */
2981    @Override
2982    public void removeWindowLw(WindowState win) {
2983        if (mStatusBar == win) {
2984            mStatusBar = null;
2985            mStatusBarController.setWindow(null);
2986        } else if (mNavigationBar == win) {
2987            mNavigationBar = null;
2988            mNavigationBarController.setWindow(null);
2989        }
2990    }
2991
2992    static final boolean PRINT_ANIM = false;
2993
2994    /** {@inheritDoc} */
2995    @Override
2996    public int selectAnimationLw(WindowState win, int transit) {
2997        if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
2998              + ": transit=" + transit);
2999        if (win == mStatusBar) {
3000            boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
3001            if (transit == TRANSIT_EXIT
3002                    || transit == TRANSIT_HIDE) {
3003                return isKeyguard ? -1 : R.anim.dock_top_exit;
3004            } else if (transit == TRANSIT_ENTER
3005                    || transit == TRANSIT_SHOW) {
3006                return isKeyguard ? -1 : R.anim.dock_top_enter;
3007            }
3008        } else if (win == mNavigationBar) {
3009            if (win.getAttrs().windowAnimations != 0) {
3010                return 0;
3011            }
3012            // This can be on either the bottom or the right or the left.
3013            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
3014                if (transit == TRANSIT_EXIT
3015                        || transit == TRANSIT_HIDE) {
3016                    if (isKeyguardShowingAndNotOccluded()) {
3017                        return R.anim.dock_bottom_exit_keyguard;
3018                    } else {
3019                        return R.anim.dock_bottom_exit;
3020                    }
3021                } else if (transit == TRANSIT_ENTER
3022                        || transit == TRANSIT_SHOW) {
3023                    return R.anim.dock_bottom_enter;
3024                }
3025            } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
3026                if (transit == TRANSIT_EXIT
3027                        || transit == TRANSIT_HIDE) {
3028                    return R.anim.dock_right_exit;
3029                } else if (transit == TRANSIT_ENTER
3030                        || transit == TRANSIT_SHOW) {
3031                    return R.anim.dock_right_enter;
3032                }
3033            } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
3034                if (transit == TRANSIT_EXIT
3035                        || transit == TRANSIT_HIDE) {
3036                    return R.anim.dock_left_exit;
3037                } else if (transit == TRANSIT_ENTER
3038                        || transit == TRANSIT_SHOW) {
3039                    return R.anim.dock_left_enter;
3040                }
3041            }
3042        } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) {
3043            return selectDockedDividerAnimationLw(win, transit);
3044        }
3045
3046        if (transit == TRANSIT_PREVIEW_DONE) {
3047            if (win.hasAppShownWindows()) {
3048                if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
3049                return com.android.internal.R.anim.app_starting_exit;
3050            }
3051        } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
3052                && transit == TRANSIT_ENTER) {
3053            // Special case: we are animating in a dream, while the keyguard
3054            // is shown.  We don't want an animation on the dream, because
3055            // we need it shown immediately with the keyguard animating away
3056            // to reveal it.
3057            return -1;
3058        }
3059
3060        return 0;
3061    }
3062
3063    private int selectDockedDividerAnimationLw(WindowState win, int transit) {
3064        int insets = mWindowManagerFuncs.getDockedDividerInsetsLw();
3065
3066        // If the divider is behind the navigation bar, don't animate.
3067        final Rect frame = win.getFrameLw();
3068        final boolean behindNavBar = mNavigationBar != null
3069                && ((mNavigationBarPosition == NAV_BAR_BOTTOM
3070                        && frame.top + insets >= mNavigationBar.getFrameLw().top)
3071                || (mNavigationBarPosition == NAV_BAR_RIGHT
3072                        && frame.left + insets >= mNavigationBar.getFrameLw().left)
3073                || (mNavigationBarPosition == NAV_BAR_LEFT
3074                        && frame.right - insets <= mNavigationBar.getFrameLw().right));
3075        final boolean landscape = frame.height() > frame.width();
3076        final boolean offscreenLandscape = landscape && (frame.right - insets <= 0
3077                || frame.left + insets >= win.getDisplayFrameLw().right);
3078        final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0
3079                || frame.bottom + insets >= win.getDisplayFrameLw().bottom);
3080        final boolean offscreen = offscreenLandscape || offscreenPortrait;
3081        if (behindNavBar || offscreen) {
3082            return 0;
3083        }
3084        if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
3085            return R.anim.fade_in;
3086        } else if (transit == TRANSIT_EXIT) {
3087            return R.anim.fade_out;
3088        } else {
3089            return 0;
3090        }
3091    }
3092
3093    @Override
3094    public void selectRotationAnimationLw(int anim[]) {
3095        if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
3096                + mTopFullscreenOpaqueWindowState + " rotationAnimation="
3097                + (mTopFullscreenOpaqueWindowState == null ?
3098                        "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation));
3099        if (mTopFullscreenOpaqueWindowState != null) {
3100            int animationHint = mTopFullscreenOpaqueWindowState.getRotationAnimationHint();
3101            if (animationHint < 0 && mTopIsFullscreen) {
3102                animationHint = mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation;
3103            }
3104            switch (animationHint) {
3105                case ROTATION_ANIMATION_CROSSFADE:
3106                case ROTATION_ANIMATION_SEAMLESS: // Crossfade is fallback for seamless.
3107                    anim[0] = R.anim.rotation_animation_xfade_exit;
3108                    anim[1] = R.anim.rotation_animation_enter;
3109                    break;
3110                case ROTATION_ANIMATION_JUMPCUT:
3111                    anim[0] = R.anim.rotation_animation_jump_exit;
3112                    anim[1] = R.anim.rotation_animation_enter;
3113                    break;
3114                case ROTATION_ANIMATION_ROTATE:
3115                default:
3116                    anim[0] = anim[1] = 0;
3117                    break;
3118            }
3119        } else {
3120            anim[0] = anim[1] = 0;
3121        }
3122    }
3123
3124    @Override
3125    public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId,
3126            boolean forceDefault) {
3127        switch (exitAnimId) {
3128            case R.anim.rotation_animation_xfade_exit:
3129            case R.anim.rotation_animation_jump_exit:
3130                // These are the only cases that matter.
3131                if (forceDefault) {
3132                    return false;
3133                }
3134                int anim[] = new int[2];
3135                selectRotationAnimationLw(anim);
3136                return (exitAnimId == anim[0] && enterAnimId == anim[1]);
3137            default:
3138                return true;
3139        }
3140    }
3141
3142    @Override
3143    public Animation createHiddenByKeyguardExit(boolean onWallpaper,
3144            boolean goingToNotificationShade) {
3145        if (goingToNotificationShade) {
3146            return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
3147        }
3148
3149        AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ?
3150                    R.anim.lock_screen_behind_enter_wallpaper :
3151                    R.anim.lock_screen_behind_enter);
3152
3153        // TODO: Use XML interpolators when we have log interpolators available in XML.
3154        final List<Animation> animations = set.getAnimations();
3155        for (int i = animations.size() - 1; i >= 0; --i) {
3156            animations.get(i).setInterpolator(mLogDecelerateInterpolator);
3157        }
3158
3159        return set;
3160    }
3161
3162
3163    @Override
3164    public Animation createKeyguardWallpaperExit(boolean goingToNotificationShade) {
3165        if (goingToNotificationShade) {
3166            return null;
3167        } else {
3168            return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
3169        }
3170    }
3171
3172    private static void awakenDreams() {
3173        IDreamManager dreamManager = getDreamManager();
3174        if (dreamManager != null) {
3175            try {
3176                dreamManager.awaken();
3177            } catch (RemoteException e) {
3178                // fine, stay asleep then
3179            }
3180        }
3181    }
3182
3183    static IDreamManager getDreamManager() {
3184        return IDreamManager.Stub.asInterface(
3185                ServiceManager.checkService(DreamService.DREAM_SERVICE));
3186    }
3187
3188    TelecomManager getTelecommService() {
3189        return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
3190    }
3191
3192    static IAudioService getAudioService() {
3193        IAudioService audioService = IAudioService.Stub.asInterface(
3194                ServiceManager.checkService(Context.AUDIO_SERVICE));
3195        if (audioService == null) {
3196            Log.w(TAG, "Unable to find IAudioService interface.");
3197        }
3198        return audioService;
3199    }
3200
3201    boolean keyguardOn() {
3202        return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode();
3203    }
3204
3205    private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
3206            WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
3207            WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
3208        };
3209
3210    /** {@inheritDoc} */
3211    @Override
3212    public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
3213        final boolean keyguardOn = keyguardOn();
3214        final int keyCode = event.getKeyCode();
3215        final int repeatCount = event.getRepeatCount();
3216        final int metaState = event.getMetaState();
3217        final int flags = event.getFlags();
3218        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
3219        final boolean canceled = event.isCanceled();
3220
3221        if (DEBUG_INPUT) {
3222            Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
3223                    + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
3224                    + " canceled=" + canceled);
3225        }
3226
3227        // If we think we might have a volume down & power key chord on the way
3228        // but we're not sure, then tell the dispatcher to wait a little while and
3229        // try again later before dispatching.
3230        if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
3231            if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
3232                final long now = SystemClock.uptimeMillis();
3233                final long timeoutTime = mScreenshotChordVolumeDownKeyTime
3234                        + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
3235                if (now < timeoutTime) {
3236                    return timeoutTime - now;
3237                }
3238            }
3239            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3240                    && mScreenshotChordVolumeDownKeyConsumed) {
3241                if (!down) {
3242                    mScreenshotChordVolumeDownKeyConsumed = false;
3243                }
3244                return -1;
3245            }
3246        }
3247
3248        // Cancel any pending meta actions if we see any other keys being pressed between the down
3249        // of the meta key and its corresponding up.
3250        if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
3251            mPendingMetaAction = false;
3252        }
3253        // Any key that is not Alt or Meta cancels Caps Lock combo tracking.
3254        if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) {
3255            mPendingCapsLockToggle = false;
3256        }
3257
3258        // First we always handle the home key here, so applications
3259        // can never break it, although if keyguard is on, we do let
3260        // it handle it, because that gives us the correct 5 second
3261        // timeout.
3262        if (keyCode == KeyEvent.KEYCODE_HOME) {
3263
3264            // If we have released the home key, and didn't do anything else
3265            // while it was pressed, then it is time to go home!
3266            if (!down) {
3267                cancelPreloadRecentApps();
3268
3269                mHomePressed = false;
3270                if (mHomeConsumed) {
3271                    mHomeConsumed = false;
3272                    return -1;
3273                }
3274
3275                if (canceled) {
3276                    Log.i(TAG, "Ignoring HOME; event canceled.");
3277                    return -1;
3278                }
3279
3280                // Delay handling home if a double-tap is possible.
3281                if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
3282                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
3283                    mHomeDoubleTapPending = true;
3284                    mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
3285                            ViewConfiguration.getDoubleTapTimeout());
3286                    return -1;
3287                }
3288
3289                handleShortPressOnHome();
3290                return -1;
3291            }
3292
3293            // If a system window has focus, then it doesn't make sense
3294            // right now to interact with applications.
3295            WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
3296            if (attrs != null) {
3297                final int type = attrs.type;
3298                if (type == TYPE_KEYGUARD_DIALOG
3299                        || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
3300                    // the "app" is keyguard, so give it the key
3301                    return 0;
3302                }
3303                final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
3304                for (int i=0; i<typeCount; i++) {
3305                    if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
3306                        // don't do anything, but also don't pass it to the app
3307                        return -1;
3308                    }
3309                }
3310            }
3311
3312            // Remember that home is pressed and handle special actions.
3313            if (repeatCount == 0) {
3314                mHomePressed = true;
3315                if (mHomeDoubleTapPending) {
3316                    mHomeDoubleTapPending = false;
3317                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
3318                    handleDoubleTapOnHome();
3319                } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI
3320                        || mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
3321                    preloadRecentApps();
3322                }
3323            } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
3324                if (!keyguardOn) {
3325                    handleLongPressOnHome(event.getDeviceId());
3326                }
3327            }
3328            return -1;
3329        } else if (keyCode == KeyEvent.KEYCODE_MENU) {
3330            // Hijack modified menu keys for debugging features
3331            final int chordBug = KeyEvent.META_SHIFT_ON;
3332
3333            if (down && repeatCount == 0) {
3334                if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
3335                    Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
3336                    mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
3337                            null, null, null, 0, null, null);
3338                    return -1;
3339                }
3340            }
3341        } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
3342            if (down) {
3343                if (repeatCount == 0) {
3344                    mSearchKeyShortcutPending = true;
3345                    mConsumeSearchKeyUp = false;
3346                }
3347            } else {
3348                mSearchKeyShortcutPending = false;
3349                if (mConsumeSearchKeyUp) {
3350                    mConsumeSearchKeyUp = false;
3351                    return -1;
3352                }
3353            }
3354            return 0;
3355        } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
3356            if (!keyguardOn) {
3357                if (down && repeatCount == 0) {
3358                    preloadRecentApps();
3359                } else if (!down) {
3360                    toggleRecentApps();
3361                }
3362            }
3363            return -1;
3364        } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) {
3365            if (down) {
3366                IStatusBarService service = getStatusBarService();
3367                if (service != null) {
3368                    try {
3369                        service.expandNotificationsPanel();
3370                    } catch (RemoteException e) {
3371                        // do nothing.
3372                    }
3373                }
3374            }
3375        } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed()
3376                && event.isCtrlPressed()) {
3377            if (down && repeatCount == 0) {
3378                int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION
3379                        : TAKE_SCREENSHOT_FULLSCREEN;
3380                mScreenshotRunnable.setScreenshotType(type);
3381                mHandler.post(mScreenshotRunnable);
3382                return -1;
3383            }
3384        } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
3385            if (down && repeatCount == 0 && !isKeyguardLocked()) {
3386                toggleKeyboardShortcutsMenu(event.getDeviceId());
3387            }
3388        } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
3389            if (down) {
3390                if (repeatCount == 0) {
3391                    mAssistKeyLongPressed = false;
3392                } else if (repeatCount == 1) {
3393                    mAssistKeyLongPressed = true;
3394                    if (!keyguardOn) {
3395                         launchAssistLongPressAction();
3396                    }
3397                }
3398            } else {
3399                if (mAssistKeyLongPressed) {
3400                    mAssistKeyLongPressed = false;
3401                } else {
3402                    if (!keyguardOn) {
3403                        launchAssistAction(null, event.getDeviceId());
3404                    }
3405                }
3406            }
3407            return -1;
3408        } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
3409            if (!down) {
3410                Intent voiceIntent;
3411                if (!keyguardOn) {
3412                    voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
3413                } else {
3414                    IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
3415                            ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
3416                    if (dic != null) {
3417                        try {
3418                            dic.exitIdle("voice-search");
3419                        } catch (RemoteException e) {
3420                        }
3421                    }
3422                    voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
3423                    voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
3424                }
3425                startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
3426            }
3427        } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
3428            if (down && repeatCount == 0) {
3429                mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
3430                mHandler.post(mScreenshotRunnable);
3431            }
3432            return -1;
3433        } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP
3434                || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) {
3435            if (down) {
3436                int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
3437
3438                // Disable autobrightness if it's on
3439                int auto = Settings.System.getIntForUser(
3440                        mContext.getContentResolver(),
3441                        Settings.System.SCREEN_BRIGHTNESS_MODE,
3442                        Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3443                        UserHandle.USER_CURRENT_OR_SELF);
3444                if (auto != 0) {
3445                    Settings.System.putIntForUser(mContext.getContentResolver(),
3446                            Settings.System.SCREEN_BRIGHTNESS_MODE,
3447                            Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
3448                            UserHandle.USER_CURRENT_OR_SELF);
3449                }
3450
3451                int min = mPowerManager.getMinimumScreenBrightnessSetting();
3452                int max = mPowerManager.getMaximumScreenBrightnessSetting();
3453                int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction;
3454                int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
3455                        Settings.System.SCREEN_BRIGHTNESS,
3456                        mPowerManager.getDefaultScreenBrightnessSetting(),
3457                        UserHandle.USER_CURRENT_OR_SELF);
3458                brightness += step;
3459                // Make sure we don't go beyond the limits.
3460                brightness = Math.min(max, brightness);
3461                brightness = Math.max(min, brightness);
3462
3463                Settings.System.putIntForUser(mContext.getContentResolver(),
3464                        Settings.System.SCREEN_BRIGHTNESS, brightness,
3465                        UserHandle.USER_CURRENT_OR_SELF);
3466                startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
3467                        UserHandle.CURRENT_OR_SELF);
3468            }
3469            return -1;
3470        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
3471                || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
3472                || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
3473            if (mUseTvRouting) {
3474                // On TVs volume keys never go to the foreground app.
3475                dispatchDirectAudioEvent(event);
3476                return -1;
3477            }
3478        }
3479
3480        // Toggle Caps Lock on META-ALT.
3481        boolean actionTriggered = false;
3482        if (KeyEvent.isModifierKey(keyCode)) {
3483            if (!mPendingCapsLockToggle) {
3484                // Start tracking meta state for combo.
3485                mInitialMetaState = mMetaState;
3486                mPendingCapsLockToggle = true;
3487            } else if (event.getAction() == KeyEvent.ACTION_UP) {
3488                int altOnMask = mMetaState & KeyEvent.META_ALT_MASK;
3489                int metaOnMask = mMetaState & KeyEvent.META_META_MASK;
3490
3491                // Check for Caps Lock toggle
3492                if ((metaOnMask != 0) && (altOnMask != 0)) {
3493                    // Check if nothing else is pressed
3494                    if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) {
3495                        // Handle Caps Lock Toggle
3496                        mInputManagerInternal.toggleCapsLock(event.getDeviceId());
3497                        actionTriggered = true;
3498                    }
3499                }
3500
3501                // Always stop tracking when key goes up.
3502                mPendingCapsLockToggle = false;
3503            }
3504        }
3505        // Store current meta state to be able to evaluate it later.
3506        mMetaState = metaState;
3507
3508        if (actionTriggered) {
3509            return -1;
3510        }
3511
3512        if (KeyEvent.isMetaKey(keyCode)) {
3513            if (down) {
3514                mPendingMetaAction = true;
3515            } else if (mPendingMetaAction) {
3516                launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId());
3517            }
3518            return -1;
3519        }
3520
3521        // Shortcuts are invoked through Search+key, so intercept those here
3522        // Any printing key that is chorded with Search should be consumed
3523        // even if no shortcut was invoked.  This prevents text from being
3524        // inadvertently inserted when using a keyboard that has built-in macro
3525        // shortcut keys (that emit Search+x) and some of them are not registered.
3526        if (mSearchKeyShortcutPending) {
3527            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3528            if (kcm.isPrintingKey(keyCode)) {
3529                mConsumeSearchKeyUp = true;
3530                mSearchKeyShortcutPending = false;
3531                if (down && repeatCount == 0 && !keyguardOn) {
3532                    Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
3533                    if (shortcutIntent != null) {
3534                        shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3535                        try {
3536                            startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3537                            dismissKeyboardShortcutsMenu();
3538                        } catch (ActivityNotFoundException ex) {
3539                            Slog.w(TAG, "Dropping shortcut key combination because "
3540                                    + "the activity to which it is registered was not found: "
3541                                    + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);
3542                        }
3543                    } else {
3544                        Slog.i(TAG, "Dropping unregistered shortcut key combination: "
3545                                + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));
3546                    }
3547                }
3548                return -1;
3549            }
3550        }
3551
3552        // Invoke shortcuts using Meta.
3553        if (down && repeatCount == 0 && !keyguardOn
3554                && (metaState & KeyEvent.META_META_ON) != 0) {
3555            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3556            if (kcm.isPrintingKey(keyCode)) {
3557                Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
3558                        metaState & ~(KeyEvent.META_META_ON
3559                                | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
3560                if (shortcutIntent != null) {
3561                    shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3562                    try {
3563                        startActivityAsUser(shortcutIntent, UserHandle.CURRENT);
3564                        dismissKeyboardShortcutsMenu();
3565                    } catch (ActivityNotFoundException ex) {
3566                        Slog.w(TAG, "Dropping shortcut key combination because "
3567                                + "the activity to which it is registered was not found: "
3568                                + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
3569                    }
3570                    return -1;
3571                }
3572            }
3573        }
3574
3575        // Handle application launch keys.
3576        if (down && repeatCount == 0 && !keyguardOn) {
3577            String category = sApplicationLaunchKeyCategories.get(keyCode);
3578            if (category != null) {
3579                Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
3580                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3581                try {
3582                    startActivityAsUser(intent, UserHandle.CURRENT);
3583                    dismissKeyboardShortcutsMenu();
3584                } catch (ActivityNotFoundException ex) {
3585                    Slog.w(TAG, "Dropping application launch key because "
3586                            + "the activity to which it is registered was not found: "
3587                            + "keyCode=" + keyCode + ", category=" + category, ex);
3588                }
3589                return -1;
3590            }
3591        }
3592
3593        // Display task switcher for ALT-TAB.
3594        if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
3595            if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
3596                final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
3597                if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
3598                    mRecentAppsHeldModifiers = shiftlessModifiers;
3599                    showRecentApps(true, false);
3600                    return -1;
3601                }
3602            }
3603        } else if (!down && mRecentAppsHeldModifiers != 0
3604                && (metaState & mRecentAppsHeldModifiers) == 0) {
3605            mRecentAppsHeldModifiers = 0;
3606            hideRecentApps(true, false);
3607        }
3608
3609        // Handle input method switching.
3610        if (down && repeatCount == 0
3611                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3612                        || (keyCode == KeyEvent.KEYCODE_SPACE
3613                                && (metaState & KeyEvent.META_META_MASK) != 0))) {
3614            final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0;
3615            mWindowManagerFuncs.switchInputMethod(forwardDirection);
3616            return -1;
3617        }
3618        if (mLanguageSwitchKeyPressed && !down
3619                && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
3620                        || keyCode == KeyEvent.KEYCODE_SPACE)) {
3621            mLanguageSwitchKeyPressed = false;
3622            return -1;
3623        }
3624
3625        if (isValidGlobalKey(keyCode)
3626                && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
3627            return -1;
3628        }
3629
3630        if (down) {
3631            long shortcutCode = keyCode;
3632            if (event.isCtrlPressed()) {
3633                shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
3634            }
3635
3636            if (event.isAltPressed()) {
3637                shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
3638            }
3639
3640            if (event.isShiftPressed()) {
3641                shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
3642            }
3643
3644            if (event.isMetaPressed()) {
3645                shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE;
3646            }
3647
3648            IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode);
3649            if (shortcutService != null) {
3650                try {
3651                    if (isUserSetupComplete()) {
3652                        shortcutService.notifyShortcutKeyPressed(shortcutCode);
3653                    }
3654                } catch (RemoteException e) {
3655                    mShortcutKeyServices.delete(shortcutCode);
3656                }
3657                return -1;
3658            }
3659        }
3660
3661        // Reserve all the META modifier combos for system behavior
3662        if ((metaState & KeyEvent.META_META_ON) != 0) {
3663            return -1;
3664        }
3665
3666        // Let the application handle the key.
3667        return 0;
3668    }
3669
3670    /** {@inheritDoc} */
3671    @Override
3672    public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
3673        // Note: This method is only called if the initial down was unhandled.
3674        if (DEBUG_INPUT) {
3675            Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
3676                    + ", flags=" + event.getFlags()
3677                    + ", keyCode=" + event.getKeyCode()
3678                    + ", scanCode=" + event.getScanCode()
3679                    + ", metaState=" + event.getMetaState()
3680                    + ", repeatCount=" + event.getRepeatCount()
3681                    + ", policyFlags=" + policyFlags);
3682        }
3683
3684        KeyEvent fallbackEvent = null;
3685        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3686            final KeyCharacterMap kcm = event.getKeyCharacterMap();
3687            final int keyCode = event.getKeyCode();
3688            final int metaState = event.getMetaState();
3689            final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
3690                    && event.getRepeatCount() == 0;
3691
3692            // Check for fallback actions specified by the key character map.
3693            final FallbackAction fallbackAction;
3694            if (initialDown) {
3695                fallbackAction = kcm.getFallbackAction(keyCode, metaState);
3696            } else {
3697                fallbackAction = mFallbackActions.get(keyCode);
3698            }
3699
3700            if (fallbackAction != null) {
3701                if (DEBUG_INPUT) {
3702                    Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode
3703                            + " metaState=" + Integer.toHexString(fallbackAction.metaState));
3704                }
3705
3706                final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
3707                fallbackEvent = KeyEvent.obtain(
3708                        event.getDownTime(), event.getEventTime(),
3709                        event.getAction(), fallbackAction.keyCode,
3710                        event.getRepeatCount(), fallbackAction.metaState,
3711                        event.getDeviceId(), event.getScanCode(),
3712                        flags, event.getSource(), null);
3713
3714                if (!interceptFallback(win, fallbackEvent, policyFlags)) {
3715                    fallbackEvent.recycle();
3716                    fallbackEvent = null;
3717                }
3718
3719                if (initialDown) {
3720                    mFallbackActions.put(keyCode, fallbackAction);
3721                } else if (event.getAction() == KeyEvent.ACTION_UP) {
3722                    mFallbackActions.remove(keyCode);
3723                    fallbackAction.recycle();
3724                }
3725            }
3726        }
3727
3728        if (DEBUG_INPUT) {
3729            if (fallbackEvent == null) {
3730                Slog.d(TAG, "No fallback.");
3731            } else {
3732                Slog.d(TAG, "Performing fallback: " + fallbackEvent);
3733            }
3734        }
3735        return fallbackEvent;
3736    }
3737
3738    private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
3739        int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
3740        if ((actions & ACTION_PASS_TO_USER) != 0) {
3741            long delayMillis = interceptKeyBeforeDispatching(
3742                    win, fallbackEvent, policyFlags);
3743            if (delayMillis == 0) {
3744                return true;
3745            }
3746        }
3747        return false;
3748    }
3749
3750    @Override
3751    public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
3752            throws RemoteException {
3753        synchronized (mLock) {
3754            IShortcutService service = mShortcutKeyServices.get(shortcutCode);
3755            if (service != null && service.asBinder().pingBinder()) {
3756                throw new RemoteException("Key already exists.");
3757            }
3758
3759            mShortcutKeyServices.put(shortcutCode, shortcutService);
3760        }
3761    }
3762
3763    @Override
3764    public void onKeyguardOccludedChangedLw(boolean occluded) {
3765        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
3766            mPendingKeyguardOccluded = occluded;
3767            mKeyguardOccludedChanged = true;
3768        } else {
3769            setKeyguardOccludedLw(occluded);
3770        }
3771    }
3772
3773    private int handleStartTransitionForKeyguardLw(int transit, @Nullable Animation anim) {
3774        if (mKeyguardOccludedChanged) {
3775            if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded="
3776                    + mPendingKeyguardOccluded);
3777            mKeyguardOccludedChanged = false;
3778            if (setKeyguardOccludedLw(mPendingKeyguardOccluded)) {
3779                return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER;
3780            }
3781        }
3782        if (AppTransition.isKeyguardGoingAwayTransit(transit)) {
3783            if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation");
3784            final long startTime = anim != null
3785                    ? SystemClock.uptimeMillis() + anim.getStartOffset()
3786                    : SystemClock.uptimeMillis();
3787            final long duration = anim != null
3788                    ? anim.getDuration()
3789                    : 0;
3790            startKeyguardExitAnimation(startTime, duration);
3791        }
3792        return 0;
3793    }
3794
3795    private void launchAssistLongPressAction() {
3796        performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
3797        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
3798
3799        // launch the search activity
3800        Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
3801        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3802        try {
3803            // TODO: This only stops the factory-installed search manager.
3804            // Need to formalize an API to handle others
3805            SearchManager searchManager = getSearchManager();
3806            if (searchManager != null) {
3807                searchManager.stopSearch();
3808            }
3809            startActivityAsUser(intent, UserHandle.CURRENT);
3810        } catch (ActivityNotFoundException e) {
3811            Slog.w(TAG, "No activity to handle assist long press action.", e);
3812        }
3813    }
3814
3815    private void launchAssistAction(String hint, int deviceId) {
3816        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
3817        if (!isUserSetupComplete()) {
3818            // Disable opening assist window during setup
3819            return;
3820        }
3821        Bundle args = null;
3822        if (deviceId > Integer.MIN_VALUE) {
3823            args = new Bundle();
3824            args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
3825        }
3826        if ((mContext.getResources().getConfiguration().uiMode
3827                & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
3828            // On TV, use legacy handling until assistants are implemented in the proper way.
3829            ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
3830                    .launchLegacyAssist(hint, UserHandle.myUserId(), args);
3831        } else {
3832            if (hint != null) {
3833                if (args == null) {
3834                    args = new Bundle();
3835                }
3836                args.putBoolean(hint, true);
3837            }
3838            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3839            if (statusbar != null) {
3840                statusbar.startAssist(args);
3841            }
3842        }
3843    }
3844
3845    private void startActivityAsUser(Intent intent, UserHandle handle) {
3846        if (isUserSetupComplete()) {
3847            mContext.startActivityAsUser(intent, handle);
3848        } else {
3849            Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent);
3850        }
3851    }
3852
3853    private SearchManager getSearchManager() {
3854        if (mSearchManager == null) {
3855            mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
3856        }
3857        return mSearchManager;
3858    }
3859
3860    private void preloadRecentApps() {
3861        mPreloadedRecentApps = true;
3862        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3863        if (statusbar != null) {
3864            statusbar.preloadRecentApps();
3865        }
3866    }
3867
3868    private void cancelPreloadRecentApps() {
3869        if (mPreloadedRecentApps) {
3870            mPreloadedRecentApps = false;
3871            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3872            if (statusbar != null) {
3873                statusbar.cancelPreloadRecentApps();
3874            }
3875        }
3876    }
3877
3878    private void toggleRecentApps() {
3879        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3880        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3881        if (statusbar != null) {
3882            statusbar.toggleRecentApps();
3883        }
3884    }
3885
3886    @Override
3887    public void showRecentApps(boolean fromHome) {
3888        mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
3889        mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget();
3890    }
3891
3892    private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
3893        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3894        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3895        if (statusbar != null) {
3896            statusbar.showRecentApps(triggeredFromAltTab, fromHome);
3897        }
3898    }
3899
3900    private void toggleKeyboardShortcutsMenu(int deviceId) {
3901        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3902        if (statusbar != null) {
3903            statusbar.toggleKeyboardShortcutsMenu(deviceId);
3904        }
3905    }
3906
3907    private void dismissKeyboardShortcutsMenu() {
3908        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3909        if (statusbar != null) {
3910            statusbar.dismissKeyboardShortcutsMenu();
3911        }
3912    }
3913
3914    private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
3915        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
3916        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
3917        if (statusbar != null) {
3918            statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
3919        }
3920    }
3921
3922    void launchHomeFromHotKey() {
3923        launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/);
3924    }
3925
3926    /**
3927     * A home key -> launch home action was detected.  Take the appropriate action
3928     * given the situation with the keyguard.
3929     */
3930    void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) {
3931        if (respectKeyguard) {
3932            if (isKeyguardShowingAndNotOccluded()) {
3933                // don't launch home if keyguard showing
3934                return;
3935            }
3936
3937            if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) {
3938                // when in keyguard restricted mode, must first verify unlock
3939                // before launching home
3940                mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
3941                    @Override
3942                    public void onKeyguardExitResult(boolean success) {
3943                        if (success) {
3944                            try {
3945                                ActivityManagerNative.getDefault().stopAppSwitches();
3946                            } catch (RemoteException e) {
3947                            }
3948                            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
3949                            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
3950                        }
3951                    }
3952                });
3953                return;
3954            }
3955        }
3956
3957        // no keyguard stuff to worry about, just launch home!
3958        try {
3959            ActivityManagerNative.getDefault().stopAppSwitches();
3960        } catch (RemoteException e) {
3961        }
3962        if (mRecentsVisible) {
3963            // Hide Recents and notify it to launch Home
3964            if (awakenFromDreams) {
3965                awakenDreams();
3966            }
3967            hideRecentApps(false, true);
3968        } else {
3969            // Otherwise, just launch Home
3970            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
3971            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
3972        }
3973    }
3974
3975    private final Runnable mClearHideNavigationFlag = new Runnable() {
3976        @Override
3977        public void run() {
3978            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
3979                // Clear flags.
3980                mForceClearedSystemUiFlags &=
3981                        ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
3982            }
3983            mWindowManagerFuncs.reevaluateStatusBarVisibility();
3984        }
3985    };
3986
3987    /**
3988     * Input handler used while nav bar is hidden.  Captures any touch on the screen,
3989     * to determine when the nav bar should be shown and prevent applications from
3990     * receiving those touches.
3991     */
3992    final class HideNavInputEventReceiver extends InputEventReceiver {
3993        public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
3994            super(inputChannel, looper);
3995        }
3996
3997        @Override
3998        public void onInputEvent(InputEvent event) {
3999            boolean handled = false;
4000            try {
4001                if (event instanceof MotionEvent
4002                        && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
4003                    final MotionEvent motionEvent = (MotionEvent)event;
4004                    if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
4005                        // When the user taps down, we re-show the nav bar.
4006                        boolean changed = false;
4007                        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
4008                            if (mInputConsumer == null) {
4009                                return;
4010                            }
4011                            // Any user activity always causes us to show the
4012                            // navigation controls, if they had been hidden.
4013                            // We also clear the low profile and only content
4014                            // flags so that tapping on the screen will atomically
4015                            // restore all currently hidden screen decorations.
4016                            int newVal = mResettingSystemUiFlags |
4017                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
4018                                    View.SYSTEM_UI_FLAG_LOW_PROFILE |
4019                                    View.SYSTEM_UI_FLAG_FULLSCREEN;
4020                            if (mResettingSystemUiFlags != newVal) {
4021                                mResettingSystemUiFlags = newVal;
4022                                changed = true;
4023                            }
4024                            // We don't allow the system's nav bar to be hidden
4025                            // again for 1 second, to prevent applications from
4026                            // spamming us and keeping it from being shown.
4027                            newVal = mForceClearedSystemUiFlags |
4028                                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
4029                            if (mForceClearedSystemUiFlags != newVal) {
4030                                mForceClearedSystemUiFlags = newVal;
4031                                changed = true;
4032                                mHandler.postDelayed(mClearHideNavigationFlag, 1000);
4033                            }
4034                        }
4035                        if (changed) {
4036                            mWindowManagerFuncs.reevaluateStatusBarVisibility();
4037                        }
4038                    }
4039                }
4040            } finally {
4041                finishInputEvent(event, handled);
4042            }
4043        }
4044    }
4045
4046    @Override
4047    public void setRecentsVisibilityLw(boolean visible) {
4048        mRecentsVisible = visible;
4049    }
4050
4051    @Override
4052    public void setTvPipVisibilityLw(boolean visible) {
4053        mTvPictureInPictureVisible = visible;
4054    }
4055
4056    @Override
4057    public int adjustSystemUiVisibilityLw(int visibility) {
4058        mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4059        mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
4060
4061        // Reset any bits in mForceClearingStatusBarVisibility that
4062        // are now clear.
4063        mResettingSystemUiFlags &= visibility;
4064        // Clear any bits in the new visibility that are currently being
4065        // force cleared, before reporting it.
4066        return visibility & ~mResettingSystemUiFlags
4067                & ~mForceClearedSystemUiFlags;
4068    }
4069
4070    @Override
4071    public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
4072            int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets,
4073            Rect outStableInsets, Rect outOutsets) {
4074        final int fl = PolicyControl.getWindowFlags(null, attrs);
4075        final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
4076        final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
4077
4078        final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
4079        if (useOutsets) {
4080            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
4081            if (outset > 0) {
4082                if (displayRotation == Surface.ROTATION_0) {
4083                    outOutsets.bottom += outset;
4084                } else if (displayRotation == Surface.ROTATION_90) {
4085                    outOutsets.right += outset;
4086                } else if (displayRotation == Surface.ROTATION_180) {
4087                    outOutsets.top += outset;
4088                } else if (displayRotation == Surface.ROTATION_270) {
4089                    outOutsets.left += outset;
4090                }
4091            }
4092        }
4093
4094        if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4095                == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4096            int availRight, availBottom;
4097            if (canHideNavigationBar() &&
4098                    (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
4099                availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4100                availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4101            } else {
4102                availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
4103                availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4104            }
4105            if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4106                if ((fl & FLAG_FULLSCREEN) != 0) {
4107                    outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop,
4108                            availRight - mStableFullscreenRight,
4109                            availBottom - mStableFullscreenBottom);
4110                } else {
4111                    outContentInsets.set(mStableLeft, mStableTop,
4112                            availRight - mStableRight, availBottom - mStableBottom);
4113                }
4114            } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
4115                outContentInsets.setEmpty();
4116            } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
4117                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
4118                outContentInsets.set(mCurLeft, mCurTop,
4119                        availRight - mCurRight, availBottom - mCurBottom);
4120            } else {
4121                outContentInsets.set(mCurLeft, mCurTop,
4122                        availRight - mCurRight, availBottom - mCurBottom);
4123            }
4124
4125            outStableInsets.set(mStableLeft, mStableTop,
4126                    availRight - mStableRight, availBottom - mStableBottom);
4127            if (taskBounds != null) {
4128                calculateRelevantTaskInsets(taskBounds, outContentInsets,
4129                        displayWidth, displayHeight);
4130                calculateRelevantTaskInsets(taskBounds, outStableInsets,
4131                        displayWidth, displayHeight);
4132            }
4133            return mForceShowSystemBars;
4134        }
4135        outContentInsets.setEmpty();
4136        outStableInsets.setEmpty();
4137        return mForceShowSystemBars;
4138    }
4139
4140    /**
4141     * For any given task bounds, the insets relevant for these bounds given the insets relevant
4142     * for the entire display.
4143     */
4144    private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth,
4145            int displayHeight) {
4146        mTmpRect.set(0, 0, displayWidth, displayHeight);
4147        mTmpRect.inset(inOutInsets);
4148        mTmpRect.intersect(taskBounds);
4149        int leftInset = mTmpRect.left - taskBounds.left;
4150        int topInset = mTmpRect.top - taskBounds.top;
4151        int rightInset = taskBounds.right - mTmpRect.right;
4152        int bottomInset = taskBounds.bottom - mTmpRect.bottom;
4153        inOutInsets.set(leftInset, topInset, rightInset, bottomInset);
4154    }
4155
4156    private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
4157        return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN
4158                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0;
4159    }
4160
4161    /** {@inheritDoc} */
4162    @Override
4163    public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
4164                              int displayRotation, int uiMode) {
4165        mDisplayRotation = displayRotation;
4166        final int overscanLeft, overscanTop, overscanRight, overscanBottom;
4167        if (isDefaultDisplay) {
4168            switch (displayRotation) {
4169                case Surface.ROTATION_90:
4170                    overscanLeft = mOverscanTop;
4171                    overscanTop = mOverscanRight;
4172                    overscanRight = mOverscanBottom;
4173                    overscanBottom = mOverscanLeft;
4174                    break;
4175                case Surface.ROTATION_180:
4176                    overscanLeft = mOverscanRight;
4177                    overscanTop = mOverscanBottom;
4178                    overscanRight = mOverscanLeft;
4179                    overscanBottom = mOverscanTop;
4180                    break;
4181                case Surface.ROTATION_270:
4182                    overscanLeft = mOverscanBottom;
4183                    overscanTop = mOverscanLeft;
4184                    overscanRight = mOverscanTop;
4185                    overscanBottom = mOverscanRight;
4186                    break;
4187                default:
4188                    overscanLeft = mOverscanLeft;
4189                    overscanTop = mOverscanTop;
4190                    overscanRight = mOverscanRight;
4191                    overscanBottom = mOverscanBottom;
4192                    break;
4193            }
4194        } else {
4195            overscanLeft = 0;
4196            overscanTop = 0;
4197            overscanRight = 0;
4198            overscanBottom = 0;
4199        }
4200        mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0;
4201        mOverscanScreenTop = mRestrictedOverscanScreenTop = 0;
4202        mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth;
4203        mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight;
4204        mSystemLeft = 0;
4205        mSystemTop = 0;
4206        mSystemRight = displayWidth;
4207        mSystemBottom = displayHeight;
4208        mUnrestrictedScreenLeft = overscanLeft;
4209        mUnrestrictedScreenTop = overscanTop;
4210        mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight;
4211        mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom;
4212        mRestrictedScreenLeft = mUnrestrictedScreenLeft;
4213        mRestrictedScreenTop = mUnrestrictedScreenTop;
4214        mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth;
4215        mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight;
4216        mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft
4217                = mCurLeft = mUnrestrictedScreenLeft;
4218        mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop
4219                = mCurTop = mUnrestrictedScreenTop;
4220        mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight
4221                = mCurRight = displayWidth - overscanRight;
4222        mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom
4223                = mCurBottom = displayHeight - overscanBottom;
4224        mDockLayer = 0x10000000;
4225        mStatusBarLayer = -1;
4226
4227        // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
4228        final Rect pf = mTmpParentFrame;
4229        final Rect df = mTmpDisplayFrame;
4230        final Rect of = mTmpOverscanFrame;
4231        final Rect vf = mTmpVisibleFrame;
4232        final Rect dcf = mTmpDecorFrame;
4233        pf.left = df.left = of.left = vf.left = mDockLeft;
4234        pf.top = df.top = of.top = vf.top = mDockTop;
4235        pf.right = df.right = of.right = vf.right = mDockRight;
4236        pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom;
4237        dcf.setEmpty();  // Decor frame N/A for system bars.
4238
4239        if (isDefaultDisplay) {
4240            // For purposes of putting out fake window up to steal focus, we will
4241            // drive nav being hidden only by whether it is requested.
4242            final int sysui = mLastSystemUiFlags;
4243            boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
4244            boolean navTranslucent = (sysui
4245                    & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
4246            boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
4247            boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
4248            boolean navAllowedHidden = immersive || immersiveSticky;
4249            navTranslucent &= !immersiveSticky;  // transient trumps translucent
4250            boolean isKeyguardShowing = isStatusBarKeyguard() && !mKeyguardOccluded;
4251            if (!isKeyguardShowing) {
4252                navTranslucent &= areTranslucentBarsAllowed();
4253            }
4254            boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null
4255                    && mStatusBar.getAttrs().height == MATCH_PARENT
4256                    && mStatusBar.getAttrs().width == MATCH_PARENT;
4257
4258            // When the navigation bar isn't visible, we put up a fake
4259            // input window to catch all touch events.  This way we can
4260            // detect when the user presses anywhere to bring back the nav
4261            // bar and ensure the application doesn't see the event.
4262            if (navVisible || navAllowedHidden) {
4263                if (mInputConsumer != null) {
4264                    mHandler.sendMessage(
4265                            mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
4266                    mInputConsumer = null;
4267                }
4268            } else if (mInputConsumer == null) {
4269                mInputConsumer = mWindowManagerFuncs.createInputConsumer(mHandler.getLooper(),
4270                        INPUT_CONSUMER_NAVIGATION,
4271                        (channel, looper) -> new HideNavInputEventReceiver(channel, looper));
4272            }
4273
4274            // For purposes of positioning and showing the nav bar, if we have
4275            // decided that it can't be hidden (because of the screen aspect ratio),
4276            // then take that into account.
4277            navVisible |= !canHideNavigationBar();
4278
4279            boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight,
4280                    displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom, dcf, navVisible, navTranslucent,
4281                    navAllowedHidden, statusBarExpandedNotKeyguard);
4282            if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
4283                    mDockLeft, mDockTop, mDockRight, mDockBottom));
4284            updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing);
4285            if (updateSysUiVisibility) {
4286                updateSystemUiVisibilityLw();
4287            }
4288        }
4289    }
4290
4291    private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui,
4292            boolean isKeyguardShowing) {
4293        // decide where the status bar goes ahead of time
4294        if (mStatusBar != null) {
4295            // apply any navigation bar insets
4296            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4297            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4298            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4299            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
4300                    + mUnrestrictedScreenTop;
4301            vf.left = mStableLeft;
4302            vf.top = mStableTop;
4303            vf.right = mStableRight;
4304            vf.bottom = mStableBottom;
4305
4306            mStatusBarLayer = mStatusBar.getSurfaceLayer();
4307
4308            // Let the status bar determine its size.
4309            mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
4310                    vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
4311                    dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */);
4312
4313            // For layout, the status bar is always at the top with our fixed height.
4314            mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
4315
4316            boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
4317            boolean statusBarTranslucent = (sysui
4318                    & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
4319            if (!isKeyguardShowing) {
4320                statusBarTranslucent &= areTranslucentBarsAllowed();
4321            }
4322
4323            // If the status bar is hidden, we don't want to cause
4324            // windows behind it to scroll.
4325            if (mStatusBar.isVisibleLw() && !statusBarTransient) {
4326                // Status bar may go away, so the screen area it occupies
4327                // is available to apps but just covering them when the
4328                // status bar is visible.
4329                mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
4330
4331                mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4332                mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4333                mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4334                mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4335
4336                if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " +
4337                        String.format(
4338                                "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
4339                                mDockLeft, mDockTop, mDockRight, mDockBottom,
4340                                mContentLeft, mContentTop, mContentRight, mContentBottom,
4341                                mCurLeft, mCurTop, mCurRight, mCurBottom));
4342            }
4343            if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()
4344                    && !statusBarTransient && !statusBarTranslucent
4345                    && !mStatusBarController.wasRecentlyTranslucent()) {
4346                // If the opaque status bar is currently requested to be visible,
4347                // and not in the process of animating on or off, then
4348                // we can tell the app that it is covered by it.
4349                mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
4350            }
4351            if (mStatusBarController.checkHiddenLw()) {
4352                return true;
4353            }
4354        }
4355        return false;
4356    }
4357
4358    private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation,
4359            int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf,
4360            boolean navVisible, boolean navTranslucent, boolean navAllowedHidden,
4361            boolean statusBarExpandedNotKeyguard) {
4362        if (mNavigationBar != null) {
4363            boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
4364            // Force the navigation bar to its appropriate place and
4365            // size.  We need to do this directly, instead of relying on
4366            // it to bubble up from the nav bar, because this needs to
4367            // change atomically with screen rotations.
4368            mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight,
4369                    displayRotation);
4370            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
4371                // It's a system nav bar or a portrait screen; nav bar goes on bottom.
4372                int top = displayHeight - overscanBottom
4373                        - getNavigationBarHeight(displayRotation, uiMode);
4374                mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
4375                mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
4376                if (transientNavBarShowing) {
4377                    mNavigationBarController.setBarShowingLw(true);
4378                } else if (navVisible) {
4379                    mNavigationBarController.setBarShowingLw(true);
4380                    mDockBottom = mTmpNavigationFrame.top;
4381                    mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
4382                    mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
4383                } else {
4384                    // We currently want to hide the navigation UI - unless we expanded the status
4385                    // bar.
4386                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4387                }
4388                if (navVisible && !navTranslucent && !navAllowedHidden
4389                        && !mNavigationBar.isAnimatingLw()
4390                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4391                    // If the opaque nav bar is currently requested to be visible,
4392                    // and not in the process of animating on or off, then
4393                    // we can tell the app that it is covered by it.
4394                    mSystemBottom = mTmpNavigationFrame.top;
4395                }
4396            } else if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4397                // Landscape screen; nav bar goes to the right.
4398                int left = displayWidth - overscanRight
4399                        - getNavigationBarWidth(displayRotation, uiMode);
4400                mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
4401                mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
4402                if (transientNavBarShowing) {
4403                    mNavigationBarController.setBarShowingLw(true);
4404                } else if (navVisible) {
4405                    mNavigationBarController.setBarShowingLw(true);
4406                    mDockRight = mTmpNavigationFrame.left;
4407                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4408                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4409                } else {
4410                    // We currently want to hide the navigation UI - unless we expanded the status
4411                    // bar.
4412                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4413                }
4414                if (navVisible && !navTranslucent && !navAllowedHidden
4415                        && !mNavigationBar.isAnimatingLw()
4416                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4417                    // If the nav bar is currently requested to be visible,
4418                    // and not in the process of animating on or off, then
4419                    // we can tell the app that it is covered by it.
4420                    mSystemRight = mTmpNavigationFrame.left;
4421                }
4422            } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4423                // Seascape screen; nav bar goes to the left.
4424                int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode);
4425                mTmpNavigationFrame.set(overscanLeft, 0, right, displayHeight);
4426                mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right;
4427                if (transientNavBarShowing) {
4428                    mNavigationBarController.setBarShowingLw(true);
4429                } else if (navVisible) {
4430                    mNavigationBarController.setBarShowingLw(true);
4431                    mDockLeft = mTmpNavigationFrame.right;
4432                    // TODO: not so sure about those:
4433                    mRestrictedScreenLeft = mRestrictedOverscanScreenLeft = mDockLeft;
4434                    mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
4435                    mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
4436                } else {
4437                    // We currently want to hide the navigation UI - unless we expanded the status
4438                    // bar.
4439                    mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard);
4440                }
4441                if (navVisible && !navTranslucent && !navAllowedHidden
4442                        && !mNavigationBar.isAnimatingLw()
4443                        && !mNavigationBarController.wasRecentlyTranslucent()) {
4444                    // If the nav bar is currently requested to be visible,
4445                    // and not in the process of animating on or off, then
4446                    // we can tell the app that it is covered by it.
4447                    mSystemLeft = mTmpNavigationFrame.right;
4448                }
4449            }
4450            // Make sure the content and current rectangles are updated to
4451            // account for the restrictions from the navigation bar.
4452            mContentTop = mVoiceContentTop = mCurTop = mDockTop;
4453            mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom;
4454            mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft;
4455            mContentRight = mVoiceContentRight = mCurRight = mDockRight;
4456            mStatusBarLayer = mNavigationBar.getSurfaceLayer();
4457            // And compute the final frame.
4458            mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
4459                    mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
4460                    mTmpNavigationFrame, mTmpNavigationFrame);
4461            if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
4462            if (mNavigationBarController.checkHiddenLw()) {
4463                return true;
4464            }
4465        }
4466        return false;
4467    }
4468
4469    private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
4470        if (mNavigationBarCanMove && displayWidth > displayHeight) {
4471            if (displayRotation == Surface.ROTATION_270) {
4472                return NAV_BAR_LEFT;
4473            } else {
4474                return NAV_BAR_RIGHT;
4475            }
4476        }
4477        return NAV_BAR_BOTTOM;
4478    }
4479
4480    /** {@inheritDoc} */
4481    @Override
4482    public int getSystemDecorLayerLw() {
4483        if (mStatusBar != null && mStatusBar.isVisibleLw()) {
4484            return mStatusBar.getSurfaceLayer();
4485        }
4486
4487        if (mNavigationBar != null && mNavigationBar.isVisibleLw()) {
4488            return mNavigationBar.getSurfaceLayer();
4489        }
4490
4491        return 0;
4492    }
4493
4494    @Override
4495    public void getContentRectLw(Rect r) {
4496        r.set(mContentLeft, mContentTop, mContentRight, mContentBottom);
4497    }
4498
4499    void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
4500            boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
4501        if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
4502            // Here's a special case: if this attached window is a panel that is
4503            // above the dock window, and the window it is attached to is below
4504            // the dock window, then the frames we computed for the window it is
4505            // attached to can not be used because the dock is effectively part
4506            // of the underlying window and the attached window is floating on top
4507            // of the whole thing.  So, we ignore the attached window and explicitly
4508            // compute the frames that would be appropriate without the dock.
4509            df.left = of.left = cf.left = vf.left = mDockLeft;
4510            df.top = of.top = cf.top = vf.top = mDockTop;
4511            df.right = of.right = cf.right = vf.right = mDockRight;
4512            df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom;
4513        } else {
4514            // The effective display frame of the attached window depends on
4515            // whether it is taking care of insetting its content.  If not,
4516            // we need to use the parent's content frame so that the entire
4517            // window is positioned within that content.  Otherwise we can use
4518            // the overscan frame and let the attached window take care of
4519            // positioning its content appropriately.
4520            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4521                // Set the content frame of the attached window to the parent's decor frame
4522                // (same as content frame when IME isn't present) if specifically requested by
4523                // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
4524                // Otherwise, use the overscan frame.
4525                cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
4526                        ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
4527            } else {
4528                // If the window is resizing, then we want to base the content
4529                // frame on our attached content frame to resize...  however,
4530                // things can be tricky if the attached window is NOT in resize
4531                // mode, in which case its content frame will be larger.
4532                // Ungh.  So to deal with that, make sure the content frame
4533                // we end up using is not covering the IM dock.
4534                cf.set(attached.getContentFrameLw());
4535                if (attached.isVoiceInteraction()) {
4536                    if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft;
4537                    if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop;
4538                    if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight;
4539                    if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom;
4540                } else if (attached.getSurfaceLayer() < mDockLayer) {
4541                    if (cf.left < mContentLeft) cf.left = mContentLeft;
4542                    if (cf.top < mContentTop) cf.top = mContentTop;
4543                    if (cf.right > mContentRight) cf.right = mContentRight;
4544                    if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
4545                }
4546            }
4547            df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
4548            of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
4549            vf.set(attached.getVisibleFrameLw());
4550        }
4551        // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
4552        // window should be positioned relative to its parent or the entire
4553        // screen.
4554        pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
4555                ? attached.getFrameLw() : df);
4556    }
4557
4558    private void applyStableConstraints(int sysui, int fl, Rect r) {
4559        if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
4560            // If app is requesting a stable layout, don't let the
4561            // content insets go below the stable values.
4562            if ((fl & FLAG_FULLSCREEN) != 0) {
4563                if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft;
4564                if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop;
4565                if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight;
4566                if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom;
4567            } else {
4568                if (r.left < mStableLeft) r.left = mStableLeft;
4569                if (r.top < mStableTop) r.top = mStableTop;
4570                if (r.right > mStableRight) r.right = mStableRight;
4571                if (r.bottom > mStableBottom) r.bottom = mStableBottom;
4572            }
4573        }
4574    }
4575
4576    private boolean canReceiveInput(WindowState win) {
4577        boolean notFocusable =
4578                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
4579        boolean altFocusableIm =
4580                (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0;
4581        boolean notFocusableForIm = notFocusable ^ altFocusableIm;
4582        return !notFocusableForIm;
4583    }
4584
4585    /** {@inheritDoc} */
4586    @Override
4587    public void layoutWindowLw(WindowState win, WindowState attached) {
4588        // We've already done the navigation bar and status bar. If the status bar can receive
4589        // input, we need to layout it again to accomodate for the IME window.
4590        if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) {
4591            return;
4592        }
4593        final WindowManager.LayoutParams attrs = win.getAttrs();
4594        final boolean isDefaultDisplay = win.isDefaultDisplay();
4595        final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
4596                (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
4597        if (needsToOffsetInputMethodTarget) {
4598            if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
4599            offsetInputMethodWindowLw(mLastInputMethodWindow);
4600        }
4601
4602        final int fl = PolicyControl.getWindowFlags(win, attrs);
4603        final int pfl = attrs.privateFlags;
4604        final int sim = attrs.softInputMode;
4605        final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
4606
4607        final Rect pf = mTmpParentFrame;
4608        final Rect df = mTmpDisplayFrame;
4609        final Rect of = mTmpOverscanFrame;
4610        final Rect cf = mTmpContentFrame;
4611        final Rect vf = mTmpVisibleFrame;
4612        final Rect dcf = mTmpDecorFrame;
4613        final Rect sf = mTmpStableFrame;
4614        Rect osf = null;
4615        dcf.setEmpty();
4616
4617        final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
4618                && mNavigationBar != null && mNavigationBar.isVisibleLw());
4619
4620        final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
4621
4622        if (isDefaultDisplay) {
4623            sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom);
4624        } else {
4625            sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom);
4626        }
4627
4628        if (!isDefaultDisplay) {
4629            if (attached != null) {
4630                // If this window is attached to another, our display
4631                // frame is the same as the one we are attached to.
4632                setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4633            } else {
4634                // Give the window full screen.
4635                pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4636                pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4637                pf.right = df.right = of.right = cf.right
4638                        = mOverscanScreenLeft + mOverscanScreenWidth;
4639                pf.bottom = df.bottom = of.bottom = cf.bottom
4640                        = mOverscanScreenTop + mOverscanScreenHeight;
4641            }
4642        } else if (attrs.type == TYPE_INPUT_METHOD) {
4643            pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
4644            pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
4645            pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
4646            // IM dock windows layout below the nav bar...
4647            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4648            // ...with content insets above the nav bar
4649            cf.bottom = vf.bottom = mStableBottom;
4650            if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
4651                // The status bar forces the navigation bar while it's visible. Make sure the IME
4652                // avoids the navigation bar in that case.
4653                if (mNavigationBarPosition == NAV_BAR_RIGHT) {
4654                    pf.right = df.right = of.right = cf.right = vf.right = mStableRight;
4655                } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
4656                    pf.left = df.left = of.left = cf.left = vf.left = mStableLeft;
4657                }
4658            }
4659            // IM dock windows always go to the bottom of the screen.
4660            attrs.gravity = Gravity.BOTTOM;
4661            mDockLayer = win.getSurfaceLayer();
4662        } else if (attrs.type == TYPE_VOICE_INTERACTION) {
4663            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4664            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4665            pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4666            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4667            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4668                cf.left = mDockLeft;
4669                cf.top = mDockTop;
4670                cf.right = mDockRight;
4671                cf.bottom = mDockBottom;
4672            } else {
4673                cf.left = mContentLeft;
4674                cf.top = mContentTop;
4675                cf.right = mContentRight;
4676                cf.bottom = mContentBottom;
4677            }
4678            if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4679                vf.left = mCurLeft;
4680                vf.top = mCurTop;
4681                vf.right = mCurRight;
4682                vf.bottom = mCurBottom;
4683            } else {
4684                vf.set(cf);
4685            }
4686        } else if (attrs.type == TYPE_WALLPAPER) {
4687           layoutWallpaper(win, pf, df, of, cf);
4688        } else if (win == mStatusBar) {
4689            pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4690            pf.top = df.top = of.top = mUnrestrictedScreenTop;
4691            pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
4692            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop;
4693            cf.left = vf.left = mStableLeft;
4694            cf.top = vf.top = mStableTop;
4695            cf.right = vf.right = mStableRight;
4696            vf.bottom = mStableBottom;
4697
4698            if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
4699                cf.bottom = mContentBottom;
4700            } else {
4701                cf.bottom = mDockBottom;
4702                vf.bottom = mContentBottom;
4703            }
4704        } else {
4705
4706            // Default policy decor for the default display
4707            dcf.left = mSystemLeft;
4708            dcf.top = mSystemTop;
4709            dcf.right = mSystemRight;
4710            dcf.bottom = mSystemBottom;
4711            final boolean inheritTranslucentDecor = (attrs.privateFlags
4712                    & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0;
4713            final boolean isAppWindow =
4714                    attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW &&
4715                    attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
4716            final boolean topAtRest =
4717                    win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
4718            if (isAppWindow && !inheritTranslucentDecor && !topAtRest) {
4719                if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
4720                        && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0
4721                        && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
4722                        && (fl & WindowManager.LayoutParams.
4723                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
4724                        && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) {
4725                    // Ensure policy decor includes status bar
4726                    dcf.top = mStableTop;
4727                }
4728                if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0
4729                        && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
4730                        && (fl & WindowManager.LayoutParams.
4731                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
4732                    // Ensure policy decor includes navigation bar
4733                    dcf.bottom = mStableBottom;
4734                    dcf.right = mStableRight;
4735                }
4736            }
4737
4738            if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
4739                    == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
4740                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
4741                            + "): IN_SCREEN, INSET_DECOR");
4742                // This is the case for a normal activity window: we want it
4743                // to cover all of the screen space, and it can take care of
4744                // moving its contents to account for screen decorations that
4745                // intrude into that space.
4746                if (attached != null) {
4747                    // If this window is attached to another, our display
4748                    // frame is the same as the one we are attached to.
4749                    setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
4750                } else {
4751                    if (attrs.type == TYPE_STATUS_BAR_PANEL
4752                            || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
4753                        // Status bar panels are the only windows who can go on top of
4754                        // the status bar.  They are protected by the STATUS_BAR_SERVICE
4755                        // permission, so they have the same privileges as the status
4756                        // bar itself.
4757                        //
4758                        // However, they should still dodge the navigation bar if it exists.
4759
4760                        pf.left = df.left = of.left = hasNavBar
4761                                ? mDockLeft : mUnrestrictedScreenLeft;
4762                        pf.top = df.top = of.top = mUnrestrictedScreenTop;
4763                        pf.right = df.right = of.right = hasNavBar
4764                                ? mRestrictedScreenLeft+mRestrictedScreenWidth
4765                                : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4766                        pf.bottom = df.bottom = of.bottom = hasNavBar
4767                                ? mRestrictedScreenTop+mRestrictedScreenHeight
4768                                : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4769
4770                        if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4771                                        "Laying out status bar window: (%d,%d - %d,%d)",
4772                                        pf.left, pf.top, pf.right, pf.bottom));
4773                    } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4774                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4775                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4776                        // Asking to layout into the overscan region, so give it that pure
4777                        // unrestricted area.
4778                        pf.left = df.left = of.left = mOverscanScreenLeft;
4779                        pf.top = df.top = of.top = mOverscanScreenTop;
4780                        pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth;
4781                        pf.bottom = df.bottom = of.bottom = mOverscanScreenTop
4782                                + mOverscanScreenHeight;
4783                    } else if (canHideNavigationBar()
4784                            && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4785                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4786                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4787                        // Asking for layout as if the nav bar is hidden, lets the
4788                        // application extend into the unrestricted overscan screen area.  We
4789                        // only do this for application windows to ensure no window that
4790                        // can be above the nav bar can do this.
4791                        pf.left = df.left = mOverscanScreenLeft;
4792                        pf.top = df.top = mOverscanScreenTop;
4793                        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
4794                        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
4795                        // We need to tell the app about where the frame inside the overscan
4796                        // is, so it can inset its content by that amount -- it didn't ask
4797                        // to actually extend itself into the overscan region.
4798                        of.left = mUnrestrictedScreenLeft;
4799                        of.top = mUnrestrictedScreenTop;
4800                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4801                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4802                    } else {
4803                        pf.left = df.left = mRestrictedOverscanScreenLeft;
4804                        pf.top = df.top = mRestrictedOverscanScreenTop;
4805                        pf.right = df.right = mRestrictedOverscanScreenLeft
4806                                + mRestrictedOverscanScreenWidth;
4807                        pf.bottom = df.bottom = mRestrictedOverscanScreenTop
4808                                + mRestrictedOverscanScreenHeight;
4809                        // We need to tell the app about where the frame inside the overscan
4810                        // is, so it can inset its content by that amount -- it didn't ask
4811                        // to actually extend itself into the overscan region.
4812                        of.left = mUnrestrictedScreenLeft;
4813                        of.top = mUnrestrictedScreenTop;
4814                        of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4815                        of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4816                    }
4817
4818                    if ((fl & FLAG_FULLSCREEN) == 0) {
4819                        if (win.isVoiceInteraction()) {
4820                            cf.left = mVoiceContentLeft;
4821                            cf.top = mVoiceContentTop;
4822                            cf.right = mVoiceContentRight;
4823                            cf.bottom = mVoiceContentBottom;
4824                        } else {
4825                            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4826                                cf.left = mDockLeft;
4827                                cf.top = mDockTop;
4828                                cf.right = mDockRight;
4829                                cf.bottom = mDockBottom;
4830                            } else {
4831                                cf.left = mContentLeft;
4832                                cf.top = mContentTop;
4833                                cf.right = mContentRight;
4834                                cf.bottom = mContentBottom;
4835                            }
4836                        }
4837                    } else {
4838                        // Full screen windows are always given a layout that is as if the
4839                        // status bar and other transient decors are gone.  This is to avoid
4840                        // bad states when moving from a window that is not hding the
4841                        // status bar to one that is.
4842                        cf.left = mRestrictedScreenLeft;
4843                        cf.top = mRestrictedScreenTop;
4844                        cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
4845                        cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight;
4846                    }
4847                    applyStableConstraints(sysUiFl, fl, cf);
4848                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4849                        vf.left = mCurLeft;
4850                        vf.top = mCurTop;
4851                        vf.right = mCurRight;
4852                        vf.bottom = mCurBottom;
4853                    } else {
4854                        vf.set(cf);
4855                    }
4856                }
4857            } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
4858                    & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
4859                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
4860                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4861                        "): IN_SCREEN");
4862                // A window that has requested to fill the entire screen just
4863                // gets everything, period.
4864                if (attrs.type == TYPE_STATUS_BAR_PANEL
4865                        || attrs.type == TYPE_STATUS_BAR_SUB_PANEL
4866                        || attrs.type == TYPE_VOLUME_OVERLAY) {
4867                    pf.left = df.left = of.left = cf.left = hasNavBar
4868                            ? mDockLeft : mUnrestrictedScreenLeft;
4869                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
4870                    pf.right = df.right = of.right = cf.right = hasNavBar
4871                                        ? mRestrictedScreenLeft+mRestrictedScreenWidth
4872                                        : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
4873                    pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar
4874                                          ? mRestrictedScreenTop+mRestrictedScreenHeight
4875                                          : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
4876                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4877                                    "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
4878                                    pf.left, pf.top, pf.right, pf.bottom));
4879                } else if (attrs.type == TYPE_NAVIGATION_BAR
4880                        || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
4881                    // The navigation bar has Real Ultimate Power.
4882                    pf.left = df.left = of.left = mUnrestrictedScreenLeft;
4883                    pf.top = df.top = of.top = mUnrestrictedScreenTop;
4884                    pf.right = df.right = of.right = mUnrestrictedScreenLeft
4885                            + mUnrestrictedScreenWidth;
4886                    pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop
4887                            + mUnrestrictedScreenHeight;
4888                    if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
4889                                    "Laying out navigation bar window: (%d,%d - %d,%d)",
4890                                    pf.left, pf.top, pf.right, pf.bottom));
4891                } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
4892                                || attrs.type == TYPE_BOOT_PROGRESS
4893                                || attrs.type == TYPE_SCREENSHOT)
4894                        && ((fl & FLAG_FULLSCREEN) != 0)) {
4895                    // Fullscreen secure system overlays get what they ask for. Screenshot region
4896                    // selection overlay should also expand to full screen.
4897                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4898                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4899                    pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
4900                            + mOverscanScreenWidth;
4901                    pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
4902                            + mOverscanScreenHeight;
4903                } else if (attrs.type == TYPE_BOOT_PROGRESS) {
4904                    // Boot progress screen always covers entire display.
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 ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
4912                        && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4913                        && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
4914                    // Asking to layout into the overscan region, so give it that pure
4915                    // unrestricted area.
4916                    pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
4917                    pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
4918                    pf.right = df.right = of.right = cf.right
4919                            = mOverscanScreenLeft + mOverscanScreenWidth;
4920                    pf.bottom = df.bottom = of.bottom = cf.bottom
4921                            = mOverscanScreenTop + mOverscanScreenHeight;
4922                } else if (canHideNavigationBar()
4923                        && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
4924                        && (attrs.type == TYPE_STATUS_BAR
4925                            || attrs.type == TYPE_TOAST
4926                            || attrs.type == TYPE_DOCK_DIVIDER
4927                            || attrs.type == TYPE_VOICE_INTERACTION_STARTING
4928                            || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
4929                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
4930                    // Asking for layout as if the nav bar is hidden, lets the
4931                    // application extend into the unrestricted screen area.  We
4932                    // only do this for application windows (or toasts) to ensure no window that
4933                    // can be above the nav bar can do this.
4934                    // XXX This assumes that an app asking for this will also
4935                    // ask for layout in only content.  We can't currently figure out
4936                    // what the screen would be if only laying out to hide the nav bar.
4937                    pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
4938                    pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
4939                    pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft
4940                            + mUnrestrictedScreenWidth;
4941                    pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
4942                            + mUnrestrictedScreenHeight;
4943                } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
4944                    pf.left = df.left = of.left = mRestrictedScreenLeft;
4945                    pf.top = df.top = of.top  = mRestrictedScreenTop;
4946                    pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
4947                    pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop
4948                            + mRestrictedScreenHeight;
4949                    if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
4950                        cf.left = mDockLeft;
4951                        cf.top = mDockTop;
4952                        cf.right = mDockRight;
4953                        cf.bottom = mDockBottom;
4954                    } else {
4955                        cf.left = mContentLeft;
4956                        cf.top = mContentTop;
4957                        cf.right = mContentRight;
4958                        cf.bottom = mContentBottom;
4959                    }
4960                } else {
4961                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
4962                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
4963                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
4964                            + mRestrictedScreenWidth;
4965                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
4966                            + mRestrictedScreenHeight;
4967                }
4968
4969                applyStableConstraints(sysUiFl, fl, cf);
4970
4971                if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
4972                    vf.left = mCurLeft;
4973                    vf.top = mCurTop;
4974                    vf.right = mCurRight;
4975                    vf.bottom = mCurBottom;
4976                } else {
4977                    vf.set(cf);
4978                }
4979            } else if (attached != null) {
4980                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4981                        "): attached to " + attached);
4982                // A child window should be placed inside of the same visible
4983                // frame that its parent had.
4984                setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf);
4985            } else {
4986                if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
4987                        "): normal window");
4988                // Otherwise, a normal window must be placed inside the content
4989                // of all screen decorations.
4990                if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) {
4991                    // Status bar panels and the volume dialog are the only windows who can go on
4992                    // top of the status bar.  They are protected by the STATUS_BAR_SERVICE
4993                    // permission, so they have the same privileges as the status
4994                    // bar itself.
4995                    pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
4996                    pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
4997                    pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
4998                            + mRestrictedScreenWidth;
4999                    pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
5000                            + mRestrictedScreenHeight;
5001                } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) {
5002                    // These dialogs are stable to interim decor changes.
5003                    pf.left = df.left = of.left = cf.left = mStableLeft;
5004                    pf.top = df.top = of.top = cf.top = mStableTop;
5005                    pf.right = df.right = of.right = cf.right = mStableRight;
5006                    pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom;
5007                } else {
5008                    pf.left = mContentLeft;
5009                    pf.top = mContentTop;
5010                    pf.right = mContentRight;
5011                    pf.bottom = mContentBottom;
5012                    if (win.isVoiceInteraction()) {
5013                        df.left = of.left = cf.left = mVoiceContentLeft;
5014                        df.top = of.top = cf.top = mVoiceContentTop;
5015                        df.right = of.right = cf.right = mVoiceContentRight;
5016                        df.bottom = of.bottom = cf.bottom = mVoiceContentBottom;
5017                    } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
5018                        df.left = of.left = cf.left = mDockLeft;
5019                        df.top = of.top = cf.top = mDockTop;
5020                        df.right = of.right = cf.right = mDockRight;
5021                        df.bottom = of.bottom = cf.bottom = mDockBottom;
5022                    } else {
5023                        df.left = of.left = cf.left = mContentLeft;
5024                        df.top = of.top = cf.top = mContentTop;
5025                        df.right = of.right = cf.right = mContentRight;
5026                        df.bottom = of.bottom = cf.bottom = mContentBottom;
5027                    }
5028                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
5029                        vf.left = mCurLeft;
5030                        vf.top = mCurTop;
5031                        vf.right = mCurRight;
5032                        vf.bottom = mCurBottom;
5033                    } else {
5034                        vf.set(cf);
5035                    }
5036                }
5037            }
5038        }
5039
5040        // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
5041        // Also, we don't allow windows in multi-window mode to extend out of the screen.
5042        if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR
5043                && !win.isInMultiWindowMode()) {
5044            df.left = df.top = -10000;
5045            df.right = df.bottom = 10000;
5046            if (attrs.type != TYPE_WALLPAPER) {
5047                of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
5048                of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
5049            }
5050        }
5051
5052        // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we
5053        // need to provide information to the clients that want to pretend that you can draw there.
5054        // We only want to apply outsets to certain types of windows. For example, we never want to
5055        // apply the outsets to floating dialogs, because they wouldn't make sense there.
5056        final boolean useOutsets = shouldUseOutsets(attrs, fl);
5057        if (isDefaultDisplay && useOutsets) {
5058            osf = mTmpOutsetFrame;
5059            osf.set(cf.left, cf.top, cf.right, cf.bottom);
5060            int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
5061            if (outset > 0) {
5062                int rotation = mDisplayRotation;
5063                if (rotation == Surface.ROTATION_0) {
5064                    osf.bottom += outset;
5065                } else if (rotation == Surface.ROTATION_90) {
5066                    osf.right += outset;
5067                } else if (rotation == Surface.ROTATION_180) {
5068                    osf.top -= outset;
5069                } else if (rotation == Surface.ROTATION_270) {
5070                    osf.left -= outset;
5071                }
5072                if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset
5073                        + " with rotation " + rotation + ", result: " + osf);
5074            }
5075        }
5076
5077        if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
5078                + ": sim=#" + Integer.toHexString(sim)
5079                + " attach=" + attached + " type=" + attrs.type
5080                + String.format(" flags=0x%08x", fl)
5081                + " pf=" + pf.toShortString() + " df=" + df.toShortString()
5082                + " of=" + of.toShortString()
5083                + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
5084                + " dcf=" + dcf.toShortString()
5085                + " sf=" + sf.toShortString()
5086                + " osf=" + (osf == null ? "null" : osf.toShortString()));
5087
5088        win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf);
5089
5090        // Dock windows carve out the bottom of the screen, so normal windows
5091        // can't appear underneath them.
5092        if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleLw()
5093                && !win.getGivenInsetsPendingLw()) {
5094            setLastInputMethodWindowLw(null, null);
5095            offsetInputMethodWindowLw(win);
5096        }
5097        if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleLw()
5098                && !win.getGivenInsetsPendingLw()) {
5099            offsetVoiceInputWindowLw(win);
5100        }
5101    }
5102
5103    private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) {
5104
5105        // The wallpaper also has Real Ultimate Power, but we want to tell
5106        // it about the overscan area.
5107        pf.left = df.left = mOverscanScreenLeft;
5108        pf.top = df.top = mOverscanScreenTop;
5109        pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
5110        pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
5111        of.left = cf.left = mUnrestrictedScreenLeft;
5112        of.top = cf.top = mUnrestrictedScreenTop;
5113        of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
5114        of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
5115    }
5116
5117    private void offsetInputMethodWindowLw(WindowState win) {
5118        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5119        top += win.getGivenContentInsetsLw().top;
5120        if (mContentBottom > top) {
5121            mContentBottom = top;
5122        }
5123        if (mVoiceContentBottom > top) {
5124            mVoiceContentBottom = top;
5125        }
5126        top = win.getVisibleFrameLw().top;
5127        top += win.getGivenVisibleInsetsLw().top;
5128        if (mCurBottom > top) {
5129            mCurBottom = top;
5130        }
5131        if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom="
5132                + mDockBottom + " mContentBottom="
5133                + mContentBottom + " mCurBottom=" + mCurBottom);
5134    }
5135
5136    private void offsetVoiceInputWindowLw(WindowState win) {
5137        int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top);
5138        top += win.getGivenContentInsetsLw().top;
5139        if (mVoiceContentBottom > top) {
5140            mVoiceContentBottom = top;
5141        }
5142    }
5143
5144    /** {@inheritDoc} */
5145    @Override
5146    public void finishLayoutLw() {
5147        return;
5148    }
5149
5150    /** {@inheritDoc} */
5151    @Override
5152    public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
5153        mTopFullscreenOpaqueWindowState = null;
5154        mTopFullscreenOpaqueOrDimmingWindowState = null;
5155        mTopDockedOpaqueWindowState = null;
5156        mTopDockedOpaqueOrDimmingWindowState = null;
5157        mForceStatusBar = false;
5158        mForceStatusBarFromKeyguard = false;
5159        mForceStatusBarTransparent = false;
5160        mForcingShowNavBar = false;
5161        mForcingShowNavBarLayer = -1;
5162
5163        mAllowLockscreenWhenOn = false;
5164        mShowingDream = false;
5165    }
5166
5167    /** {@inheritDoc} */
5168    @Override
5169    public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
5170            WindowState attached, WindowState imeTarget) {
5171        final boolean visible = win.isVisibleLw();
5172        if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisible=" + visible);
5173        applyKeyguardPolicyLw(win, imeTarget);
5174        final int fl = PolicyControl.getWindowFlags(win, attrs);
5175        if (mTopFullscreenOpaqueWindowState == null && visible && attrs.type == TYPE_INPUT_METHOD) {
5176            mForcingShowNavBar = true;
5177            mForcingShowNavBarLayer = win.getSurfaceLayer();
5178        }
5179        if (attrs.type == TYPE_STATUS_BAR) {
5180            if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
5181                mForceStatusBarFromKeyguard = true;
5182            }
5183            if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
5184                mForceStatusBarTransparent = true;
5185            }
5186        }
5187
5188        boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
5189                && attrs.type < FIRST_SYSTEM_WINDOW;
5190        final int stackId = win.getStackId();
5191        if (mTopFullscreenOpaqueWindowState == null && visible) {
5192            if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
5193                mForceStatusBar = true;
5194            }
5195            if (attrs.type == TYPE_DREAM) {
5196                // If the lockscreen was showing when the dream started then wait
5197                // for the dream to draw before hiding the lockscreen.
5198                if (!mDreamingLockscreen
5199                        || (win.isVisibleLw() && win.hasDrawnLw())) {
5200                    mShowingDream = true;
5201                    appWindow = true;
5202                }
5203            }
5204
5205            // For app windows that are not attached, we decide if all windows in the app they
5206            // represent should be hidden or if we should hide the lockscreen. For attached app
5207            // windows we defer the decision to the window it is attached to.
5208            if (appWindow && attached == null) {
5209                if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
5210                    if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
5211                    mTopFullscreenOpaqueWindowState = win;
5212                    if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5213                        mTopFullscreenOpaqueOrDimmingWindowState = win;
5214                    }
5215                    if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
5216                        mAllowLockscreenWhenOn = true;
5217                    }
5218                }
5219            }
5220        }
5221
5222        // Voice interaction overrides both top fullscreen and top docked.
5223        if (visible && win.getAttrs().type == TYPE_VOICE_INTERACTION) {
5224            if (mTopFullscreenOpaqueWindowState == null) {
5225                mTopFullscreenOpaqueWindowState = win;
5226                if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
5227                    mTopFullscreenOpaqueOrDimmingWindowState = win;
5228                }
5229            }
5230            if (mTopDockedOpaqueWindowState == null) {
5231                mTopDockedOpaqueWindowState = win;
5232                if (mTopDockedOpaqueOrDimmingWindowState == null) {
5233                    mTopDockedOpaqueOrDimmingWindowState = win;
5234                }
5235            }
5236        }
5237
5238        // Keep track of the window if it's dimming but not necessarily fullscreen.
5239        if (mTopFullscreenOpaqueOrDimmingWindowState == null && visible
5240                && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
5241            mTopFullscreenOpaqueOrDimmingWindowState = win;
5242        }
5243
5244        // We need to keep track of the top "fullscreen" opaque window for the docked stack
5245        // separately, because both the "real fullscreen" opaque window and the one for the docked
5246        // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
5247        if (mTopDockedOpaqueWindowState == null && visible && appWindow && attached == null
5248                && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
5249            mTopDockedOpaqueWindowState = win;
5250            if (mTopDockedOpaqueOrDimmingWindowState == null) {
5251                mTopDockedOpaqueOrDimmingWindowState = win;
5252            }
5253        }
5254
5255        // Also keep track of any windows that are dimming but not necessarily fullscreen in the
5256        // docked stack.
5257        if (mTopDockedOpaqueOrDimmingWindowState == null && visible && win.isDimming()
5258                && stackId == DOCKED_STACK_ID) {
5259            mTopDockedOpaqueOrDimmingWindowState = win;
5260        }
5261    }
5262
5263    private void applyKeyguardPolicyLw(WindowState win, WindowState imeTarget) {
5264        if (canBeHiddenByKeyguardLw(win)) {
5265            if (shouldBeHiddenByKeyguard(win, imeTarget)) {
5266                win.hideLw(false /* doAnimation */);
5267            } else {
5268                win.showLw(false /* doAnimation */);
5269            }
5270        }
5271    }
5272
5273    private boolean isFullscreen(WindowManager.LayoutParams attrs) {
5274        return attrs.x == 0 && attrs.y == 0
5275                && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
5276                && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
5277    }
5278
5279    /** {@inheritDoc} */
5280    @Override
5281    public int finishPostLayoutPolicyLw() {
5282        int changes = 0;
5283        boolean topIsFullscreen = false;
5284
5285        final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
5286                ? mTopFullscreenOpaqueWindowState.getAttrs()
5287                : null;
5288
5289        // If we are not currently showing a dream then remember the current
5290        // lockscreen state.  We will use this to determine whether the dream
5291        // started while the lockscreen was showing and remember this state
5292        // while the dream is showing.
5293        if (!mShowingDream) {
5294            mDreamingLockscreen = isKeyguardShowingAndNotOccluded();
5295            if (mDreamingSleepTokenNeeded) {
5296                mDreamingSleepTokenNeeded = false;
5297                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
5298            }
5299        } else {
5300            if (!mDreamingSleepTokenNeeded) {
5301                mDreamingSleepTokenNeeded = true;
5302                mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget();
5303            }
5304        }
5305
5306        if (mStatusBar != null) {
5307            if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
5308                    + " forcefkg=" + mForceStatusBarFromKeyguard
5309                    + " top=" + mTopFullscreenOpaqueWindowState);
5310            boolean shouldBeTransparent = mForceStatusBarTransparent
5311                    && !mForceStatusBar
5312                    && !mForceStatusBarFromKeyguard;
5313            if (!shouldBeTransparent) {
5314                mStatusBarController.setShowTransparent(false /* transparent */);
5315            } else if (!mStatusBar.isVisibleLw()) {
5316                mStatusBarController.setShowTransparent(true /* transparent */);
5317            }
5318
5319            WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs();
5320            boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT
5321                    && statusBarAttrs.width == MATCH_PARENT;
5322            if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
5323                    || statusBarExpanded) {
5324                if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
5325                if (mStatusBarController.setBarShowingLw(true)) {
5326                    changes |= FINISH_LAYOUT_REDO_LAYOUT;
5327                }
5328                // Maintain fullscreen layout until incoming animation is complete.
5329                topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
5330                // Transient status bar on the lockscreen is not allowed
5331                if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) {
5332                    mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
5333                            mLastSystemUiFlags, mLastSystemUiFlags);
5334                }
5335                if (statusBarExpanded && mNavigationBar != null) {
5336                    if (mNavigationBarController.setBarShowingLw(true)) {
5337                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5338                    }
5339                }
5340            } else if (mTopFullscreenOpaqueWindowState != null) {
5341                final int fl = PolicyControl.getWindowFlags(null, lp);
5342                if (localLOGV) {
5343                    Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
5344                            + " shown position: "
5345                            + mTopFullscreenOpaqueWindowState.getShownPositionLw());
5346                    Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
5347                            + " lp.flags=0x" + Integer.toHexString(fl));
5348                }
5349                topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
5350                        || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
5351                // The subtle difference between the window for mTopFullscreenOpaqueWindowState
5352                // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
5353                // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
5354                // case though.
5355                if (mStatusBarController.isTransientShowing()) {
5356                    if (mStatusBarController.setBarShowingLw(true)) {
5357                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5358                    }
5359                } else if (topIsFullscreen
5360                        && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)
5361                        && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) {
5362                    if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
5363                    if (mStatusBarController.setBarShowingLw(false)) {
5364                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5365                    } else {
5366                        if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
5367                    }
5368                } else {
5369                    if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
5370                    if (mStatusBarController.setBarShowingLw(true)) {
5371                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
5372                    }
5373                }
5374            }
5375        }
5376
5377        if (mTopIsFullscreen != topIsFullscreen) {
5378            if (!topIsFullscreen) {
5379                // Force another layout when status bar becomes fully shown.
5380                changes |= FINISH_LAYOUT_REDO_LAYOUT;
5381            }
5382            mTopIsFullscreen = topIsFullscreen;
5383        }
5384
5385        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5386            // If the navigation bar has been hidden or shown, we need to do another
5387            // layout pass to update that window.
5388            changes |= FINISH_LAYOUT_REDO_LAYOUT;
5389        }
5390
5391        if (mShowingDream != mLastShowingDream) {
5392            mLastShowingDream = mShowingDream;
5393            mWindowManagerFuncs.notifyShowingDreamChanged();
5394        }
5395
5396        // update since mAllowLockscreenWhenOn might have changed
5397        updateLockScreenTimeout();
5398        return changes;
5399    }
5400
5401    /**
5402     * Updates the occluded state of the Keyguard.
5403     *
5404     * @return Whether the flags have changed and we have to redo the layout.
5405     */
5406    private boolean setKeyguardOccludedLw(boolean isOccluded) {
5407        if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded);
5408        boolean wasOccluded = mKeyguardOccluded;
5409        boolean showing = mKeyguardDelegate.isShowing();
5410        if (wasOccluded && !isOccluded && showing) {
5411            mKeyguardOccluded = false;
5412            mKeyguardDelegate.setOccluded(false, true /* animate */);
5413            mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
5414            if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
5415                mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
5416            }
5417            return true;
5418        } else if (!wasOccluded && isOccluded && showing) {
5419            mKeyguardOccluded = true;
5420            mKeyguardDelegate.setOccluded(true, false /* animate */);
5421            mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
5422            mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
5423            return true;
5424        } else if (wasOccluded != isOccluded) {
5425            mKeyguardOccluded = isOccluded;
5426            mKeyguardDelegate.setOccluded(isOccluded, false /* animate */);
5427            return false;
5428        } else {
5429            return false;
5430        }
5431    }
5432
5433    private boolean isStatusBarKeyguard() {
5434        return mStatusBar != null
5435                && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
5436    }
5437
5438    @Override
5439    public boolean allowAppAnimationsLw() {
5440        if (mShowingDream) {
5441            // If keyguard or dreams is currently visible, no reason to animate behind it.
5442            return false;
5443        }
5444        return true;
5445    }
5446
5447    @Override
5448    public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
5449        mFocusedWindow = newFocus;
5450        if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
5451            // If the navigation bar has been hidden or shown, we need to do another
5452            // layout pass to update that window.
5453            return FINISH_LAYOUT_REDO_LAYOUT;
5454        }
5455        return 0;
5456    }
5457
5458    /** {@inheritDoc} */
5459    @Override
5460    public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
5461        // lid changed state
5462        final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
5463        if (newLidState == mLidState) {
5464            return;
5465        }
5466
5467        mLidState = newLidState;
5468        applyLidSwitchState();
5469        updateRotation(true);
5470
5471        if (lidOpen) {
5472            wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
5473                    "android.policy:LID");
5474        } else if (!mLidControlsSleep) {
5475            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
5476        }
5477    }
5478
5479    @Override
5480    public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
5481        int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
5482        if (mCameraLensCoverState == lensCoverState) {
5483            return;
5484        }
5485        if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
5486                lensCoverState == CAMERA_LENS_UNCOVERED) {
5487            Intent intent;
5488            final boolean keyguardActive = mKeyguardDelegate == null ? false :
5489                    mKeyguardDelegate.isShowing();
5490            if (keyguardActive) {
5491                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
5492            } else {
5493                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
5494            }
5495            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
5496                    "android.policy:CAMERA_COVER");
5497            startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
5498        }
5499        mCameraLensCoverState = lensCoverState;
5500    }
5501
5502    void setHdmiPlugged(boolean plugged) {
5503        if (mHdmiPlugged != plugged) {
5504            mHdmiPlugged = plugged;
5505            updateRotation(true, true);
5506            Intent intent = new Intent(ACTION_HDMI_PLUGGED);
5507            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
5508            intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
5509            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
5510        }
5511    }
5512
5513    void initializeHdmiState() {
5514        boolean plugged = false;
5515        // watch for HDMI plug messages if the hdmi switch exists
5516        if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
5517            mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
5518
5519            final String filename = "/sys/class/switch/hdmi/state";
5520            FileReader reader = null;
5521            try {
5522                reader = new FileReader(filename);
5523                char[] buf = new char[15];
5524                int n = reader.read(buf);
5525                if (n > 1) {
5526                    plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
5527                }
5528            } catch (IOException ex) {
5529                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5530            } catch (NumberFormatException ex) {
5531                Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
5532            } finally {
5533                if (reader != null) {
5534                    try {
5535                        reader.close();
5536                    } catch (IOException ex) {
5537                    }
5538                }
5539            }
5540        }
5541        // This dance forces the code in setHdmiPlugged to run.
5542        // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
5543        mHdmiPlugged = !plugged;
5544        setHdmiPlugged(!mHdmiPlugged);
5545    }
5546
5547    final Object mScreenshotLock = new Object();
5548    ServiceConnection mScreenshotConnection = null;
5549
5550    final Runnable mScreenshotTimeout = new Runnable() {
5551        @Override public void run() {
5552            synchronized (mScreenshotLock) {
5553                if (mScreenshotConnection != null) {
5554                    mContext.unbindService(mScreenshotConnection);
5555                    mScreenshotConnection = null;
5556                    notifyScreenshotError();
5557                }
5558            }
5559        }
5560    };
5561
5562    // Assume this is called from the Handler thread.
5563    private void takeScreenshot(final int screenshotType) {
5564        synchronized (mScreenshotLock) {
5565            if (mScreenshotConnection != null) {
5566                return;
5567            }
5568            final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
5569                    SYSUI_SCREENSHOT_SERVICE);
5570            final Intent serviceIntent = new Intent();
5571            serviceIntent.setComponent(serviceComponent);
5572            ServiceConnection conn = new ServiceConnection() {
5573                @Override
5574                public void onServiceConnected(ComponentName name, IBinder service) {
5575                    synchronized (mScreenshotLock) {
5576                        if (mScreenshotConnection != this) {
5577                            return;
5578                        }
5579                        Messenger messenger = new Messenger(service);
5580                        Message msg = Message.obtain(null, screenshotType);
5581                        final ServiceConnection myConn = this;
5582                        Handler h = new Handler(mHandler.getLooper()) {
5583                            @Override
5584                            public void handleMessage(Message msg) {
5585                                synchronized (mScreenshotLock) {
5586                                    if (mScreenshotConnection == myConn) {
5587                                        mContext.unbindService(mScreenshotConnection);
5588                                        mScreenshotConnection = null;
5589                                        mHandler.removeCallbacks(mScreenshotTimeout);
5590                                    }
5591                                }
5592                            }
5593                        };
5594                        msg.replyTo = new Messenger(h);
5595                        msg.arg1 = msg.arg2 = 0;
5596                        if (mStatusBar != null && mStatusBar.isVisibleLw())
5597                            msg.arg1 = 1;
5598                        if (mNavigationBar != null && mNavigationBar.isVisibleLw())
5599                            msg.arg2 = 1;
5600                        try {
5601                            messenger.send(msg);
5602                        } catch (RemoteException e) {
5603                        }
5604                    }
5605                }
5606
5607                @Override
5608                public void onServiceDisconnected(ComponentName name) {
5609                    synchronized (mScreenshotLock) {
5610                        if (mScreenshotConnection != null) {
5611                            mContext.unbindService(mScreenshotConnection);
5612                            mScreenshotConnection = null;
5613                            mHandler.removeCallbacks(mScreenshotTimeout);
5614                            notifyScreenshotError();
5615                        }
5616                    }
5617                }
5618            };
5619            if (mContext.bindServiceAsUser(serviceIntent, conn,
5620                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
5621                    UserHandle.CURRENT)) {
5622                mScreenshotConnection = conn;
5623                mHandler.postDelayed(mScreenshotTimeout, 10000);
5624            }
5625        }
5626    }
5627
5628    /**
5629     * Notifies the screenshot service to show an error.
5630     */
5631    private void notifyScreenshotError() {
5632        // If the service process is killed, then ask it to clean up after itself
5633        final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
5634                SYSUI_SCREENSHOT_ERROR_RECEIVER);
5635        Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT);
5636        errorIntent.setComponent(errorComponent);
5637        errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
5638                Intent.FLAG_RECEIVER_FOREGROUND);
5639        mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT);
5640    }
5641
5642    /** {@inheritDoc} */
5643    @Override
5644    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
5645        if (!mSystemBooted) {
5646            // If we have not yet booted, don't let key events do anything.
5647            return 0;
5648        }
5649
5650        final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
5651        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
5652        final boolean canceled = event.isCanceled();
5653        final int keyCode = event.getKeyCode();
5654
5655        final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
5656
5657        // If screen is off then we treat the case where the keyguard is open but hidden
5658        // the same as if it were open and in front.
5659        // This will prevent any keys other than the power button from waking the screen
5660        // when the keyguard is hidden by another activity.
5661        final boolean keyguardActive = (mKeyguardDelegate == null ? false :
5662                                            (interactive ?
5663                                                isKeyguardShowingAndNotOccluded() :
5664                                                mKeyguardDelegate.isShowing()));
5665
5666        if (DEBUG_INPUT) {
5667            Log.d(TAG, "interceptKeyTq keycode=" + keyCode
5668                    + " interactive=" + interactive + " keyguardActive=" + keyguardActive
5669                    + " policyFlags=" + Integer.toHexString(policyFlags));
5670        }
5671
5672        // Basic policy based on interactive state.
5673        int result;
5674        boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
5675                || event.isWakeKey();
5676        if (interactive || (isInjected && !isWakeKey)) {
5677            // When the device is interactive or the key is injected pass the
5678            // key to the application.
5679            result = ACTION_PASS_TO_USER;
5680            isWakeKey = false;
5681
5682            if (interactive) {
5683                // If the screen is awake, but the button pressed was the one that woke the device
5684                // then don't pass it to the application
5685                if (keyCode == mPendingWakeKey && !down) {
5686                    result = 0;
5687                }
5688                // Reset the pending key
5689                mPendingWakeKey = PENDING_KEY_NULL;
5690            }
5691        } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
5692            // If we're currently dozing with the screen on and the keyguard showing, pass the key
5693            // to the application but preserve its wake key status to make sure we still move
5694            // from dozing to fully interactive if we would normally go from off to fully
5695            // interactive.
5696            result = ACTION_PASS_TO_USER;
5697            // Since we're dispatching the input, reset the pending key
5698            mPendingWakeKey = PENDING_KEY_NULL;
5699        } else {
5700            // When the screen is off and the key is not injected, determine whether
5701            // to wake the device but don't pass the key to the application.
5702            result = 0;
5703            if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
5704                isWakeKey = false;
5705            }
5706            // Cache the wake key on down event so we can also avoid sending the up event to the app
5707            if (isWakeKey && down) {
5708                mPendingWakeKey = keyCode;
5709            }
5710        }
5711
5712        // If the key would be handled globally, just return the result, don't worry about special
5713        // key processing.
5714        if (isValidGlobalKey(keyCode)
5715                && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
5716            if (isWakeKey) {
5717                wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5718            }
5719            return result;
5720        }
5721
5722        boolean useHapticFeedback = down
5723                && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
5724                && event.getRepeatCount() == 0;
5725
5726        // Handle special keys.
5727        switch (keyCode) {
5728            case KeyEvent.KEYCODE_BACK: {
5729                if (down) {
5730                    interceptBackKeyDown();
5731                } else {
5732                    boolean handled = interceptBackKeyUp(event);
5733
5734                    // Don't pass back press to app if we've already handled it via long press
5735                    if (handled) {
5736                        result &= ~ACTION_PASS_TO_USER;
5737                    }
5738                }
5739                break;
5740            }
5741
5742            case KeyEvent.KEYCODE_VOLUME_DOWN:
5743            case KeyEvent.KEYCODE_VOLUME_UP:
5744            case KeyEvent.KEYCODE_VOLUME_MUTE: {
5745                if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
5746                    if (down) {
5747                        if (interactive && !mScreenshotChordVolumeDownKeyTriggered
5748                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5749                            mScreenshotChordVolumeDownKeyTriggered = true;
5750                            mScreenshotChordVolumeDownKeyTime = event.getDownTime();
5751                            mScreenshotChordVolumeDownKeyConsumed = false;
5752                            cancelPendingPowerKeyAction();
5753                            interceptScreenshotChord();
5754                        }
5755                    } else {
5756                        mScreenshotChordVolumeDownKeyTriggered = false;
5757                        cancelPendingScreenshotChordAction();
5758                    }
5759                } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
5760                    if (down) {
5761                        if (interactive && !mScreenshotChordVolumeUpKeyTriggered
5762                                && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
5763                            mScreenshotChordVolumeUpKeyTriggered = true;
5764                            cancelPendingPowerKeyAction();
5765                            cancelPendingScreenshotChordAction();
5766                        }
5767                    } else {
5768                        mScreenshotChordVolumeUpKeyTriggered = false;
5769                        cancelPendingScreenshotChordAction();
5770                    }
5771                }
5772                if (down) {
5773                    TelecomManager telecomManager = getTelecommService();
5774                    if (telecomManager != null) {
5775                        if (telecomManager.isRinging()) {
5776                            // If an incoming call is ringing, either VOLUME key means
5777                            // "silence ringer".  We handle these keys here, rather than
5778                            // in the InCallScreen, to make sure we'll respond to them
5779                            // even if the InCallScreen hasn't come to the foreground yet.
5780                            // Look for the DOWN event here, to agree with the "fallback"
5781                            // behavior in the InCallScreen.
5782                            Log.i(TAG, "interceptKeyBeforeQueueing:"
5783                                  + " VOLUME key-down while ringing: Silence ringer!");
5784
5785                            // Silence the ringer.  (It's safe to call this
5786                            // even if the ringer has already been silenced.)
5787                            telecomManager.silenceRinger();
5788
5789                            // And *don't* pass this key thru to the current activity
5790                            // (which is probably the InCallScreen.)
5791                            result &= ~ACTION_PASS_TO_USER;
5792                            break;
5793                        }
5794                        if (telecomManager.isInCall()
5795                                && (result & ACTION_PASS_TO_USER) == 0) {
5796                            // If we are in call but we decided not to pass the key to
5797                            // the application, just pass it to the session service.
5798
5799                            MediaSessionLegacyHelper.getHelper(mContext)
5800                                    .sendVolumeKeyEvent(event, false);
5801                            break;
5802                        }
5803                    }
5804                }
5805                if (mUseTvRouting) {
5806                    // On TVs, defer special key handlings to
5807                    // {@link interceptKeyBeforeDispatching()}.
5808                    result |= ACTION_PASS_TO_USER;
5809                } else if ((result & ACTION_PASS_TO_USER) == 0) {
5810                    // If we aren't passing to the user and no one else
5811                    // handled it send it to the session manager to
5812                    // figure out.
5813                    MediaSessionLegacyHelper.getHelper(mContext)
5814                            .sendVolumeKeyEvent(event, true);
5815                }
5816                break;
5817            }
5818
5819            case KeyEvent.KEYCODE_ENDCALL: {
5820                result &= ~ACTION_PASS_TO_USER;
5821                if (down) {
5822                    TelecomManager telecomManager = getTelecommService();
5823                    boolean hungUp = false;
5824                    if (telecomManager != null) {
5825                        hungUp = telecomManager.endCall();
5826                    }
5827                    if (interactive && !hungUp) {
5828                        mEndCallKeyHandled = false;
5829                        mHandler.postDelayed(mEndCallLongPress,
5830                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
5831                    } else {
5832                        mEndCallKeyHandled = true;
5833                    }
5834                } else {
5835                    if (!mEndCallKeyHandled) {
5836                        mHandler.removeCallbacks(mEndCallLongPress);
5837                        if (!canceled) {
5838                            if ((mEndcallBehavior
5839                                    & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
5840                                if (goHome()) {
5841                                    break;
5842                                }
5843                            }
5844                            if ((mEndcallBehavior
5845                                    & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
5846                                mPowerManager.goToSleep(event.getEventTime(),
5847                                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
5848                                isWakeKey = false;
5849                            }
5850                        }
5851                    }
5852                }
5853                break;
5854            }
5855
5856            case KeyEvent.KEYCODE_POWER: {
5857                result &= ~ACTION_PASS_TO_USER;
5858                isWakeKey = false; // wake-up will be handled separately
5859                if (down) {
5860                    interceptPowerKeyDown(event, interactive);
5861                } else {
5862                    interceptPowerKeyUp(event, interactive, canceled);
5863                }
5864                break;
5865            }
5866
5867            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
5868                // fall through
5869            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
5870                // fall through
5871            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
5872                // fall through
5873            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
5874                result &= ~ACTION_PASS_TO_USER;
5875                interceptSystemNavigationKey(event);
5876                break;
5877            }
5878
5879            case KeyEvent.KEYCODE_SLEEP: {
5880                result &= ~ACTION_PASS_TO_USER;
5881                isWakeKey = false;
5882                if (!mPowerManager.isInteractive()) {
5883                    useHapticFeedback = false; // suppress feedback if already non-interactive
5884                }
5885                if (down) {
5886                    sleepPress(event.getEventTime());
5887                } else {
5888                    sleepRelease(event.getEventTime());
5889                }
5890                break;
5891            }
5892
5893            case KeyEvent.KEYCODE_SOFT_SLEEP: {
5894                result &= ~ACTION_PASS_TO_USER;
5895                isWakeKey = false;
5896                if (!down) {
5897                    mPowerManagerInternal.setUserInactiveOverrideFromWindowManager();
5898                }
5899                break;
5900            }
5901
5902            case KeyEvent.KEYCODE_WAKEUP: {
5903                result &= ~ACTION_PASS_TO_USER;
5904                isWakeKey = true;
5905                break;
5906            }
5907
5908            case KeyEvent.KEYCODE_MEDIA_PLAY:
5909            case KeyEvent.KEYCODE_MEDIA_PAUSE:
5910            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
5911            case KeyEvent.KEYCODE_HEADSETHOOK:
5912            case KeyEvent.KEYCODE_MUTE:
5913            case KeyEvent.KEYCODE_MEDIA_STOP:
5914            case KeyEvent.KEYCODE_MEDIA_NEXT:
5915            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
5916            case KeyEvent.KEYCODE_MEDIA_REWIND:
5917            case KeyEvent.KEYCODE_MEDIA_RECORD:
5918            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
5919            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
5920                if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
5921                    // If the global session is active pass all media keys to it
5922                    // instead of the active window.
5923                    result &= ~ACTION_PASS_TO_USER;
5924                }
5925                if ((result & ACTION_PASS_TO_USER) == 0) {
5926                    // Only do this if we would otherwise not pass it to the user. In that
5927                    // case, the PhoneWindow class will do the same thing, except it will
5928                    // only do it if the showing app doesn't process the key on its own.
5929                    // Note that we need to make a copy of the key event here because the
5930                    // original key event will be recycled when we return.
5931                    mBroadcastWakeLock.acquire();
5932                    Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
5933                            new KeyEvent(event));
5934                    msg.setAsynchronous(true);
5935                    msg.sendToTarget();
5936                }
5937                break;
5938            }
5939
5940            case KeyEvent.KEYCODE_CALL: {
5941                if (down) {
5942                    TelecomManager telecomManager = getTelecommService();
5943                    if (telecomManager != null) {
5944                        if (telecomManager.isRinging()) {
5945                            Log.i(TAG, "interceptKeyBeforeQueueing:"
5946                                  + " CALL key-down while ringing: Answer the call!");
5947                            telecomManager.acceptRingingCall();
5948
5949                            // And *don't* pass this key thru to the current activity
5950                            // (which is presumably the InCallScreen.)
5951                            result &= ~ACTION_PASS_TO_USER;
5952                        }
5953                    }
5954                }
5955                break;
5956            }
5957            case KeyEvent.KEYCODE_VOICE_ASSIST: {
5958                // Only do this if we would otherwise not pass it to the user. In that case,
5959                // interceptKeyBeforeDispatching would apply a similar but different policy in
5960                // order to invoke voice assist actions. Note that we need to make a copy of the
5961                // key event here because the original key event will be recycled when we return.
5962                if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
5963                    mBroadcastWakeLock.acquire();
5964                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
5965                            keyguardActive ? 1 : 0, 0);
5966                    msg.setAsynchronous(true);
5967                    msg.sendToTarget();
5968                }
5969                break;
5970            }
5971            case KeyEvent.KEYCODE_WINDOW: {
5972                if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) {
5973                    if (mTvPictureInPictureVisible) {
5974                        // Consumes the key only if picture-in-picture is visible
5975                        // to show picture-in-picture control menu.
5976                        // This gives a chance to the foreground activity
5977                        // to customize PIP key behavior.
5978                        if (!down) {
5979                            showTvPictureInPictureMenu(event);
5980                        }
5981                        result &= ~ACTION_PASS_TO_USER;
5982                    }
5983                }
5984                break;
5985            }
5986        }
5987
5988        if (useHapticFeedback) {
5989            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
5990        }
5991
5992        if (isWakeKey) {
5993            wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
5994        }
5995
5996        return result;
5997    }
5998
5999    /**
6000     * Handle statusbar expansion events.
6001     * @param event
6002     */
6003    private void interceptSystemNavigationKey(KeyEvent event) {
6004        if (event.getAction() == KeyEvent.ACTION_UP && areSystemNavigationKeysEnabled()) {
6005            IStatusBarService sbar = getStatusBarService();
6006            if (sbar != null) {
6007                try {
6008                    sbar.handleSystemNavigationKey(event.getKeyCode());
6009                } catch (RemoteException e1) {
6010                    // oops, no statusbar. Ignore event.
6011                }
6012            }
6013        }
6014    }
6015
6016    /**
6017     * Returns true if the key can have global actions attached to it.
6018     * We reserve all power management keys for the system since they require
6019     * very careful handling.
6020     */
6021    private static boolean isValidGlobalKey(int keyCode) {
6022        switch (keyCode) {
6023            case KeyEvent.KEYCODE_POWER:
6024            case KeyEvent.KEYCODE_WAKEUP:
6025            case KeyEvent.KEYCODE_SLEEP:
6026                return false;
6027            default:
6028                return true;
6029        }
6030    }
6031
6032    /**
6033     * When the screen is off we ignore some keys that might otherwise typically
6034     * be considered wake keys.  We filter them out here.
6035     *
6036     * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
6037     * is always considered a wake key.
6038     */
6039    private boolean isWakeKeyWhenScreenOff(int keyCode) {
6040        switch (keyCode) {
6041            // ignore volume keys unless docked
6042            case KeyEvent.KEYCODE_VOLUME_UP:
6043            case KeyEvent.KEYCODE_VOLUME_DOWN:
6044            case KeyEvent.KEYCODE_VOLUME_MUTE:
6045                return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
6046
6047            // ignore media and camera keys
6048            case KeyEvent.KEYCODE_MUTE:
6049            case KeyEvent.KEYCODE_HEADSETHOOK:
6050            case KeyEvent.KEYCODE_MEDIA_PLAY:
6051            case KeyEvent.KEYCODE_MEDIA_PAUSE:
6052            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
6053            case KeyEvent.KEYCODE_MEDIA_STOP:
6054            case KeyEvent.KEYCODE_MEDIA_NEXT:
6055            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
6056            case KeyEvent.KEYCODE_MEDIA_REWIND:
6057            case KeyEvent.KEYCODE_MEDIA_RECORD:
6058            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
6059            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
6060            case KeyEvent.KEYCODE_CAMERA:
6061                return false;
6062        }
6063        return true;
6064    }
6065
6066
6067    /** {@inheritDoc} */
6068    @Override
6069    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
6070        if ((policyFlags & FLAG_WAKE) != 0) {
6071            if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
6072                    "android.policy:MOTION")) {
6073                return 0;
6074            }
6075        }
6076
6077        if (shouldDispatchInputWhenNonInteractive(null)) {
6078            return ACTION_PASS_TO_USER;
6079        }
6080
6081        // If we have not passed the action up and we are in theater mode without dreaming,
6082        // there will be no dream to intercept the touch and wake into ambient.  The device should
6083        // wake up in this case.
6084        if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
6085            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
6086                    "android.policy:MOTION");
6087        }
6088
6089        return 0;
6090    }
6091
6092    private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
6093        final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
6094
6095        if (displayOff && !mHasFeatureWatch) {
6096            return false;
6097        }
6098
6099        // Send events to keyguard while the screen is on and it's showing.
6100        if (isKeyguardShowingAndNotOccluded() && !displayOff) {
6101            return true;
6102        }
6103
6104        // Watches handle BACK specially
6105        if (mHasFeatureWatch
6106                && event != null
6107                && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
6108                        || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
6109            return false;
6110        }
6111
6112        // Send events to a dozing dream even if the screen is off since the dream
6113        // is in control of the state of the screen.
6114        IDreamManager dreamManager = getDreamManager();
6115
6116        try {
6117            if (dreamManager != null && dreamManager.isDreaming()) {
6118                return true;
6119            }
6120        } catch (RemoteException e) {
6121            Slog.e(TAG, "RemoteException when checking if dreaming", e);
6122        }
6123
6124        // Otherwise, consume events since the user can't see what is being
6125        // interacted with.
6126        return false;
6127    }
6128
6129    private void dispatchDirectAudioEvent(KeyEvent event) {
6130        if (event.getAction() != KeyEvent.ACTION_DOWN) {
6131            return;
6132        }
6133        int keyCode = event.getKeyCode();
6134        int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
6135                | AudioManager.FLAG_FROM_KEY;
6136        String pkgName = mContext.getOpPackageName();
6137        switch (keyCode) {
6138            case KeyEvent.KEYCODE_VOLUME_UP:
6139                try {
6140                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
6141                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6142                } catch (RemoteException e) {
6143                    Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
6144                }
6145                break;
6146            case KeyEvent.KEYCODE_VOLUME_DOWN:
6147                try {
6148                    getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
6149                            AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6150                } catch (RemoteException e) {
6151                    Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
6152                }
6153                break;
6154            case KeyEvent.KEYCODE_VOLUME_MUTE:
6155                try {
6156                    if (event.getRepeatCount() == 0) {
6157                        getAudioService().adjustSuggestedStreamVolume(
6158                                AudioManager.ADJUST_TOGGLE_MUTE,
6159                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
6160                    }
6161                } catch (RemoteException e) {
6162                    Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
6163                }
6164                break;
6165        }
6166    }
6167
6168    void dispatchMediaKeyWithWakeLock(KeyEvent event) {
6169        if (DEBUG_INPUT) {
6170            Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
6171        }
6172
6173        if (mHavePendingMediaKeyRepeatWithWakeLock) {
6174            if (DEBUG_INPUT) {
6175                Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
6176            }
6177
6178            mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
6179            mHavePendingMediaKeyRepeatWithWakeLock = false;
6180            mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
6181        }
6182
6183        dispatchMediaKeyWithWakeLockToAudioService(event);
6184
6185        if (event.getAction() == KeyEvent.ACTION_DOWN
6186                && event.getRepeatCount() == 0) {
6187            mHavePendingMediaKeyRepeatWithWakeLock = true;
6188
6189            Message msg = mHandler.obtainMessage(
6190                    MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
6191            msg.setAsynchronous(true);
6192            mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
6193        } else {
6194            mBroadcastWakeLock.release();
6195        }
6196    }
6197
6198    void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
6199        mHavePendingMediaKeyRepeatWithWakeLock = false;
6200
6201        KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
6202                SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6203        if (DEBUG_INPUT) {
6204            Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
6205        }
6206
6207        dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
6208        mBroadcastWakeLock.release();
6209    }
6210
6211    void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
6212        if (mActivityManagerInternal.isSystemReady()) {
6213            MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
6214        }
6215    }
6216
6217    void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
6218        IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
6219                ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
6220        if (dic != null) {
6221            try {
6222                dic.exitIdle("voice-search");
6223            } catch (RemoteException e) {
6224            }
6225        }
6226        Intent voiceIntent =
6227            new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
6228        voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
6229        startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
6230        mBroadcastWakeLock.release();
6231    }
6232
6233    BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
6234        @Override
6235        public void onReceive(Context context, Intent intent) {
6236            if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
6237                mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6238                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
6239            } else {
6240                try {
6241                    IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
6242                            ServiceManager.getService(Context.UI_MODE_SERVICE));
6243                    mUiMode = uiModeService.getCurrentModeType();
6244                } catch (RemoteException e) {
6245                }
6246            }
6247            updateRotation(true);
6248            synchronized (mLock) {
6249                updateOrientationListenerLp();
6250            }
6251        }
6252    };
6253
6254    BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
6255        @Override
6256        public void onReceive(Context context, Intent intent) {
6257            if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
6258                if (mKeyguardDelegate != null) {
6259                    mKeyguardDelegate.onDreamingStarted();
6260                }
6261            } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
6262                if (mKeyguardDelegate != null) {
6263                    mKeyguardDelegate.onDreamingStopped();
6264                }
6265            }
6266        }
6267    };
6268
6269    BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
6270        @Override
6271        public void onReceive(Context context, Intent intent) {
6272            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
6273                // tickle the settings observer: this first ensures that we're
6274                // observing the relevant settings for the newly-active user,
6275                // and then updates our own bookkeeping based on the now-
6276                // current user.
6277                mSettingsObserver.onChange(false);
6278
6279                // force a re-application of focused window sysui visibility.
6280                // the window may never have been shown for this user
6281                // e.g. the keyguard when going through the new-user setup flow
6282                synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6283                    mLastSystemUiFlags = 0;
6284                    updateSystemUiVisibilityLw();
6285                }
6286            }
6287        }
6288    };
6289
6290    private final Runnable mHiddenNavPanic = new Runnable() {
6291        @Override
6292        public void run() {
6293            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6294                if (!isUserSetupComplete()) {
6295                    // Swipe-up for navigation bar is disabled during setup
6296                    return;
6297                }
6298                mPendingPanicGestureUptime = SystemClock.uptimeMillis();
6299                if (!isNavBarEmpty(mLastSystemUiFlags)) {
6300                    mNavigationBarController.showTransient();
6301                }
6302            }
6303        }
6304    };
6305
6306    private void requestTransientBars(WindowState swipeTarget) {
6307        synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
6308            if (!isUserSetupComplete()) {
6309                // Swipe-up for navigation bar is disabled during setup
6310                return;
6311            }
6312            boolean sb = mStatusBarController.checkShowTransientBarLw();
6313            boolean nb = mNavigationBarController.checkShowTransientBarLw()
6314                    && !isNavBarEmpty(mLastSystemUiFlags);
6315            if (sb || nb) {
6316                // Don't show status bar when swiping on already visible navigation bar
6317                if (!nb && swipeTarget == mNavigationBar) {
6318                    if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
6319                    return;
6320                }
6321                if (sb) mStatusBarController.showTransient();
6322                if (nb) mNavigationBarController.showTransient();
6323                mImmersiveModeConfirmation.confirmCurrentPrompt();
6324                updateSystemUiVisibilityLw();
6325            }
6326        }
6327    }
6328
6329    // Called on the PowerManager's Notifier thread.
6330    @Override
6331    public void startedGoingToSleep(int why) {
6332        if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
6333        mCameraGestureTriggeredDuringGoingToSleep = false;
6334        mGoingToSleep = true;
6335        if (mKeyguardDelegate != null) {
6336            mKeyguardDelegate.onStartedGoingToSleep(why);
6337        }
6338    }
6339
6340    // Called on the PowerManager's Notifier thread.
6341    @Override
6342    public void finishedGoingToSleep(int why) {
6343        EventLog.writeEvent(70000, 0);
6344        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
6345        MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
6346
6347        mGoingToSleep = false;
6348
6349        // We must get this work done here because the power manager will drop
6350        // the wake lock and let the system suspend once this function returns.
6351        synchronized (mLock) {
6352            mAwake = false;
6353            updateWakeGestureListenerLp();
6354            updateOrientationListenerLp();
6355            updateLockScreenTimeout();
6356        }
6357        if (mKeyguardDelegate != null) {
6358            mKeyguardDelegate.onFinishedGoingToSleep(why,
6359                    mCameraGestureTriggeredDuringGoingToSleep);
6360        }
6361        mCameraGestureTriggeredDuringGoingToSleep = false;
6362    }
6363
6364    // Called on the PowerManager's Notifier thread.
6365    @Override
6366    public void startedWakingUp() {
6367        EventLog.writeEvent(70000, 1);
6368        if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
6369
6370        // Since goToSleep performs these functions synchronously, we must
6371        // do the same here.  We cannot post this work to a handler because
6372        // that might cause it to become reordered with respect to what
6373        // may happen in a future call to goToSleep.
6374        synchronized (mLock) {
6375            mAwake = true;
6376
6377            updateWakeGestureListenerLp();
6378            updateOrientationListenerLp();
6379            updateLockScreenTimeout();
6380        }
6381
6382        if (mKeyguardDelegate != null) {
6383            mKeyguardDelegate.onStartedWakingUp();
6384        }
6385    }
6386
6387    // Called on the PowerManager's Notifier thread.
6388    @Override
6389    public void finishedWakingUp() {
6390        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
6391    }
6392
6393    private void wakeUpFromPowerKey(long eventTime) {
6394        wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
6395    }
6396
6397    private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
6398        final boolean theaterModeEnabled = isTheaterModeEnabled();
6399        if (!wakeInTheaterMode && theaterModeEnabled) {
6400            return false;
6401        }
6402
6403        if (theaterModeEnabled) {
6404            Settings.Global.putInt(mContext.getContentResolver(),
6405                    Settings.Global.THEATER_MODE_ON, 0);
6406        }
6407
6408        mPowerManager.wakeUp(wakeTime, reason);
6409        return true;
6410    }
6411
6412    private void finishKeyguardDrawn() {
6413        synchronized (mLock) {
6414            if (!mScreenOnEarly || mKeyguardDrawComplete) {
6415                return; // We are not awake yet or we have already informed of this event.
6416            }
6417
6418            mKeyguardDrawComplete = true;
6419            if (mKeyguardDelegate != null) {
6420                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6421            }
6422            mWindowManagerDrawComplete = false;
6423        }
6424
6425        // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
6426        // as well as enabling the orientation change logic/sensor.
6427        mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
6428                WAITING_FOR_DRAWN_TIMEOUT);
6429    }
6430
6431    // Called on the DisplayManager's DisplayPowerController thread.
6432    @Override
6433    public void screenTurnedOff() {
6434        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
6435
6436        updateScreenOffSleepToken(true);
6437        synchronized (mLock) {
6438            mScreenOnEarly = false;
6439            mScreenOnFully = false;
6440            mKeyguardDrawComplete = false;
6441            mWindowManagerDrawComplete = false;
6442            mScreenOnListener = null;
6443            updateOrientationListenerLp();
6444
6445            if (mKeyguardDelegate != null) {
6446                mKeyguardDelegate.onScreenTurnedOff();
6447            }
6448        }
6449    }
6450
6451    // Called on the DisplayManager's DisplayPowerController thread.
6452    @Override
6453    public void screenTurningOn(final ScreenOnListener screenOnListener) {
6454        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
6455
6456        updateScreenOffSleepToken(false);
6457        synchronized (mLock) {
6458            mScreenOnEarly = true;
6459            mScreenOnFully = false;
6460            mKeyguardDrawComplete = false;
6461            mWindowManagerDrawComplete = false;
6462            mScreenOnListener = screenOnListener;
6463
6464            if (mKeyguardDelegate != null) {
6465                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
6466                mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
6467                mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
6468            } else {
6469                if (DEBUG_WAKEUP) Slog.d(TAG,
6470                        "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
6471                finishKeyguardDrawn();
6472            }
6473        }
6474    }
6475
6476    // Called on the DisplayManager's DisplayPowerController thread.
6477    @Override
6478    public void screenTurnedOn() {
6479        synchronized (mLock) {
6480            if (mKeyguardDelegate != null) {
6481                mKeyguardDelegate.onScreenTurnedOn();
6482            }
6483        }
6484    }
6485
6486    private void finishWindowsDrawn() {
6487        synchronized (mLock) {
6488            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
6489                return; // Screen is not turned on or we did already handle this case earlier.
6490            }
6491
6492            mWindowManagerDrawComplete = true;
6493        }
6494
6495        finishScreenTurningOn();
6496    }
6497
6498    private void finishScreenTurningOn() {
6499        synchronized (mLock) {
6500            // We have just finished drawing screen content. Since the orientation listener
6501            // gets only installed when all windows are drawn, we try to install it again.
6502            updateOrientationListenerLp();
6503        }
6504        final ScreenOnListener listener;
6505        final boolean enableScreen;
6506        synchronized (mLock) {
6507            if (DEBUG_WAKEUP) Slog.d(TAG,
6508                    "finishScreenTurningOn: mAwake=" + mAwake
6509                            + ", mScreenOnEarly=" + mScreenOnEarly
6510                            + ", mScreenOnFully=" + mScreenOnFully
6511                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
6512                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
6513
6514            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
6515                    || (mAwake && !mKeyguardDrawComplete)) {
6516                return; // spurious or not ready yet
6517            }
6518
6519            if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
6520            listener = mScreenOnListener;
6521            mScreenOnListener = null;
6522            mScreenOnFully = true;
6523
6524            // Remember the first time we draw the keyguard so we know when we're done with
6525            // the main part of booting and can enable the screen and hide boot messages.
6526            if (!mKeyguardDrawnOnce && mAwake) {
6527                mKeyguardDrawnOnce = true;
6528                enableScreen = true;
6529                if (mBootMessageNeedsHiding) {
6530                    mBootMessageNeedsHiding = false;
6531                    hideBootMessages();
6532                }
6533            } else {
6534                enableScreen = false;
6535            }
6536        }
6537
6538        if (listener != null) {
6539            listener.onScreenOn();
6540        }
6541
6542        if (enableScreen) {
6543            try {
6544                mWindowManager.enableScreenIfNeeded();
6545            } catch (RemoteException unhandled) {
6546            }
6547        }
6548    }
6549
6550    private void handleHideBootMessage() {
6551        synchronized (mLock) {
6552            if (!mKeyguardDrawnOnce) {
6553                mBootMessageNeedsHiding = true;
6554                return; // keyguard hasn't drawn the first time yet, not done booting
6555            }
6556        }
6557
6558        if (mBootMsgDialog != null) {
6559            if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
6560            mBootMsgDialog.dismiss();
6561            mBootMsgDialog = null;
6562        }
6563    }
6564
6565    @Override
6566    public boolean isScreenOn() {
6567        return mScreenOnFully;
6568    }
6569
6570    /** {@inheritDoc} */
6571    @Override
6572    public void enableKeyguard(boolean enabled) {
6573        if (mKeyguardDelegate != null) {
6574            mKeyguardDelegate.setKeyguardEnabled(enabled);
6575        }
6576    }
6577
6578    /** {@inheritDoc} */
6579    @Override
6580    public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
6581        if (mKeyguardDelegate != null) {
6582            mKeyguardDelegate.verifyUnlock(callback);
6583        }
6584    }
6585
6586    @Override
6587    public boolean isKeyguardShowingAndNotOccluded() {
6588        if (mKeyguardDelegate == null) return false;
6589        return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
6590    }
6591
6592    @Override
6593    public boolean isKeyguardTrustedLw() {
6594        if (mKeyguardDelegate == null) return false;
6595        return mKeyguardDelegate.isTrusted();
6596    }
6597
6598    /** {@inheritDoc} */
6599    @Override
6600    public boolean isKeyguardLocked() {
6601        return keyguardOn();
6602    }
6603
6604    /** {@inheritDoc} */
6605    @Override
6606    public boolean isKeyguardSecure(int userId) {
6607        if (mKeyguardDelegate == null) return false;
6608        return mKeyguardDelegate.isSecure(userId);
6609    }
6610
6611    /** {@inheritDoc} */
6612    @Override
6613    public boolean isKeyguardOccluded() {
6614        if (mKeyguardDelegate == null) return false;
6615        return mKeyguardOccluded;
6616    }
6617
6618    /** {@inheritDoc} */
6619    @Override
6620    public boolean inKeyguardRestrictedKeyInputMode() {
6621        if (mKeyguardDelegate == null) return false;
6622        return mKeyguardDelegate.isInputRestricted();
6623    }
6624
6625    @Override
6626    public void dismissKeyguardLw() {
6627        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
6628            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
6629
6630            // ask the keyguard to prompt the user to authenticate if necessary
6631            mKeyguardDelegate.dismiss(true /* allowWhileOccluded */);
6632        }
6633    }
6634
6635    @Override
6636    public boolean isKeyguardDrawnLw() {
6637        synchronized (mLock) {
6638            return mKeyguardDrawnOnce;
6639        }
6640    }
6641
6642    @Override
6643    public boolean isShowingDreamLw() {
6644        return mShowingDream;
6645    }
6646
6647    @Override
6648    public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
6649        if (mKeyguardDelegate != null) {
6650            if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
6651            mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
6652        }
6653    }
6654
6655    @Override
6656    public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6657            Rect outInsets) {
6658        outInsets.setEmpty();
6659
6660        // Navigation bar and status bar.
6661        getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
6662        if (mStatusBar != null) {
6663            outInsets.top = mStatusBarHeight;
6664        }
6665    }
6666
6667    @Override
6668    public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
6669            Rect outInsets) {
6670        outInsets.setEmpty();
6671
6672        // Only navigation bar
6673        if (mNavigationBar != null) {
6674            int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
6675            if (position == NAV_BAR_BOTTOM) {
6676                outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
6677            } else if (position == NAV_BAR_RIGHT) {
6678                outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
6679            } else if (position == NAV_BAR_LEFT) {
6680                outInsets.left = getNavigationBarWidth(displayRotation, mUiMode);
6681            }
6682        }
6683    }
6684
6685    @Override
6686    public boolean isNavBarForcedShownLw(WindowState windowState) {
6687        return mForceShowSystemBars;
6688    }
6689
6690    @Override
6691    public boolean isDockSideAllowed(int dockSide) {
6692
6693        // We do not allow all dock sides at which the navigation bar touches the docked stack.
6694        if (!mNavigationBarCanMove) {
6695            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT;
6696        } else {
6697            return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT;
6698        }
6699    }
6700
6701    void sendCloseSystemWindows() {
6702        PhoneWindow.sendCloseSystemWindows(mContext, null);
6703    }
6704
6705    void sendCloseSystemWindows(String reason) {
6706        PhoneWindow.sendCloseSystemWindows(mContext, reason);
6707    }
6708
6709    @Override
6710    public int rotationForOrientationLw(int orientation, int lastRotation) {
6711        if (false) {
6712            Slog.v(TAG, "rotationForOrientationLw(orient="
6713                        + orientation + ", last=" + lastRotation
6714                        + "); user=" + mUserRotation + " "
6715                        + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
6716                            ? "USER_ROTATION_LOCKED" : "")
6717                        );
6718        }
6719
6720        if (mForceDefaultOrientation) {
6721            return Surface.ROTATION_0;
6722        }
6723
6724        synchronized (mLock) {
6725            int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
6726            if (sensorRotation < 0) {
6727                sensorRotation = lastRotation;
6728            }
6729
6730            final int preferredRotation;
6731            if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
6732                // Ignore sensor when lid switch is open and rotation is forced.
6733                preferredRotation = mLidOpenRotation;
6734            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
6735                    && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
6736                // Ignore sensor when in car dock unless explicitly enabled.
6737                // This case can override the behavior of NOSENSOR, and can also
6738                // enable 180 degree rotation while docked.
6739                preferredRotation = mCarDockEnablesAccelerometer
6740                        ? sensorRotation : mCarDockRotation;
6741            } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
6742                    || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
6743                    || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
6744                    && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
6745                // Ignore sensor when in desk dock unless explicitly enabled.
6746                // This case can override the behavior of NOSENSOR, and can also
6747                // enable 180 degree rotation while docked.
6748                preferredRotation = mDeskDockEnablesAccelerometer
6749                        ? sensorRotation : mDeskDockRotation;
6750            } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
6751                // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
6752                // Note that the dock orientation overrides the HDMI orientation.
6753                preferredRotation = mDemoHdmiRotation;
6754            } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
6755                    && mUndockedHdmiRotation >= 0) {
6756                // Ignore sensor when plugged into HDMI and an undocked orientation has
6757                // been specified in the configuration (only for legacy devices without
6758                // full multi-display support).
6759                // Note that the dock orientation overrides the HDMI orientation.
6760                preferredRotation = mUndockedHdmiRotation;
6761            } else if (mDemoRotationLock) {
6762                // Ignore sensor when demo rotation lock is enabled.
6763                // Note that the dock orientation and HDMI rotation lock override this.
6764                preferredRotation = mDemoRotation;
6765            } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
6766                // Application just wants to remain locked in the last rotation.
6767                preferredRotation = lastRotation;
6768            } else if (!mSupportAutoRotation) {
6769                // If we don't support auto-rotation then bail out here and ignore
6770                // the sensor and any rotation lock settings.
6771                preferredRotation = -1;
6772            } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
6773                            && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
6774                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
6775                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
6776                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
6777                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
6778                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
6779                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6780                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
6781                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
6782                // Otherwise, use sensor only if requested by the application or enabled
6783                // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
6784                if (mAllowAllRotations < 0) {
6785                    // Can't read this during init() because the context doesn't
6786                    // have display metrics at that time so we cannot determine
6787                    // tablet vs. phone then.
6788                    mAllowAllRotations = mContext.getResources().getBoolean(
6789                            com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
6790                }
6791                if (sensorRotation != Surface.ROTATION_180
6792                        || mAllowAllRotations == 1
6793                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
6794                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
6795                    preferredRotation = sensorRotation;
6796                } else {
6797                    preferredRotation = lastRotation;
6798                }
6799            } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
6800                    && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
6801                // Apply rotation lock.  Does not apply to NOSENSOR.
6802                // The idea is that the user rotation expresses a weak preference for the direction
6803                // of gravity and as NOSENSOR is never affected by gravity, then neither should
6804                // NOSENSOR be affected by rotation lock (although it will be affected by docks).
6805                preferredRotation = mUserRotation;
6806            } else {
6807                // No overriding preference.
6808                // We will do exactly what the application asked us to do.
6809                preferredRotation = -1;
6810            }
6811
6812            switch (orientation) {
6813                case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6814                    // Return portrait unless overridden.
6815                    if (isAnyPortrait(preferredRotation)) {
6816                        return preferredRotation;
6817                    }
6818                    return mPortraitRotation;
6819
6820                case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6821                    // Return landscape unless overridden.
6822                    if (isLandscapeOrSeascape(preferredRotation)) {
6823                        return preferredRotation;
6824                    }
6825                    return mLandscapeRotation;
6826
6827                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6828                    // Return reverse portrait unless overridden.
6829                    if (isAnyPortrait(preferredRotation)) {
6830                        return preferredRotation;
6831                    }
6832                    return mUpsideDownRotation;
6833
6834                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6835                    // Return seascape unless overridden.
6836                    if (isLandscapeOrSeascape(preferredRotation)) {
6837                        return preferredRotation;
6838                    }
6839                    return mSeascapeRotation;
6840
6841                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6842                case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
6843                    // Return either landscape rotation.
6844                    if (isLandscapeOrSeascape(preferredRotation)) {
6845                        return preferredRotation;
6846                    }
6847                    if (isLandscapeOrSeascape(lastRotation)) {
6848                        return lastRotation;
6849                    }
6850                    return mLandscapeRotation;
6851
6852                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6853                case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
6854                    // Return either portrait rotation.
6855                    if (isAnyPortrait(preferredRotation)) {
6856                        return preferredRotation;
6857                    }
6858                    if (isAnyPortrait(lastRotation)) {
6859                        return lastRotation;
6860                    }
6861                    return mPortraitRotation;
6862
6863                default:
6864                    // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
6865                    // just return the preferred orientation we already calculated.
6866                    if (preferredRotation >= 0) {
6867                        return preferredRotation;
6868                    }
6869                    return Surface.ROTATION_0;
6870            }
6871        }
6872    }
6873
6874    @Override
6875    public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
6876        switch (orientation) {
6877            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
6878            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
6879            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
6880                return isAnyPortrait(rotation);
6881
6882            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
6883            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
6884            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
6885                return isLandscapeOrSeascape(rotation);
6886
6887            default:
6888                return true;
6889        }
6890    }
6891
6892    @Override
6893    public void setRotationLw(int rotation) {
6894        mOrientationListener.setCurrentRotation(rotation);
6895    }
6896
6897    private boolean isLandscapeOrSeascape(int rotation) {
6898        return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
6899    }
6900
6901    private boolean isAnyPortrait(int rotation) {
6902        return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
6903    }
6904
6905    @Override
6906    public int getUserRotationMode() {
6907        return Settings.System.getIntForUser(mContext.getContentResolver(),
6908                Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
6909                        WindowManagerPolicy.USER_ROTATION_FREE :
6910                                WindowManagerPolicy.USER_ROTATION_LOCKED;
6911    }
6912
6913    // User rotation: to be used when all else fails in assigning an orientation to the device
6914    @Override
6915    public void setUserRotationMode(int mode, int rot) {
6916        ContentResolver res = mContext.getContentResolver();
6917
6918        // mUserRotationMode and mUserRotation will be assigned by the content observer
6919        if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
6920            Settings.System.putIntForUser(res,
6921                    Settings.System.USER_ROTATION,
6922                    rot,
6923                    UserHandle.USER_CURRENT);
6924            Settings.System.putIntForUser(res,
6925                    Settings.System.ACCELEROMETER_ROTATION,
6926                    0,
6927                    UserHandle.USER_CURRENT);
6928        } else {
6929            Settings.System.putIntForUser(res,
6930                    Settings.System.ACCELEROMETER_ROTATION,
6931                    1,
6932                    UserHandle.USER_CURRENT);
6933        }
6934    }
6935
6936    @Override
6937    public void setSafeMode(boolean safeMode) {
6938        mSafeMode = safeMode;
6939        performHapticFeedbackLw(null, safeMode
6940                ? HapticFeedbackConstants.SAFE_MODE_ENABLED
6941                : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
6942    }
6943
6944    static long[] getLongIntArray(Resources r, int resid) {
6945        int[] ar = r.getIntArray(resid);
6946        if (ar == null) {
6947            return null;
6948        }
6949        long[] out = new long[ar.length];
6950        for (int i=0; i<ar.length; i++) {
6951            out[i] = ar[i];
6952        }
6953        return out;
6954    }
6955
6956    /** {@inheritDoc} */
6957    @Override
6958    public void systemReady() {
6959        mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
6960        mKeyguardDelegate.onSystemReady();
6961
6962        readCameraLensCoverState();
6963        updateUiMode();
6964        boolean bindKeyguardNow;
6965        synchronized (mLock) {
6966            updateOrientationListenerLp();
6967            mSystemReady = true;
6968            mHandler.post(new Runnable() {
6969                @Override
6970                public void run() {
6971                    updateSettings();
6972                }
6973            });
6974
6975            bindKeyguardNow = mDeferBindKeyguard;
6976            if (bindKeyguardNow) {
6977                // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now.
6978                mDeferBindKeyguard = false;
6979            }
6980        }
6981
6982        if (bindKeyguardNow) {
6983            mKeyguardDelegate.bindService(mContext);
6984            mKeyguardDelegate.onBootCompleted();
6985        }
6986        mSystemGestures.systemReady();
6987        mImmersiveModeConfirmation.systemReady();
6988    }
6989
6990    /** {@inheritDoc} */
6991    @Override
6992    public void systemBooted() {
6993        boolean bindKeyguardNow = false;
6994        synchronized (mLock) {
6995            // Time to bind Keyguard; take care to only bind it once, either here if ready or
6996            // in systemReady if not.
6997            if (mKeyguardDelegate != null) {
6998                bindKeyguardNow = true;
6999            } else {
7000                // Because mKeyguardDelegate is null, we know that the synchronized block in
7001                // systemReady didn't run yet and setting this will actually have an effect.
7002                mDeferBindKeyguard = true;
7003            }
7004        }
7005        if (bindKeyguardNow) {
7006            mKeyguardDelegate.bindService(mContext);
7007            mKeyguardDelegate.onBootCompleted();
7008        }
7009        synchronized (mLock) {
7010            mSystemBooted = true;
7011        }
7012        startedWakingUp();
7013        screenTurningOn(null);
7014        screenTurnedOn();
7015    }
7016
7017    ProgressDialog mBootMsgDialog = null;
7018
7019    /** {@inheritDoc} */
7020    @Override
7021    public void showBootMessage(final CharSequence msg, final boolean always) {
7022        mHandler.post(new Runnable() {
7023            @Override public void run() {
7024                if (mBootMsgDialog == null) {
7025                    int theme;
7026                    if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) {
7027                        theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
7028                    } else {
7029                        theme = 0;
7030                    }
7031
7032                    mBootMsgDialog = new ProgressDialog(mContext, theme) {
7033                        // This dialog will consume all events coming in to
7034                        // it, to avoid it trying to do things too early in boot.
7035                        @Override public boolean dispatchKeyEvent(KeyEvent event) {
7036                            return true;
7037                        }
7038                        @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7039                            return true;
7040                        }
7041                        @Override public boolean dispatchTouchEvent(MotionEvent ev) {
7042                            return true;
7043                        }
7044                        @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
7045                            return true;
7046                        }
7047                        @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
7048                            return true;
7049                        }
7050                        @Override public boolean dispatchPopulateAccessibilityEvent(
7051                                AccessibilityEvent event) {
7052                            return true;
7053                        }
7054                    };
7055                    if (mContext.getPackageManager().isUpgrade()) {
7056                        mBootMsgDialog.setTitle(R.string.android_upgrading_title);
7057                    } else {
7058                        mBootMsgDialog.setTitle(R.string.android_start_title);
7059                    }
7060                    mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
7061                    mBootMsgDialog.setIndeterminate(true);
7062                    mBootMsgDialog.getWindow().setType(
7063                            WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
7064                    mBootMsgDialog.getWindow().addFlags(
7065                            WindowManager.LayoutParams.FLAG_DIM_BEHIND
7066                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
7067                    mBootMsgDialog.getWindow().setDimAmount(1);
7068                    WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
7069                    lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
7070                    mBootMsgDialog.getWindow().setAttributes(lp);
7071                    mBootMsgDialog.setCancelable(false);
7072                    mBootMsgDialog.show();
7073                }
7074                mBootMsgDialog.setMessage(msg);
7075            }
7076        });
7077    }
7078
7079    /** {@inheritDoc} */
7080    @Override
7081    public void hideBootMessages() {
7082        mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
7083    }
7084
7085    /** {@inheritDoc} */
7086    @Override
7087    public void userActivity() {
7088        // ***************************************
7089        // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
7090        // ***************************************
7091        // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
7092        // WITH ITS LOCKS HELD.
7093        //
7094        // This code must be VERY careful about the locks
7095        // it acquires.
7096        // In fact, the current code acquires way too many,
7097        // and probably has lurking deadlocks.
7098
7099        synchronized (mScreenLockTimeout) {
7100            if (mLockScreenTimerActive) {
7101                // reset the timer
7102                mHandler.removeCallbacks(mScreenLockTimeout);
7103                mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7104            }
7105        }
7106    }
7107
7108    class ScreenLockTimeout implements Runnable {
7109        Bundle options;
7110
7111        @Override
7112        public void run() {
7113            synchronized (this) {
7114                if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
7115                if (mKeyguardDelegate != null) {
7116                    mKeyguardDelegate.doKeyguardTimeout(options);
7117                }
7118                mLockScreenTimerActive = false;
7119                options = null;
7120            }
7121        }
7122
7123        public void setLockOptions(Bundle options) {
7124            this.options = options;
7125        }
7126    }
7127
7128    ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
7129
7130    @Override
7131    public void lockNow(Bundle options) {
7132        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
7133        mHandler.removeCallbacks(mScreenLockTimeout);
7134        if (options != null) {
7135            // In case multiple calls are made to lockNow, we don't wipe out the options
7136            // until the runnable actually executes.
7137            mScreenLockTimeout.setLockOptions(options);
7138        }
7139        mHandler.post(mScreenLockTimeout);
7140    }
7141
7142    private void updateLockScreenTimeout() {
7143        synchronized (mScreenLockTimeout) {
7144            boolean enable = (mAllowLockscreenWhenOn && mAwake &&
7145                    mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
7146            if (mLockScreenTimerActive != enable) {
7147                if (enable) {
7148                    if (localLOGV) Log.v(TAG, "setting lockscreen timer");
7149                    mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
7150                    mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
7151                } else {
7152                    if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
7153                    mHandler.removeCallbacks(mScreenLockTimeout);
7154                }
7155                mLockScreenTimerActive = enable;
7156            }
7157        }
7158    }
7159
7160    private void updateDreamingSleepToken(boolean acquire) {
7161        if (acquire) {
7162            if (mDreamingSleepToken == null) {
7163                mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream");
7164            }
7165        } else {
7166            if (mDreamingSleepToken != null) {
7167                mDreamingSleepToken.release();
7168                mDreamingSleepToken = null;
7169            }
7170        }
7171    }
7172
7173    private void updateScreenOffSleepToken(boolean acquire) {
7174        if (acquire) {
7175            if (mScreenOffSleepToken == null) {
7176                mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff");
7177            }
7178        } else {
7179            if (mScreenOffSleepToken != null) {
7180                mScreenOffSleepToken.release();
7181                mScreenOffSleepToken = null;
7182            }
7183        }
7184    }
7185
7186    /** {@inheritDoc} */
7187    @Override
7188    public void enableScreenAfterBoot() {
7189        readLidState();
7190        applyLidSwitchState();
7191        updateRotation(true);
7192    }
7193
7194    private void applyLidSwitchState() {
7195        if (mLidState == LID_CLOSED && mLidControlsSleep) {
7196            mPowerManager.goToSleep(SystemClock.uptimeMillis(),
7197                    PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
7198                    PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
7199        } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
7200            mWindowManagerFuncs.lockDeviceNow();
7201        }
7202
7203        synchronized (mLock) {
7204            updateWakeGestureListenerLp();
7205        }
7206    }
7207
7208    void updateUiMode() {
7209        if (mUiModeManager == null) {
7210            mUiModeManager = IUiModeManager.Stub.asInterface(
7211                    ServiceManager.getService(Context.UI_MODE_SERVICE));
7212        }
7213        try {
7214            mUiMode = mUiModeManager.getCurrentModeType();
7215        } catch (RemoteException e) {
7216        }
7217    }
7218
7219    void updateRotation(boolean alwaysSendConfiguration) {
7220        try {
7221            //set orientation on WindowManager
7222            mWindowManager.updateRotation(alwaysSendConfiguration, false);
7223        } catch (RemoteException e) {
7224            // Ignore
7225        }
7226    }
7227
7228    void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
7229        try {
7230            //set orientation on WindowManager
7231            mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
7232        } catch (RemoteException e) {
7233            // Ignore
7234        }
7235    }
7236
7237    /**
7238     * Return an Intent to launch the currently active dock app as home.  Returns
7239     * null if the standard home should be launched, which is the case if any of the following is
7240     * true:
7241     * <ul>
7242     *  <li>The device is not in either car mode or desk mode
7243     *  <li>The device is in car mode but mEnableCarDockHomeCapture is false
7244     *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
7245     *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
7246     *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
7247     * </ul>
7248     * @return A dock intent.
7249     */
7250    Intent createHomeDockIntent() {
7251        Intent intent = null;
7252
7253        // What home does is based on the mode, not the dock state.  That
7254        // is, when in car mode you should be taken to car home regardless
7255        // of whether we are actually in a car dock.
7256        if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
7257            if (mEnableCarDockHomeCapture) {
7258                intent = mCarDockIntent;
7259            }
7260        } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
7261            if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
7262                intent = mDeskDockIntent;
7263            }
7264        } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
7265                && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
7266                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
7267                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
7268            // Always launch dock home from home when watch is docked, if it exists.
7269            intent = mDeskDockIntent;
7270        }
7271
7272        if (intent == null) {
7273            return null;
7274        }
7275
7276        ActivityInfo ai = null;
7277        ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
7278                intent,
7279                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
7280                mCurrentUserId);
7281        if (info != null) {
7282            ai = info.activityInfo;
7283        }
7284        if (ai != null
7285                && ai.metaData != null
7286                && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
7287            intent = new Intent(intent);
7288            intent.setClassName(ai.packageName, ai.name);
7289            return intent;
7290        }
7291
7292        return null;
7293    }
7294
7295    void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
7296        if (awakenFromDreams) {
7297            awakenDreams();
7298        }
7299
7300        Intent dock = createHomeDockIntent();
7301        if (dock != null) {
7302            try {
7303                if (fromHomeKey) {
7304                    dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7305                }
7306                startActivityAsUser(dock, UserHandle.CURRENT);
7307                return;
7308            } catch (ActivityNotFoundException e) {
7309            }
7310        }
7311
7312        Intent intent;
7313
7314        if (fromHomeKey) {
7315            intent = new Intent(mHomeIntent);
7316            intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
7317        } else {
7318            intent = mHomeIntent;
7319        }
7320
7321        startActivityAsUser(intent, UserHandle.CURRENT);
7322    }
7323
7324    /**
7325     * goes to the home screen
7326     * @return whether it did anything
7327     */
7328    boolean goHome() {
7329        if (!isUserSetupComplete()) {
7330            Slog.i(TAG, "Not going home because user setup is in progress.");
7331            return false;
7332        }
7333        if (false) {
7334            // This code always brings home to the front.
7335            try {
7336                ActivityManagerNative.getDefault().stopAppSwitches();
7337            } catch (RemoteException e) {
7338            }
7339            sendCloseSystemWindows();
7340            startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
7341        } else {
7342            // This code brings home to the front or, if it is already
7343            // at the front, puts the device to sleep.
7344            try {
7345                if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
7346                    /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
7347                    Log.d(TAG, "UTS-TEST-MODE");
7348                } else {
7349                    ActivityManagerNative.getDefault().stopAppSwitches();
7350                    sendCloseSystemWindows();
7351                    Intent dock = createHomeDockIntent();
7352                    if (dock != null) {
7353                        int result = ActivityManagerNative.getDefault()
7354                                .startActivityAsUser(null, null, dock,
7355                                        dock.resolveTypeIfNeeded(mContext.getContentResolver()),
7356                                        null, null, 0,
7357                                        ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7358                                        null, null, UserHandle.USER_CURRENT);
7359                        if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7360                            return false;
7361                        }
7362                    }
7363                }
7364                int result = ActivityManagerNative.getDefault()
7365                        .startActivityAsUser(null, null, mHomeIntent,
7366                                mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
7367                                null, null, 0,
7368                                ActivityManager.START_FLAG_ONLY_IF_NEEDED,
7369                                null, null, UserHandle.USER_CURRENT);
7370                if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
7371                    return false;
7372                }
7373            } catch (RemoteException ex) {
7374                // bummer, the activity manager, which is in this process, is dead
7375            }
7376        }
7377        return true;
7378    }
7379
7380    @Override
7381    public void setCurrentOrientationLw(int newOrientation) {
7382        synchronized (mLock) {
7383            if (newOrientation != mCurrentAppOrientation) {
7384                mCurrentAppOrientation = newOrientation;
7385                updateOrientationListenerLp();
7386            }
7387        }
7388    }
7389
7390    private void performAuditoryFeedbackForAccessibilityIfNeed() {
7391        if (!isGlobalAccessibilityGestureEnabled()) {
7392            return;
7393        }
7394        AudioManager audioManager = (AudioManager) mContext.getSystemService(
7395                Context.AUDIO_SERVICE);
7396        if (audioManager.isSilentMode()) {
7397            return;
7398        }
7399        Ringtone ringTone = RingtoneManager.getRingtone(mContext,
7400                Settings.System.DEFAULT_NOTIFICATION_URI);
7401        ringTone.setStreamType(AudioManager.STREAM_MUSIC);
7402        ringTone.play();
7403    }
7404
7405    private boolean isTheaterModeEnabled() {
7406        return Settings.Global.getInt(mContext.getContentResolver(),
7407                Settings.Global.THEATER_MODE_ON, 0) == 1;
7408    }
7409
7410    private boolean isGlobalAccessibilityGestureEnabled() {
7411        return Settings.Global.getInt(mContext.getContentResolver(),
7412                Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1;
7413    }
7414
7415    private boolean areSystemNavigationKeysEnabled() {
7416        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
7417                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
7418    }
7419
7420    @Override
7421    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
7422        if (!mVibrator.hasVibrator()) {
7423            return false;
7424        }
7425        final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
7426                Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
7427        if (hapticsDisabled && !always) {
7428            return false;
7429        }
7430        long[] pattern = null;
7431        switch (effectId) {
7432            case HapticFeedbackConstants.LONG_PRESS:
7433                pattern = mLongPressVibePattern;
7434                break;
7435            case HapticFeedbackConstants.VIRTUAL_KEY:
7436                pattern = mVirtualKeyVibePattern;
7437                break;
7438            case HapticFeedbackConstants.KEYBOARD_TAP:
7439                pattern = mKeyboardTapVibePattern;
7440                break;
7441            case HapticFeedbackConstants.CLOCK_TICK:
7442                pattern = mClockTickVibePattern;
7443                break;
7444            case HapticFeedbackConstants.CALENDAR_DATE:
7445                pattern = mCalendarDateVibePattern;
7446                break;
7447            case HapticFeedbackConstants.SAFE_MODE_DISABLED:
7448                pattern = mSafeModeDisabledVibePattern;
7449                break;
7450            case HapticFeedbackConstants.SAFE_MODE_ENABLED:
7451                pattern = mSafeModeEnabledVibePattern;
7452                break;
7453            case HapticFeedbackConstants.CONTEXT_CLICK:
7454                pattern = mContextClickVibePattern;
7455                break;
7456            default:
7457                return false;
7458        }
7459        int owningUid;
7460        String owningPackage;
7461        if (win != null) {
7462            owningUid = win.getOwningUid();
7463            owningPackage = win.getOwningPackage();
7464        } else {
7465            owningUid = android.os.Process.myUid();
7466            owningPackage = mContext.getOpPackageName();
7467        }
7468        if (pattern.length == 1) {
7469            // One-shot vibration
7470            mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES);
7471        } else {
7472            // Pattern vibration
7473            mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES);
7474        }
7475        return true;
7476    }
7477
7478    @Override
7479    public void keepScreenOnStartedLw() {
7480    }
7481
7482    @Override
7483    public void keepScreenOnStoppedLw() {
7484        if (isKeyguardShowingAndNotOccluded()) {
7485            mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
7486        }
7487    }
7488
7489    private int updateSystemUiVisibilityLw() {
7490        // If there is no window focused, there will be nobody to handle the events
7491        // anyway, so just hang on in whatever state we're in until things settle down.
7492        WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
7493                : mTopFullscreenOpaqueWindowState;
7494        if (winCandidate == null) {
7495            return 0;
7496        }
7497        if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
7498            // The immersive mode confirmation should never affect the system bar visibility,
7499            // otherwise it will unhide the navigation bar and hide itself.
7500            winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState;
7501            if (winCandidate == null) {
7502                return 0;
7503            }
7504        }
7505        final WindowState win = winCandidate;
7506        if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mKeyguardOccluded) {
7507            // We are updating at a point where the keyguard has gotten
7508            // focus, but we were last in a state where the top window is
7509            // hiding it.  This is probably because the keyguard as been
7510            // shown while the top window was displayed, so we want to ignore
7511            // it here because this is just a very transient change and it
7512            // will quickly lose focus once it correctly gets hidden.
7513            return 0;
7514        }
7515
7516        int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
7517                & ~mResettingSystemUiFlags
7518                & ~mForceClearedSystemUiFlags;
7519        if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
7520            tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
7521        }
7522
7523        final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
7524                mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
7525        final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
7526                mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
7527        mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);
7528        mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);
7529        final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
7530        final int diff = visibility ^ mLastSystemUiFlags;
7531        final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
7532        final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
7533        final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
7534        if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
7535                && mFocusedApp == win.getAppToken()
7536                && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
7537                && mLastDockedStackBounds.equals(mDockedStackBounds)) {
7538            return 0;
7539        }
7540        mLastSystemUiFlags = visibility;
7541        mLastFullscreenStackSysUiFlags = fullscreenVisibility;
7542        mLastDockedStackSysUiFlags = dockedVisibility;
7543        mLastFocusNeedsMenu = needsMenu;
7544        mFocusedApp = win.getAppToken();
7545        final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
7546        final Rect dockedStackBounds = new Rect(mDockedStackBounds);
7547        mHandler.post(new Runnable() {
7548                @Override
7549                public void run() {
7550                    StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
7551                    if (statusbar != null) {
7552                        statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
7553                                dockedVisibility, 0xffffffff, fullscreenStackBounds,
7554                                dockedStackBounds, win.toString());
7555                        statusbar.topAppWindowChanged(needsMenu);
7556                    }
7557                }
7558            });
7559        return diff;
7560    }
7561
7562    private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
7563        WindowState statusColorWin = isStatusBarKeyguard() && !mKeyguardOccluded
7564                ? mStatusBar
7565                : opaqueOrDimming;
7566
7567        if (statusColorWin != null) {
7568            if (statusColorWin == opaque) {
7569                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
7570                // its light flag.
7571                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7572                vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
7573                        & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7574            } else if (statusColorWin != null && statusColorWin.isDimming()) {
7575                // Otherwise if it's dimming, clear the light flag.
7576                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7577            }
7578        }
7579        return vis;
7580    }
7581
7582    private boolean drawsSystemBarBackground(WindowState win) {
7583        return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
7584    }
7585
7586    private boolean forcesDrawStatusBarBackground(WindowState win) {
7587        return win == null || (win.getAttrs().privateFlags
7588                & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
7589    }
7590
7591    private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
7592        final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
7593        final boolean freeformStackVisible =
7594                mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
7595        final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
7596
7597        // We need to force system bars when the docked stack is visible, when the freeform stack
7598        // is visible but also when we are resizing for the transitions when docked stack
7599        // visibility changes.
7600        mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
7601        final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
7602
7603        // apply translucent bar vis flags
7604        WindowState fullscreenTransWin = isStatusBarKeyguard() && !mKeyguardOccluded
7605                ? mStatusBar
7606                : mTopFullscreenOpaqueWindowState;
7607        vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7608        vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
7609        final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
7610                mTopDockedOpaqueWindowState, 0, 0);
7611
7612        final boolean fullscreenDrawsStatusBarBackground =
7613                (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
7614                        && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
7615                || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
7616        final boolean dockedDrawsStatusBarBackground =
7617                (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
7618                        && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
7619                || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
7620
7621        // prevent status bar interaction from clearing certain flags
7622        int type = win.getAttrs().type;
7623        boolean statusBarHasFocus = type == TYPE_STATUS_BAR;
7624        if (statusBarHasFocus && !isStatusBarKeyguard()) {
7625            int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
7626                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
7627                    | View.SYSTEM_UI_FLAG_IMMERSIVE
7628                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
7629                    | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
7630            if (mKeyguardOccluded) {
7631                flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
7632            }
7633            vis = (vis & ~flags) | (oldVis & flags);
7634        }
7635
7636        if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
7637            vis |= View.STATUS_BAR_TRANSPARENT;
7638            vis &= ~View.STATUS_BAR_TRANSLUCENT;
7639        } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
7640                || forceOpaqueStatusBar) {
7641            vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
7642        }
7643
7644        vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
7645
7646        // update status bar
7647        boolean immersiveSticky =
7648                (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7649        final boolean hideStatusBarWM =
7650                mTopFullscreenOpaqueWindowState != null
7651                && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
7652                        & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
7653        final boolean hideStatusBarSysui =
7654                (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
7655        final boolean hideNavBarSysui =
7656                (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
7657
7658        final boolean transientStatusBarAllowed = mStatusBar != null
7659                && (statusBarHasFocus || (!mForceShowSystemBars
7660                        && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
7661
7662        final boolean transientNavBarAllowed = mNavigationBar != null
7663                && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
7664
7665        final long now = SystemClock.uptimeMillis();
7666        final boolean pendingPanic = mPendingPanicGestureUptime != 0
7667                && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
7668        if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
7669            // The user performed the panic gesture recently, we're about to hide the bars,
7670            // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
7671            mPendingPanicGestureUptime = 0;
7672            mStatusBarController.showTransient();
7673            if (!isNavBarEmpty(vis)) {
7674                mNavigationBarController.showTransient();
7675            }
7676        }
7677
7678        final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested()
7679                && !transientStatusBarAllowed && hideStatusBarSysui;
7680        final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
7681                && !transientNavBarAllowed;
7682        if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
7683            // clear the clearable flags instead
7684            clearClearableFlagsLw();
7685            vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
7686        }
7687
7688        final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
7689        immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
7690        final boolean navAllowedHidden = immersive || immersiveSticky;
7691
7692        if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType())
7693                > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) {
7694            // We can't hide the navbar from this window otherwise the input consumer would not get
7695            // the input events.
7696            vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
7697        }
7698
7699        vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
7700
7701        // update navigation bar
7702        boolean oldImmersiveMode = isImmersiveMode(oldVis);
7703        boolean newImmersiveMode = isImmersiveMode(vis);
7704        if (win != null && oldImmersiveMode != newImmersiveMode) {
7705            final String pkg = win.getOwningPackage();
7706            mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
7707                    isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility()));
7708        }
7709
7710        vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
7711
7712        return vis;
7713    }
7714
7715    /**
7716     * @return the current visibility flags with the nav-bar opacity related flags toggled based
7717     *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
7718     */
7719    private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
7720            boolean freeformStackVisible, boolean isDockedDividerResizing) {
7721        if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
7722            if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
7723                visibility = setNavBarOpaqueFlag(visibility);
7724            }
7725        } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
7726            if (isDockedDividerResizing) {
7727                visibility = setNavBarOpaqueFlag(visibility);
7728            } else if (freeformStackVisible) {
7729                visibility = setNavBarTranslucentFlag(visibility);
7730            } else {
7731                visibility = setNavBarOpaqueFlag(visibility);
7732            }
7733        }
7734
7735        if (!areTranslucentBarsAllowed()) {
7736            visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
7737        }
7738        return visibility;
7739    }
7740
7741    private int setNavBarOpaqueFlag(int visibility) {
7742        return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
7743    }
7744
7745    private int setNavBarTranslucentFlag(int visibility) {
7746        visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
7747        return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
7748    }
7749
7750    private void clearClearableFlagsLw() {
7751        int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
7752        if (newVal != mResettingSystemUiFlags) {
7753            mResettingSystemUiFlags = newVal;
7754            mWindowManagerFuncs.reevaluateStatusBarVisibility();
7755        }
7756    }
7757
7758    private boolean isImmersiveMode(int vis) {
7759        final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
7760        return mNavigationBar != null
7761                && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
7762                && (vis & flags) != 0
7763                && canHideNavigationBar();
7764    }
7765
7766    private static boolean isNavBarEmpty(int systemUiFlags) {
7767        final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
7768                | View.STATUS_BAR_DISABLE_BACK
7769                | View.STATUS_BAR_DISABLE_RECENT);
7770
7771        return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
7772    }
7773
7774    /**
7775     * @return whether the navigation or status bar can be made translucent
7776     *
7777     * This should return true unless touch exploration is not enabled or
7778     * R.boolean.config_enableTranslucentDecor is false.
7779     */
7780    private boolean areTranslucentBarsAllowed() {
7781        return mTranslucentDecorEnabled;
7782    }
7783
7784    // Use this instead of checking config_showNavigationBar so that it can be consistently
7785    // overridden by qemu.hw.mainkeys in the emulator.
7786    @Override
7787    public boolean hasNavigationBar() {
7788        return mHasNavigationBar;
7789    }
7790
7791    @Override
7792    public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
7793        mLastInputMethodWindow = ime;
7794        mLastInputMethodTargetWindow = target;
7795    }
7796
7797    @Override
7798    public int getInputMethodWindowVisibleHeightLw() {
7799        return mDockBottom - mCurBottom;
7800    }
7801
7802    @Override
7803    public void setCurrentUserLw(int newUserId) {
7804        mCurrentUserId = newUserId;
7805        if (mKeyguardDelegate != null) {
7806            mKeyguardDelegate.setCurrentUser(newUserId);
7807        }
7808        StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
7809        if (statusBar != null) {
7810            statusBar.setCurrentUser(newUserId);
7811        }
7812        setLastInputMethodWindowLw(null, null);
7813    }
7814
7815    @Override
7816    public void setSwitchingUser(boolean switching) {
7817        mKeyguardDelegate.setSwitchingUser(switching);
7818    }
7819
7820    @Override
7821    public boolean canMagnifyWindow(int windowType) {
7822        switch (windowType) {
7823            case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
7824            case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
7825            case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
7826            case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
7827                return false;
7828            }
7829        }
7830        return true;
7831    }
7832
7833    @Override
7834    public boolean isTopLevelWindow(int windowType) {
7835        if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
7836                && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
7837            return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
7838        }
7839        return true;
7840    }
7841
7842    @Override
7843    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
7844        // For the upside down rotation we don't rotate seamlessly as the navigation
7845        // bar moves position.
7846        // Note most apps (using orientation:sensor or user as opposed to fullSensor)
7847        // will not enter the reverse portrait orientation, so actually the
7848        // orientation won't change at all.
7849        if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
7850            return false;
7851        }
7852        // If the navigation bar can't change sides, then it will
7853        // jump when we change orientations and we don't rotate
7854        // seamlessly.
7855        if (!mNavigationBarCanMove) {
7856            return false;
7857        }
7858        int delta = newRotation - oldRotation;
7859        if (delta < 0) delta += 4;
7860        // Likewise we don't rotate seamlessly for 180 degree rotations
7861        // in this case the surfaces never resize, and our logic to
7862        // revert the transformations on size change will fail. We could
7863        // fix this in the future with the "tagged" frames idea.
7864        if (delta == Surface.ROTATION_180) {
7865            return false;
7866        }
7867
7868        final WindowState w = mTopFullscreenOpaqueWindowState;
7869        if (w != mFocusedWindow) {
7870            return false;
7871        }
7872
7873        // We only enable seamless rotation if the top window has requested
7874        // it and is in the fullscreen opaque state. Seamless rotation
7875        // requires freezing various Surface states and won't work well
7876        // with animations, so we disable it in the animation case for now.
7877        if (w != null && !w.isAnimatingLw() &&
7878                ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) ||
7879                        (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) {
7880            return true;
7881        }
7882        return false;
7883    }
7884
7885    @Override
7886    public void dump(String prefix, PrintWriter pw, String[] args) {
7887        pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
7888                pw.print(" mSystemReady="); pw.print(mSystemReady);
7889                pw.print(" mSystemBooted="); pw.println(mSystemBooted);
7890        pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
7891                pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
7892                pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
7893                pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
7894        if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
7895                || mForceClearedSystemUiFlags != 0) {
7896            pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
7897                    pw.print(Integer.toHexString(mLastSystemUiFlags));
7898                    pw.print(" mResettingSystemUiFlags=0x");
7899                    pw.print(Integer.toHexString(mResettingSystemUiFlags));
7900                    pw.print(" mForceClearedSystemUiFlags=0x");
7901                    pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
7902        }
7903        if (mLastFocusNeedsMenu) {
7904            pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
7905                    pw.println(mLastFocusNeedsMenu);
7906        }
7907        pw.print(prefix); pw.print("mWakeGestureEnabledSetting=");
7908                pw.println(mWakeGestureEnabledSetting);
7909
7910        pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
7911        pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
7912                pw.print(" mDockMode="); pw.print(mDockMode);
7913                pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
7914                pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
7915                pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
7916        pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
7917                pw.print(" mUserRotation="); pw.print(mUserRotation);
7918                pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
7919        pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
7920        pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
7921                pw.print(mCarDockEnablesAccelerometer);
7922                pw.print(" mDeskDockEnablesAccelerometer=");
7923                pw.println(mDeskDockEnablesAccelerometer);
7924        pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
7925                pw.print(mLidKeyboardAccessibility);
7926                pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
7927                pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
7928                pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
7929        pw.print(prefix);
7930                pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
7931        pw.print(prefix);
7932                pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
7933                pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
7934        pw.print(prefix);
7935                pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
7936                pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
7937        pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
7938        pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
7939        pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
7940                pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
7941        pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
7942                pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
7943        pw.print(prefix); pw.print("mOrientationSensorEnabled=");
7944                pw.println(mOrientationSensorEnabled);
7945        pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
7946                pw.print(","); pw.print(mOverscanScreenTop);
7947                pw.print(") "); pw.print(mOverscanScreenWidth);
7948                pw.print("x"); pw.println(mOverscanScreenHeight);
7949        if (mOverscanLeft != 0 || mOverscanTop != 0
7950                || mOverscanRight != 0 || mOverscanBottom != 0) {
7951            pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
7952                    pw.print(" top="); pw.print(mOverscanTop);
7953                    pw.print(" right="); pw.print(mOverscanRight);
7954                    pw.print(" bottom="); pw.println(mOverscanBottom);
7955        }
7956        pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
7957                pw.print(mRestrictedOverscanScreenLeft);
7958                pw.print(","); pw.print(mRestrictedOverscanScreenTop);
7959                pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
7960                pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
7961        pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
7962                pw.print(","); pw.print(mUnrestrictedScreenTop);
7963                pw.print(") "); pw.print(mUnrestrictedScreenWidth);
7964                pw.print("x"); pw.println(mUnrestrictedScreenHeight);
7965        pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
7966                pw.print(","); pw.print(mRestrictedScreenTop);
7967                pw.print(") "); pw.print(mRestrictedScreenWidth);
7968                pw.print("x"); pw.println(mRestrictedScreenHeight);
7969        pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
7970                pw.print(","); pw.print(mStableFullscreenTop);
7971                pw.print(")-("); pw.print(mStableFullscreenRight);
7972                pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
7973        pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
7974                pw.print(","); pw.print(mStableTop);
7975                pw.print(")-("); pw.print(mStableRight);
7976                pw.print(","); pw.print(mStableBottom); pw.println(")");
7977        pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
7978                pw.print(","); pw.print(mSystemTop);
7979                pw.print(")-("); pw.print(mSystemRight);
7980                pw.print(","); pw.print(mSystemBottom); pw.println(")");
7981        pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
7982                pw.print(","); pw.print(mCurTop);
7983                pw.print(")-("); pw.print(mCurRight);
7984                pw.print(","); pw.print(mCurBottom); pw.println(")");
7985        pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
7986                pw.print(","); pw.print(mContentTop);
7987                pw.print(")-("); pw.print(mContentRight);
7988                pw.print(","); pw.print(mContentBottom); pw.println(")");
7989        pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft);
7990                pw.print(","); pw.print(mVoiceContentTop);
7991                pw.print(")-("); pw.print(mVoiceContentRight);
7992                pw.print(","); pw.print(mVoiceContentBottom); pw.println(")");
7993        pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
7994                pw.print(","); pw.print(mDockTop);
7995                pw.print(")-("); pw.print(mDockRight);
7996                pw.print(","); pw.print(mDockBottom); pw.println(")");
7997        pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
7998                pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
7999        pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
8000                pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
8001                pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
8002        if (mLastInputMethodWindow != null) {
8003            pw.print(prefix); pw.print("mLastInputMethodWindow=");
8004                    pw.println(mLastInputMethodWindow);
8005        }
8006        if (mLastInputMethodTargetWindow != null) {
8007            pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
8008                    pw.println(mLastInputMethodTargetWindow);
8009        }
8010        if (mStatusBar != null) {
8011            pw.print(prefix); pw.print("mStatusBar=");
8012                    pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
8013                    pw.println(isStatusBarKeyguard());
8014        }
8015        if (mNavigationBar != null) {
8016            pw.print(prefix); pw.print("mNavigationBar=");
8017                    pw.println(mNavigationBar);
8018        }
8019        if (mFocusedWindow != null) {
8020            pw.print(prefix); pw.print("mFocusedWindow=");
8021                    pw.println(mFocusedWindow);
8022        }
8023        if (mFocusedApp != null) {
8024            pw.print(prefix); pw.print("mFocusedApp=");
8025                    pw.println(mFocusedApp);
8026        }
8027        if (mTopFullscreenOpaqueWindowState != null) {
8028            pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
8029                    pw.println(mTopFullscreenOpaqueWindowState);
8030        }
8031        if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
8032            pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
8033                    pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
8034        }
8035        if (mForcingShowNavBar) {
8036            pw.print(prefix); pw.print("mForcingShowNavBar=");
8037                    pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
8038                    pw.println(mForcingShowNavBarLayer);
8039        }
8040        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
8041                pw.print(" mKeyguardOccluded="); pw.println(mKeyguardOccluded);
8042                pw.print(" mKeyguardOccludedChanged="); pw.println(mKeyguardOccludedChanged);
8043                pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded);
8044        pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
8045                pw.print(" mForceStatusBarFromKeyguard=");
8046                pw.println(mForceStatusBarFromKeyguard);
8047        pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
8048        pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
8049                pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
8050                pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
8051        pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
8052                pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
8053                pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior);
8054                pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
8055        pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
8056                pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
8057        pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
8058                pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
8059        pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
8060                pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
8061        pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
8062
8063        mGlobalKeyManager.dump(prefix, pw);
8064        mStatusBarController.dump(pw, prefix);
8065        mNavigationBarController.dump(pw, prefix);
8066        PolicyControl.dump(prefix, pw);
8067
8068        if (mWakeGestureListener != null) {
8069            mWakeGestureListener.dump(pw, prefix);
8070        }
8071        if (mOrientationListener != null) {
8072            mOrientationListener.dump(pw, prefix);
8073        }
8074        if (mBurnInProtectionHelper != null) {
8075            mBurnInProtectionHelper.dump(prefix, pw);
8076        }
8077        if (mKeyguardDelegate != null) {
8078            mKeyguardDelegate.dump(prefix, pw);
8079        }
8080    }
8081}
8082