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