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