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