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