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