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