PhoneWindowManager.java revision bfa81adfbe1819d55737dbbb2fb9157e50dbe022
1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.policy; 18 19import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; 20import static android.Manifest.permission.SYSTEM_ALERT_WINDOW; 21import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; 22import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; 23import static android.app.ActivityManager.StackId.HOME_STACK_ID; 24import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW; 25import static android.app.AppOpsManager.OP_TOAST_WINDOW; 26import static android.content.Context.DISPLAY_SERVICE; 27import static android.content.Context.WINDOW_SERVICE; 28import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; 29import static android.content.pm.PackageManager.FEATURE_LEANBACK; 30import static android.content.pm.PackageManager.FEATURE_WATCH; 31import static android.content.pm.PackageManager.PERMISSION_GRANTED; 32import static android.content.res.Configuration.EMPTY; 33import static android.content.res.Configuration.UI_MODE_TYPE_CAR; 34import static android.content.res.Configuration.UI_MODE_TYPE_MASK; 35import static android.os.Build.VERSION_CODES.M; 36import static android.os.Build.VERSION_CODES.O; 37import static android.view.WindowManager.DOCKED_LEFT; 38import static android.view.WindowManager.DOCKED_RIGHT; 39import static android.view.WindowManager.DOCKED_TOP; 40import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION; 41import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; 42import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; 43import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW; 44import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; 45import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; 46import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN; 47import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; 48import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR; 49import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; 50import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN; 51import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; 52import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; 53import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 54import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; 55import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; 56import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; 57import static android.view.WindowManager.LayoutParams.LAST_SYSTEM_WINDOW; 58import static android.view.WindowManager.LayoutParams.MATCH_PARENT; 59import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND; 60import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; 61import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 62import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; 63import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR; 64import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE; 65import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT; 66import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE; 67import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS; 68import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; 69import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; 70import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; 71import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; 72import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 73import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; 74import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; 75import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY; 76import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; 77import static android.view.WindowManager.LayoutParams.TYPE_DREAM; 78import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER; 79import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 80import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; 81import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY; 82import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; 83import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; 84import static android.view.WindowManager.LayoutParams.TYPE_PHONE; 85import static android.view.WindowManager.LayoutParams.TYPE_POINTER; 86import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; 87import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE; 88import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION; 89import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG; 90import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT; 91import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR; 92import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY; 93import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; 94import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL; 95import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL; 96import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; 97import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; 98import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; 99import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY; 100import static android.view.WindowManager.LayoutParams.TYPE_TOAST; 101import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION; 102import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING; 103import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY; 104import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 105import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType; 106import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN; 107import static android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION; 108import static android.view.WindowManagerGlobal.ADD_OKAY; 109import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED; 110import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED; 111import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT; 112import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED; 113import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT; 114import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED; 115import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN; 116 117import android.annotation.Nullable; 118import android.app.ActivityManager; 119import android.app.ActivityManager.StackId; 120import android.app.ActivityManagerInternal; 121import android.app.ActivityManagerInternal.SleepToken; 122import android.app.AppOpsManager; 123import android.app.IUiModeManager; 124import android.app.ProgressDialog; 125import android.app.SearchManager; 126import android.app.StatusBarManager; 127import android.app.UiModeManager; 128import android.content.ActivityNotFoundException; 129import android.content.BroadcastReceiver; 130import android.content.ComponentName; 131import android.content.ContentResolver; 132import android.content.Context; 133import android.content.Intent; 134import android.content.IntentFilter; 135import android.content.ServiceConnection; 136import android.content.pm.ActivityInfo; 137import android.content.pm.ApplicationInfo; 138import android.content.pm.PackageManager; 139import android.content.pm.ResolveInfo; 140import android.content.res.CompatibilityInfo; 141import android.content.res.Configuration; 142import android.content.res.Resources; 143import android.content.res.TypedArray; 144import android.database.ContentObserver; 145import android.graphics.PixelFormat; 146import android.graphics.Rect; 147import android.graphics.drawable.Drawable; 148import android.hardware.display.DisplayManager; 149import android.hardware.hdmi.HdmiControlManager; 150import android.hardware.hdmi.HdmiPlaybackClient; 151import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback; 152import android.hardware.input.InputManager; 153import android.hardware.input.InputManagerInternal; 154import android.hardware.power.V1_0.PowerHint; 155import android.media.AudioAttributes; 156import android.media.AudioManager; 157import android.media.AudioSystem; 158import android.media.IAudioService; 159import android.media.session.MediaSessionLegacyHelper; 160import android.os.Binder; 161import android.os.Build; 162import android.os.Bundle; 163import android.os.FactoryTest; 164import android.os.Handler; 165import android.os.IBinder; 166import android.os.IDeviceIdleController; 167import android.os.Looper; 168import android.os.Message; 169import android.os.Messenger; 170import android.os.PowerManager; 171import android.os.PowerManagerInternal; 172import android.os.Process; 173import android.os.RemoteException; 174import android.os.ServiceManager; 175import android.os.SystemClock; 176import android.os.SystemProperties; 177import android.os.UEventObserver; 178import android.os.UserHandle; 179import android.os.Vibrator; 180import android.os.VibrationEffect; 181import android.provider.MediaStore; 182import android.provider.Settings; 183import android.service.dreams.DreamManagerInternal; 184import android.service.dreams.DreamService; 185import android.service.dreams.IDreamManager; 186import android.service.vr.IPersistentVrStateCallbacks; 187import android.speech.RecognizerIntent; 188import android.telecom.TelecomManager; 189import android.util.DisplayMetrics; 190import android.util.EventLog; 191import android.util.Log; 192import android.util.LongSparseArray; 193import android.util.MutableBoolean; 194import android.util.Slog; 195import android.util.SparseArray; 196import android.view.Display; 197import android.view.Gravity; 198import android.view.HapticFeedbackConstants; 199import android.view.IApplicationToken; 200import android.view.IWindowManager; 201import android.view.InputChannel; 202import android.view.InputDevice; 203import android.view.InputEvent; 204import android.view.InputEventReceiver; 205import android.view.KeyCharacterMap; 206import android.view.KeyCharacterMap.FallbackAction; 207import android.view.KeyEvent; 208import android.view.MotionEvent; 209import android.view.PointerIcon; 210import android.view.Surface; 211import android.view.View; 212import android.view.ViewConfiguration; 213import android.view.WindowManager; 214import android.view.WindowManager.LayoutParams; 215import android.view.WindowManagerGlobal; 216import android.view.WindowManagerInternal; 217import android.view.WindowManagerInternal.AppTransitionListener; 218import android.view.WindowManagerPolicy; 219import android.view.accessibility.AccessibilityEvent; 220import android.view.accessibility.AccessibilityManager; 221import android.view.animation.Animation; 222import android.view.animation.AnimationSet; 223import android.view.animation.AnimationUtils; 224import android.view.inputmethod.InputMethodManagerInternal; 225 226import com.android.internal.R; 227import com.android.internal.logging.MetricsLogger; 228import com.android.internal.policy.IKeyguardDismissCallback; 229import com.android.internal.policy.IShortcutService; 230import com.android.internal.policy.PhoneWindow; 231import com.android.internal.statusbar.IStatusBarService; 232import com.android.internal.util.ScreenShapeHelper; 233import com.android.internal.widget.PointerLocationView; 234import com.android.server.GestureLauncherService; 235import com.android.server.LocalServices; 236import com.android.server.SystemServiceManager; 237import com.android.server.policy.keyguard.KeyguardServiceDelegate; 238import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener; 239import com.android.server.policy.keyguard.KeyguardStateMonitor.StateCallback; 240import com.android.server.statusbar.StatusBarManagerInternal; 241import com.android.server.wm.AppTransition; 242import com.android.server.vr.VrManagerInternal; 243 244import java.io.File; 245import java.io.FileReader; 246import java.io.IOException; 247import java.io.PrintWriter; 248import java.util.List; 249 250/** 251 * WindowManagerPolicy implementation for the Android phone UI. This 252 * introduces a new method suffix, Lp, for an internal lock of the 253 * PhoneWindowManager. This is used to protect some internal state, and 254 * can be acquired with either the Lw and Li lock held, so has the restrictions 255 * of both of those when held. 256 */ 257public class PhoneWindowManager implements WindowManagerPolicy { 258 static final String TAG = "WindowManager"; 259 static final boolean DEBUG = false; 260 static final boolean localLOGV = false; 261 static final boolean DEBUG_INPUT = false; 262 static final boolean DEBUG_KEYGUARD = false; 263 static final boolean DEBUG_LAYOUT = false; 264 static final boolean DEBUG_SPLASH_SCREEN = false; 265 static final boolean DEBUG_WAKEUP = false; 266 static final boolean SHOW_SPLASH_SCREENS = true; 267 268 // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key. 269 // No longer recommended for desk docks; 270 static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false; 271 272 // Whether to allow devices placed in vr headset viewers to have an alternative Home intent. 273 static final boolean ENABLE_VR_HEADSET_HOME_CAPTURE = true; 274 275 static final boolean ALTERNATE_CAR_MODE_NAV_SIZE = false; 276 277 static final int SHORT_PRESS_POWER_NOTHING = 0; 278 static final int SHORT_PRESS_POWER_GO_TO_SLEEP = 1; 279 static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2; 280 static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3; 281 static final int SHORT_PRESS_POWER_GO_HOME = 4; 282 static final int SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME = 5; 283 284 static final int LONG_PRESS_POWER_NOTHING = 0; 285 static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1; 286 static final int LONG_PRESS_POWER_SHUT_OFF = 2; 287 static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3; 288 289 static final int LONG_PRESS_BACK_NOTHING = 0; 290 static final int LONG_PRESS_BACK_GO_TO_VOICE_ASSIST = 1; 291 292 static final int MULTI_PRESS_POWER_NOTHING = 0; 293 static final int MULTI_PRESS_POWER_THEATER_MODE = 1; 294 static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2; 295 296 // Number of presses needed before we induce panic press behavior on the back button 297 static final int PANIC_PRESS_BACK_COUNT = 4; 298 static final int PANIC_PRESS_BACK_NOTHING = 0; 299 static final int PANIC_PRESS_BACK_HOME = 1; 300 301 // These need to match the documentation/constant in 302 // core/res/res/values/config.xml 303 static final int LONG_PRESS_HOME_NOTHING = 0; 304 static final int LONG_PRESS_HOME_ALL_APPS = 1; 305 static final int LONG_PRESS_HOME_ASSIST = 2; 306 static final int LAST_LONG_PRESS_HOME_BEHAVIOR = LONG_PRESS_HOME_ASSIST; 307 308 static final int DOUBLE_TAP_HOME_NOTHING = 0; 309 static final int DOUBLE_TAP_HOME_RECENT_SYSTEM_UI = 1; 310 311 static final int SHORT_PRESS_WINDOW_NOTHING = 0; 312 static final int SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE = 1; 313 314 static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP = 0; 315 static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME = 1; 316 317 static final int PENDING_KEY_NULL = -1; 318 319 // Controls navigation bar opacity depending on which workspace stacks are currently 320 // visible. 321 // Nav bar is always opaque when either the freeform stack or docked stack is visible. 322 static final int NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED = 0; 323 // Nav bar is always translucent when the freeform stack is visible, otherwise always opaque. 324 static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1; 325 326 static public final String SYSTEM_DIALOG_REASON_KEY = "reason"; 327 static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions"; 328 static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps"; 329 static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey"; 330 static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist"; 331 332 /** 333 * These are the system UI flags that, when changing, can cause the layout 334 * of the screen to change. 335 */ 336 static final int SYSTEM_UI_CHANGING_LAYOUT = 337 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 338 | View.SYSTEM_UI_FLAG_FULLSCREEN 339 | View.STATUS_BAR_TRANSLUCENT 340 | View.NAVIGATION_BAR_TRANSLUCENT 341 | View.STATUS_BAR_TRANSPARENT 342 | View.NAVIGATION_BAR_TRANSPARENT; 343 344 private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder() 345 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) 346 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) 347 .build(); 348 349 // The panic gesture may become active only after the keyguard is dismissed and the immersive 350 // app shows again. If that doesn't happen for 30s we drop the gesture. 351 private static final long PANIC_GESTURE_EXPIRATION = 30000; 352 353 private static final String SYSUI_PACKAGE = "com.android.systemui"; 354 private static final String SYSUI_SCREENSHOT_SERVICE = 355 "com.android.systemui.screenshot.TakeScreenshotService"; 356 private static final String SYSUI_SCREENSHOT_ERROR_RECEIVER = 357 "com.android.systemui.screenshot.ScreenshotServiceErrorReceiver"; 358 359 private static final int NAV_BAR_BOTTOM = 0; 360 private static final int NAV_BAR_RIGHT = 1; 361 private static final int NAV_BAR_LEFT = 2; 362 363 /** 364 * Keyguard stuff 365 */ 366 private boolean mKeyguardDrawnOnce; 367 368 /* Table of Application Launch keys. Maps from key codes to intent categories. 369 * 370 * These are special keys that are used to launch particular kinds of applications, 371 * such as a web browser. HID defines nearly a hundred of them in the Consumer (0x0C) 372 * usage page. We don't support quite that many yet... 373 */ 374 static SparseArray<String> sApplicationLaunchKeyCategories; 375 static { 376 sApplicationLaunchKeyCategories = new SparseArray<String>(); 377 sApplicationLaunchKeyCategories.append( 378 KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER); 379 sApplicationLaunchKeyCategories.append( 380 KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL); 381 sApplicationLaunchKeyCategories.append( 382 KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS); 383 sApplicationLaunchKeyCategories.append( 384 KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR); 385 sApplicationLaunchKeyCategories.append( 386 KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC); 387 sApplicationLaunchKeyCategories.append( 388 KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR); 389 } 390 391 /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */ 392 static final int WAITING_FOR_DRAWN_TIMEOUT = 1000; 393 394 /** Amount of time (in milliseconds) a toast window can be shown. */ 395 public static final int TOAST_WINDOW_TIMEOUT = 3500; // 3.5 seconds 396 397 /** 398 * Lock protecting internal state. Must not call out into window 399 * manager with lock held. (This lock will be acquired in places 400 * where the window manager is calling in with its own lock held.) 401 */ 402 private final Object mLock = new Object(); 403 404 Context mContext; 405 IWindowManager mWindowManager; 406 WindowManagerFuncs mWindowManagerFuncs; 407 WindowManagerInternal mWindowManagerInternal; 408 PowerManager mPowerManager; 409 ActivityManagerInternal mActivityManagerInternal; 410 InputManagerInternal mInputManagerInternal; 411 InputMethodManagerInternal mInputMethodManagerInternal; 412 DreamManagerInternal mDreamManagerInternal; 413 PowerManagerInternal mPowerManagerInternal; 414 IStatusBarService mStatusBarService; 415 StatusBarManagerInternal mStatusBarManagerInternal; 416 boolean mPreloadedRecentApps; 417 final Object mServiceAquireLock = new Object(); 418 Vibrator mVibrator; // Vibrator for giving feedback of orientation changes 419 SearchManager mSearchManager; 420 AccessibilityManager mAccessibilityManager; 421 BurnInProtectionHelper mBurnInProtectionHelper; 422 AppOpsManager mAppOpsManager; 423 private boolean mHasFeatureWatch; 424 private boolean mHasFeatureLeanback; 425 426 // Assigned on main thread, accessed on UI thread 427 volatile VrManagerInternal mVrManagerInternal; 428 429 // Vibrator pattern for haptic feedback of a long press. 430 long[] mLongPressVibePattern; 431 432 // Vibrator pattern for haptic feedback of virtual key press. 433 long[] mVirtualKeyVibePattern; 434 435 // Vibrator pattern for a short vibration. 436 long[] mKeyboardTapVibePattern; 437 438 // Vibrator pattern for a short vibration when tapping on an hour/minute tick of a Clock. 439 long[] mClockTickVibePattern; 440 441 // Vibrator pattern for a short vibration when tapping on a day/month/year date of a Calendar. 442 long[] mCalendarDateVibePattern; 443 444 // Vibrator pattern for haptic feedback during boot when safe mode is disabled. 445 long[] mSafeModeDisabledVibePattern; 446 447 // Vibrator pattern for haptic feedback during boot when safe mode is enabled. 448 long[] mSafeModeEnabledVibePattern; 449 450 // Vibrator pattern for haptic feedback of a context click. 451 long[] mContextClickVibePattern; 452 453 /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */ 454 boolean mEnableShiftMenuBugReports = false; 455 456 /** Controller that supports enabling an AccessibilityService by holding down the volume keys */ 457 private AccessibilityShortcutController mAccessibilityShortcutController; 458 459 boolean mSafeMode; 460 WindowState mStatusBar = null; 461 int mStatusBarHeight; 462 WindowState mNavigationBar = null; 463 boolean mHasNavigationBar = false; 464 boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side? 465 int mNavigationBarPosition = NAV_BAR_BOTTOM; 466 int[] mNavigationBarHeightForRotationDefault = new int[4]; 467 int[] mNavigationBarWidthForRotationDefault = new int[4]; 468 int[] mNavigationBarHeightForRotationInCarMode = new int[4]; 469 int[] mNavigationBarWidthForRotationInCarMode = new int[4]; 470 471 private LongSparseArray<IShortcutService> mShortcutKeyServices = new LongSparseArray<>(); 472 473 // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key. 474 // This is for car dock and this is updated from resource. 475 private boolean mEnableCarDockHomeCapture = true; 476 477 boolean mBootMessageNeedsHiding; 478 KeyguardServiceDelegate mKeyguardDelegate; 479 private boolean mKeyguardBound; 480 final Runnable mWindowManagerDrawCallback = new Runnable() { 481 @Override 482 public void run() { 483 if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!"); 484 mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE); 485 } 486 }; 487 final DrawnListener mKeyguardDrawnCallback = new DrawnListener() { 488 @Override 489 public void onDrawn() { 490 if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn."); 491 mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE); 492 } 493 }; 494 495 GlobalActions mGlobalActions; 496 Handler mHandler; 497 WindowState mLastInputMethodWindow = null; 498 WindowState mLastInputMethodTargetWindow = null; 499 500 // FIXME This state is shared between the input reader and handler thread. 501 // Technically it's broken and buggy but it has been like this for many years 502 // and we have not yet seen any problems. Someday we'll rewrite this logic 503 // so that only one thread is involved in handling input policy. Unfortunately 504 // it's on a critical path for power management so we can't just post the work to the 505 // handler thread. We'll need to resolve this someday by teaching the input dispatcher 506 // to hold wakelocks during dispatch and eliminating the critical path. 507 volatile boolean mPowerKeyHandled; 508 volatile boolean mBackKeyHandled; 509 volatile boolean mBeganFromNonInteractive; 510 volatile int mPowerKeyPressCounter; 511 volatile int mBackKeyPressCounter; 512 volatile boolean mEndCallKeyHandled; 513 volatile boolean mCameraGestureTriggeredDuringGoingToSleep; 514 volatile boolean mGoingToSleep; 515 volatile boolean mRecentsVisible; 516 volatile boolean mPictureInPictureVisible; 517 // Written by vr manager thread, only read in this class. 518 volatile private boolean mPersistentVrModeEnabled; 519 volatile private boolean mDismissImeOnBackKeyPressed; 520 521 // Used to hold the last user key used to wake the device. This helps us prevent up events 522 // from being passed to the foregrounded app without a corresponding down event 523 volatile int mPendingWakeKey = PENDING_KEY_NULL; 524 525 int mRecentAppsHeldModifiers; 526 boolean mLanguageSwitchKeyPressed; 527 528 int mLidState = LID_ABSENT; 529 int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT; 530 boolean mHaveBuiltInKeyboard; 531 532 boolean mSystemReady; 533 boolean mSystemBooted; 534 boolean mHdmiPlugged; 535 HdmiControl mHdmiControl; 536 IUiModeManager mUiModeManager; 537 int mUiMode; 538 int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED; 539 int mLidOpenRotation; 540 int mCarDockRotation; 541 int mDeskDockRotation; 542 int mUndockedHdmiRotation; 543 int mDemoHdmiRotation; 544 boolean mDemoHdmiRotationLock; 545 int mDemoRotation; 546 boolean mDemoRotationLock; 547 548 boolean mWakeGestureEnabledSetting; 549 MyWakeGestureListener mWakeGestureListener; 550 551 // Default display does not rotate, apps that require non-default orientation will have to 552 // have the orientation emulated. 553 private boolean mForceDefaultOrientation = false; 554 555 int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE; 556 int mUserRotation = Surface.ROTATION_0; 557 boolean mAccelerometerDefault; 558 559 boolean mSupportAutoRotation; 560 int mAllowAllRotations = -1; 561 boolean mCarDockEnablesAccelerometer; 562 boolean mDeskDockEnablesAccelerometer; 563 int mLidKeyboardAccessibility; 564 int mLidNavigationAccessibility; 565 boolean mLidControlsScreenLock; 566 boolean mLidControlsSleep; 567 int mShortPressOnPowerBehavior; 568 int mLongPressOnPowerBehavior; 569 int mDoublePressOnPowerBehavior; 570 int mTriplePressOnPowerBehavior; 571 int mLongPressOnBackBehavior; 572 int mPanicPressOnBackBehavior; 573 int mShortPressOnSleepBehavior; 574 int mShortPressWindowBehavior; 575 boolean mAwake; 576 boolean mScreenOnEarly; 577 boolean mScreenOnFully; 578 ScreenOnListener mScreenOnListener; 579 boolean mKeyguardDrawComplete; 580 boolean mWindowManagerDrawComplete; 581 boolean mOrientationSensorEnabled = false; 582 int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 583 boolean mHasSoftInput = false; 584 boolean mTranslucentDecorEnabled = true; 585 boolean mUseTvRouting; 586 587 private boolean mHandleVolumeKeysInWM; 588 589 int mPointerLocationMode = 0; // guarded by mLock 590 591 // The last window we were told about in focusChanged. 592 WindowState mFocusedWindow; 593 IApplicationToken mFocusedApp; 594 595 PointerLocationView mPointerLocationView; 596 597 // The current size of the screen; really; extends into the overscan area of 598 // the screen and doesn't account for any system elements like the status bar. 599 int mOverscanScreenLeft, mOverscanScreenTop; 600 int mOverscanScreenWidth, mOverscanScreenHeight; 601 // The current visible size of the screen; really; (ir)regardless of whether the status 602 // bar can be hidden but not extending into the overscan area. 603 int mUnrestrictedScreenLeft, mUnrestrictedScreenTop; 604 int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight; 605 // Like mOverscanScreen*, but allowed to move into the overscan region where appropriate. 606 int mRestrictedOverscanScreenLeft, mRestrictedOverscanScreenTop; 607 int mRestrictedOverscanScreenWidth, mRestrictedOverscanScreenHeight; 608 // The current size of the screen; these may be different than (0,0)-(dw,dh) 609 // if the status bar can't be hidden; in that case it effectively carves out 610 // that area of the display from all other windows. 611 int mRestrictedScreenLeft, mRestrictedScreenTop; 612 int mRestrictedScreenWidth, mRestrictedScreenHeight; 613 // During layout, the current screen borders accounting for any currently 614 // visible system UI elements. 615 int mSystemLeft, mSystemTop, mSystemRight, mSystemBottom; 616 // For applications requesting stable content insets, these are them. 617 int mStableLeft, mStableTop, mStableRight, mStableBottom; 618 // For applications requesting stable content insets but have also set the 619 // fullscreen window flag, these are the stable dimensions without the status bar. 620 int mStableFullscreenLeft, mStableFullscreenTop; 621 int mStableFullscreenRight, mStableFullscreenBottom; 622 // During layout, the current screen borders with all outer decoration 623 // (status bar, input method dock) accounted for. 624 int mCurLeft, mCurTop, mCurRight, mCurBottom; 625 // During layout, the frame in which content should be displayed 626 // to the user, accounting for all screen decoration except for any 627 // space they deem as available for other content. This is usually 628 // the same as mCur*, but may be larger if the screen decor has supplied 629 // content insets. 630 int mContentLeft, mContentTop, mContentRight, mContentBottom; 631 // During layout, the frame in which voice content should be displayed 632 // to the user, accounting for all screen decoration except for any 633 // space they deem as available for other content. 634 int mVoiceContentLeft, mVoiceContentTop, mVoiceContentRight, mVoiceContentBottom; 635 // During layout, the current screen borders along which input method 636 // windows are placed. 637 int mDockLeft, mDockTop, mDockRight, mDockBottom; 638 // During layout, the layer at which the doc window is placed. 639 int mDockLayer; 640 // During layout, this is the layer of the status bar. 641 int mStatusBarLayer; 642 int mLastSystemUiFlags; 643 // Bits that we are in the process of clearing, so we want to prevent 644 // them from being set by applications until everything has been updated 645 // to have them clear. 646 int mResettingSystemUiFlags = 0; 647 // Bits that we are currently always keeping cleared. 648 int mForceClearedSystemUiFlags = 0; 649 int mLastFullscreenStackSysUiFlags; 650 int mLastDockedStackSysUiFlags; 651 final Rect mNonDockedStackBounds = new Rect(); 652 final Rect mDockedStackBounds = new Rect(); 653 final Rect mLastNonDockedStackBounds = new Rect(); 654 final Rect mLastDockedStackBounds = new Rect(); 655 656 // What we last reported to system UI about whether the compatibility 657 // menu needs to be displayed. 658 boolean mLastFocusNeedsMenu = false; 659 // If nonzero, a panic gesture was performed at that time in uptime millis and is still pending. 660 private long mPendingPanicGestureUptime; 661 662 InputConsumer mInputConsumer = null; 663 664 static final Rect mTmpParentFrame = new Rect(); 665 static final Rect mTmpDisplayFrame = new Rect(); 666 static final Rect mTmpOverscanFrame = new Rect(); 667 static final Rect mTmpContentFrame = new Rect(); 668 static final Rect mTmpVisibleFrame = new Rect(); 669 static final Rect mTmpDecorFrame = new Rect(); 670 static final Rect mTmpStableFrame = new Rect(); 671 static final Rect mTmpNavigationFrame = new Rect(); 672 static final Rect mTmpOutsetFrame = new Rect(); 673 private static final Rect mTmpRect = new Rect(); 674 675 WindowState mTopFullscreenOpaqueWindowState; 676 WindowState mTopFullscreenOpaqueOrDimmingWindowState; 677 WindowState mTopDockedOpaqueWindowState; 678 WindowState mTopDockedOpaqueOrDimmingWindowState; 679 boolean mTopIsFullscreen; 680 boolean mForceStatusBar; 681 boolean mForceStatusBarFromKeyguard; 682 private boolean mForceStatusBarTransparent; 683 int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED; 684 boolean mForcingShowNavBar; 685 int mForcingShowNavBarLayer; 686 687 private boolean mPendingKeyguardOccluded; 688 private boolean mKeyguardOccludedChanged; 689 690 boolean mShowingDream; 691 private boolean mLastShowingDream; 692 boolean mDreamingLockscreen; 693 boolean mDreamingSleepTokenNeeded; 694 SleepToken mDreamingSleepToken; 695 SleepToken mScreenOffSleepToken; 696 volatile boolean mKeyguardOccluded; 697 boolean mHomePressed; 698 boolean mHomeConsumed; 699 boolean mHomeDoubleTapPending; 700 Intent mHomeIntent; 701 Intent mCarDockIntent; 702 Intent mDeskDockIntent; 703 Intent mVrHeadsetHomeIntent; 704 boolean mSearchKeyShortcutPending; 705 boolean mConsumeSearchKeyUp; 706 boolean mAssistKeyLongPressed; 707 boolean mPendingMetaAction; 708 boolean mPendingCapsLockToggle; 709 int mMetaState; 710 int mInitialMetaState; 711 boolean mForceShowSystemBars; 712 713 // support for activating the lock screen while the screen is on 714 boolean mAllowLockscreenWhenOn; 715 int mLockScreenTimeout; 716 boolean mLockScreenTimerActive; 717 718 // Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.) 719 int mEndcallBehavior; 720 721 // Behavior of POWER button while in-call and screen on. 722 // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.) 723 int mIncallPowerBehavior; 724 725 // Behavior of Back button while in-call and screen on 726 int mIncallBackBehavior; 727 728 Display mDisplay; 729 730 private int mDisplayRotation; 731 732 int mLandscapeRotation = 0; // default landscape rotation 733 int mSeascapeRotation = 0; // "other" landscape rotation, 180 degrees from mLandscapeRotation 734 int mPortraitRotation = 0; // default portrait rotation 735 int mUpsideDownRotation = 0; // "other" portrait rotation 736 737 int mOverscanLeft = 0; 738 int mOverscanTop = 0; 739 int mOverscanRight = 0; 740 int mOverscanBottom = 0; 741 742 // What we do when the user long presses on home 743 private int mLongPressOnHomeBehavior; 744 745 // What we do when the user double-taps on home 746 private int mDoubleTapOnHomeBehavior; 747 748 // Allowed theater mode wake actions 749 private boolean mAllowTheaterModeWakeFromKey; 750 private boolean mAllowTheaterModeWakeFromPowerKey; 751 private boolean mAllowTheaterModeWakeFromMotion; 752 private boolean mAllowTheaterModeWakeFromMotionWhenNotDreaming; 753 private boolean mAllowTheaterModeWakeFromCameraLens; 754 private boolean mAllowTheaterModeWakeFromLidSwitch; 755 private boolean mAllowTheaterModeWakeFromWakeGesture; 756 757 // Whether to support long press from power button in non-interactive mode 758 private boolean mSupportLongPressPowerWhenNonInteractive; 759 760 // Whether to go to sleep entering theater mode from power button 761 private boolean mGoToSleepOnButtonPressTheaterMode; 762 763 // Screenshot trigger states 764 // Time to volume and power must be pressed within this interval of each other. 765 private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150; 766 // Increase the chord delay when taking a screenshot from the keyguard 767 private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f; 768 private boolean mScreenshotChordEnabled; 769 private boolean mScreenshotChordVolumeDownKeyTriggered; 770 private long mScreenshotChordVolumeDownKeyTime; 771 private boolean mScreenshotChordVolumeDownKeyConsumed; 772 private boolean mA11yShortcutChordVolumeUpKeyTriggered; 773 private long mA11yShortcutChordVolumeUpKeyTime; 774 private boolean mA11yShortcutChordVolumeUpKeyConsumed; 775 776 private boolean mScreenshotChordPowerKeyTriggered; 777 private long mScreenshotChordPowerKeyTime; 778 779 private static final long BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS = 1000; 780 781 private boolean mBugreportTvKey1Pressed; 782 private boolean mBugreportTvKey2Pressed; 783 private boolean mBugreportTvScheduled; 784 785 private boolean mAccessibilityTvKey1Pressed; 786 private boolean mAccessibilityTvKey2Pressed; 787 private boolean mAccessibilityTvScheduled; 788 789 /* The number of steps between min and max brightness */ 790 private static final int BRIGHTNESS_STEPS = 10; 791 792 SettingsObserver mSettingsObserver; 793 ShortcutManager mShortcutManager; 794 PowerManager.WakeLock mBroadcastWakeLock; 795 PowerManager.WakeLock mPowerKeyWakeLock; 796 boolean mHavePendingMediaKeyRepeatWithWakeLock; 797 798 private int mCurrentUserId; 799 800 // Maps global key codes to the components that will handle them. 801 private GlobalKeyManager mGlobalKeyManager; 802 803 // Fallback actions by key code. 804 private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions = 805 new SparseArray<KeyCharacterMap.FallbackAction>(); 806 807 private final LogDecelerateInterpolator mLogDecelerateInterpolator 808 = new LogDecelerateInterpolator(100, 0); 809 810 private final MutableBoolean mTmpBoolean = new MutableBoolean(false); 811 812 private static final int MSG_ENABLE_POINTER_LOCATION = 1; 813 private static final int MSG_DISABLE_POINTER_LOCATION = 2; 814 private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3; 815 private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4; 816 private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5; 817 private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6; 818 private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7; 819 private static final int MSG_DISPATCH_SHOW_RECENTS = 9; 820 private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10; 821 private static final int MSG_HIDE_BOOT_MESSAGE = 11; 822 private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12; 823 private static final int MSG_POWER_DELAYED_PRESS = 13; 824 private static final int MSG_POWER_LONG_PRESS = 14; 825 private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 15; 826 private static final int MSG_REQUEST_TRANSIENT_BARS = 16; 827 private static final int MSG_SHOW_PICTURE_IN_PICTURE_MENU = 17; 828 private static final int MSG_BACK_LONG_PRESS = 18; 829 private static final int MSG_DISPOSE_INPUT_CONSUMER = 19; 830 private static final int MSG_BACK_DELAYED_PRESS = 20; 831 private static final int MSG_ACCESSIBILITY_SHORTCUT = 21; 832 private static final int MSG_BUGREPORT_TV = 22; 833 private static final int MSG_ACCESSIBILITY_TV = 23; 834 835 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0; 836 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1; 837 838 private class PolicyHandler extends Handler { 839 @Override 840 public void handleMessage(Message msg) { 841 switch (msg.what) { 842 case MSG_ENABLE_POINTER_LOCATION: 843 enablePointerLocation(); 844 break; 845 case MSG_DISABLE_POINTER_LOCATION: 846 disablePointerLocation(); 847 break; 848 case MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK: 849 dispatchMediaKeyWithWakeLock((KeyEvent)msg.obj); 850 break; 851 case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK: 852 dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj); 853 break; 854 case MSG_DISPATCH_SHOW_RECENTS: 855 showRecentApps(false, msg.arg1 != 0); 856 break; 857 case MSG_DISPATCH_SHOW_GLOBAL_ACTIONS: 858 showGlobalActionsInternal(); 859 break; 860 case MSG_KEYGUARD_DRAWN_COMPLETE: 861 if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete"); 862 finishKeyguardDrawn(); 863 break; 864 case MSG_KEYGUARD_DRAWN_TIMEOUT: 865 Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete"); 866 finishKeyguardDrawn(); 867 break; 868 case MSG_WINDOW_MANAGER_DRAWN_COMPLETE: 869 if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete"); 870 finishWindowsDrawn(); 871 break; 872 case MSG_HIDE_BOOT_MESSAGE: 873 handleHideBootMessage(); 874 break; 875 case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK: 876 launchVoiceAssistWithWakeLock(msg.arg1 != 0); 877 break; 878 case MSG_POWER_DELAYED_PRESS: 879 powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2); 880 finishPowerKeyPress(); 881 break; 882 case MSG_POWER_LONG_PRESS: 883 powerLongPress(); 884 break; 885 case MSG_UPDATE_DREAMING_SLEEP_TOKEN: 886 updateDreamingSleepToken(msg.arg1 != 0); 887 break; 888 case MSG_REQUEST_TRANSIENT_BARS: 889 WindowState targetBar = (msg.arg1 == MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS) ? 890 mStatusBar : mNavigationBar; 891 if (targetBar != null) { 892 requestTransientBars(targetBar); 893 } 894 break; 895 case MSG_SHOW_PICTURE_IN_PICTURE_MENU: 896 showPictureInPictureMenuInternal(); 897 break; 898 case MSG_BACK_LONG_PRESS: 899 backLongPress(); 900 finishBackKeyPress(); 901 break; 902 case MSG_DISPOSE_INPUT_CONSUMER: 903 disposeInputConsumer((InputConsumer) msg.obj); 904 break; 905 case MSG_BACK_DELAYED_PRESS: 906 backMultiPressAction((Long) msg.obj, msg.arg1); 907 finishBackKeyPress(); 908 break; 909 case MSG_ACCESSIBILITY_SHORTCUT: 910 accessibilityShortcutActivated(); 911 break; 912 case MSG_BUGREPORT_TV: 913 takeBugreport(); 914 break; 915 case MSG_ACCESSIBILITY_TV: 916 if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(false)) { 917 accessibilityShortcutActivated(); 918 } 919 break; 920 } 921 } 922 } 923 924 private UEventObserver mHDMIObserver = new UEventObserver() { 925 @Override 926 public void onUEvent(UEventObserver.UEvent event) { 927 setHdmiPlugged("1".equals(event.get("SWITCH_STATE"))); 928 } 929 }; 930 931 class SettingsObserver extends ContentObserver { 932 SettingsObserver(Handler handler) { 933 super(handler); 934 } 935 936 void observe() { 937 // Observe all users' changes 938 ContentResolver resolver = mContext.getContentResolver(); 939 resolver.registerContentObserver(Settings.System.getUriFor( 940 Settings.System.END_BUTTON_BEHAVIOR), false, this, 941 UserHandle.USER_ALL); 942 resolver.registerContentObserver(Settings.Secure.getUriFor( 943 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this, 944 UserHandle.USER_ALL); 945 resolver.registerContentObserver(Settings.Secure.getUriFor( 946 Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR), false, this, 947 UserHandle.USER_ALL); 948 resolver.registerContentObserver(Settings.Secure.getUriFor( 949 Settings.Secure.WAKE_GESTURE_ENABLED), false, this, 950 UserHandle.USER_ALL); 951 resolver.registerContentObserver(Settings.System.getUriFor( 952 Settings.System.ACCELEROMETER_ROTATION), false, this, 953 UserHandle.USER_ALL); 954 resolver.registerContentObserver(Settings.System.getUriFor( 955 Settings.System.USER_ROTATION), false, this, 956 UserHandle.USER_ALL); 957 resolver.registerContentObserver(Settings.System.getUriFor( 958 Settings.System.SCREEN_OFF_TIMEOUT), false, this, 959 UserHandle.USER_ALL); 960 resolver.registerContentObserver(Settings.System.getUriFor( 961 Settings.System.POINTER_LOCATION), false, this, 962 UserHandle.USER_ALL); 963 resolver.registerContentObserver(Settings.Secure.getUriFor( 964 Settings.Secure.DEFAULT_INPUT_METHOD), false, this, 965 UserHandle.USER_ALL); 966 resolver.registerContentObserver(Settings.Secure.getUriFor( 967 Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this, 968 UserHandle.USER_ALL); 969 resolver.registerContentObserver(Settings.Global.getUriFor( 970 Settings.Global.POLICY_CONTROL), false, this, 971 UserHandle.USER_ALL); 972 updateSettings(); 973 } 974 975 @Override public void onChange(boolean selfChange) { 976 updateSettings(); 977 updateRotation(false); 978 } 979 } 980 981 class MyWakeGestureListener extends WakeGestureListener { 982 MyWakeGestureListener(Context context, Handler handler) { 983 super(context, handler); 984 } 985 986 @Override 987 public void onWakeUp() { 988 synchronized (mLock) { 989 if (shouldEnableWakeGestureLp()) { 990 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); 991 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture, 992 "android.policy:GESTURE"); 993 } 994 } 995 } 996 } 997 998 class MyOrientationListener extends WindowOrientationListener { 999 private final Runnable mUpdateRotationRunnable = new Runnable() { 1000 @Override 1001 public void run() { 1002 // send interaction hint to improve redraw performance 1003 mPowerManagerInternal.powerHint(PowerHint.INTERACTION, 0); 1004 updateRotation(false); 1005 } 1006 }; 1007 1008 MyOrientationListener(Context context, Handler handler) { 1009 super(context, handler); 1010 } 1011 1012 @Override 1013 public void onProposedRotationChanged(int rotation) { 1014 if (localLOGV) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation); 1015 mHandler.post(mUpdateRotationRunnable); 1016 } 1017 } 1018 MyOrientationListener mOrientationListener; 1019 1020 final IPersistentVrStateCallbacks mPersistentVrModeListener = 1021 new IPersistentVrStateCallbacks.Stub() { 1022 @Override 1023 public void onPersistentVrStateChanged(boolean enabled) { 1024 mPersistentVrModeEnabled = enabled; 1025 } 1026 }; 1027 1028 private final StatusBarController mStatusBarController = new StatusBarController(); 1029 1030 private final BarController mNavigationBarController = new BarController("NavigationBar", 1031 View.NAVIGATION_BAR_TRANSIENT, 1032 View.NAVIGATION_BAR_UNHIDE, 1033 View.NAVIGATION_BAR_TRANSLUCENT, 1034 StatusBarManager.WINDOW_NAVIGATION_BAR, 1035 WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, 1036 View.NAVIGATION_BAR_TRANSPARENT); 1037 1038 private final BarController.OnBarVisibilityChangedListener mNavBarVisibilityListener = 1039 new BarController.OnBarVisibilityChangedListener() { 1040 @Override 1041 public void onBarVisibilityChanged(boolean visible) { 1042 mAccessibilityManager.notifyAccessibilityButtonAvailabilityChanged(visible); 1043 } 1044 }; 1045 1046 private ImmersiveModeConfirmation mImmersiveModeConfirmation; 1047 1048 private SystemGesturesPointerEventListener mSystemGestures; 1049 1050 IStatusBarService getStatusBarService() { 1051 synchronized (mServiceAquireLock) { 1052 if (mStatusBarService == null) { 1053 mStatusBarService = IStatusBarService.Stub.asInterface( 1054 ServiceManager.getService("statusbar")); 1055 } 1056 return mStatusBarService; 1057 } 1058 } 1059 1060 StatusBarManagerInternal getStatusBarManagerInternal() { 1061 synchronized (mServiceAquireLock) { 1062 if (mStatusBarManagerInternal == null) { 1063 mStatusBarManagerInternal = 1064 LocalServices.getService(StatusBarManagerInternal.class); 1065 } 1066 return mStatusBarManagerInternal; 1067 } 1068 } 1069 1070 /* 1071 * We always let the sensor be switched on by default except when 1072 * the user has explicitly disabled sensor based rotation or when the 1073 * screen is switched off. 1074 */ 1075 boolean needSensorRunningLp() { 1076 if (mSupportAutoRotation) { 1077 if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR 1078 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 1079 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT 1080 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) { 1081 // If the application has explicitly requested to follow the 1082 // orientation, then we need to turn the sensor on. 1083 return true; 1084 } 1085 } 1086 if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) || 1087 (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK 1088 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK 1089 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) { 1090 // enable accelerometer if we are docked in a dock that enables accelerometer 1091 // orientation management, 1092 return true; 1093 } 1094 if (mUserRotationMode == USER_ROTATION_LOCKED) { 1095 // If the setting for using the sensor by default is enabled, then 1096 // we will always leave it on. Note that the user could go to 1097 // a window that forces an orientation that does not use the 1098 // sensor and in theory we could turn it off... however, when next 1099 // turning it on we won't have a good value for the current 1100 // orientation for a little bit, which can cause orientation 1101 // changes to lag, so we'd like to keep it always on. (It will 1102 // still be turned off when the screen is off.) 1103 return false; 1104 } 1105 return mSupportAutoRotation; 1106 } 1107 1108 /* 1109 * Various use cases for invoking this function 1110 * screen turning off, should always disable listeners if already enabled 1111 * screen turned on and current app has sensor based orientation, enable listeners 1112 * if not already enabled 1113 * screen turned on and current app does not have sensor orientation, disable listeners if 1114 * already enabled 1115 * screen turning on and current app has sensor based orientation, enable listeners if needed 1116 * screen turning on and current app has nosensor based orientation, do nothing 1117 */ 1118 void updateOrientationListenerLp() { 1119 if (!mOrientationListener.canDetectOrientation()) { 1120 // If sensor is turned off or nonexistent for some reason 1121 return; 1122 } 1123 // Could have been invoked due to screen turning on or off or 1124 // change of the currently visible window's orientation. 1125 if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly 1126 + ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation 1127 + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled 1128 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete 1129 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete); 1130 final boolean keyguardGoingAway = mWindowManagerInternal.isKeyguardGoingAway(); 1131 1132 boolean disable = true; 1133 // Note: We postpone the rotating of the screen until the keyguard as well as the 1134 // window manager have reported a draw complete or the keyguard is going away in dismiss 1135 // mode. 1136 if (mScreenOnEarly && mAwake && ((mKeyguardDrawComplete && mWindowManagerDrawComplete) 1137 || keyguardGoingAway)) { 1138 if (needSensorRunningLp()) { 1139 disable = false; 1140 //enable listener if not already enabled 1141 if (!mOrientationSensorEnabled) { 1142 // Don't clear the current sensor orientation if the keyguard is going away in 1143 // dismiss mode. This allows window manager to use the last sensor reading to 1144 // determine the orientation vs. falling back to the last known orientation if 1145 // the sensor reading was cleared which can cause it to relaunch the app that 1146 // will show in the wrong orientation first before correcting leading to app 1147 // launch delays. 1148 mOrientationListener.enable(!keyguardGoingAway /* clearCurrentRotation */); 1149 if(localLOGV) Slog.v(TAG, "Enabling listeners"); 1150 mOrientationSensorEnabled = true; 1151 } 1152 } 1153 } 1154 //check if sensors need to be disabled 1155 if (disable && mOrientationSensorEnabled) { 1156 mOrientationListener.disable(); 1157 if(localLOGV) Slog.v(TAG, "Disabling listeners"); 1158 mOrientationSensorEnabled = false; 1159 } 1160 } 1161 1162 private void interceptBackKeyDown() { 1163 MetricsLogger.count(mContext, "key_back_down", 1); 1164 // Reset back key state for long press 1165 mBackKeyHandled = false; 1166 1167 // Cancel multi-press detection timeout. 1168 if (hasPanicPressOnBackBehavior()) { 1169 if (mBackKeyPressCounter != 0 1170 && mBackKeyPressCounter < PANIC_PRESS_BACK_COUNT) { 1171 mHandler.removeMessages(MSG_BACK_DELAYED_PRESS); 1172 } 1173 } 1174 1175 if (hasLongPressOnBackBehavior()) { 1176 Message msg = mHandler.obtainMessage(MSG_BACK_LONG_PRESS); 1177 msg.setAsynchronous(true); 1178 mHandler.sendMessageDelayed(msg, 1179 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 1180 } 1181 } 1182 1183 // returns true if the key was handled and should not be passed to the user 1184 private boolean interceptBackKeyUp(KeyEvent event) { 1185 // Cache handled state 1186 boolean handled = mBackKeyHandled; 1187 1188 if (hasPanicPressOnBackBehavior()) { 1189 // Check for back key panic press 1190 ++mBackKeyPressCounter; 1191 1192 final long eventTime = event.getDownTime(); 1193 1194 if (mBackKeyPressCounter <= PANIC_PRESS_BACK_COUNT) { 1195 // This could be a multi-press. Wait a little bit longer to confirm. 1196 Message msg = mHandler.obtainMessage(MSG_BACK_DELAYED_PRESS, 1197 mBackKeyPressCounter, 0, eventTime); 1198 msg.setAsynchronous(true); 1199 mHandler.sendMessageDelayed(msg, ViewConfiguration.getMultiPressTimeout()); 1200 } 1201 } 1202 1203 // Reset back long press state 1204 cancelPendingBackKeyAction(); 1205 1206 if (mHasFeatureWatch) { 1207 TelecomManager telecomManager = getTelecommService(); 1208 1209 if (telecomManager != null) { 1210 if (telecomManager.isRinging()) { 1211 // Pressing back while there's a ringing incoming 1212 // call should silence the ringer. 1213 telecomManager.silenceRinger(); 1214 1215 // It should not prevent navigating away 1216 return false; 1217 } else if ( 1218 (mIncallBackBehavior & Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_HANGUP) != 0 1219 && telecomManager.isInCall()) { 1220 // Otherwise, if "Back button ends call" is enabled, 1221 // the Back button will hang up any current active call. 1222 return telecomManager.endCall(); 1223 } 1224 } 1225 } 1226 1227 return handled; 1228 } 1229 1230 private void interceptPowerKeyDown(KeyEvent event, boolean interactive) { 1231 // Hold a wake lock until the power key is released. 1232 if (!mPowerKeyWakeLock.isHeld()) { 1233 mPowerKeyWakeLock.acquire(); 1234 } 1235 1236 // Cancel multi-press detection timeout. 1237 if (mPowerKeyPressCounter != 0) { 1238 mHandler.removeMessages(MSG_POWER_DELAYED_PRESS); 1239 } 1240 1241 // Detect user pressing the power button in panic when an application has 1242 // taken over the whole screen. 1243 boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive, 1244 SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags), 1245 isNavBarEmpty(mLastSystemUiFlags)); 1246 if (panic) { 1247 mHandler.post(mHiddenNavPanic); 1248 } 1249 1250 // Latch power key state to detect screenshot chord. 1251 if (interactive && !mScreenshotChordPowerKeyTriggered 1252 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 1253 mScreenshotChordPowerKeyTriggered = true; 1254 mScreenshotChordPowerKeyTime = event.getDownTime(); 1255 interceptScreenshotChord(); 1256 } 1257 1258 // Stop ringing or end call if configured to do so when power is pressed. 1259 TelecomManager telecomManager = getTelecommService(); 1260 boolean hungUp = false; 1261 if (telecomManager != null) { 1262 if (telecomManager.isRinging()) { 1263 // Pressing Power while there's a ringing incoming 1264 // call should silence the ringer. 1265 telecomManager.silenceRinger(); 1266 } else if ((mIncallPowerBehavior 1267 & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0 1268 && telecomManager.isInCall() && interactive) { 1269 // Otherwise, if "Power button ends call" is enabled, 1270 // the Power button will hang up any current active call. 1271 hungUp = telecomManager.endCall(); 1272 } 1273 } 1274 1275 GestureLauncherService gestureService = LocalServices.getService( 1276 GestureLauncherService.class); 1277 boolean gesturedServiceIntercepted = false; 1278 if (gestureService != null) { 1279 gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive, 1280 mTmpBoolean); 1281 if (mTmpBoolean.value && mGoingToSleep) { 1282 mCameraGestureTriggeredDuringGoingToSleep = true; 1283 } 1284 } 1285 1286 // If the power key has still not yet been handled, then detect short 1287 // press, long press, or multi press and decide what to do. 1288 mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered 1289 || mA11yShortcutChordVolumeUpKeyTriggered || gesturedServiceIntercepted; 1290 if (!mPowerKeyHandled) { 1291 if (interactive) { 1292 // When interactive, we're already awake. 1293 // Wait for a long press or for the button to be released to decide what to do. 1294 if (hasLongPressOnPowerBehavior()) { 1295 Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS); 1296 msg.setAsynchronous(true); 1297 mHandler.sendMessageDelayed(msg, 1298 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 1299 } 1300 } else { 1301 wakeUpFromPowerKey(event.getDownTime()); 1302 1303 if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) { 1304 Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS); 1305 msg.setAsynchronous(true); 1306 mHandler.sendMessageDelayed(msg, 1307 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 1308 mBeganFromNonInteractive = true; 1309 } else { 1310 final int maxCount = getMaxMultiPressPowerCount(); 1311 1312 if (maxCount <= 1) { 1313 mPowerKeyHandled = true; 1314 } else { 1315 mBeganFromNonInteractive = true; 1316 } 1317 } 1318 } 1319 } 1320 } 1321 1322 private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) { 1323 final boolean handled = canceled || mPowerKeyHandled; 1324 mScreenshotChordPowerKeyTriggered = false; 1325 cancelPendingScreenshotChordAction(); 1326 cancelPendingPowerKeyAction(); 1327 1328 if (!handled) { 1329 // Figure out how to handle the key now that it has been released. 1330 mPowerKeyPressCounter += 1; 1331 1332 final int maxCount = getMaxMultiPressPowerCount(); 1333 final long eventTime = event.getDownTime(); 1334 if (mPowerKeyPressCounter < maxCount) { 1335 // This could be a multi-press. Wait a little bit longer to confirm. 1336 // Continue holding the wake lock. 1337 Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS, 1338 interactive ? 1 : 0, mPowerKeyPressCounter, eventTime); 1339 msg.setAsynchronous(true); 1340 mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout()); 1341 return; 1342 } 1343 1344 // No other actions. Handle it immediately. 1345 powerPress(eventTime, interactive, mPowerKeyPressCounter); 1346 } 1347 1348 // Done. Reset our state. 1349 finishPowerKeyPress(); 1350 } 1351 1352 private void finishPowerKeyPress() { 1353 mBeganFromNonInteractive = false; 1354 mPowerKeyPressCounter = 0; 1355 if (mPowerKeyWakeLock.isHeld()) { 1356 mPowerKeyWakeLock.release(); 1357 } 1358 } 1359 1360 private void finishBackKeyPress() { 1361 mBackKeyPressCounter = 0; 1362 } 1363 1364 private void cancelPendingPowerKeyAction() { 1365 if (!mPowerKeyHandled) { 1366 mPowerKeyHandled = true; 1367 mHandler.removeMessages(MSG_POWER_LONG_PRESS); 1368 } 1369 } 1370 1371 private void cancelPendingBackKeyAction() { 1372 if (!mBackKeyHandled) { 1373 mBackKeyHandled = true; 1374 mHandler.removeMessages(MSG_BACK_LONG_PRESS); 1375 } 1376 } 1377 1378 private void backMultiPressAction(long eventTime, int count) { 1379 if (count >= PANIC_PRESS_BACK_COUNT) { 1380 switch (mPanicPressOnBackBehavior) { 1381 case PANIC_PRESS_BACK_NOTHING: 1382 break; 1383 case PANIC_PRESS_BACK_HOME: 1384 launchHomeFromHotKey(); 1385 break; 1386 } 1387 } 1388 } 1389 1390 private void powerPress(long eventTime, boolean interactive, int count) { 1391 if (mScreenOnEarly && !mScreenOnFully) { 1392 Slog.i(TAG, "Suppressed redundant power key press while " 1393 + "already in the process of turning the screen on."); 1394 return; 1395 } 1396 1397 if (count == 2) { 1398 powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior); 1399 } else if (count == 3) { 1400 powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior); 1401 } else if (interactive && !mBeganFromNonInteractive) { 1402 switch (mShortPressOnPowerBehavior) { 1403 case SHORT_PRESS_POWER_NOTHING: 1404 break; 1405 case SHORT_PRESS_POWER_GO_TO_SLEEP: 1406 mPowerManager.goToSleep(eventTime, 1407 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); 1408 break; 1409 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP: 1410 mPowerManager.goToSleep(eventTime, 1411 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 1412 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); 1413 break; 1414 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME: 1415 mPowerManager.goToSleep(eventTime, 1416 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 1417 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); 1418 launchHomeFromHotKey(); 1419 break; 1420 case SHORT_PRESS_POWER_GO_HOME: 1421 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 || attrs.type == TYPE_VOLUME_OVERLAY) { 5040 pf.left = df.left = of.left = cf.left = hasNavBar 5041 ? mDockLeft : mUnrestrictedScreenLeft; 5042 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop; 5043 pf.right = df.right = of.right = cf.right = hasNavBar 5044 ? mRestrictedScreenLeft+mRestrictedScreenWidth 5045 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 5046 pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar 5047 ? mRestrictedScreenTop+mRestrictedScreenHeight 5048 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 5049 if (DEBUG_LAYOUT) Slog.v(TAG, String.format( 5050 "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)", 5051 pf.left, pf.top, pf.right, pf.bottom)); 5052 } else if (attrs.type == TYPE_NAVIGATION_BAR 5053 || attrs.type == TYPE_NAVIGATION_BAR_PANEL) { 5054 // The navigation bar has Real Ultimate Power. 5055 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 5056 pf.top = df.top = of.top = mUnrestrictedScreenTop; 5057 pf.right = df.right = of.right = mUnrestrictedScreenLeft 5058 + mUnrestrictedScreenWidth; 5059 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop 5060 + mUnrestrictedScreenHeight; 5061 if (DEBUG_LAYOUT) Slog.v(TAG, String.format( 5062 "Laying out navigation bar window: (%d,%d - %d,%d)", 5063 pf.left, pf.top, pf.right, pf.bottom)); 5064 } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY 5065 || attrs.type == TYPE_BOOT_PROGRESS 5066 || attrs.type == TYPE_SCREENSHOT) 5067 && ((fl & FLAG_FULLSCREEN) != 0)) { 5068 // Fullscreen secure system overlays get what they ask for. Screenshot region 5069 // selection overlay should also expand to full screen. 5070 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 5071 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 5072 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft 5073 + mOverscanScreenWidth; 5074 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop 5075 + mOverscanScreenHeight; 5076 } else if (attrs.type == TYPE_BOOT_PROGRESS) { 5077 // Boot progress screen always covers entire display. 5078 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 5079 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 5080 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft 5081 + mOverscanScreenWidth; 5082 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop 5083 + mOverscanScreenHeight; 5084 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0 5085 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 5086 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 5087 // Asking to layout into the overscan region, so give it that pure 5088 // unrestricted area. 5089 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 5090 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 5091 pf.right = df.right = of.right = cf.right 5092 = mOverscanScreenLeft + mOverscanScreenWidth; 5093 pf.bottom = df.bottom = of.bottom = cf.bottom 5094 = mOverscanScreenTop + mOverscanScreenHeight; 5095 } else if (canHideNavigationBar() 5096 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 5097 && (attrs.type == TYPE_STATUS_BAR 5098 || attrs.type == TYPE_TOAST 5099 || attrs.type == TYPE_DOCK_DIVIDER 5100 || attrs.type == TYPE_VOICE_INTERACTION_STARTING 5101 || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 5102 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) { 5103 // Asking for layout as if the nav bar is hidden, lets the 5104 // application extend into the unrestricted screen area. We 5105 // only do this for application windows (or toasts) to ensure no window that 5106 // can be above the nav bar can do this. 5107 // XXX This assumes that an app asking for this will also 5108 // ask for layout in only content. We can't currently figure out 5109 // what the screen would be if only laying out to hide the nav bar. 5110 pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft; 5111 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop; 5112 pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft 5113 + mUnrestrictedScreenWidth; 5114 pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop 5115 + mUnrestrictedScreenHeight; 5116 } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) { 5117 pf.left = df.left = of.left = mRestrictedScreenLeft; 5118 pf.top = df.top = of.top = mRestrictedScreenTop; 5119 pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth; 5120 pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop 5121 + mRestrictedScreenHeight; 5122 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 5123 cf.left = mDockLeft; 5124 cf.top = mDockTop; 5125 cf.right = mDockRight; 5126 cf.bottom = mDockBottom; 5127 } else { 5128 cf.left = mContentLeft; 5129 cf.top = mContentTop; 5130 cf.right = mContentRight; 5131 cf.bottom = mContentBottom; 5132 } 5133 } else { 5134 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft; 5135 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop; 5136 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft 5137 + mRestrictedScreenWidth; 5138 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop 5139 + mRestrictedScreenHeight; 5140 } 5141 5142 applyStableConstraints(sysUiFl, fl, cf); 5143 5144 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 5145 vf.left = mCurLeft; 5146 vf.top = mCurTop; 5147 vf.right = mCurRight; 5148 vf.bottom = mCurBottom; 5149 } else { 5150 vf.set(cf); 5151 } 5152 } else if (attached != null) { 5153 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + 5154 "): attached to " + attached); 5155 // A child window should be placed inside of the same visible 5156 // frame that its parent had. 5157 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf); 5158 } else { 5159 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + 5160 "): normal window"); 5161 // Otherwise, a normal window must be placed inside the content 5162 // of all screen decorations. 5163 if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) { 5164 // Status bar panels and the volume dialog are the only windows who can go on 5165 // top of the status bar. They are protected by the STATUS_BAR_SERVICE 5166 // permission, so they have the same privileges as the status 5167 // bar itself. 5168 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft; 5169 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop; 5170 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft 5171 + mRestrictedScreenWidth; 5172 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop 5173 + mRestrictedScreenHeight; 5174 } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) { 5175 // These dialogs are stable to interim decor changes. 5176 pf.left = df.left = of.left = cf.left = mStableLeft; 5177 pf.top = df.top = of.top = cf.top = mStableTop; 5178 pf.right = df.right = of.right = cf.right = mStableRight; 5179 pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom; 5180 } else { 5181 pf.left = mContentLeft; 5182 pf.top = mContentTop; 5183 pf.right = mContentRight; 5184 pf.bottom = mContentBottom; 5185 if (win.isVoiceInteraction()) { 5186 df.left = of.left = cf.left = mVoiceContentLeft; 5187 df.top = of.top = cf.top = mVoiceContentTop; 5188 df.right = of.right = cf.right = mVoiceContentRight; 5189 df.bottom = of.bottom = cf.bottom = mVoiceContentBottom; 5190 } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 5191 df.left = of.left = cf.left = mDockLeft; 5192 df.top = of.top = cf.top = mDockTop; 5193 df.right = of.right = cf.right = mDockRight; 5194 df.bottom = of.bottom = cf.bottom = mDockBottom; 5195 } else { 5196 df.left = of.left = cf.left = mContentLeft; 5197 df.top = of.top = cf.top = mContentTop; 5198 df.right = of.right = cf.right = mContentRight; 5199 df.bottom = of.bottom = cf.bottom = mContentBottom; 5200 } 5201 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 5202 vf.left = mCurLeft; 5203 vf.top = mCurTop; 5204 vf.right = mCurRight; 5205 vf.bottom = mCurBottom; 5206 } else { 5207 vf.set(cf); 5208 } 5209 } 5210 } 5211 } 5212 5213 // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it. 5214 // Also, we don't allow windows in multi-window mode to extend out of the screen. 5215 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR 5216 && !win.isInMultiWindowMode()) { 5217 df.left = df.top = -10000; 5218 df.right = df.bottom = 10000; 5219 if (attrs.type != TYPE_WALLPAPER) { 5220 of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000; 5221 of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000; 5222 } 5223 } 5224 5225 // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we 5226 // need to provide information to the clients that want to pretend that you can draw there. 5227 // We only want to apply outsets to certain types of windows. For example, we never want to 5228 // apply the outsets to floating dialogs, because they wouldn't make sense there. 5229 final boolean useOutsets = shouldUseOutsets(attrs, fl); 5230 if (isDefaultDisplay && useOutsets) { 5231 osf = mTmpOutsetFrame; 5232 osf.set(cf.left, cf.top, cf.right, cf.bottom); 5233 int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources()); 5234 if (outset > 0) { 5235 int rotation = mDisplayRotation; 5236 if (rotation == Surface.ROTATION_0) { 5237 osf.bottom += outset; 5238 } else if (rotation == Surface.ROTATION_90) { 5239 osf.right += outset; 5240 } else if (rotation == Surface.ROTATION_180) { 5241 osf.top -= outset; 5242 } else if (rotation == Surface.ROTATION_270) { 5243 osf.left -= outset; 5244 } 5245 if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset 5246 + " with rotation " + rotation + ", result: " + osf); 5247 } 5248 } 5249 5250 if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle() 5251 + ": sim=#" + Integer.toHexString(sim) 5252 + " attach=" + attached + " type=" + attrs.type 5253 + String.format(" flags=0x%08x", fl) 5254 + " pf=" + pf.toShortString() + " df=" + df.toShortString() 5255 + " of=" + of.toShortString() 5256 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString() 5257 + " dcf=" + dcf.toShortString() 5258 + " sf=" + sf.toShortString() 5259 + " osf=" + (osf == null ? "null" : osf.toShortString())); 5260 5261 win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf); 5262 5263 // Dock windows carve out the bottom of the screen, so normal windows 5264 // can't appear underneath them. 5265 if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleLw() 5266 && !win.getGivenInsetsPendingLw()) { 5267 setLastInputMethodWindowLw(null, null); 5268 offsetInputMethodWindowLw(win); 5269 } 5270 if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleLw() 5271 && !win.getGivenInsetsPendingLw()) { 5272 offsetVoiceInputWindowLw(win); 5273 } 5274 } 5275 5276 private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) { 5277 5278 // The wallpaper also has Real Ultimate Power, but we want to tell 5279 // it about the overscan area. 5280 pf.left = df.left = mOverscanScreenLeft; 5281 pf.top = df.top = mOverscanScreenTop; 5282 pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth; 5283 pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight; 5284 of.left = cf.left = mUnrestrictedScreenLeft; 5285 of.top = cf.top = mUnrestrictedScreenTop; 5286 of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 5287 of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 5288 } 5289 5290 private void offsetInputMethodWindowLw(WindowState win) { 5291 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top); 5292 top += win.getGivenContentInsetsLw().top; 5293 if (mContentBottom > top) { 5294 mContentBottom = top; 5295 } 5296 if (mVoiceContentBottom > top) { 5297 mVoiceContentBottom = top; 5298 } 5299 top = win.getVisibleFrameLw().top; 5300 top += win.getGivenVisibleInsetsLw().top; 5301 if (mCurBottom > top) { 5302 mCurBottom = top; 5303 } 5304 if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom=" 5305 + mDockBottom + " mContentBottom=" 5306 + mContentBottom + " mCurBottom=" + mCurBottom); 5307 } 5308 5309 private void offsetVoiceInputWindowLw(WindowState win) { 5310 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top); 5311 top += win.getGivenContentInsetsLw().top; 5312 if (mVoiceContentBottom > top) { 5313 mVoiceContentBottom = top; 5314 } 5315 } 5316 5317 /** {@inheritDoc} */ 5318 @Override 5319 public void finishLayoutLw() { 5320 return; 5321 } 5322 5323 /** {@inheritDoc} */ 5324 @Override 5325 public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) { 5326 mTopFullscreenOpaqueWindowState = null; 5327 mTopFullscreenOpaqueOrDimmingWindowState = null; 5328 mTopDockedOpaqueWindowState = null; 5329 mTopDockedOpaqueOrDimmingWindowState = null; 5330 mForceStatusBar = false; 5331 mForceStatusBarFromKeyguard = false; 5332 mForceStatusBarTransparent = false; 5333 mForcingShowNavBar = false; 5334 mForcingShowNavBarLayer = -1; 5335 5336 mAllowLockscreenWhenOn = false; 5337 mShowingDream = false; 5338 } 5339 5340 /** {@inheritDoc} */ 5341 @Override 5342 public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs, 5343 WindowState attached, WindowState imeTarget) { 5344 final boolean affectsSystemUi = win.canAffectSystemUiFlags(); 5345 if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": affectsSystemUi=" + affectsSystemUi); 5346 applyKeyguardPolicyLw(win, imeTarget); 5347 final int fl = PolicyControl.getWindowFlags(win, attrs); 5348 if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi 5349 && attrs.type == TYPE_INPUT_METHOD) { 5350 mForcingShowNavBar = true; 5351 mForcingShowNavBarLayer = win.getSurfaceLayer(); 5352 } 5353 if (attrs.type == TYPE_STATUS_BAR) { 5354 if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 5355 mForceStatusBarFromKeyguard = true; 5356 } 5357 if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) { 5358 mForceStatusBarTransparent = true; 5359 } 5360 } 5361 5362 boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW 5363 && attrs.type < FIRST_SYSTEM_WINDOW; 5364 final int stackId = win.getStackId(); 5365 if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi) { 5366 if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) { 5367 mForceStatusBar = true; 5368 } 5369 if (attrs.type == TYPE_DREAM) { 5370 // If the lockscreen was showing when the dream started then wait 5371 // for the dream to draw before hiding the lockscreen. 5372 if (!mDreamingLockscreen 5373 || (win.isVisibleLw() && win.hasDrawnLw())) { 5374 mShowingDream = true; 5375 appWindow = true; 5376 } 5377 } 5378 5379 // For app windows that are not attached, we decide if all windows in the app they 5380 // represent should be hidden or if we should hide the lockscreen. For attached app 5381 // windows we defer the decision to the window it is attached to. 5382 if (appWindow && attached == null) { 5383 if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) { 5384 if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win); 5385 mTopFullscreenOpaqueWindowState = win; 5386 if (mTopFullscreenOpaqueOrDimmingWindowState == null) { 5387 mTopFullscreenOpaqueOrDimmingWindowState = win; 5388 } 5389 if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) { 5390 mAllowLockscreenWhenOn = true; 5391 } 5392 } 5393 } 5394 } 5395 5396 // Voice interaction overrides both top fullscreen and top docked. 5397 if (affectsSystemUi && win.getAttrs().type == TYPE_VOICE_INTERACTION) { 5398 if (mTopFullscreenOpaqueWindowState == null) { 5399 mTopFullscreenOpaqueWindowState = win; 5400 if (mTopFullscreenOpaqueOrDimmingWindowState == null) { 5401 mTopFullscreenOpaqueOrDimmingWindowState = win; 5402 } 5403 } 5404 if (mTopDockedOpaqueWindowState == null) { 5405 mTopDockedOpaqueWindowState = win; 5406 if (mTopDockedOpaqueOrDimmingWindowState == null) { 5407 mTopDockedOpaqueOrDimmingWindowState = win; 5408 } 5409 } 5410 } 5411 5412 // Keep track of the window if it's dimming but not necessarily fullscreen. 5413 if (mTopFullscreenOpaqueOrDimmingWindowState == null && affectsSystemUi 5414 && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) { 5415 mTopFullscreenOpaqueOrDimmingWindowState = win; 5416 } 5417 5418 // We need to keep track of the top "fullscreen" opaque window for the docked stack 5419 // separately, because both the "real fullscreen" opaque window and the one for the docked 5420 // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR. 5421 if (mTopDockedOpaqueWindowState == null && affectsSystemUi && appWindow && attached == null 5422 && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) { 5423 mTopDockedOpaqueWindowState = win; 5424 if (mTopDockedOpaqueOrDimmingWindowState == null) { 5425 mTopDockedOpaqueOrDimmingWindowState = win; 5426 } 5427 } 5428 5429 // Also keep track of any windows that are dimming but not necessarily fullscreen in the 5430 // docked stack. 5431 if (mTopDockedOpaqueOrDimmingWindowState == null && affectsSystemUi && win.isDimming() 5432 && stackId == DOCKED_STACK_ID) { 5433 mTopDockedOpaqueOrDimmingWindowState = win; 5434 } 5435 } 5436 5437 private void applyKeyguardPolicyLw(WindowState win, WindowState imeTarget) { 5438 if (canBeHiddenByKeyguardLw(win)) { 5439 if (shouldBeHiddenByKeyguard(win, imeTarget)) { 5440 win.hideLw(false /* doAnimation */); 5441 } else { 5442 win.showLw(false /* doAnimation */); 5443 } 5444 } 5445 } 5446 5447 private boolean isFullscreen(WindowManager.LayoutParams attrs) { 5448 return attrs.x == 0 && attrs.y == 0 5449 && attrs.width == WindowManager.LayoutParams.MATCH_PARENT 5450 && attrs.height == WindowManager.LayoutParams.MATCH_PARENT; 5451 } 5452 5453 /** {@inheritDoc} */ 5454 @Override 5455 public int finishPostLayoutPolicyLw() { 5456 int changes = 0; 5457 boolean topIsFullscreen = false; 5458 5459 final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null) 5460 ? mTopFullscreenOpaqueWindowState.getAttrs() 5461 : null; 5462 5463 // If we are not currently showing a dream then remember the current 5464 // lockscreen state. We will use this to determine whether the dream 5465 // started while the lockscreen was showing and remember this state 5466 // while the dream is showing. 5467 if (!mShowingDream) { 5468 mDreamingLockscreen = isKeyguardShowingAndNotOccluded(); 5469 if (mDreamingSleepTokenNeeded) { 5470 mDreamingSleepTokenNeeded = false; 5471 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget(); 5472 } 5473 } else { 5474 if (!mDreamingSleepTokenNeeded) { 5475 mDreamingSleepTokenNeeded = true; 5476 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget(); 5477 } 5478 } 5479 5480 if (mStatusBar != null) { 5481 if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar 5482 + " forcefkg=" + mForceStatusBarFromKeyguard 5483 + " top=" + mTopFullscreenOpaqueWindowState); 5484 boolean shouldBeTransparent = mForceStatusBarTransparent 5485 && !mForceStatusBar 5486 && !mForceStatusBarFromKeyguard; 5487 if (!shouldBeTransparent) { 5488 mStatusBarController.setShowTransparent(false /* transparent */); 5489 } else if (!mStatusBar.isVisibleLw()) { 5490 mStatusBarController.setShowTransparent(true /* transparent */); 5491 } 5492 5493 WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs(); 5494 boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT 5495 && statusBarAttrs.width == MATCH_PARENT; 5496 if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent 5497 || statusBarExpanded) { 5498 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced"); 5499 if (mStatusBarController.setBarShowingLw(true)) { 5500 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5501 } 5502 // Maintain fullscreen layout until incoming animation is complete. 5503 topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw(); 5504 // Transient status bar on the lockscreen is not allowed 5505 if ((mForceStatusBarFromKeyguard || statusBarExpanded) 5506 && mStatusBarController.isTransientShowing()) { 5507 mStatusBarController.updateVisibilityLw(false /*transientAllowed*/, 5508 mLastSystemUiFlags, mLastSystemUiFlags); 5509 } 5510 if (statusBarExpanded && mNavigationBar != null) { 5511 if (mNavigationBarController.setBarShowingLw(true)) { 5512 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5513 } 5514 } 5515 } else if (mTopFullscreenOpaqueWindowState != null) { 5516 final int fl = PolicyControl.getWindowFlags(null, lp); 5517 if (localLOGV) { 5518 Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() 5519 + " shown position: " 5520 + mTopFullscreenOpaqueWindowState.getShownPositionLw()); 5521 Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs() 5522 + " lp.flags=0x" + Integer.toHexString(fl)); 5523 } 5524 topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0 5525 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 5526 // The subtle difference between the window for mTopFullscreenOpaqueWindowState 5527 // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window 5528 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the 5529 // case though. 5530 if (mStatusBarController.isTransientShowing()) { 5531 if (mStatusBarController.setBarShowingLw(true)) { 5532 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5533 } 5534 } else if (topIsFullscreen 5535 && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID) 5536 && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) { 5537 if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar"); 5538 if (mStatusBarController.setBarShowingLw(false)) { 5539 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5540 } else { 5541 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding"); 5542 } 5543 } else { 5544 if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen"); 5545 if (mStatusBarController.setBarShowingLw(true)) { 5546 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5547 } 5548 } 5549 } 5550 } 5551 5552 if (mTopIsFullscreen != topIsFullscreen) { 5553 if (!topIsFullscreen) { 5554 // Force another layout when status bar becomes fully shown. 5555 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5556 } 5557 mTopIsFullscreen = topIsFullscreen; 5558 } 5559 5560 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5561 // If the navigation bar has been hidden or shown, we need to do another 5562 // layout pass to update that window. 5563 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5564 } 5565 5566 if (mShowingDream != mLastShowingDream) { 5567 mLastShowingDream = mShowingDream; 5568 mWindowManagerFuncs.notifyShowingDreamChanged(); 5569 } 5570 5571 // update since mAllowLockscreenWhenOn might have changed 5572 updateLockScreenTimeout(); 5573 return changes; 5574 } 5575 5576 /** 5577 * Updates the occluded state of the Keyguard. 5578 * 5579 * @return Whether the flags have changed and we have to redo the layout. 5580 */ 5581 private boolean setKeyguardOccludedLw(boolean isOccluded, boolean force) { 5582 if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded); 5583 final boolean wasOccluded = mKeyguardOccluded; 5584 final boolean showing = mKeyguardDelegate.isShowing(); 5585 final boolean changed = wasOccluded != isOccluded || force; 5586 if (!isOccluded && changed && showing) { 5587 mKeyguardOccluded = false; 5588 mKeyguardDelegate.setOccluded(false, true /* animate */); 5589 if (mStatusBar != null) { 5590 mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD; 5591 if (!mKeyguardDelegate.hasLockscreenWallpaper()) { 5592 mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER; 5593 } 5594 } 5595 return true; 5596 } else if (isOccluded && changed && showing) { 5597 mKeyguardOccluded = true; 5598 mKeyguardDelegate.setOccluded(true, false /* animate */); 5599 if (mStatusBar != null) { 5600 mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD; 5601 mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER; 5602 } 5603 return true; 5604 } else if (changed) { 5605 mKeyguardOccluded = isOccluded; 5606 mKeyguardDelegate.setOccluded(isOccluded, false /* animate */); 5607 return false; 5608 } else { 5609 return false; 5610 } 5611 } 5612 5613 private boolean isStatusBarKeyguard() { 5614 return mStatusBar != null 5615 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0; 5616 } 5617 5618 @Override 5619 public boolean allowAppAnimationsLw() { 5620 if (mShowingDream) { 5621 // If keyguard or dreams is currently visible, no reason to animate behind it. 5622 return false; 5623 } 5624 return true; 5625 } 5626 5627 @Override 5628 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) { 5629 mFocusedWindow = newFocus; 5630 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5631 // If the navigation bar has been hidden or shown, we need to do another 5632 // layout pass to update that window. 5633 return FINISH_LAYOUT_REDO_LAYOUT; 5634 } 5635 return 0; 5636 } 5637 5638 /** {@inheritDoc} */ 5639 @Override 5640 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { 5641 // lid changed state 5642 final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED; 5643 if (newLidState == mLidState) { 5644 return; 5645 } 5646 5647 mLidState = newLidState; 5648 applyLidSwitchState(); 5649 updateRotation(true); 5650 5651 if (lidOpen) { 5652 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch, 5653 "android.policy:LID"); 5654 } else if (!mLidControlsSleep) { 5655 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 5656 } 5657 } 5658 5659 @Override 5660 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) { 5661 int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED; 5662 if (mCameraLensCoverState == lensCoverState) { 5663 return; 5664 } 5665 if (mCameraLensCoverState == CAMERA_LENS_COVERED && 5666 lensCoverState == CAMERA_LENS_UNCOVERED) { 5667 Intent intent; 5668 final boolean keyguardActive = mKeyguardDelegate == null ? false : 5669 mKeyguardDelegate.isShowing(); 5670 if (keyguardActive) { 5671 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE); 5672 } else { 5673 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); 5674 } 5675 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens, 5676 "android.policy:CAMERA_COVER"); 5677 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); 5678 } 5679 mCameraLensCoverState = lensCoverState; 5680 } 5681 5682 void setHdmiPlugged(boolean plugged) { 5683 if (mHdmiPlugged != plugged) { 5684 mHdmiPlugged = plugged; 5685 updateRotation(true, true); 5686 Intent intent = new Intent(ACTION_HDMI_PLUGGED); 5687 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5688 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged); 5689 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 5690 } 5691 } 5692 5693 void initializeHdmiState() { 5694 boolean plugged = false; 5695 // watch for HDMI plug messages if the hdmi switch exists 5696 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) { 5697 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi"); 5698 5699 final String filename = "/sys/class/switch/hdmi/state"; 5700 FileReader reader = null; 5701 try { 5702 reader = new FileReader(filename); 5703 char[] buf = new char[15]; 5704 int n = reader.read(buf); 5705 if (n > 1) { 5706 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1)); 5707 } 5708 } catch (IOException ex) { 5709 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5710 } catch (NumberFormatException ex) { 5711 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5712 } finally { 5713 if (reader != null) { 5714 try { 5715 reader.close(); 5716 } catch (IOException ex) { 5717 } 5718 } 5719 } 5720 } 5721 // This dance forces the code in setHdmiPlugged to run. 5722 // Always do this so the sticky intent is stuck (to false) if there is no hdmi. 5723 mHdmiPlugged = !plugged; 5724 setHdmiPlugged(!mHdmiPlugged); 5725 } 5726 5727 final Object mScreenshotLock = new Object(); 5728 ServiceConnection mScreenshotConnection = null; 5729 5730 final Runnable mScreenshotTimeout = new Runnable() { 5731 @Override public void run() { 5732 synchronized (mScreenshotLock) { 5733 if (mScreenshotConnection != null) { 5734 mContext.unbindService(mScreenshotConnection); 5735 mScreenshotConnection = null; 5736 notifyScreenshotError(); 5737 } 5738 } 5739 } 5740 }; 5741 5742 // Assume this is called from the Handler thread. 5743 private void takeScreenshot(final int screenshotType) { 5744 synchronized (mScreenshotLock) { 5745 if (mScreenshotConnection != null) { 5746 return; 5747 } 5748 final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE, 5749 SYSUI_SCREENSHOT_SERVICE); 5750 final Intent serviceIntent = new Intent(); 5751 serviceIntent.setComponent(serviceComponent); 5752 ServiceConnection conn = new ServiceConnection() { 5753 @Override 5754 public void onServiceConnected(ComponentName name, IBinder service) { 5755 synchronized (mScreenshotLock) { 5756 if (mScreenshotConnection != this) { 5757 return; 5758 } 5759 Messenger messenger = new Messenger(service); 5760 Message msg = Message.obtain(null, screenshotType); 5761 final ServiceConnection myConn = this; 5762 Handler h = new Handler(mHandler.getLooper()) { 5763 @Override 5764 public void handleMessage(Message msg) { 5765 synchronized (mScreenshotLock) { 5766 if (mScreenshotConnection == myConn) { 5767 mContext.unbindService(mScreenshotConnection); 5768 mScreenshotConnection = null; 5769 mHandler.removeCallbacks(mScreenshotTimeout); 5770 } 5771 } 5772 } 5773 }; 5774 msg.replyTo = new Messenger(h); 5775 msg.arg1 = msg.arg2 = 0; 5776 if (mStatusBar != null && mStatusBar.isVisibleLw()) 5777 msg.arg1 = 1; 5778 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) 5779 msg.arg2 = 1; 5780 try { 5781 messenger.send(msg); 5782 } catch (RemoteException e) { 5783 } 5784 } 5785 } 5786 5787 @Override 5788 public void onServiceDisconnected(ComponentName name) { 5789 synchronized (mScreenshotLock) { 5790 if (mScreenshotConnection != null) { 5791 mContext.unbindService(mScreenshotConnection); 5792 mScreenshotConnection = null; 5793 mHandler.removeCallbacks(mScreenshotTimeout); 5794 notifyScreenshotError(); 5795 } 5796 } 5797 } 5798 }; 5799 if (mContext.bindServiceAsUser(serviceIntent, conn, 5800 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, 5801 UserHandle.CURRENT)) { 5802 mScreenshotConnection = conn; 5803 mHandler.postDelayed(mScreenshotTimeout, 10000); 5804 } 5805 } 5806 } 5807 5808 /** 5809 * Notifies the screenshot service to show an error. 5810 */ 5811 private void notifyScreenshotError() { 5812 // If the service process is killed, then ask it to clean up after itself 5813 final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE, 5814 SYSUI_SCREENSHOT_ERROR_RECEIVER); 5815 Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT); 5816 errorIntent.setComponent(errorComponent); 5817 errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | 5818 Intent.FLAG_RECEIVER_FOREGROUND); 5819 mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT); 5820 } 5821 5822 /** {@inheritDoc} */ 5823 @Override 5824 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { 5825 if (!mSystemBooted) { 5826 // If we have not yet booted, don't let key events do anything. 5827 return 0; 5828 } 5829 5830 final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0; 5831 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; 5832 final boolean canceled = event.isCanceled(); 5833 final int keyCode = event.getKeyCode(); 5834 5835 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; 5836 5837 // If screen is off then we treat the case where the keyguard is open but hidden 5838 // the same as if it were open and in front. 5839 // This will prevent any keys other than the power button from waking the screen 5840 // when the keyguard is hidden by another activity. 5841 final boolean keyguardActive = (mKeyguardDelegate == null ? false : 5842 (interactive ? 5843 isKeyguardShowingAndNotOccluded() : 5844 mKeyguardDelegate.isShowing())); 5845 5846 if (DEBUG_INPUT) { 5847 Log.d(TAG, "interceptKeyTq keycode=" + keyCode 5848 + " interactive=" + interactive + " keyguardActive=" + keyguardActive 5849 + " policyFlags=" + Integer.toHexString(policyFlags)); 5850 } 5851 5852 // Basic policy based on interactive state. 5853 int result; 5854 boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0 5855 || event.isWakeKey(); 5856 if (interactive || (isInjected && !isWakeKey)) { 5857 // When the device is interactive or the key is injected pass the 5858 // key to the application. 5859 result = ACTION_PASS_TO_USER; 5860 isWakeKey = false; 5861 5862 if (interactive) { 5863 // If the screen is awake, but the button pressed was the one that woke the device 5864 // then don't pass it to the application 5865 if (keyCode == mPendingWakeKey && !down) { 5866 result = 0; 5867 } 5868 // Reset the pending key 5869 mPendingWakeKey = PENDING_KEY_NULL; 5870 } 5871 } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) { 5872 // If we're currently dozing with the screen on and the keyguard showing, pass the key 5873 // to the application but preserve its wake key status to make sure we still move 5874 // from dozing to fully interactive if we would normally go from off to fully 5875 // interactive. 5876 result = ACTION_PASS_TO_USER; 5877 // Since we're dispatching the input, reset the pending key 5878 mPendingWakeKey = PENDING_KEY_NULL; 5879 } else { 5880 // When the screen is off and the key is not injected, determine whether 5881 // to wake the device but don't pass the key to the application. 5882 result = 0; 5883 if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) { 5884 isWakeKey = false; 5885 } 5886 // Cache the wake key on down event so we can also avoid sending the up event to the app 5887 if (isWakeKey && down) { 5888 mPendingWakeKey = keyCode; 5889 } 5890 } 5891 5892 // If the key would be handled globally, just return the result, don't worry about special 5893 // key processing. 5894 if (isValidGlobalKey(keyCode) 5895 && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) { 5896 if (isWakeKey) { 5897 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 5898 } 5899 return result; 5900 } 5901 5902 boolean useHapticFeedback = down 5903 && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0 5904 && event.getRepeatCount() == 0; 5905 5906 // Handle special keys. 5907 switch (keyCode) { 5908 case KeyEvent.KEYCODE_BACK: { 5909 if (down) { 5910 interceptBackKeyDown(); 5911 } else { 5912 boolean handled = interceptBackKeyUp(event); 5913 5914 // Don't pass back press to app if we've already handled it via long press 5915 if (handled) { 5916 result &= ~ACTION_PASS_TO_USER; 5917 } 5918 } 5919 break; 5920 } 5921 5922 case KeyEvent.KEYCODE_VOLUME_DOWN: 5923 case KeyEvent.KEYCODE_VOLUME_UP: 5924 case KeyEvent.KEYCODE_VOLUME_MUTE: { 5925 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { 5926 if (down) { 5927 if (interactive && !mScreenshotChordVolumeDownKeyTriggered 5928 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5929 mScreenshotChordVolumeDownKeyTriggered = true; 5930 mScreenshotChordVolumeDownKeyTime = event.getDownTime(); 5931 mScreenshotChordVolumeDownKeyConsumed = false; 5932 cancelPendingPowerKeyAction(); 5933 interceptScreenshotChord(); 5934 interceptAccessibilityShortcutChord(); 5935 } 5936 } else { 5937 mScreenshotChordVolumeDownKeyTriggered = false; 5938 cancelPendingScreenshotChordAction(); 5939 cancelPendingAccessibilityShortcutAction(); 5940 } 5941 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 5942 if (down) { 5943 if (interactive && !mA11yShortcutChordVolumeUpKeyTriggered 5944 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5945 mA11yShortcutChordVolumeUpKeyTriggered = true; 5946 mA11yShortcutChordVolumeUpKeyTime = event.getDownTime(); 5947 mA11yShortcutChordVolumeUpKeyConsumed = false; 5948 cancelPendingPowerKeyAction(); 5949 cancelPendingScreenshotChordAction(); 5950 interceptAccessibilityShortcutChord(); 5951 } 5952 } else { 5953 mA11yShortcutChordVolumeUpKeyTriggered = false; 5954 cancelPendingScreenshotChordAction(); 5955 cancelPendingAccessibilityShortcutAction(); 5956 } 5957 } 5958 if (down) { 5959 TelecomManager telecomManager = getTelecommService(); 5960 if (telecomManager != null) { 5961 if (telecomManager.isRinging()) { 5962 // If an incoming call is ringing, either VOLUME key means 5963 // "silence ringer". We handle these keys here, rather than 5964 // in the InCallScreen, to make sure we'll respond to them 5965 // even if the InCallScreen hasn't come to the foreground yet. 5966 // Look for the DOWN event here, to agree with the "fallback" 5967 // behavior in the InCallScreen. 5968 Log.i(TAG, "interceptKeyBeforeQueueing:" 5969 + " VOLUME key-down while ringing: Silence ringer!"); 5970 5971 // Silence the ringer. (It's safe to call this 5972 // even if the ringer has already been silenced.) 5973 telecomManager.silenceRinger(); 5974 5975 // And *don't* pass this key thru to the current activity 5976 // (which is probably the InCallScreen.) 5977 result &= ~ACTION_PASS_TO_USER; 5978 break; 5979 } 5980 } 5981 int audioMode = AudioManager.MODE_NORMAL; 5982 try { 5983 audioMode = getAudioService().getMode(); 5984 } catch (Exception e) { 5985 Log.e(TAG, "Error getting AudioService in interceptKeyBeforeQueueing.", e); 5986 } 5987 boolean isInCall = (telecomManager != null && telecomManager.isInCall()) || 5988 audioMode == AudioManager.MODE_IN_COMMUNICATION; 5989 if (isInCall && (result & ACTION_PASS_TO_USER) == 0) { 5990 // If we are in call but we decided not to pass the key to 5991 // the application, just pass it to the session service. 5992 MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent( 5993 event, AudioManager.USE_DEFAULT_STREAM_TYPE, false); 5994 break; 5995 } 5996 5997 } 5998 if (mUseTvRouting || mHandleVolumeKeysInWM) { 5999 // Defer special key handlings to 6000 // {@link interceptKeyBeforeDispatching()}. 6001 result |= ACTION_PASS_TO_USER; 6002 } else if ((result & ACTION_PASS_TO_USER) == 0) { 6003 // If we aren't passing to the user and no one else 6004 // handled it send it to the session manager to 6005 // figure out. 6006 MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent( 6007 event, AudioManager.USE_DEFAULT_STREAM_TYPE, true); 6008 } 6009 break; 6010 } 6011 6012 case KeyEvent.KEYCODE_ENDCALL: { 6013 result &= ~ACTION_PASS_TO_USER; 6014 if (down) { 6015 TelecomManager telecomManager = getTelecommService(); 6016 boolean hungUp = false; 6017 if (telecomManager != null) { 6018 hungUp = telecomManager.endCall(); 6019 } 6020 if (interactive && !hungUp) { 6021 mEndCallKeyHandled = false; 6022 mHandler.postDelayed(mEndCallLongPress, 6023 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 6024 } else { 6025 mEndCallKeyHandled = true; 6026 } 6027 } else { 6028 if (!mEndCallKeyHandled) { 6029 mHandler.removeCallbacks(mEndCallLongPress); 6030 if (!canceled) { 6031 if ((mEndcallBehavior 6032 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) { 6033 if (goHome()) { 6034 break; 6035 } 6036 } 6037 if ((mEndcallBehavior 6038 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) { 6039 mPowerManager.goToSleep(event.getEventTime(), 6040 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); 6041 isWakeKey = false; 6042 } 6043 } 6044 } 6045 } 6046 break; 6047 } 6048 6049 case KeyEvent.KEYCODE_POWER: { 6050 // Any activity on the power button stops the accessibility shortcut 6051 cancelPendingAccessibilityShortcutAction(); 6052 result &= ~ACTION_PASS_TO_USER; 6053 isWakeKey = false; // wake-up will be handled separately 6054 if (down) { 6055 interceptPowerKeyDown(event, interactive); 6056 } else { 6057 interceptPowerKeyUp(event, interactive, canceled); 6058 } 6059 break; 6060 } 6061 6062 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN: 6063 // fall through 6064 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP: 6065 // fall through 6066 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT: 6067 // fall through 6068 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: { 6069 result &= ~ACTION_PASS_TO_USER; 6070 interceptSystemNavigationKey(event); 6071 break; 6072 } 6073 6074 case KeyEvent.KEYCODE_SLEEP: { 6075 result &= ~ACTION_PASS_TO_USER; 6076 isWakeKey = false; 6077 if (!mPowerManager.isInteractive()) { 6078 useHapticFeedback = false; // suppress feedback if already non-interactive 6079 } 6080 if (down) { 6081 sleepPress(event.getEventTime()); 6082 } else { 6083 sleepRelease(event.getEventTime()); 6084 } 6085 break; 6086 } 6087 6088 case KeyEvent.KEYCODE_SOFT_SLEEP: { 6089 result &= ~ACTION_PASS_TO_USER; 6090 isWakeKey = false; 6091 if (!down) { 6092 mPowerManagerInternal.setUserInactiveOverrideFromWindowManager(); 6093 } 6094 break; 6095 } 6096 6097 case KeyEvent.KEYCODE_WAKEUP: { 6098 result &= ~ACTION_PASS_TO_USER; 6099 isWakeKey = true; 6100 break; 6101 } 6102 6103 case KeyEvent.KEYCODE_MEDIA_PLAY: 6104 case KeyEvent.KEYCODE_MEDIA_PAUSE: 6105 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 6106 case KeyEvent.KEYCODE_HEADSETHOOK: 6107 case KeyEvent.KEYCODE_MUTE: 6108 case KeyEvent.KEYCODE_MEDIA_STOP: 6109 case KeyEvent.KEYCODE_MEDIA_NEXT: 6110 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 6111 case KeyEvent.KEYCODE_MEDIA_REWIND: 6112 case KeyEvent.KEYCODE_MEDIA_RECORD: 6113 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 6114 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { 6115 if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) { 6116 // If the global session is active pass all media keys to it 6117 // instead of the active window. 6118 result &= ~ACTION_PASS_TO_USER; 6119 } 6120 if ((result & ACTION_PASS_TO_USER) == 0) { 6121 // Only do this if we would otherwise not pass it to the user. In that 6122 // case, the PhoneWindow class will do the same thing, except it will 6123 // only do it if the showing app doesn't process the key on its own. 6124 // Note that we need to make a copy of the key event here because the 6125 // original key event will be recycled when we return. 6126 mBroadcastWakeLock.acquire(); 6127 Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK, 6128 new KeyEvent(event)); 6129 msg.setAsynchronous(true); 6130 msg.sendToTarget(); 6131 } 6132 break; 6133 } 6134 6135 case KeyEvent.KEYCODE_CALL: { 6136 if (down) { 6137 TelecomManager telecomManager = getTelecommService(); 6138 if (telecomManager != null) { 6139 if (telecomManager.isRinging()) { 6140 Log.i(TAG, "interceptKeyBeforeQueueing:" 6141 + " CALL key-down while ringing: Answer the call!"); 6142 telecomManager.acceptRingingCall(); 6143 6144 // And *don't* pass this key thru to the current activity 6145 // (which is presumably the InCallScreen.) 6146 result &= ~ACTION_PASS_TO_USER; 6147 } 6148 } 6149 } 6150 break; 6151 } 6152 case KeyEvent.KEYCODE_VOICE_ASSIST: { 6153 // Only do this if we would otherwise not pass it to the user. In that case, 6154 // interceptKeyBeforeDispatching would apply a similar but different policy in 6155 // order to invoke voice assist actions. Note that we need to make a copy of the 6156 // key event here because the original key event will be recycled when we return. 6157 if ((result & ACTION_PASS_TO_USER) == 0 && !down) { 6158 mBroadcastWakeLock.acquire(); 6159 Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK, 6160 keyguardActive ? 1 : 0, 0); 6161 msg.setAsynchronous(true); 6162 msg.sendToTarget(); 6163 } 6164 break; 6165 } 6166 case KeyEvent.KEYCODE_WINDOW: { 6167 if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) { 6168 if (mPictureInPictureVisible) { 6169 // Consumes the key only if picture-in-picture is visible to show 6170 // picture-in-picture control menu. This gives a chance to the foreground 6171 // activity to customize PIP key behavior. 6172 if (!down) { 6173 showPictureInPictureMenu(event); 6174 } 6175 result &= ~ACTION_PASS_TO_USER; 6176 } 6177 } 6178 break; 6179 } 6180 } 6181 6182 if (useHapticFeedback) { 6183 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); 6184 } 6185 6186 if (isWakeKey) { 6187 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 6188 } 6189 6190 return result; 6191 } 6192 6193 /** 6194 * Handle statusbar expansion events. 6195 * @param event 6196 */ 6197 private void interceptSystemNavigationKey(KeyEvent event) { 6198 if (event.getAction() == KeyEvent.ACTION_UP) { 6199 if (!mAccessibilityManager.isEnabled() 6200 || !mAccessibilityManager.sendFingerprintGesture(event.getKeyCode())) { 6201 if (areSystemNavigationKeysEnabled()) { 6202 IStatusBarService sbar = getStatusBarService(); 6203 if (sbar != null) { 6204 try { 6205 sbar.handleSystemNavigationKey(event.getKeyCode()); 6206 } catch (RemoteException e1) { 6207 // oops, no statusbar. Ignore event. 6208 } 6209 } 6210 } 6211 } 6212 } 6213 } 6214 6215 /** 6216 * Returns true if the key can have global actions attached to it. 6217 * We reserve all power management keys for the system since they require 6218 * very careful handling. 6219 */ 6220 private static boolean isValidGlobalKey(int keyCode) { 6221 switch (keyCode) { 6222 case KeyEvent.KEYCODE_POWER: 6223 case KeyEvent.KEYCODE_WAKEUP: 6224 case KeyEvent.KEYCODE_SLEEP: 6225 return false; 6226 default: 6227 return true; 6228 } 6229 } 6230 6231 /** 6232 * When the screen is off we ignore some keys that might otherwise typically 6233 * be considered wake keys. We filter them out here. 6234 * 6235 * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it 6236 * is always considered a wake key. 6237 */ 6238 private boolean isWakeKeyWhenScreenOff(int keyCode) { 6239 switch (keyCode) { 6240 // ignore volume keys unless docked 6241 case KeyEvent.KEYCODE_VOLUME_UP: 6242 case KeyEvent.KEYCODE_VOLUME_DOWN: 6243 case KeyEvent.KEYCODE_VOLUME_MUTE: 6244 return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED; 6245 6246 // ignore media and camera keys 6247 case KeyEvent.KEYCODE_MUTE: 6248 case KeyEvent.KEYCODE_HEADSETHOOK: 6249 case KeyEvent.KEYCODE_MEDIA_PLAY: 6250 case KeyEvent.KEYCODE_MEDIA_PAUSE: 6251 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 6252 case KeyEvent.KEYCODE_MEDIA_STOP: 6253 case KeyEvent.KEYCODE_MEDIA_NEXT: 6254 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 6255 case KeyEvent.KEYCODE_MEDIA_REWIND: 6256 case KeyEvent.KEYCODE_MEDIA_RECORD: 6257 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 6258 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: 6259 case KeyEvent.KEYCODE_CAMERA: 6260 return false; 6261 } 6262 return true; 6263 } 6264 6265 6266 /** {@inheritDoc} */ 6267 @Override 6268 public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) { 6269 if ((policyFlags & FLAG_WAKE) != 0) { 6270 if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion, 6271 "android.policy:MOTION")) { 6272 return 0; 6273 } 6274 } 6275 6276 if (shouldDispatchInputWhenNonInteractive(null)) { 6277 return ACTION_PASS_TO_USER; 6278 } 6279 6280 // If we have not passed the action up and we are in theater mode without dreaming, 6281 // there will be no dream to intercept the touch and wake into ambient. The device should 6282 // wake up in this case. 6283 if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) { 6284 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming, 6285 "android.policy:MOTION"); 6286 } 6287 6288 return 0; 6289 } 6290 6291 private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) { 6292 final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF); 6293 6294 if (displayOff && !mHasFeatureWatch) { 6295 return false; 6296 } 6297 6298 // Send events to keyguard while the screen is on and it's showing. 6299 if (isKeyguardShowingAndNotOccluded() && !displayOff) { 6300 return true; 6301 } 6302 6303 // Watches handle BACK specially 6304 if (mHasFeatureWatch 6305 && event != null 6306 && (event.getKeyCode() == KeyEvent.KEYCODE_BACK 6307 || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) { 6308 return false; 6309 } 6310 6311 // Send events to a dozing dream even if the screen is off since the dream 6312 // is in control of the state of the screen. 6313 IDreamManager dreamManager = getDreamManager(); 6314 6315 try { 6316 if (dreamManager != null && dreamManager.isDreaming()) { 6317 return true; 6318 } 6319 } catch (RemoteException e) { 6320 Slog.e(TAG, "RemoteException when checking if dreaming", e); 6321 } 6322 6323 // Otherwise, consume events since the user can't see what is being 6324 // interacted with. 6325 return false; 6326 } 6327 6328 private void dispatchDirectAudioEvent(KeyEvent event) { 6329 if (event.getAction() != KeyEvent.ACTION_DOWN) { 6330 return; 6331 } 6332 int keyCode = event.getKeyCode(); 6333 int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND 6334 | AudioManager.FLAG_FROM_KEY; 6335 String pkgName = mContext.getOpPackageName(); 6336 switch (keyCode) { 6337 case KeyEvent.KEYCODE_VOLUME_UP: 6338 try { 6339 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE, 6340 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6341 } catch (Exception e) { 6342 Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e); 6343 } 6344 break; 6345 case KeyEvent.KEYCODE_VOLUME_DOWN: 6346 try { 6347 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER, 6348 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6349 } catch (Exception e) { 6350 Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e); 6351 } 6352 break; 6353 case KeyEvent.KEYCODE_VOLUME_MUTE: 6354 try { 6355 if (event.getRepeatCount() == 0) { 6356 getAudioService().adjustSuggestedStreamVolume( 6357 AudioManager.ADJUST_TOGGLE_MUTE, 6358 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6359 } 6360 } catch (Exception e) { 6361 Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e); 6362 } 6363 break; 6364 } 6365 } 6366 6367 void dispatchMediaKeyWithWakeLock(KeyEvent event) { 6368 if (DEBUG_INPUT) { 6369 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event); 6370 } 6371 6372 if (mHavePendingMediaKeyRepeatWithWakeLock) { 6373 if (DEBUG_INPUT) { 6374 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat"); 6375 } 6376 6377 mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK); 6378 mHavePendingMediaKeyRepeatWithWakeLock = false; 6379 mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock 6380 } 6381 6382 dispatchMediaKeyWithWakeLockToAudioService(event); 6383 6384 if (event.getAction() == KeyEvent.ACTION_DOWN 6385 && event.getRepeatCount() == 0) { 6386 mHavePendingMediaKeyRepeatWithWakeLock = true; 6387 6388 Message msg = mHandler.obtainMessage( 6389 MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event); 6390 msg.setAsynchronous(true); 6391 mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout()); 6392 } else { 6393 mBroadcastWakeLock.release(); 6394 } 6395 } 6396 6397 void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) { 6398 mHavePendingMediaKeyRepeatWithWakeLock = false; 6399 6400 KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event, 6401 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS); 6402 if (DEBUG_INPUT) { 6403 Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent); 6404 } 6405 6406 dispatchMediaKeyWithWakeLockToAudioService(repeatEvent); 6407 mBroadcastWakeLock.release(); 6408 } 6409 6410 void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) { 6411 if (mActivityManagerInternal.isSystemReady()) { 6412 MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true); 6413 } 6414 } 6415 6416 void launchVoiceAssistWithWakeLock(boolean keyguardActive) { 6417 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface( 6418 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); 6419 if (dic != null) { 6420 try { 6421 dic.exitIdle("voice-search"); 6422 } catch (RemoteException e) { 6423 } 6424 } 6425 Intent voiceIntent = 6426 new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); 6427 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive); 6428 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF); 6429 mBroadcastWakeLock.release(); 6430 } 6431 6432 BroadcastReceiver mDockReceiver = new BroadcastReceiver() { 6433 @Override 6434 public void onReceive(Context context, Intent intent) { 6435 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) { 6436 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 6437 Intent.EXTRA_DOCK_STATE_UNDOCKED); 6438 } else { 6439 try { 6440 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface( 6441 ServiceManager.getService(Context.UI_MODE_SERVICE)); 6442 mUiMode = uiModeService.getCurrentModeType(); 6443 } catch (RemoteException e) { 6444 } 6445 } 6446 updateRotation(true); 6447 synchronized (mLock) { 6448 updateOrientationListenerLp(); 6449 } 6450 } 6451 }; 6452 6453 BroadcastReceiver mDreamReceiver = new BroadcastReceiver() { 6454 @Override 6455 public void onReceive(Context context, Intent intent) { 6456 if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) { 6457 if (mKeyguardDelegate != null) { 6458 mKeyguardDelegate.onDreamingStarted(); 6459 } 6460 } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) { 6461 if (mKeyguardDelegate != null) { 6462 mKeyguardDelegate.onDreamingStopped(); 6463 } 6464 } 6465 } 6466 }; 6467 6468 BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() { 6469 @Override 6470 public void onReceive(Context context, Intent intent) { 6471 if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) { 6472 // tickle the settings observer: this first ensures that we're 6473 // observing the relevant settings for the newly-active user, 6474 // and then updates our own bookkeeping based on the now- 6475 // current user. 6476 mSettingsObserver.onChange(false); 6477 6478 // force a re-application of focused window sysui visibility. 6479 // the window may never have been shown for this user 6480 // e.g. the keyguard when going through the new-user setup flow 6481 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6482 mLastSystemUiFlags = 0; 6483 updateSystemUiVisibilityLw(); 6484 } 6485 } 6486 } 6487 }; 6488 6489 private final Runnable mHiddenNavPanic = new Runnable() { 6490 @Override 6491 public void run() { 6492 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6493 if (!isUserSetupComplete()) { 6494 // Swipe-up for navigation bar is disabled during setup 6495 return; 6496 } 6497 mPendingPanicGestureUptime = SystemClock.uptimeMillis(); 6498 if (!isNavBarEmpty(mLastSystemUiFlags)) { 6499 mNavigationBarController.showTransient(); 6500 } 6501 } 6502 } 6503 }; 6504 6505 private void requestTransientBars(WindowState swipeTarget) { 6506 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6507 if (!isUserSetupComplete()) { 6508 // Swipe-up for navigation bar is disabled during setup 6509 return; 6510 } 6511 boolean sb = mStatusBarController.checkShowTransientBarLw(); 6512 boolean nb = mNavigationBarController.checkShowTransientBarLw() 6513 && !isNavBarEmpty(mLastSystemUiFlags); 6514 if (sb || nb) { 6515 // Don't show status bar when swiping on already visible navigation bar 6516 if (!nb && swipeTarget == mNavigationBar) { 6517 if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target"); 6518 return; 6519 } 6520 if (sb) mStatusBarController.showTransient(); 6521 if (nb) mNavigationBarController.showTransient(); 6522 mImmersiveModeConfirmation.confirmCurrentPrompt(); 6523 updateSystemUiVisibilityLw(); 6524 } 6525 } 6526 } 6527 6528 // Called on the PowerManager's Notifier thread. 6529 @Override 6530 public void startedGoingToSleep(int why) { 6531 if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")"); 6532 mCameraGestureTriggeredDuringGoingToSleep = false; 6533 mGoingToSleep = true; 6534 if (mKeyguardDelegate != null) { 6535 mKeyguardDelegate.onStartedGoingToSleep(why); 6536 } 6537 } 6538 6539 // Called on the PowerManager's Notifier thread. 6540 @Override 6541 public void finishedGoingToSleep(int why) { 6542 EventLog.writeEvent(70000, 0); 6543 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")"); 6544 MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000); 6545 6546 mGoingToSleep = false; 6547 6548 // We must get this work done here because the power manager will drop 6549 // the wake lock and let the system suspend once this function returns. 6550 synchronized (mLock) { 6551 mAwake = false; 6552 updateWakeGestureListenerLp(); 6553 updateOrientationListenerLp(); 6554 updateLockScreenTimeout(); 6555 } 6556 if (mKeyguardDelegate != null) { 6557 mKeyguardDelegate.onFinishedGoingToSleep(why, 6558 mCameraGestureTriggeredDuringGoingToSleep); 6559 } 6560 mCameraGestureTriggeredDuringGoingToSleep = false; 6561 } 6562 6563 // Called on the PowerManager's Notifier thread. 6564 @Override 6565 public void startedWakingUp() { 6566 EventLog.writeEvent(70000, 1); 6567 if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up..."); 6568 6569 // Since goToSleep performs these functions synchronously, we must 6570 // do the same here. We cannot post this work to a handler because 6571 // that might cause it to become reordered with respect to what 6572 // may happen in a future call to goToSleep. 6573 synchronized (mLock) { 6574 mAwake = true; 6575 6576 updateWakeGestureListenerLp(); 6577 updateOrientationListenerLp(); 6578 updateLockScreenTimeout(); 6579 } 6580 6581 if (mKeyguardDelegate != null) { 6582 mKeyguardDelegate.onStartedWakingUp(); 6583 } 6584 } 6585 6586 // Called on the PowerManager's Notifier thread. 6587 @Override 6588 public void finishedWakingUp() { 6589 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up..."); 6590 } 6591 6592 private void wakeUpFromPowerKey(long eventTime) { 6593 wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER"); 6594 } 6595 6596 private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) { 6597 final boolean theaterModeEnabled = isTheaterModeEnabled(); 6598 if (!wakeInTheaterMode && theaterModeEnabled) { 6599 return false; 6600 } 6601 6602 if (theaterModeEnabled) { 6603 Settings.Global.putInt(mContext.getContentResolver(), 6604 Settings.Global.THEATER_MODE_ON, 0); 6605 } 6606 6607 mPowerManager.wakeUp(wakeTime, reason); 6608 return true; 6609 } 6610 6611 private void finishKeyguardDrawn() { 6612 synchronized (mLock) { 6613 if (!mScreenOnEarly || mKeyguardDrawComplete) { 6614 return; // We are not awake yet or we have already informed of this event. 6615 } 6616 6617 mKeyguardDrawComplete = true; 6618 if (mKeyguardDelegate != null) { 6619 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6620 } 6621 mWindowManagerDrawComplete = false; 6622 } 6623 6624 // ... eventually calls finishWindowsDrawn which will finalize our screen turn on 6625 // as well as enabling the orientation change logic/sensor. 6626 mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback, 6627 WAITING_FOR_DRAWN_TIMEOUT); 6628 } 6629 6630 // Called on the DisplayManager's DisplayPowerController thread. 6631 @Override 6632 public void screenTurnedOff() { 6633 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off..."); 6634 6635 updateScreenOffSleepToken(true); 6636 synchronized (mLock) { 6637 mScreenOnEarly = false; 6638 mScreenOnFully = false; 6639 mKeyguardDrawComplete = false; 6640 mWindowManagerDrawComplete = false; 6641 mScreenOnListener = null; 6642 updateOrientationListenerLp(); 6643 6644 if (mKeyguardDelegate != null) { 6645 mKeyguardDelegate.onScreenTurnedOff(); 6646 } 6647 } 6648 reportScreenStateToVrManager(false); 6649 } 6650 6651 private long getKeyguardDrawnTimeout() { 6652 final boolean bootCompleted = 6653 LocalServices.getService(SystemServiceManager.class).isBootCompleted(); 6654 // Set longer timeout if it has not booted yet to prevent showing empty window. 6655 return bootCompleted ? 1000 : 5000; 6656 } 6657 6658 // Called on the DisplayManager's DisplayPowerController thread. 6659 @Override 6660 public void screenTurningOn(final ScreenOnListener screenOnListener) { 6661 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on..."); 6662 6663 updateScreenOffSleepToken(false); 6664 synchronized (mLock) { 6665 mScreenOnEarly = true; 6666 mScreenOnFully = false; 6667 mKeyguardDrawComplete = false; 6668 mWindowManagerDrawComplete = false; 6669 mScreenOnListener = screenOnListener; 6670 6671 if (mKeyguardDelegate != null) { 6672 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6673 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 6674 getKeyguardDrawnTimeout()); 6675 mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback); 6676 } else { 6677 if (DEBUG_WAKEUP) Slog.d(TAG, 6678 "null mKeyguardDelegate: setting mKeyguardDrawComplete."); 6679 finishKeyguardDrawn(); 6680 } 6681 } 6682 } 6683 6684 // Called on the DisplayManager's DisplayPowerController thread. 6685 @Override 6686 public void screenTurnedOn() { 6687 synchronized (mLock) { 6688 if (mKeyguardDelegate != null) { 6689 mKeyguardDelegate.onScreenTurnedOn(); 6690 } 6691 } 6692 reportScreenStateToVrManager(true); 6693 } 6694 6695 @Override 6696 public void screenTurningOff(ScreenOffListener screenOffListener) { 6697 mWindowManagerFuncs.screenTurningOff(screenOffListener); 6698 } 6699 6700 private void reportScreenStateToVrManager(boolean isScreenOn) { 6701 if (mVrManagerInternal == null) { 6702 return; 6703 } 6704 mVrManagerInternal.onScreenStateChanged(isScreenOn); 6705 } 6706 6707 private void finishWindowsDrawn() { 6708 synchronized (mLock) { 6709 if (!mScreenOnEarly || mWindowManagerDrawComplete) { 6710 return; // Screen is not turned on or we did already handle this case earlier. 6711 } 6712 6713 mWindowManagerDrawComplete = true; 6714 } 6715 6716 finishScreenTurningOn(); 6717 } 6718 6719 private void finishScreenTurningOn() { 6720 synchronized (mLock) { 6721 // We have just finished drawing screen content. Since the orientation listener 6722 // gets only installed when all windows are drawn, we try to install it again. 6723 updateOrientationListenerLp(); 6724 } 6725 final ScreenOnListener listener; 6726 final boolean enableScreen; 6727 synchronized (mLock) { 6728 if (DEBUG_WAKEUP) Slog.d(TAG, 6729 "finishScreenTurningOn: mAwake=" + mAwake 6730 + ", mScreenOnEarly=" + mScreenOnEarly 6731 + ", mScreenOnFully=" + mScreenOnFully 6732 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete 6733 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete); 6734 6735 if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete 6736 || (mAwake && !mKeyguardDrawComplete)) { 6737 return; // spurious or not ready yet 6738 } 6739 6740 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on..."); 6741 listener = mScreenOnListener; 6742 mScreenOnListener = null; 6743 mScreenOnFully = true; 6744 6745 // Remember the first time we draw the keyguard so we know when we're done with 6746 // the main part of booting and can enable the screen and hide boot messages. 6747 if (!mKeyguardDrawnOnce && mAwake) { 6748 mKeyguardDrawnOnce = true; 6749 enableScreen = true; 6750 if (mBootMessageNeedsHiding) { 6751 mBootMessageNeedsHiding = false; 6752 hideBootMessages(); 6753 } 6754 } else { 6755 enableScreen = false; 6756 } 6757 } 6758 6759 if (listener != null) { 6760 listener.onScreenOn(); 6761 } 6762 6763 if (enableScreen) { 6764 try { 6765 mWindowManager.enableScreenIfNeeded(); 6766 } catch (RemoteException unhandled) { 6767 } 6768 } 6769 } 6770 6771 private void handleHideBootMessage() { 6772 synchronized (mLock) { 6773 if (!mKeyguardDrawnOnce) { 6774 mBootMessageNeedsHiding = true; 6775 return; // keyguard hasn't drawn the first time yet, not done booting 6776 } 6777 } 6778 6779 if (mBootMsgDialog != null) { 6780 if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing"); 6781 mBootMsgDialog.dismiss(); 6782 mBootMsgDialog = null; 6783 } 6784 } 6785 6786 @Override 6787 public boolean isScreenOn() { 6788 return mScreenOnFully; 6789 } 6790 6791 /** {@inheritDoc} */ 6792 @Override 6793 public void enableKeyguard(boolean enabled) { 6794 if (mKeyguardDelegate != null) { 6795 mKeyguardDelegate.setKeyguardEnabled(enabled); 6796 } 6797 } 6798 6799 /** {@inheritDoc} */ 6800 @Override 6801 public void exitKeyguardSecurely(OnKeyguardExitResult callback) { 6802 if (mKeyguardDelegate != null) { 6803 mKeyguardDelegate.verifyUnlock(callback); 6804 } 6805 } 6806 6807 @Override 6808 public boolean isKeyguardShowingAndNotOccluded() { 6809 if (mKeyguardDelegate == null) return false; 6810 return mKeyguardDelegate.isShowing() && !mKeyguardOccluded; 6811 } 6812 6813 @Override 6814 public boolean isKeyguardTrustedLw() { 6815 if (mKeyguardDelegate == null) return false; 6816 return mKeyguardDelegate.isTrusted(); 6817 } 6818 6819 /** {@inheritDoc} */ 6820 @Override 6821 public boolean isKeyguardLocked() { 6822 return keyguardOn(); 6823 } 6824 6825 /** {@inheritDoc} */ 6826 @Override 6827 public boolean isKeyguardSecure(int userId) { 6828 if (mKeyguardDelegate == null) return false; 6829 return mKeyguardDelegate.isSecure(userId); 6830 } 6831 6832 /** {@inheritDoc} */ 6833 @Override 6834 public boolean isKeyguardOccluded() { 6835 if (mKeyguardDelegate == null) return false; 6836 return mKeyguardOccluded; 6837 } 6838 6839 /** {@inheritDoc} */ 6840 @Override 6841 public boolean inKeyguardRestrictedKeyInputMode() { 6842 if (mKeyguardDelegate == null) return false; 6843 return mKeyguardDelegate.isInputRestricted(); 6844 } 6845 6846 @Override 6847 public void dismissKeyguardLw(IKeyguardDismissCallback callback) { 6848 if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) { 6849 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw"); 6850 6851 // ask the keyguard to prompt the user to authenticate if necessary 6852 mKeyguardDelegate.dismiss(callback); 6853 } else if (callback != null) { 6854 try { 6855 callback.onDismissError(); 6856 } catch (RemoteException e) { 6857 Slog.w(TAG, "Failed to call callback", e); 6858 } 6859 } 6860 } 6861 6862 @Override 6863 public boolean isKeyguardDrawnLw() { 6864 synchronized (mLock) { 6865 return mKeyguardDrawnOnce; 6866 } 6867 } 6868 6869 @Override 6870 public boolean isShowingDreamLw() { 6871 return mShowingDream; 6872 } 6873 6874 @Override 6875 public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) { 6876 if (mKeyguardDelegate != null) { 6877 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation"); 6878 mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration); 6879 } 6880 } 6881 6882 @Override 6883 public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6884 Rect outInsets) { 6885 outInsets.setEmpty(); 6886 6887 // Navigation bar and status bar. 6888 getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets); 6889 outInsets.top = mStatusBarHeight; 6890 } 6891 6892 @Override 6893 public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6894 Rect outInsets) { 6895 outInsets.setEmpty(); 6896 6897 // Only navigation bar 6898 if (mHasNavigationBar) { 6899 int position = navigationBarPosition(displayWidth, displayHeight, displayRotation); 6900 if (position == NAV_BAR_BOTTOM) { 6901 outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode); 6902 } else if (position == NAV_BAR_RIGHT) { 6903 outInsets.right = getNavigationBarWidth(displayRotation, mUiMode); 6904 } else if (position == NAV_BAR_LEFT) { 6905 outInsets.left = getNavigationBarWidth(displayRotation, mUiMode); 6906 } 6907 } 6908 } 6909 6910 @Override 6911 public boolean isNavBarForcedShownLw(WindowState windowState) { 6912 return mForceShowSystemBars; 6913 } 6914 6915 @Override 6916 public boolean isDockSideAllowed(int dockSide) { 6917 6918 // We do not allow all dock sides at which the navigation bar touches the docked stack. 6919 if (!mNavigationBarCanMove) { 6920 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT; 6921 } else { 6922 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT; 6923 } 6924 } 6925 6926 void sendCloseSystemWindows() { 6927 PhoneWindow.sendCloseSystemWindows(mContext, null); 6928 } 6929 6930 void sendCloseSystemWindows(String reason) { 6931 PhoneWindow.sendCloseSystemWindows(mContext, reason); 6932 } 6933 6934 @Override 6935 public int rotationForOrientationLw(int orientation, int lastRotation) { 6936 if (false) { 6937 Slog.v(TAG, "rotationForOrientationLw(orient=" 6938 + orientation + ", last=" + lastRotation 6939 + "); user=" + mUserRotation + " " 6940 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) 6941 ? "USER_ROTATION_LOCKED" : "") 6942 ); 6943 } 6944 6945 if (mForceDefaultOrientation) { 6946 return Surface.ROTATION_0; 6947 } 6948 6949 synchronized (mLock) { 6950 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1 6951 if (sensorRotation < 0) { 6952 sensorRotation = lastRotation; 6953 } 6954 6955 final int preferredRotation; 6956 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) { 6957 // Ignore sensor when lid switch is open and rotation is forced. 6958 preferredRotation = mLidOpenRotation; 6959 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR 6960 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) { 6961 // Ignore sensor when in car dock unless explicitly enabled. 6962 // This case can override the behavior of NOSENSOR, and can also 6963 // enable 180 degree rotation while docked. 6964 preferredRotation = mCarDockEnablesAccelerometer 6965 ? sensorRotation : mCarDockRotation; 6966 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK 6967 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK 6968 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK) 6969 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) { 6970 // Ignore sensor when in desk dock unless explicitly enabled. 6971 // This case can override the behavior of NOSENSOR, and can also 6972 // enable 180 degree rotation while docked. 6973 preferredRotation = mDeskDockEnablesAccelerometer 6974 ? sensorRotation : mDeskDockRotation; 6975 } else if (mHdmiPlugged && mDemoHdmiRotationLock) { 6976 // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled. 6977 // Note that the dock orientation overrides the HDMI orientation. 6978 preferredRotation = mDemoHdmiRotation; 6979 } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED 6980 && mUndockedHdmiRotation >= 0) { 6981 // Ignore sensor when plugged into HDMI and an undocked orientation has 6982 // been specified in the configuration (only for legacy devices without 6983 // full multi-display support). 6984 // Note that the dock orientation overrides the HDMI orientation. 6985 preferredRotation = mUndockedHdmiRotation; 6986 } else if (mDemoRotationLock) { 6987 // Ignore sensor when demo rotation lock is enabled. 6988 // Note that the dock orientation and HDMI rotation lock override this. 6989 preferredRotation = mDemoRotation; 6990 } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) { 6991 // Application just wants to remain locked in the last rotation. 6992 preferredRotation = lastRotation; 6993 } else if (!mSupportAutoRotation) { 6994 // If we don't support auto-rotation then bail out here and ignore 6995 // the sensor and any rotation lock settings. 6996 preferredRotation = -1; 6997 } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE 6998 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER 6999 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 7000 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE 7001 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT 7002 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER)) 7003 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR 7004 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 7005 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE 7006 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) { 7007 // Otherwise, use sensor only if requested by the application or enabled 7008 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR. 7009 if (mAllowAllRotations < 0) { 7010 // Can't read this during init() because the context doesn't 7011 // have display metrics at that time so we cannot determine 7012 // tablet vs. phone then. 7013 mAllowAllRotations = mContext.getResources().getBoolean( 7014 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0; 7015 } 7016 if (sensorRotation != Surface.ROTATION_180 7017 || mAllowAllRotations == 1 7018 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 7019 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) { 7020 // In VrMode, we report the sensor as always being in default orientation so: 7021 // 1) The orientation doesn't change as the user moves their head. 7022 // 2) 2D apps within VR show in the device's default orientation. 7023 // This only overwrites the sensor-provided orientation and does not affect any 7024 // explicit orientation preferences specified by any activities. 7025 preferredRotation = 7026 mPersistentVrModeEnabled ? Surface.ROTATION_0 : sensorRotation; 7027 } else { 7028 preferredRotation = lastRotation; 7029 } 7030 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED 7031 && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) { 7032 // Apply rotation lock. Does not apply to NOSENSOR. 7033 // The idea is that the user rotation expresses a weak preference for the direction 7034 // of gravity and as NOSENSOR is never affected by gravity, then neither should 7035 // NOSENSOR be affected by rotation lock (although it will be affected by docks). 7036 preferredRotation = mUserRotation; 7037 } else { 7038 // No overriding preference. 7039 // We will do exactly what the application asked us to do. 7040 preferredRotation = -1; 7041 } 7042 7043 switch (orientation) { 7044 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 7045 // Return portrait unless overridden. 7046 if (isAnyPortrait(preferredRotation)) { 7047 return preferredRotation; 7048 } 7049 return mPortraitRotation; 7050 7051 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 7052 // Return landscape unless overridden. 7053 if (isLandscapeOrSeascape(preferredRotation)) { 7054 return preferredRotation; 7055 } 7056 return mLandscapeRotation; 7057 7058 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 7059 // Return reverse portrait unless overridden. 7060 if (isAnyPortrait(preferredRotation)) { 7061 return preferredRotation; 7062 } 7063 return mUpsideDownRotation; 7064 7065 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 7066 // Return seascape unless overridden. 7067 if (isLandscapeOrSeascape(preferredRotation)) { 7068 return preferredRotation; 7069 } 7070 return mSeascapeRotation; 7071 7072 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 7073 case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE: 7074 // Return either landscape rotation. 7075 if (isLandscapeOrSeascape(preferredRotation)) { 7076 return preferredRotation; 7077 } 7078 if (isLandscapeOrSeascape(lastRotation)) { 7079 return lastRotation; 7080 } 7081 return mLandscapeRotation; 7082 7083 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 7084 case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT: 7085 // Return either portrait rotation. 7086 if (isAnyPortrait(preferredRotation)) { 7087 return preferredRotation; 7088 } 7089 if (isAnyPortrait(lastRotation)) { 7090 return lastRotation; 7091 } 7092 return mPortraitRotation; 7093 7094 default: 7095 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR, 7096 // just return the preferred orientation we already calculated. 7097 if (preferredRotation >= 0) { 7098 return preferredRotation; 7099 } 7100 return Surface.ROTATION_0; 7101 } 7102 } 7103 } 7104 7105 @Override 7106 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) { 7107 switch (orientation) { 7108 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 7109 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 7110 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 7111 return isAnyPortrait(rotation); 7112 7113 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 7114 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 7115 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 7116 return isLandscapeOrSeascape(rotation); 7117 7118 default: 7119 return true; 7120 } 7121 } 7122 7123 @Override 7124 public void setRotationLw(int rotation) { 7125 mOrientationListener.setCurrentRotation(rotation); 7126 } 7127 7128 private boolean isLandscapeOrSeascape(int rotation) { 7129 return rotation == mLandscapeRotation || rotation == mSeascapeRotation; 7130 } 7131 7132 private boolean isAnyPortrait(int rotation) { 7133 return rotation == mPortraitRotation || rotation == mUpsideDownRotation; 7134 } 7135 7136 @Override 7137 public int getUserRotationMode() { 7138 return Settings.System.getIntForUser(mContext.getContentResolver(), 7139 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ? 7140 WindowManagerPolicy.USER_ROTATION_FREE : 7141 WindowManagerPolicy.USER_ROTATION_LOCKED; 7142 } 7143 7144 // User rotation: to be used when all else fails in assigning an orientation to the device 7145 @Override 7146 public void setUserRotationMode(int mode, int rot) { 7147 ContentResolver res = mContext.getContentResolver(); 7148 7149 // mUserRotationMode and mUserRotation will be assigned by the content observer 7150 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) { 7151 Settings.System.putIntForUser(res, 7152 Settings.System.USER_ROTATION, 7153 rot, 7154 UserHandle.USER_CURRENT); 7155 Settings.System.putIntForUser(res, 7156 Settings.System.ACCELEROMETER_ROTATION, 7157 0, 7158 UserHandle.USER_CURRENT); 7159 } else { 7160 Settings.System.putIntForUser(res, 7161 Settings.System.ACCELEROMETER_ROTATION, 7162 1, 7163 UserHandle.USER_CURRENT); 7164 } 7165 } 7166 7167 @Override 7168 public void setSafeMode(boolean safeMode) { 7169 mSafeMode = safeMode; 7170 performHapticFeedbackLw(null, safeMode 7171 ? HapticFeedbackConstants.SAFE_MODE_ENABLED 7172 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true); 7173 } 7174 7175 static long[] getLongIntArray(Resources r, int resid) { 7176 int[] ar = r.getIntArray(resid); 7177 if (ar == null) { 7178 return null; 7179 } 7180 long[] out = new long[ar.length]; 7181 for (int i=0; i<ar.length; i++) { 7182 out[i] = ar[i]; 7183 } 7184 return out; 7185 } 7186 7187 private void bindKeyguard() { 7188 synchronized (mLock) { 7189 if (mKeyguardBound) { 7190 return; 7191 } 7192 mKeyguardBound = true; 7193 } 7194 mKeyguardDelegate.bindService(mContext); 7195 } 7196 7197 @Override 7198 public void onSystemUiStarted() { 7199 bindKeyguard(); 7200 } 7201 7202 /** {@inheritDoc} */ 7203 @Override 7204 public void systemReady() { 7205 // In normal flow, systemReady is called before other system services are ready. 7206 // So it is better not to bind keyguard here. 7207 mKeyguardDelegate.onSystemReady(); 7208 7209 mVrManagerInternal = LocalServices.getService(VrManagerInternal.class); 7210 if (mVrManagerInternal != null) { 7211 mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener); 7212 } 7213 7214 readCameraLensCoverState(); 7215 updateUiMode(); 7216 synchronized (mLock) { 7217 updateOrientationListenerLp(); 7218 mSystemReady = true; 7219 mHandler.post(new Runnable() { 7220 @Override 7221 public void run() { 7222 updateSettings(); 7223 } 7224 }); 7225 // If this happens, for whatever reason, systemReady came later than systemBooted. 7226 // And keyguard should be already bound from systemBooted 7227 if (mSystemBooted) { 7228 mKeyguardDelegate.onBootCompleted(); 7229 } 7230 } 7231 7232 mSystemGestures.systemReady(); 7233 mImmersiveModeConfirmation.systemReady(); 7234 } 7235 7236 /** {@inheritDoc} */ 7237 @Override 7238 public void systemBooted() { 7239 bindKeyguard(); 7240 synchronized (mLock) { 7241 mSystemBooted = true; 7242 if (mSystemReady) { 7243 mKeyguardDelegate.onBootCompleted(); 7244 } 7245 } 7246 startedWakingUp(); 7247 screenTurningOn(null); 7248 screenTurnedOn(); 7249 } 7250 7251 @Override 7252 public boolean canDismissBootAnimation() { 7253 synchronized (mLock) { 7254 return mKeyguardDrawComplete; 7255 } 7256 } 7257 7258 ProgressDialog mBootMsgDialog = null; 7259 7260 /** {@inheritDoc} */ 7261 @Override 7262 public void showBootMessage(final CharSequence msg, final boolean always) { 7263 mHandler.post(new Runnable() { 7264 @Override public void run() { 7265 if (mBootMsgDialog == null) { 7266 int theme; 7267 if (mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK)) { 7268 theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert; 7269 } else { 7270 theme = 0; 7271 } 7272 7273 mBootMsgDialog = new ProgressDialog(mContext, theme) { 7274 // This dialog will consume all events coming in to 7275 // it, to avoid it trying to do things too early in boot. 7276 @Override public boolean dispatchKeyEvent(KeyEvent event) { 7277 return true; 7278 } 7279 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { 7280 return true; 7281 } 7282 @Override public boolean dispatchTouchEvent(MotionEvent ev) { 7283 return true; 7284 } 7285 @Override public boolean dispatchTrackballEvent(MotionEvent ev) { 7286 return true; 7287 } 7288 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) { 7289 return true; 7290 } 7291 @Override public boolean dispatchPopulateAccessibilityEvent( 7292 AccessibilityEvent event) { 7293 return true; 7294 } 7295 }; 7296 if (mContext.getPackageManager().isUpgrade()) { 7297 mBootMsgDialog.setTitle(R.string.android_upgrading_title); 7298 } else { 7299 mBootMsgDialog.setTitle(R.string.android_start_title); 7300 } 7301 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 7302 mBootMsgDialog.setIndeterminate(true); 7303 mBootMsgDialog.getWindow().setType( 7304 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS); 7305 mBootMsgDialog.getWindow().addFlags( 7306 WindowManager.LayoutParams.FLAG_DIM_BEHIND 7307 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); 7308 mBootMsgDialog.getWindow().setDimAmount(1); 7309 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes(); 7310 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 7311 mBootMsgDialog.getWindow().setAttributes(lp); 7312 mBootMsgDialog.setCancelable(false); 7313 mBootMsgDialog.show(); 7314 } 7315 mBootMsgDialog.setMessage(msg); 7316 } 7317 }); 7318 } 7319 7320 /** {@inheritDoc} */ 7321 @Override 7322 public void hideBootMessages() { 7323 mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE); 7324 } 7325 7326 /** {@inheritDoc} */ 7327 @Override 7328 public void userActivity() { 7329 // *************************************** 7330 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE 7331 // *************************************** 7332 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER 7333 // WITH ITS LOCKS HELD. 7334 // 7335 // This code must be VERY careful about the locks 7336 // it acquires. 7337 // In fact, the current code acquires way too many, 7338 // and probably has lurking deadlocks. 7339 7340 synchronized (mScreenLockTimeout) { 7341 if (mLockScreenTimerActive) { 7342 // reset the timer 7343 mHandler.removeCallbacks(mScreenLockTimeout); 7344 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7345 } 7346 } 7347 } 7348 7349 class ScreenLockTimeout implements Runnable { 7350 Bundle options; 7351 7352 @Override 7353 public void run() { 7354 synchronized (this) { 7355 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard"); 7356 if (mKeyguardDelegate != null) { 7357 mKeyguardDelegate.doKeyguardTimeout(options); 7358 } 7359 mLockScreenTimerActive = false; 7360 options = null; 7361 } 7362 } 7363 7364 public void setLockOptions(Bundle options) { 7365 this.options = options; 7366 } 7367 } 7368 7369 ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout(); 7370 7371 @Override 7372 public void lockNow(Bundle options) { 7373 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 7374 mHandler.removeCallbacks(mScreenLockTimeout); 7375 if (options != null) { 7376 // In case multiple calls are made to lockNow, we don't wipe out the options 7377 // until the runnable actually executes. 7378 mScreenLockTimeout.setLockOptions(options); 7379 } 7380 mHandler.post(mScreenLockTimeout); 7381 } 7382 7383 private void updateLockScreenTimeout() { 7384 synchronized (mScreenLockTimeout) { 7385 boolean enable = (mAllowLockscreenWhenOn && mAwake && 7386 mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId)); 7387 if (mLockScreenTimerActive != enable) { 7388 if (enable) { 7389 if (localLOGV) Log.v(TAG, "setting lockscreen timer"); 7390 mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests 7391 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7392 } else { 7393 if (localLOGV) Log.v(TAG, "clearing lockscreen timer"); 7394 mHandler.removeCallbacks(mScreenLockTimeout); 7395 } 7396 mLockScreenTimerActive = enable; 7397 } 7398 } 7399 } 7400 7401 private void updateDreamingSleepToken(boolean acquire) { 7402 if (acquire) { 7403 if (mDreamingSleepToken == null) { 7404 mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream"); 7405 } 7406 } else { 7407 if (mDreamingSleepToken != null) { 7408 mDreamingSleepToken.release(); 7409 mDreamingSleepToken = null; 7410 } 7411 } 7412 } 7413 7414 private void updateScreenOffSleepToken(boolean acquire) { 7415 if (acquire) { 7416 if (mScreenOffSleepToken == null) { 7417 mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff"); 7418 } 7419 } else { 7420 if (mScreenOffSleepToken != null) { 7421 mScreenOffSleepToken.release(); 7422 mScreenOffSleepToken = null; 7423 } 7424 } 7425 } 7426 7427 /** {@inheritDoc} */ 7428 @Override 7429 public void enableScreenAfterBoot() { 7430 readLidState(); 7431 applyLidSwitchState(); 7432 updateRotation(true); 7433 } 7434 7435 private void applyLidSwitchState() { 7436 if (mLidState == LID_CLOSED && mLidControlsSleep) { 7437 mPowerManager.goToSleep(SystemClock.uptimeMillis(), 7438 PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH, 7439 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); 7440 } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) { 7441 mWindowManagerFuncs.lockDeviceNow(); 7442 } 7443 7444 synchronized (mLock) { 7445 updateWakeGestureListenerLp(); 7446 } 7447 } 7448 7449 void updateUiMode() { 7450 if (mUiModeManager == null) { 7451 mUiModeManager = IUiModeManager.Stub.asInterface( 7452 ServiceManager.getService(Context.UI_MODE_SERVICE)); 7453 } 7454 try { 7455 mUiMode = mUiModeManager.getCurrentModeType(); 7456 } catch (RemoteException e) { 7457 } 7458 } 7459 7460 void updateRotation(boolean alwaysSendConfiguration) { 7461 try { 7462 //set orientation on WindowManager 7463 mWindowManager.updateRotation(alwaysSendConfiguration, false); 7464 } catch (RemoteException e) { 7465 // Ignore 7466 } 7467 } 7468 7469 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 7470 try { 7471 //set orientation on WindowManager 7472 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout); 7473 } catch (RemoteException e) { 7474 // Ignore 7475 } 7476 } 7477 7478 /** 7479 * Return an Intent to launch the currently active dock app as home. Returns 7480 * null if the standard home should be launched, which is the case if any of the following is 7481 * true: 7482 * <ul> 7483 * <li>The device is not in either car mode or desk mode 7484 * <li>The device is in car mode but mEnableCarDockHomeCapture is false 7485 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false 7486 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME 7487 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME 7488 * </ul> 7489 * @return A dock intent. 7490 */ 7491 Intent createHomeDockIntent() { 7492 Intent intent = null; 7493 7494 // What home does is based on the mode, not the dock state. That 7495 // is, when in car mode you should be taken to car home regardless 7496 // of whether we are actually in a car dock. 7497 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) { 7498 if (mEnableCarDockHomeCapture) { 7499 intent = mCarDockIntent; 7500 } 7501 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) { 7502 if (ENABLE_DESK_DOCK_HOME_CAPTURE) { 7503 intent = mDeskDockIntent; 7504 } 7505 } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH 7506 && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK 7507 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK 7508 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) { 7509 // Always launch dock home from home when watch is docked, if it exists. 7510 intent = mDeskDockIntent; 7511 } else if (mUiMode == Configuration.UI_MODE_TYPE_VR_HEADSET) { 7512 if (ENABLE_VR_HEADSET_HOME_CAPTURE) { 7513 intent = mVrHeadsetHomeIntent; 7514 } 7515 } 7516 7517 if (intent == null) { 7518 return null; 7519 } 7520 7521 ActivityInfo ai = null; 7522 ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser( 7523 intent, 7524 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA, 7525 mCurrentUserId); 7526 if (info != null) { 7527 ai = info.activityInfo; 7528 } 7529 if (ai != null 7530 && ai.metaData != null 7531 && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) { 7532 intent = new Intent(intent); 7533 intent.setClassName(ai.packageName, ai.name); 7534 return intent; 7535 } 7536 7537 return null; 7538 } 7539 7540 void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) { 7541 if (awakenFromDreams) { 7542 awakenDreams(); 7543 } 7544 7545 Intent dock = createHomeDockIntent(); 7546 if (dock != null) { 7547 try { 7548 if (fromHomeKey) { 7549 dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7550 } 7551 startActivityAsUser(dock, UserHandle.CURRENT); 7552 return; 7553 } catch (ActivityNotFoundException e) { 7554 } 7555 } 7556 7557 Intent intent; 7558 7559 if (fromHomeKey) { 7560 intent = new Intent(mHomeIntent); 7561 intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7562 } else { 7563 intent = mHomeIntent; 7564 } 7565 7566 startActivityAsUser(intent, UserHandle.CURRENT); 7567 } 7568 7569 /** 7570 * goes to the home screen 7571 * @return whether it did anything 7572 */ 7573 boolean goHome() { 7574 if (!isUserSetupComplete()) { 7575 Slog.i(TAG, "Not going home because user setup is in progress."); 7576 return false; 7577 } 7578 if (false) { 7579 // This code always brings home to the front. 7580 try { 7581 ActivityManager.getService().stopAppSwitches(); 7582 } catch (RemoteException e) { 7583 } 7584 sendCloseSystemWindows(); 7585 startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */); 7586 } else { 7587 // This code brings home to the front or, if it is already 7588 // at the front, puts the device to sleep. 7589 try { 7590 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) { 7591 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry. 7592 Log.d(TAG, "UTS-TEST-MODE"); 7593 } else { 7594 ActivityManager.getService().stopAppSwitches(); 7595 sendCloseSystemWindows(); 7596 Intent dock = createHomeDockIntent(); 7597 if (dock != null) { 7598 int result = ActivityManager.getService() 7599 .startActivityAsUser(null, null, dock, 7600 dock.resolveTypeIfNeeded(mContext.getContentResolver()), 7601 null, null, 0, 7602 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7603 null, null, UserHandle.USER_CURRENT); 7604 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7605 return false; 7606 } 7607 } 7608 } 7609 int result = ActivityManager.getService() 7610 .startActivityAsUser(null, null, mHomeIntent, 7611 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()), 7612 null, null, 0, 7613 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7614 null, null, UserHandle.USER_CURRENT); 7615 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7616 return false; 7617 } 7618 } catch (RemoteException ex) { 7619 // bummer, the activity manager, which is in this process, is dead 7620 } 7621 } 7622 return true; 7623 } 7624 7625 @Override 7626 public void setCurrentOrientationLw(int newOrientation) { 7627 synchronized (mLock) { 7628 if (newOrientation != mCurrentAppOrientation) { 7629 mCurrentAppOrientation = newOrientation; 7630 updateOrientationListenerLp(); 7631 } 7632 } 7633 } 7634 7635 private boolean isTheaterModeEnabled() { 7636 return Settings.Global.getInt(mContext.getContentResolver(), 7637 Settings.Global.THEATER_MODE_ON, 0) == 1; 7638 } 7639 7640 private boolean areSystemNavigationKeysEnabled() { 7641 return Settings.Secure.getIntForUser(mContext.getContentResolver(), 7642 Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1; 7643 } 7644 7645 @Override 7646 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) { 7647 if (!mVibrator.hasVibrator()) { 7648 return false; 7649 } 7650 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(), 7651 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0; 7652 if (hapticsDisabled && !always) { 7653 return false; 7654 } 7655 7656 VibrationEffect effect = getVibrationEffect(effectId); 7657 if (effect == null) { 7658 return false; 7659 } 7660 7661 int owningUid; 7662 String owningPackage; 7663 if (win != null) { 7664 owningUid = win.getOwningUid(); 7665 owningPackage = win.getOwningPackage(); 7666 } else { 7667 owningUid = android.os.Process.myUid(); 7668 owningPackage = mContext.getOpPackageName(); 7669 } 7670 mVibrator.vibrate(owningUid, owningPackage, effect, VIBRATION_ATTRIBUTES); 7671 return true; 7672 } 7673 7674 private VibrationEffect getVibrationEffect(int effectId) { 7675 long[] pattern; 7676 switch (effectId) { 7677 case HapticFeedbackConstants.VIRTUAL_KEY: 7678 return VibrationEffect.get(VibrationEffect.EFFECT_CLICK); 7679 case HapticFeedbackConstants.LONG_PRESS: 7680 pattern = mLongPressVibePattern; 7681 break; 7682 case HapticFeedbackConstants.KEYBOARD_TAP: 7683 return VibrationEffect.get(VibrationEffect.EFFECT_CLICK); 7684 case HapticFeedbackConstants.CLOCK_TICK: 7685 pattern = mClockTickVibePattern; 7686 break; 7687 case HapticFeedbackConstants.CALENDAR_DATE: 7688 pattern = mCalendarDateVibePattern; 7689 break; 7690 case HapticFeedbackConstants.SAFE_MODE_DISABLED: 7691 pattern = mSafeModeDisabledVibePattern; 7692 break; 7693 case HapticFeedbackConstants.SAFE_MODE_ENABLED: 7694 pattern = mSafeModeEnabledVibePattern; 7695 break; 7696 case HapticFeedbackConstants.CONTEXT_CLICK: 7697 pattern = mContextClickVibePattern; 7698 break; 7699 default: 7700 return null; 7701 } 7702 if (pattern.length == 0) { 7703 // No vibration 7704 return null; 7705 } else if (pattern.length == 1) { 7706 // One-shot vibration 7707 return VibrationEffect.createOneShot(pattern[0], VibrationEffect.DEFAULT_AMPLITUDE); 7708 } else { 7709 // Pattern vibration 7710 return VibrationEffect.createWaveform(pattern, -1); 7711 } 7712 } 7713 7714 @Override 7715 public void keepScreenOnStartedLw() { 7716 } 7717 7718 @Override 7719 public void keepScreenOnStoppedLw() { 7720 if (isKeyguardShowingAndNotOccluded()) { 7721 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 7722 } 7723 } 7724 7725 private int updateSystemUiVisibilityLw() { 7726 // If there is no window focused, there will be nobody to handle the events 7727 // anyway, so just hang on in whatever state we're in until things settle down. 7728 WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow 7729 : mTopFullscreenOpaqueWindowState; 7730 if (winCandidate == null) { 7731 return 0; 7732 } 7733 if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) { 7734 // The immersive mode confirmation should never affect the system bar visibility, 7735 // otherwise it will unhide the navigation bar and hide itself. 7736 winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState; 7737 if (winCandidate == null) { 7738 return 0; 7739 } 7740 } 7741 final WindowState win = winCandidate; 7742 if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mKeyguardOccluded) { 7743 // We are updating at a point where the keyguard has gotten 7744 // focus, but we were last in a state where the top window is 7745 // hiding it. This is probably because the keyguard as been 7746 // shown while the top window was displayed, so we want to ignore 7747 // it here because this is just a very transient change and it 7748 // will quickly lose focus once it correctly gets hidden. 7749 return 0; 7750 } 7751 7752 int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null) 7753 & ~mResettingSystemUiFlags 7754 & ~mForceClearedSystemUiFlags; 7755 if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) { 7756 tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS); 7757 } 7758 7759 final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */, 7760 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState); 7761 final int dockedVisibility = updateLightStatusBarLw(0 /* vis */, 7762 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState); 7763 mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds); 7764 mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds); 7765 final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility); 7766 final int diff = visibility ^ mLastSystemUiFlags; 7767 final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags; 7768 final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags; 7769 final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState); 7770 if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu 7771 && mFocusedApp == win.getAppToken() 7772 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds) 7773 && mLastDockedStackBounds.equals(mDockedStackBounds)) { 7774 return 0; 7775 } 7776 mLastSystemUiFlags = visibility; 7777 mLastFullscreenStackSysUiFlags = fullscreenVisibility; 7778 mLastDockedStackSysUiFlags = dockedVisibility; 7779 mLastFocusNeedsMenu = needsMenu; 7780 mFocusedApp = win.getAppToken(); 7781 final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds); 7782 final Rect dockedStackBounds = new Rect(mDockedStackBounds); 7783 mHandler.post(new Runnable() { 7784 @Override 7785 public void run() { 7786 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 7787 if (statusbar != null) { 7788 statusbar.setSystemUiVisibility(visibility, fullscreenVisibility, 7789 dockedVisibility, 0xffffffff, fullscreenStackBounds, 7790 dockedStackBounds, win.toString()); 7791 statusbar.topAppWindowChanged(needsMenu); 7792 } 7793 } 7794 }); 7795 return diff; 7796 } 7797 7798 private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) { 7799 WindowState statusColorWin = isStatusBarKeyguard() && !mKeyguardOccluded 7800 ? mStatusBar 7801 : opaqueOrDimming; 7802 7803 if (statusColorWin != null) { 7804 if (statusColorWin == opaque) { 7805 // If the top fullscreen-or-dimming window is also the top fullscreen, respect 7806 // its light flag. 7807 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7808 vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null) 7809 & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7810 } else if (statusColorWin != null && statusColorWin.isDimming()) { 7811 // Otherwise if it's dimming, clear the light flag. 7812 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7813 } 7814 } 7815 return vis; 7816 } 7817 7818 private int updateLightNavigationBarLw(int vis, WindowState opaque, 7819 WindowState opaqueOrDimming) { 7820 final WindowState imeWin = mWindowManagerFuncs.getInputMethodWindowLw(); 7821 7822 final WindowState navColorWin; 7823 if (imeWin != null && imeWin.isVisibleLw()) { 7824 navColorWin = imeWin; 7825 } else { 7826 navColorWin = opaqueOrDimming; 7827 } 7828 7829 if (navColorWin != null) { 7830 if (navColorWin == opaque) { 7831 // If the top fullscreen-or-dimming window is also the top fullscreen, respect 7832 // its light flag. 7833 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; 7834 vis |= PolicyControl.getSystemUiVisibility(navColorWin, null) 7835 & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; 7836 } else if (navColorWin.isDimming() || navColorWin == imeWin) { 7837 // Otherwise if it's dimming or it's the IME window, clear the light flag. 7838 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; 7839 } 7840 } 7841 return vis; 7842 } 7843 7844 private boolean drawsSystemBarBackground(WindowState win) { 7845 return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0; 7846 } 7847 7848 private boolean forcesDrawStatusBarBackground(WindowState win) { 7849 return win == null || (win.getAttrs().privateFlags 7850 & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0; 7851 } 7852 7853 private int updateSystemBarsLw(WindowState win, int oldVis, int vis) { 7854 final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID); 7855 final boolean freeformStackVisible = 7856 mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID); 7857 final boolean resizing = mWindowManagerInternal.isDockedDividerResizing(); 7858 7859 // We need to force system bars when the docked stack is visible, when the freeform stack 7860 // is visible but also when we are resizing for the transitions when docked stack 7861 // visibility changes. 7862 mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing; 7863 final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard; 7864 7865 // apply translucent bar vis flags 7866 WindowState fullscreenTransWin = isStatusBarKeyguard() && !mKeyguardOccluded 7867 ? mStatusBar 7868 : mTopFullscreenOpaqueWindowState; 7869 vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7870 vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7871 final int dockedVis = mStatusBarController.applyTranslucentFlagLw( 7872 mTopDockedOpaqueWindowState, 0, 0); 7873 7874 final boolean fullscreenDrawsStatusBarBackground = 7875 (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState) 7876 && (vis & View.STATUS_BAR_TRANSLUCENT) == 0) 7877 || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState); 7878 final boolean dockedDrawsStatusBarBackground = 7879 (drawsSystemBarBackground(mTopDockedOpaqueWindowState) 7880 && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0) 7881 || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState); 7882 7883 // prevent status bar interaction from clearing certain flags 7884 int type = win.getAttrs().type; 7885 boolean statusBarHasFocus = type == TYPE_STATUS_BAR; 7886 if (statusBarHasFocus && !isStatusBarKeyguard()) { 7887 int flags = View.SYSTEM_UI_FLAG_FULLSCREEN 7888 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 7889 | View.SYSTEM_UI_FLAG_IMMERSIVE 7890 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 7891 | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7892 if (mKeyguardOccluded) { 7893 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT; 7894 } 7895 vis = (vis & ~flags) | (oldVis & flags); 7896 } 7897 7898 if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) { 7899 vis |= View.STATUS_BAR_TRANSPARENT; 7900 vis &= ~View.STATUS_BAR_TRANSLUCENT; 7901 } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar) 7902 || forceOpaqueStatusBar) { 7903 vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT); 7904 } 7905 7906 vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing); 7907 7908 // update status bar 7909 boolean immersiveSticky = 7910 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7911 final boolean hideStatusBarWM = 7912 mTopFullscreenOpaqueWindowState != null 7913 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null) 7914 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; 7915 final boolean hideStatusBarSysui = 7916 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 7917 final boolean hideNavBarSysui = 7918 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0; 7919 7920 final boolean transientStatusBarAllowed = mStatusBar != null 7921 && (statusBarHasFocus || (!mForceShowSystemBars 7922 && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky)))); 7923 7924 final boolean transientNavBarAllowed = mNavigationBar != null 7925 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky; 7926 7927 final long now = SystemClock.uptimeMillis(); 7928 final boolean pendingPanic = mPendingPanicGestureUptime != 0 7929 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION; 7930 if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) { 7931 // The user performed the panic gesture recently, we're about to hide the bars, 7932 // we're no longer on the Keyguard and the screen is ready. We can now request the bars. 7933 mPendingPanicGestureUptime = 0; 7934 mStatusBarController.showTransient(); 7935 if (!isNavBarEmpty(vis)) { 7936 mNavigationBarController.showTransient(); 7937 } 7938 } 7939 7940 final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested() 7941 && !transientStatusBarAllowed && hideStatusBarSysui; 7942 final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested() 7943 && !transientNavBarAllowed; 7944 if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) { 7945 // clear the clearable flags instead 7946 clearClearableFlagsLw(); 7947 vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS; 7948 } 7949 7950 final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; 7951 immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7952 final boolean navAllowedHidden = immersive || immersiveSticky; 7953 7954 if (hideNavBarSysui && !navAllowedHidden 7955 && getWindowLayerLw(win) > getWindowLayerFromTypeLw(TYPE_INPUT_CONSUMER)) { 7956 // We can't hide the navbar from this window otherwise the input consumer would not get 7957 // the input events. 7958 vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); 7959 } 7960 7961 vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis); 7962 7963 // update navigation bar 7964 boolean oldImmersiveMode = isImmersiveMode(oldVis); 7965 boolean newImmersiveMode = isImmersiveMode(vis); 7966 if (win != null && oldImmersiveMode != newImmersiveMode) { 7967 final String pkg = win.getOwningPackage(); 7968 mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode, 7969 isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility())); 7970 } 7971 7972 vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis); 7973 7974 vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState, 7975 mTopFullscreenOpaqueOrDimmingWindowState); 7976 7977 return vis; 7978 } 7979 7980 /** 7981 * @return the current visibility flags with the nav-bar opacity related flags toggled based 7982 * on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}. 7983 */ 7984 private int configureNavBarOpacity(int visibility, boolean dockedStackVisible, 7985 boolean freeformStackVisible, boolean isDockedDividerResizing) { 7986 if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) { 7987 if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) { 7988 visibility = setNavBarOpaqueFlag(visibility); 7989 } 7990 } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) { 7991 if (isDockedDividerResizing) { 7992 visibility = setNavBarOpaqueFlag(visibility); 7993 } else if (freeformStackVisible) { 7994 visibility = setNavBarTranslucentFlag(visibility); 7995 } else { 7996 visibility = setNavBarOpaqueFlag(visibility); 7997 } 7998 } 7999 8000 if (!areTranslucentBarsAllowed()) { 8001 visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT; 8002 } 8003 return visibility; 8004 } 8005 8006 private int setNavBarOpaqueFlag(int visibility) { 8007 return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT); 8008 } 8009 8010 private int setNavBarTranslucentFlag(int visibility) { 8011 visibility &= ~View.NAVIGATION_BAR_TRANSPARENT; 8012 return visibility |= View.NAVIGATION_BAR_TRANSLUCENT; 8013 } 8014 8015 private void clearClearableFlagsLw() { 8016 int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS; 8017 if (newVal != mResettingSystemUiFlags) { 8018 mResettingSystemUiFlags = newVal; 8019 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 8020 } 8021 } 8022 8023 private boolean isImmersiveMode(int vis) { 8024 final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; 8025 return mNavigationBar != null 8026 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0 8027 && (vis & flags) != 0 8028 && canHideNavigationBar(); 8029 } 8030 8031 private static boolean isNavBarEmpty(int systemUiFlags) { 8032 final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME 8033 | View.STATUS_BAR_DISABLE_BACK 8034 | View.STATUS_BAR_DISABLE_RECENT); 8035 8036 return (systemUiFlags & disableNavigationBar) == disableNavigationBar; 8037 } 8038 8039 /** 8040 * @return whether the navigation or status bar can be made translucent 8041 * 8042 * This should return true unless touch exploration is not enabled or 8043 * R.boolean.config_enableTranslucentDecor is false. 8044 */ 8045 private boolean areTranslucentBarsAllowed() { 8046 return mTranslucentDecorEnabled; 8047 } 8048 8049 // Use this instead of checking config_showNavigationBar so that it can be consistently 8050 // overridden by qemu.hw.mainkeys in the emulator. 8051 @Override 8052 public boolean hasNavigationBar() { 8053 return mHasNavigationBar; 8054 } 8055 8056 @Override 8057 public void setLastInputMethodWindowLw(WindowState ime, WindowState target) { 8058 mLastInputMethodWindow = ime; 8059 mLastInputMethodTargetWindow = target; 8060 } 8061 8062 @Override 8063 public void setDismissImeOnBackKeyPressed(boolean newValue) { 8064 mDismissImeOnBackKeyPressed = newValue; 8065 } 8066 8067 @Override 8068 public int getInputMethodWindowVisibleHeightLw() { 8069 return mDockBottom - mCurBottom; 8070 } 8071 8072 @Override 8073 public void setCurrentUserLw(int newUserId) { 8074 mCurrentUserId = newUserId; 8075 if (mKeyguardDelegate != null) { 8076 mKeyguardDelegate.setCurrentUser(newUserId); 8077 } 8078 if (mAccessibilityShortcutController != null) { 8079 mAccessibilityShortcutController.setCurrentUser(newUserId); 8080 } 8081 StatusBarManagerInternal statusBar = getStatusBarManagerInternal(); 8082 if (statusBar != null) { 8083 statusBar.setCurrentUser(newUserId); 8084 } 8085 setLastInputMethodWindowLw(null, null); 8086 } 8087 8088 @Override 8089 public void setSwitchingUser(boolean switching) { 8090 mKeyguardDelegate.setSwitchingUser(switching); 8091 } 8092 8093 @Override 8094 public boolean canMagnifyWindow(int windowType) { 8095 switch (windowType) { 8096 case WindowManager.LayoutParams.TYPE_INPUT_METHOD: 8097 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: 8098 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR: 8099 case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: { 8100 return false; 8101 } 8102 } 8103 return true; 8104 } 8105 8106 @Override 8107 public boolean isTopLevelWindow(int windowType) { 8108 if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW 8109 && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 8110 return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG); 8111 } 8112 return true; 8113 } 8114 8115 @Override 8116 public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) { 8117 // For the upside down rotation we don't rotate seamlessly as the navigation 8118 // bar moves position. 8119 // Note most apps (using orientation:sensor or user as opposed to fullSensor) 8120 // will not enter the reverse portrait orientation, so actually the 8121 // orientation won't change at all. 8122 if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) { 8123 return false; 8124 } 8125 // If the navigation bar can't change sides, then it will 8126 // jump when we change orientations and we don't rotate 8127 // seamlessly. 8128 if (!mNavigationBarCanMove) { 8129 return false; 8130 } 8131 int delta = newRotation - oldRotation; 8132 if (delta < 0) delta += 4; 8133 // Likewise we don't rotate seamlessly for 180 degree rotations 8134 // in this case the surfaces never resize, and our logic to 8135 // revert the transformations on size change will fail. We could 8136 // fix this in the future with the "tagged" frames idea. 8137 if (delta == Surface.ROTATION_180) { 8138 return false; 8139 } 8140 8141 final WindowState w = mTopFullscreenOpaqueWindowState; 8142 if (w != mFocusedWindow) { 8143 return false; 8144 } 8145 8146 // We only enable seamless rotation if the top window has requested 8147 // it and is in the fullscreen opaque state. Seamless rotation 8148 // requires freezing various Surface states and won't work well 8149 // with animations, so we disable it in the animation case for now. 8150 if (w != null && !w.isAnimatingLw() && 8151 ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) || 8152 (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) { 8153 return true; 8154 } 8155 return false; 8156 } 8157 8158 @Override 8159 public void dump(String prefix, PrintWriter pw, String[] args) { 8160 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode); 8161 pw.print(" mSystemReady="); pw.print(mSystemReady); 8162 pw.print(" mSystemBooted="); pw.println(mSystemBooted); 8163 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState); 8164 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation); 8165 pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState); 8166 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged); 8167 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0 8168 || mForceClearedSystemUiFlags != 0) { 8169 pw.print(prefix); pw.print("mLastSystemUiFlags=0x"); 8170 pw.print(Integer.toHexString(mLastSystemUiFlags)); 8171 pw.print(" mResettingSystemUiFlags=0x"); 8172 pw.print(Integer.toHexString(mResettingSystemUiFlags)); 8173 pw.print(" mForceClearedSystemUiFlags=0x"); 8174 pw.println(Integer.toHexString(mForceClearedSystemUiFlags)); 8175 } 8176 if (mLastFocusNeedsMenu) { 8177 pw.print(prefix); pw.print("mLastFocusNeedsMenu="); 8178 pw.println(mLastFocusNeedsMenu); 8179 } 8180 pw.print(prefix); pw.print("mWakeGestureEnabledSetting="); 8181 pw.println(mWakeGestureEnabledSetting); 8182 8183 pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation); 8184 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode); 8185 pw.print(" mDockMode="); pw.print(mDockMode); 8186 pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture); 8187 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation); 8188 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation); 8189 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode); 8190 pw.print(" mUserRotation="); pw.print(mUserRotation); 8191 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations); 8192 pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation); 8193 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer="); 8194 pw.print(mCarDockEnablesAccelerometer); 8195 pw.print(" mDeskDockEnablesAccelerometer="); 8196 pw.println(mDeskDockEnablesAccelerometer); 8197 pw.print(prefix); pw.print("mLidKeyboardAccessibility="); 8198 pw.print(mLidKeyboardAccessibility); 8199 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility); 8200 pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock); 8201 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep); 8202 pw.print(prefix); 8203 pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior); 8204 pw.print(prefix); 8205 pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior); 8206 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior); 8207 pw.print(prefix); 8208 pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior); 8209 pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior); 8210 pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput); 8211 pw.print(prefix); pw.print("mAwake="); pw.println(mAwake); 8212 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly); 8213 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully); 8214 pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete); 8215 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete); 8216 pw.print(prefix); pw.print("mOrientationSensorEnabled="); 8217 pw.println(mOrientationSensorEnabled); 8218 pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft); 8219 pw.print(","); pw.print(mOverscanScreenTop); 8220 pw.print(") "); pw.print(mOverscanScreenWidth); 8221 pw.print("x"); pw.println(mOverscanScreenHeight); 8222 if (mOverscanLeft != 0 || mOverscanTop != 0 8223 || mOverscanRight != 0 || mOverscanBottom != 0) { 8224 pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft); 8225 pw.print(" top="); pw.print(mOverscanTop); 8226 pw.print(" right="); pw.print(mOverscanRight); 8227 pw.print(" bottom="); pw.println(mOverscanBottom); 8228 } 8229 pw.print(prefix); pw.print("mRestrictedOverscanScreen=("); 8230 pw.print(mRestrictedOverscanScreenLeft); 8231 pw.print(","); pw.print(mRestrictedOverscanScreenTop); 8232 pw.print(") "); pw.print(mRestrictedOverscanScreenWidth); 8233 pw.print("x"); pw.println(mRestrictedOverscanScreenHeight); 8234 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft); 8235 pw.print(","); pw.print(mUnrestrictedScreenTop); 8236 pw.print(") "); pw.print(mUnrestrictedScreenWidth); 8237 pw.print("x"); pw.println(mUnrestrictedScreenHeight); 8238 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft); 8239 pw.print(","); pw.print(mRestrictedScreenTop); 8240 pw.print(") "); pw.print(mRestrictedScreenWidth); 8241 pw.print("x"); pw.println(mRestrictedScreenHeight); 8242 pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft); 8243 pw.print(","); pw.print(mStableFullscreenTop); 8244 pw.print(")-("); pw.print(mStableFullscreenRight); 8245 pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")"); 8246 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft); 8247 pw.print(","); pw.print(mStableTop); 8248 pw.print(")-("); pw.print(mStableRight); 8249 pw.print(","); pw.print(mStableBottom); pw.println(")"); 8250 pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft); 8251 pw.print(","); pw.print(mSystemTop); 8252 pw.print(")-("); pw.print(mSystemRight); 8253 pw.print(","); pw.print(mSystemBottom); pw.println(")"); 8254 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft); 8255 pw.print(","); pw.print(mCurTop); 8256 pw.print(")-("); pw.print(mCurRight); 8257 pw.print(","); pw.print(mCurBottom); pw.println(")"); 8258 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft); 8259 pw.print(","); pw.print(mContentTop); 8260 pw.print(")-("); pw.print(mContentRight); 8261 pw.print(","); pw.print(mContentBottom); pw.println(")"); 8262 pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft); 8263 pw.print(","); pw.print(mVoiceContentTop); 8264 pw.print(")-("); pw.print(mVoiceContentRight); 8265 pw.print(","); pw.print(mVoiceContentBottom); pw.println(")"); 8266 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft); 8267 pw.print(","); pw.print(mDockTop); 8268 pw.print(")-("); pw.print(mDockRight); 8269 pw.print(","); pw.print(mDockBottom); pw.println(")"); 8270 pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer); 8271 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer); 8272 pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream); 8273 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen); 8274 pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken); 8275 if (mLastInputMethodWindow != null) { 8276 pw.print(prefix); pw.print("mLastInputMethodWindow="); 8277 pw.println(mLastInputMethodWindow); 8278 } 8279 if (mLastInputMethodTargetWindow != null) { 8280 pw.print(prefix); pw.print("mLastInputMethodTargetWindow="); 8281 pw.println(mLastInputMethodTargetWindow); 8282 } 8283 pw.print(prefix); pw.print("mDismissImeOnBackKeyPressed="); 8284 pw.println(mDismissImeOnBackKeyPressed); 8285 if (mStatusBar != null) { 8286 pw.print(prefix); pw.print("mStatusBar="); 8287 pw.print(mStatusBar); pw.print(" isStatusBarKeyguard="); 8288 pw.println(isStatusBarKeyguard()); 8289 } 8290 if (mNavigationBar != null) { 8291 pw.print(prefix); pw.print("mNavigationBar="); 8292 pw.println(mNavigationBar); 8293 } 8294 if (mFocusedWindow != null) { 8295 pw.print(prefix); pw.print("mFocusedWindow="); 8296 pw.println(mFocusedWindow); 8297 } 8298 if (mFocusedApp != null) { 8299 pw.print(prefix); pw.print("mFocusedApp="); 8300 pw.println(mFocusedApp); 8301 } 8302 if (mTopFullscreenOpaqueWindowState != null) { 8303 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState="); 8304 pw.println(mTopFullscreenOpaqueWindowState); 8305 } 8306 if (mTopFullscreenOpaqueOrDimmingWindowState != null) { 8307 pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState="); 8308 pw.println(mTopFullscreenOpaqueOrDimmingWindowState); 8309 } 8310 if (mForcingShowNavBar) { 8311 pw.print(prefix); pw.print("mForcingShowNavBar="); 8312 pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer="); 8313 pw.println(mForcingShowNavBarLayer); 8314 } 8315 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen); 8316 pw.print(" mKeyguardOccluded="); pw.println(mKeyguardOccluded); 8317 pw.print(" mKeyguardOccludedChanged="); pw.println(mKeyguardOccludedChanged); 8318 pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded); 8319 pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar); 8320 pw.print(" mForceStatusBarFromKeyguard="); 8321 pw.println(mForceStatusBarFromKeyguard); 8322 pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed); 8323 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn); 8324 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout); 8325 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive); 8326 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior); 8327 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior); 8328 pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior); 8329 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior); 8330 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation); 8331 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation); 8332 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation); 8333 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation); 8334 pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation); 8335 pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock); 8336 pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation); 8337 if (mHasFeatureLeanback) { 8338 pw.print(prefix); 8339 pw.print("mAccessibilityTvKey1Pressed="); pw.println(mAccessibilityTvKey1Pressed); 8340 pw.print(prefix); 8341 pw.print("mAccessibilityTvKey2Pressed="); pw.println(mAccessibilityTvKey2Pressed); 8342 pw.print(prefix); 8343 pw.print("mAccessibilityTvScheduled="); pw.println(mAccessibilityTvScheduled); 8344 } 8345 8346 mGlobalKeyManager.dump(prefix, pw); 8347 mStatusBarController.dump(pw, prefix); 8348 mNavigationBarController.dump(pw, prefix); 8349 PolicyControl.dump(prefix, pw); 8350 8351 if (mWakeGestureListener != null) { 8352 mWakeGestureListener.dump(pw, prefix); 8353 } 8354 if (mOrientationListener != null) { 8355 mOrientationListener.dump(pw, prefix); 8356 } 8357 if (mBurnInProtectionHelper != null) { 8358 mBurnInProtectionHelper.dump(prefix, pw); 8359 } 8360 if (mKeyguardDelegate != null) { 8361 mKeyguardDelegate.dump(prefix, pw); 8362 } 8363 } 8364} 8365