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