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