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>(); sApplicationLaunchKeyCategories.append( KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER)287 sApplicationLaunchKeyCategories.append( 288 KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER); sApplicationLaunchKeyCategories.append( KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL)289 sApplicationLaunchKeyCategories.append( 290 KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL); sApplicationLaunchKeyCategories.append( KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS)291 sApplicationLaunchKeyCategories.append( 292 KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS); sApplicationLaunchKeyCategories.append( KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR)293 sApplicationLaunchKeyCategories.append( 294 KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR); sApplicationLaunchKeyCategories.append( KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC)295 sApplicationLaunchKeyCategories.append( 296 KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC); sApplicationLaunchKeyCategories.append( KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR)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 handleMessage(Message msg)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 { SettingsObserver(Handler handler)811 SettingsObserver(Handler handler) { 812 super(handler); 813 } 814 observe()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 onChange(boolean selfChange)851 @Override public void onChange(boolean selfChange) { 852 updateSettings(); 853 updateRotation(false); 854 } 855 } 856 857 class MyWakeGestureListener extends WakeGestureListener { MyWakeGestureListener(Context context, Handler handler)858 MyWakeGestureListener(Context context, Handler handler) { 859 super(context, handler); 860 } 861 862 @Override onWakeUp()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 MyOrientationListener(Context context, Handler handler)884 MyOrientationListener(Context context, Handler handler) { 885 super(context, handler); 886 } 887 888 @Override onProposedRotationChanged(int rotation)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 getStatusBarService()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 getStatusBarManagerInternal()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 */ needSensorRunningLp()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 */ updateOrientationListenerLp()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 interceptPowerKeyDown(KeyEvent event, boolean interactive)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 interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled)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 finishPowerKeyPress()1135 private void finishPowerKeyPress() { 1136 mBeganFromNonInteractive = false; 1137 mPowerKeyPressCounter = 0; 1138 if (mPowerKeyWakeLock.isHeld()) { 1139 mPowerKeyWakeLock.release(); 1140 } 1141 } 1142 cancelPendingPowerKeyAction()1143 private void cancelPendingPowerKeyAction() { 1144 if (!mPowerKeyHandled) { 1145 mPowerKeyHandled = true; 1146 mHandler.removeMessages(MSG_POWER_LONG_PRESS); 1147 } 1148 } 1149 cancelPendingBackKeyAction()1150 private void cancelPendingBackKeyAction() { 1151 if (!mBackKeyHandled) { 1152 mBackKeyHandled = true; 1153 mHandler.removeMessages(MSG_BACK_LONG_PRESS); 1154 } 1155 } 1156 powerPress(long eventTime, boolean interactive, int count)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 powerMultiPressAction(long eventTime, boolean interactive, int behavior)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 getMaxMultiPressPowerCount()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 powerLongPress()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 backLongPress()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 disposeInputConsumer(InputConsumer inputConsumer)1277 private void disposeInputConsumer(InputConsumer inputConsumer) { 1278 if (inputConsumer != null) { 1279 inputConsumer.dismiss(); 1280 } 1281 } 1282 sleepPress(long eventTime)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 sleepRelease(long eventTime)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 getResolvedLongPressOnPowerBehavior()1300 private int getResolvedLongPressOnPowerBehavior() { 1301 if (FactoryTest.isLongPressOnPowerOffEnabled()) { 1302 return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM; 1303 } 1304 return mLongPressOnPowerBehavior; 1305 } 1306 hasLongPressOnPowerBehavior()1307 private boolean hasLongPressOnPowerBehavior() { 1308 return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING; 1309 } 1310 hasLongPressOnBackBehavior()1311 private boolean hasLongPressOnBackBehavior() { 1312 return mLongPressOnBackBehavior != LONG_PRESS_BACK_NOTHING; 1313 } 1314 interceptScreenshotChord()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 getScreenshotChordLongPressDelay()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 cancelPendingScreenshotChordAction()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 setScreenshotType(int screenshotType)1358 public void setScreenshotType(int screenshotType) { 1359 mScreenshotType = screenshotType; 1360 } 1361 1362 @Override run()1363 public void run() { 1364 takeScreenshot(mScreenshotType); 1365 } 1366 } 1367 1368 private final ScreenshotRunnable mScreenshotRunnable = new ScreenshotRunnable(); 1369 1370 @Override showGlobalActions()1371 public void showGlobalActions() { 1372 mHandler.removeMessages(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS); 1373 mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS); 1374 } 1375 showGlobalActionsInternal()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 isDeviceProvisioned()1390 boolean isDeviceProvisioned() { 1391 return Settings.Global.getInt( 1392 mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0; 1393 } 1394 isUserSetupComplete()1395 boolean isUserSetupComplete() { 1396 return Settings.Secure.getIntForUser(mContext.getContentResolver(), 1397 Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0; 1398 } 1399 handleShortPressOnHome()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 */ getHdmiControl()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 HdmiControl(HdmiPlaybackClient client)1436 private HdmiControl(HdmiPlaybackClient client) { 1437 mClient = client; 1438 } 1439 turnOnTv()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 handleLongPressOnHome(int deviceId)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 handleDoubleTapOnHome()1475 private void handleDoubleTapOnHome() { 1476 if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) { 1477 mHomeConsumed = true; 1478 toggleRecentApps(); 1479 } 1480 } 1481 showTvPictureInPictureMenu(KeyEvent event)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 showTvPictureInPictureMenuInternal()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 isRoundWindow()1507 private boolean isRoundWindow() { 1508 return mContext.getResources().getConfiguration().isScreenRound(); 1509 } 1510 1511 /** {@inheritDoc} */ 1512 @Override init(Context context, IWindowManager windowManager, WindowManagerFuncs windowManagerFuncs)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 */ readConfigurationDependentBehaviors()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 setInitialDisplaySize(Display display, int width, int height, int density)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 */ canHideNavigationBar()1908 private boolean canHideNavigationBar() { 1909 return mHasNavigationBar; 1910 } 1911 1912 @Override isDefaultOrientationForced()1913 public boolean isDefaultOrientationForced() { 1914 return mForceDefaultOrientation; 1915 } 1916 1917 @Override setDisplayOverscan(Display display, int left, int top, int right, int bottom)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 updateSettings()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 updateWakeGestureListenerLp()1998 private void updateWakeGestureListenerLp() { 1999 if (shouldEnableWakeGestureLp()) { 2000 mWakeGestureListener.requestWakeUpTrigger(); 2001 } else { 2002 mWakeGestureListener.cancelWakeUpTrigger(); 2003 } 2004 } 2005 shouldEnableWakeGestureLp()2006 private boolean shouldEnableWakeGestureLp() { 2007 return mWakeGestureEnabledSetting && !mAwake 2008 && (!mLidControlsSleep || mLidState != LID_CLOSED) 2009 && mWakeGestureListener.isSupported(); 2010 } 2011 enablePointerLocation()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 disablePointerLocation()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 readRotation(int resID)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 checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp)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 checkShowToOwnerOnly(WindowManager.LayoutParams attrs)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 adjustWindowParamsLw(WindowManager.LayoutParams attrs)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 readLidState()2257 void readLidState() { 2258 mLidState = mWindowManagerFuncs.getLidState(); 2259 } 2260 readCameraLensCoverState()2261 private void readCameraLensCoverState() { 2262 mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState(); 2263 } 2264 isHidden(int accessibilityMode)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 adjustConfigurationLw(Configuration config, int keyboardPresence, int navigationPresence)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 onConfigurationChanged()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 windowTypeToLayerLw(int type)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 subWindowTypeToLayerLw(int type)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 getMaxWallpaperLayer()2465 public int getMaxWallpaperLayer() { 2466 return windowTypeToLayerLw(TYPE_STATUS_BAR); 2467 } 2468 getNavigationBarWidth(int rotation, int uiMode)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 getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode)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 getNavigationBarHeight(int rotation, int uiMode)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 getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode)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 getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode)2512 public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode) { 2513 return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode); 2514 } 2515 2516 @Override getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode)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 isForceHiding(WindowManager.LayoutParams attrs)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 isKeyguardHostWindow(WindowManager.LayoutParams attrs)2535 public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) { 2536 return attrs.type == TYPE_STATUS_BAR; 2537 } 2538 2539 @Override canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs)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 getWinShowWhenLockedLw()2556 public WindowState getWinShowWhenLockedLw() { 2557 return mWinShowWhenLocked; 2558 } 2559 2560 /** {@inheritDoc} */ 2561 @Override addStartingWindow(IBinder appToken, String packageName, int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags, Configuration overrideConfig)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 removeStartingWindow(IBinder appToken, View window)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 prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs)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 removeWindowLw(WindowState win)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 selectAnimationLw(WindowState win, int transit)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 selectDockedDividerAnimationLw(WindowState win, int transit)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 selectRotationAnimationLw(int anim[])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 validateRotationAnimationLw(int exitAnimId, int enterAnimId, boolean forceDefault)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 createForceHideEnterAnimation(boolean onWallpaper, boolean goingToNotificationShade)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 createForceHideWallpaperExitAnimation(boolean goingToNotificationShade)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 awakenDreams()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 getDreamManager()2971 static IDreamManager getDreamManager() { 2972 return IDreamManager.Stub.asInterface( 2973 ServiceManager.checkService(DreamService.DREAM_SERVICE)); 2974 } 2975 getTelecommService()2976 TelecomManager getTelecommService() { 2977 return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); 2978 } 2979 getAudioService()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 keyguardOn()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 interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags)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 dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags)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 interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags)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 registerShortcutKey(long shortcutCode, IShortcutService shortcutService)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 canShowDismissingWindowWhileLockedLw()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 launchAssistLongPressAction()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 launchAssistAction(String hint, int deviceId)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 startActivityAsUser(Intent intent, UserHandle handle)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 getSearchManager()3633 private SearchManager getSearchManager() { 3634 if (mSearchManager == null) { 3635 mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); 3636 } 3637 return mSearchManager; 3638 } 3639 preloadRecentApps()3640 private void preloadRecentApps() { 3641 mPreloadedRecentApps = true; 3642 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3643 if (statusbar != null) { 3644 statusbar.preloadRecentApps(); 3645 } 3646 } 3647 cancelPreloadRecentApps()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 toggleRecentApps()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 showRecentApps(boolean fromHome)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 showRecentApps(boolean triggeredFromAltTab, boolean fromHome)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 toggleKeyboardShortcutsMenu(int deviceId)3680 private void toggleKeyboardShortcutsMenu(int deviceId) { 3681 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3682 if (statusbar != null) { 3683 statusbar.toggleKeyboardShortcutsMenu(deviceId); 3684 } 3685 } 3686 dismissKeyboardShortcutsMenu()3687 private void dismissKeyboardShortcutsMenu() { 3688 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3689 if (statusbar != null) { 3690 statusbar.dismissKeyboardShortcutsMenu(); 3691 } 3692 } 3693 hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome)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 launchHomeFromHotKey()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 */ launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard)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 { HideNavInputEventReceiver(InputChannel inputChannel, Looper looper)3773 public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) { 3774 super(inputChannel, looper); 3775 } 3776 3777 @Override onInputEvent(InputEvent event)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 adjustSystemUiVisibilityLw(int visibility)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 getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds, int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets, Rect outStableInsets, Rect outOutsets)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 */ calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth, int displayHeight)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 shouldUseOutsets(WindowManager.LayoutParams attrs, int fl)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 beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight, int displayRotation, int uiMode)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 layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui, boolean isKeyguardShowing)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 layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation, int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf, boolean navVisible, boolean navTranslucent, boolean navAllowedHidden, boolean statusBarExpandedNotKeyguard)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 navigationBarPosition(int displayWidth, int displayHeight, int displayRotation)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 getSystemDecorLayerLw()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 getContentRectLw(Rect r)4274 public void getContentRectLw(Rect r) { 4275 r.set(mContentLeft, mContentTop, mContentRight, mContentBottom); 4276 } 4277 setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached, boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf)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 applyStableConstraints(int sysui, int fl, Rect r)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 canReceiveInput(WindowState win)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 layoutWindowLw(WindowState win, WindowState attached)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 layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf)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 offsetInputMethodWindowLw(WindowState win)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 offsetVoiceInputWindowLw(WindowState win)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 finishLayoutLw()4925 public void finishLayoutLw() { 4926 return; 4927 } 4928 4929 /** {@inheritDoc} */ 4930 @Override beginPostLayoutPolicyLw(int displayWidth, int displayHeight)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 applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs, WindowState attached)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. takeScreenshot(final int screenshotType)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 */ notifyScreenshotError()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 interceptKeyBeforeQueueing(KeyEvent event, int policyFlags)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 */ interceptSystemNavigationKey(KeyEvent event)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 */ isValidGlobalKey(int keyCode)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 */ isWakeKeyWhenScreenOff(int keyCode)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 interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags)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 shouldDispatchInputWhenNonInteractive(KeyEvent event)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 dispatchDirectAudioEvent(KeyEvent event)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 dispatchMediaKeyWithWakeLock(KeyEvent event)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 dispatchMediaKeyRepeatWithWakeLock(KeyEvent event)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 dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event)6118 void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) { 6119 if (ActivityManagerNative.isSystemReady()) { 6120 MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true); 6121 } 6122 } 6123 launchVoiceAssistWithWakeLock(boolean keyguardActive)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 requestTransientBars(WindowState swipeTarget)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 startedGoingToSleep(int why)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 finishedGoingToSleep(int why)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 startedWakingUp()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 finishedWakingUp()6296 public void finishedWakingUp() { 6297 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up..."); 6298 } 6299 wakeUpFromPowerKey(long eventTime)6300 private void wakeUpFromPowerKey(long eventTime) { 6301 wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER"); 6302 } 6303 wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason)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 finishKeyguardDrawn()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 screenTurnedOff()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 screenTurningOn(final ScreenOnListener screenOnListener)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 screenTurnedOn()6385 public void screenTurnedOn() { 6386 synchronized (mLock) { 6387 if (mKeyguardDelegate != null) { 6388 mKeyguardDelegate.onScreenTurnedOn(); 6389 } 6390 } 6391 } 6392 finishWindowsDrawn()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 finishScreenTurningOn()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 handleHideBootMessage()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 isScreenOn()6473 public boolean isScreenOn() { 6474 return mScreenOnFully; 6475 } 6476 6477 /** {@inheritDoc} */ 6478 @Override enableKeyguard(boolean enabled)6479 public void enableKeyguard(boolean enabled) { 6480 if (mKeyguardDelegate != null) { 6481 mKeyguardDelegate.setKeyguardEnabled(enabled); 6482 } 6483 } 6484 6485 /** {@inheritDoc} */ 6486 @Override exitKeyguardSecurely(OnKeyguardExitResult callback)6487 public void exitKeyguardSecurely(OnKeyguardExitResult callback) { 6488 if (mKeyguardDelegate != null) { 6489 mKeyguardDelegate.verifyUnlock(callback); 6490 } 6491 } 6492 isKeyguardShowingAndNotOccluded()6493 private boolean isKeyguardShowingAndNotOccluded() { 6494 if (mKeyguardDelegate == null) return false; 6495 return mKeyguardDelegate.isShowing() && !mKeyguardOccluded; 6496 } 6497 6498 /** {@inheritDoc} */ 6499 @Override isKeyguardLocked()6500 public boolean isKeyguardLocked() { 6501 return keyguardOn(); 6502 } 6503 6504 /** {@inheritDoc} */ 6505 @Override isKeyguardSecure(int userId)6506 public boolean isKeyguardSecure(int userId) { 6507 if (mKeyguardDelegate == null) return false; 6508 return mKeyguardDelegate.isSecure(userId); 6509 } 6510 6511 /** {@inheritDoc} */ 6512 @Override isKeyguardShowingOrOccluded()6513 public boolean isKeyguardShowingOrOccluded() { 6514 return mKeyguardDelegate == null ? false : mKeyguardDelegate.isShowing(); 6515 } 6516 6517 /** {@inheritDoc} */ 6518 @Override inKeyguardRestrictedKeyInputMode()6519 public boolean inKeyguardRestrictedKeyInputMode() { 6520 if (mKeyguardDelegate == null) return false; 6521 return mKeyguardDelegate.isInputRestricted(); 6522 } 6523 6524 @Override dismissKeyguardLw()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 notifyActivityDrawnForKeyguardLw()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 isKeyguardDrawnLw()6551 public boolean isKeyguardDrawnLw() { 6552 synchronized (mLock) { 6553 return mKeyguardDrawnOnce; 6554 } 6555 } 6556 6557 @Override startKeyguardExitAnimation(long startTime, long fadeoutDuration)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 getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight, Rect outInsets)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 getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight, Rect outInsets)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 isNavBarForcedShownLw(WindowState windowState)6596 public boolean isNavBarForcedShownLw(WindowState windowState) { 6597 return mForceShowSystemBars; 6598 } 6599 6600 @Override isDockSideAllowed(int dockSide)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 sendCloseSystemWindows()6611 void sendCloseSystemWindows() { 6612 PhoneWindow.sendCloseSystemWindows(mContext, null); 6613 } 6614 sendCloseSystemWindows(String reason)6615 void sendCloseSystemWindows(String reason) { 6616 PhoneWindow.sendCloseSystemWindows(mContext, reason); 6617 } 6618 6619 @Override rotationForOrientationLw(int orientation, int lastRotation)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 rotationHasCompatibleMetricsLw(int orientation, int rotation)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 setRotationLw(int rotation)6803 public void setRotationLw(int rotation) { 6804 mOrientationListener.setCurrentRotation(rotation); 6805 } 6806 isLandscapeOrSeascape(int rotation)6807 private boolean isLandscapeOrSeascape(int rotation) { 6808 return rotation == mLandscapeRotation || rotation == mSeascapeRotation; 6809 } 6810 isAnyPortrait(int rotation)6811 private boolean isAnyPortrait(int rotation) { 6812 return rotation == mPortraitRotation || rotation == mUpsideDownRotation; 6813 } 6814 6815 @Override getUserRotationMode()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 setUserRotationMode(int mode, int rot)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 setSafeMode(boolean safeMode)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 getLongIntArray(Resources r, int resid)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 systemReady()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 systemBooted()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 showBootMessage(final CharSequence msg, final boolean always)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 hideBootMessages()6991 public void hideBootMessages() { 6992 mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE); 6993 } 6994 6995 /** {@inheritDoc} */ 6996 @Override userActivity()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 run()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 setLockOptions(Bundle options)7033 public void setLockOptions(Bundle options) { 7034 this.options = options; 7035 } 7036 } 7037 7038 ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout(); 7039 7040 @Override lockNow(Bundle options)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 updateLockScreenTimeout()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 updateDreamingSleepToken(boolean acquire)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 updateScreenOffSleepToken(boolean acquire)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 enableScreenAfterBoot()7098 public void enableScreenAfterBoot() { 7099 readLidState(); 7100 applyLidSwitchState(); 7101 updateRotation(true); 7102 } 7103 applyLidSwitchState()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 updateUiMode()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 updateRotation(boolean alwaysSendConfiguration)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 updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout)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 */ createHomeDockIntent()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 startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams)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 */ goHome()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 setCurrentOrientationLw(int newOrientation)7291 public void setCurrentOrientationLw(int newOrientation) { 7292 synchronized (mLock) { 7293 if (newOrientation != mCurrentAppOrientation) { 7294 mCurrentAppOrientation = newOrientation; 7295 updateOrientationListenerLp(); 7296 } 7297 } 7298 } 7299 performAuditoryFeedbackForAccessibilityIfNeed()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 isTheaterModeEnabled()7315 private boolean isTheaterModeEnabled() { 7316 return Settings.Global.getInt(mContext.getContentResolver(), 7317 Settings.Global.THEATER_MODE_ON, 0) == 1; 7318 } 7319 isGlobalAccessibilityGestureEnabled()7320 private boolean isGlobalAccessibilityGestureEnabled() { 7321 return Settings.Global.getInt(mContext.getContentResolver(), 7322 Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1; 7323 } 7324 areSystemNavigationKeysEnabled()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 performHapticFeedbackLw(WindowState win, int effectId, boolean always)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 keepScreenOnStartedLw()7389 public void keepScreenOnStartedLw() { 7390 } 7391 7392 @Override keepScreenOnStoppedLw()7393 public void keepScreenOnStoppedLw() { 7394 if (isKeyguardShowingAndNotOccluded()) { 7395 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 7396 } 7397 } 7398 updateSystemUiVisibilityLw()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 updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming)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 drawsSystemBarBackground(WindowState win)7483 private boolean drawsSystemBarBackground(WindowState win) { 7484 return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0; 7485 } 7486 forcesDrawStatusBarBackground(WindowState win)7487 private boolean forcesDrawStatusBarBackground(WindowState win) { 7488 return win == null || (win.getAttrs().privateFlags 7489 & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0; 7490 } 7491 updateSystemBarsLw(WindowState win, int oldVis, int vis)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 */ configureNavBarOpacity(int visibility, boolean dockedStackVisible, boolean freeformStackVisible, boolean isDockedDividerResizing)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 setNavBarOpaqueFlag(int visibility)7642 private int setNavBarOpaqueFlag(int visibility) { 7643 return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT); 7644 } 7645 setNavBarTranslucentFlag(int visibility)7646 private int setNavBarTranslucentFlag(int visibility) { 7647 visibility &= ~View.NAVIGATION_BAR_TRANSPARENT; 7648 return visibility |= View.NAVIGATION_BAR_TRANSLUCENT; 7649 } 7650 clearClearableFlagsLw()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 isImmersiveMode(int vis)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 isNavBarEmpty(int systemUiFlags)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 */ areTranslucentBarsAllowed()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 hasNavigationBar()7688 public boolean hasNavigationBar() { 7689 return mHasNavigationBar; 7690 } 7691 7692 @Override setLastInputMethodWindowLw(WindowState ime, WindowState target)7693 public void setLastInputMethodWindowLw(WindowState ime, WindowState target) { 7694 mLastInputMethodWindow = ime; 7695 mLastInputMethodTargetWindow = target; 7696 } 7697 7698 @Override getInputMethodWindowVisibleHeightLw()7699 public int getInputMethodWindowVisibleHeightLw() { 7700 return mDockBottom - mCurBottom; 7701 } 7702 7703 @Override setCurrentUserLw(int newUserId)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 canMagnifyWindow(int windowType)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 isTopLevelWindow(int windowType)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 shouldRotateSeamlessly(int oldRotation, int newRotation)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 dump(String prefix, PrintWriter pw, String[] args)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 } 7976