OSDN Git Service

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