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