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