PhoneWindowManager.java revision 2df228c32c388a73ac4949c25755e03bd83fc5e0
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.isVisibleLw() && 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 || statusBarExpanded) 5489 && mStatusBarController.isTransientShowing()) { 5490 mStatusBarController.updateVisibilityLw(false /*transientAllowed*/, 5491 mLastSystemUiFlags, mLastSystemUiFlags); 5492 } 5493 if (statusBarExpanded && mNavigationBar != null) { 5494 if (mNavigationBarController.setBarShowingLw(true)) { 5495 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5496 } 5497 } 5498 } else if (mTopFullscreenOpaqueWindowState != null) { 5499 final int fl = PolicyControl.getWindowFlags(null, lp); 5500 if (localLOGV) { 5501 Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() 5502 + " shown position: " 5503 + mTopFullscreenOpaqueWindowState.getShownPositionLw()); 5504 Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs() 5505 + " lp.flags=0x" + Integer.toHexString(fl)); 5506 } 5507 topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0 5508 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 5509 // The subtle difference between the window for mTopFullscreenOpaqueWindowState 5510 // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window 5511 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the 5512 // case though. 5513 if (mStatusBarController.isTransientShowing()) { 5514 if (mStatusBarController.setBarShowingLw(true)) { 5515 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5516 } 5517 } else if (topIsFullscreen 5518 && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID) 5519 && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) { 5520 if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar"); 5521 if (mStatusBarController.setBarShowingLw(false)) { 5522 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5523 } else { 5524 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding"); 5525 } 5526 } else { 5527 if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen"); 5528 if (mStatusBarController.setBarShowingLw(true)) { 5529 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5530 } 5531 } 5532 } 5533 } 5534 5535 if (mTopIsFullscreen != topIsFullscreen) { 5536 if (!topIsFullscreen) { 5537 // Force another layout when status bar becomes fully shown. 5538 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5539 } 5540 mTopIsFullscreen = topIsFullscreen; 5541 } 5542 5543 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5544 // If the navigation bar has been hidden or shown, we need to do another 5545 // layout pass to update that window. 5546 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5547 } 5548 5549 if (mShowingDream != mLastShowingDream) { 5550 mLastShowingDream = mShowingDream; 5551 mWindowManagerFuncs.notifyShowingDreamChanged(); 5552 } 5553 5554 // update since mAllowLockscreenWhenOn might have changed 5555 updateLockScreenTimeout(); 5556 return changes; 5557 } 5558 5559 /** 5560 * Updates the occluded state of the Keyguard. 5561 * 5562 * @return Whether the flags have changed and we have to redo the layout. 5563 */ 5564 private boolean setKeyguardOccludedLw(boolean isOccluded, boolean force) { 5565 if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded); 5566 final boolean wasOccluded = mKeyguardOccluded; 5567 final boolean showing = mKeyguardDelegate.isShowing(); 5568 final boolean changed = wasOccluded != isOccluded || force; 5569 if (!isOccluded && changed && showing) { 5570 mKeyguardOccluded = false; 5571 mKeyguardDelegate.setOccluded(false, true /* animate */); 5572 if (mStatusBar != null) { 5573 mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD; 5574 if (!mKeyguardDelegate.hasLockscreenWallpaper()) { 5575 mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER; 5576 } 5577 } 5578 return true; 5579 } else if (isOccluded && changed && showing) { 5580 mKeyguardOccluded = true; 5581 mKeyguardDelegate.setOccluded(true, false /* animate */); 5582 if (mStatusBar != null) { 5583 mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD; 5584 mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER; 5585 } 5586 return true; 5587 } else if (changed) { 5588 mKeyguardOccluded = isOccluded; 5589 mKeyguardDelegate.setOccluded(isOccluded, false /* animate */); 5590 return false; 5591 } else { 5592 return false; 5593 } 5594 } 5595 5596 private boolean isStatusBarKeyguard() { 5597 return mStatusBar != null 5598 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0; 5599 } 5600 5601 @Override 5602 public boolean allowAppAnimationsLw() { 5603 if (mShowingDream) { 5604 // If keyguard or dreams is currently visible, no reason to animate behind it. 5605 return false; 5606 } 5607 return true; 5608 } 5609 5610 @Override 5611 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) { 5612 mFocusedWindow = newFocus; 5613 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5614 // If the navigation bar has been hidden or shown, we need to do another 5615 // layout pass to update that window. 5616 return FINISH_LAYOUT_REDO_LAYOUT; 5617 } 5618 return 0; 5619 } 5620 5621 /** {@inheritDoc} */ 5622 @Override 5623 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { 5624 // lid changed state 5625 final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED; 5626 if (newLidState == mLidState) { 5627 return; 5628 } 5629 5630 mLidState = newLidState; 5631 applyLidSwitchState(); 5632 updateRotation(true); 5633 5634 if (lidOpen) { 5635 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch, 5636 "android.policy:LID"); 5637 } else if (!mLidControlsSleep) { 5638 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 5639 } 5640 } 5641 5642 @Override 5643 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) { 5644 int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED; 5645 if (mCameraLensCoverState == lensCoverState) { 5646 return; 5647 } 5648 if (mCameraLensCoverState == CAMERA_LENS_COVERED && 5649 lensCoverState == CAMERA_LENS_UNCOVERED) { 5650 Intent intent; 5651 final boolean keyguardActive = mKeyguardDelegate == null ? false : 5652 mKeyguardDelegate.isShowing(); 5653 if (keyguardActive) { 5654 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE); 5655 } else { 5656 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); 5657 } 5658 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens, 5659 "android.policy:CAMERA_COVER"); 5660 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); 5661 } 5662 mCameraLensCoverState = lensCoverState; 5663 } 5664 5665 void setHdmiPlugged(boolean plugged) { 5666 if (mHdmiPlugged != plugged) { 5667 mHdmiPlugged = plugged; 5668 updateRotation(true, true); 5669 Intent intent = new Intent(ACTION_HDMI_PLUGGED); 5670 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5671 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged); 5672 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 5673 } 5674 } 5675 5676 void initializeHdmiState() { 5677 boolean plugged = false; 5678 // watch for HDMI plug messages if the hdmi switch exists 5679 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) { 5680 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi"); 5681 5682 final String filename = "/sys/class/switch/hdmi/state"; 5683 FileReader reader = null; 5684 try { 5685 reader = new FileReader(filename); 5686 char[] buf = new char[15]; 5687 int n = reader.read(buf); 5688 if (n > 1) { 5689 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1)); 5690 } 5691 } catch (IOException ex) { 5692 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5693 } catch (NumberFormatException ex) { 5694 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5695 } finally { 5696 if (reader != null) { 5697 try { 5698 reader.close(); 5699 } catch (IOException ex) { 5700 } 5701 } 5702 } 5703 } 5704 // This dance forces the code in setHdmiPlugged to run. 5705 // Always do this so the sticky intent is stuck (to false) if there is no hdmi. 5706 mHdmiPlugged = !plugged; 5707 setHdmiPlugged(!mHdmiPlugged); 5708 } 5709 5710 final Object mScreenshotLock = new Object(); 5711 ServiceConnection mScreenshotConnection = null; 5712 5713 final Runnable mScreenshotTimeout = new Runnable() { 5714 @Override public void run() { 5715 synchronized (mScreenshotLock) { 5716 if (mScreenshotConnection != null) { 5717 mContext.unbindService(mScreenshotConnection); 5718 mScreenshotConnection = null; 5719 notifyScreenshotError(); 5720 } 5721 } 5722 } 5723 }; 5724 5725 // Assume this is called from the Handler thread. 5726 private void takeScreenshot(final int screenshotType) { 5727 synchronized (mScreenshotLock) { 5728 if (mScreenshotConnection != null) { 5729 return; 5730 } 5731 final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE, 5732 SYSUI_SCREENSHOT_SERVICE); 5733 final Intent serviceIntent = new Intent(); 5734 serviceIntent.setComponent(serviceComponent); 5735 ServiceConnection conn = new ServiceConnection() { 5736 @Override 5737 public void onServiceConnected(ComponentName name, IBinder service) { 5738 synchronized (mScreenshotLock) { 5739 if (mScreenshotConnection != this) { 5740 return; 5741 } 5742 Messenger messenger = new Messenger(service); 5743 Message msg = Message.obtain(null, screenshotType); 5744 final ServiceConnection myConn = this; 5745 Handler h = new Handler(mHandler.getLooper()) { 5746 @Override 5747 public void handleMessage(Message msg) { 5748 synchronized (mScreenshotLock) { 5749 if (mScreenshotConnection == myConn) { 5750 mContext.unbindService(mScreenshotConnection); 5751 mScreenshotConnection = null; 5752 mHandler.removeCallbacks(mScreenshotTimeout); 5753 } 5754 } 5755 } 5756 }; 5757 msg.replyTo = new Messenger(h); 5758 msg.arg1 = msg.arg2 = 0; 5759 if (mStatusBar != null && mStatusBar.isVisibleLw()) 5760 msg.arg1 = 1; 5761 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) 5762 msg.arg2 = 1; 5763 try { 5764 messenger.send(msg); 5765 } catch (RemoteException e) { 5766 } 5767 } 5768 } 5769 5770 @Override 5771 public void onServiceDisconnected(ComponentName name) { 5772 synchronized (mScreenshotLock) { 5773 if (mScreenshotConnection != null) { 5774 mContext.unbindService(mScreenshotConnection); 5775 mScreenshotConnection = null; 5776 mHandler.removeCallbacks(mScreenshotTimeout); 5777 notifyScreenshotError(); 5778 } 5779 } 5780 } 5781 }; 5782 if (mContext.bindServiceAsUser(serviceIntent, conn, 5783 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, 5784 UserHandle.CURRENT)) { 5785 mScreenshotConnection = conn; 5786 mHandler.postDelayed(mScreenshotTimeout, 10000); 5787 } 5788 } 5789 } 5790 5791 /** 5792 * Notifies the screenshot service to show an error. 5793 */ 5794 private void notifyScreenshotError() { 5795 // If the service process is killed, then ask it to clean up after itself 5796 final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE, 5797 SYSUI_SCREENSHOT_ERROR_RECEIVER); 5798 Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT); 5799 errorIntent.setComponent(errorComponent); 5800 errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | 5801 Intent.FLAG_RECEIVER_FOREGROUND); 5802 mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT); 5803 } 5804 5805 /** {@inheritDoc} */ 5806 @Override 5807 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { 5808 if (!mSystemBooted) { 5809 // If we have not yet booted, don't let key events do anything. 5810 return 0; 5811 } 5812 5813 final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0; 5814 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; 5815 final boolean canceled = event.isCanceled(); 5816 final int keyCode = event.getKeyCode(); 5817 5818 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; 5819 5820 // If screen is off then we treat the case where the keyguard is open but hidden 5821 // the same as if it were open and in front. 5822 // This will prevent any keys other than the power button from waking the screen 5823 // when the keyguard is hidden by another activity. 5824 final boolean keyguardActive = (mKeyguardDelegate == null ? false : 5825 (interactive ? 5826 isKeyguardShowingAndNotOccluded() : 5827 mKeyguardDelegate.isShowing())); 5828 5829 if (DEBUG_INPUT) { 5830 Log.d(TAG, "interceptKeyTq keycode=" + keyCode 5831 + " interactive=" + interactive + " keyguardActive=" + keyguardActive 5832 + " policyFlags=" + Integer.toHexString(policyFlags)); 5833 } 5834 5835 // Basic policy based on interactive state. 5836 int result; 5837 boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0 5838 || event.isWakeKey(); 5839 if (interactive || (isInjected && !isWakeKey)) { 5840 // When the device is interactive or the key is injected pass the 5841 // key to the application. 5842 result = ACTION_PASS_TO_USER; 5843 isWakeKey = false; 5844 5845 if (interactive) { 5846 // If the screen is awake, but the button pressed was the one that woke the device 5847 // then don't pass it to the application 5848 if (keyCode == mPendingWakeKey && !down) { 5849 result = 0; 5850 } 5851 // Reset the pending key 5852 mPendingWakeKey = PENDING_KEY_NULL; 5853 } 5854 } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) { 5855 // If we're currently dozing with the screen on and the keyguard showing, pass the key 5856 // to the application but preserve its wake key status to make sure we still move 5857 // from dozing to fully interactive if we would normally go from off to fully 5858 // interactive. 5859 result = ACTION_PASS_TO_USER; 5860 // Since we're dispatching the input, reset the pending key 5861 mPendingWakeKey = PENDING_KEY_NULL; 5862 } else { 5863 // When the screen is off and the key is not injected, determine whether 5864 // to wake the device but don't pass the key to the application. 5865 result = 0; 5866 if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) { 5867 isWakeKey = false; 5868 } 5869 // Cache the wake key on down event so we can also avoid sending the up event to the app 5870 if (isWakeKey && down) { 5871 mPendingWakeKey = keyCode; 5872 } 5873 } 5874 5875 // If the key would be handled globally, just return the result, don't worry about special 5876 // key processing. 5877 if (isValidGlobalKey(keyCode) 5878 && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) { 5879 if (isWakeKey) { 5880 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 5881 } 5882 return result; 5883 } 5884 5885 boolean useHapticFeedback = down 5886 && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0 5887 && event.getRepeatCount() == 0; 5888 5889 // Handle special keys. 5890 switch (keyCode) { 5891 case KeyEvent.KEYCODE_BACK: { 5892 if (down) { 5893 interceptBackKeyDown(); 5894 } else { 5895 boolean handled = interceptBackKeyUp(event); 5896 5897 // Don't pass back press to app if we've already handled it via long press 5898 if (handled) { 5899 result &= ~ACTION_PASS_TO_USER; 5900 } 5901 } 5902 break; 5903 } 5904 5905 case KeyEvent.KEYCODE_VOLUME_DOWN: 5906 case KeyEvent.KEYCODE_VOLUME_UP: 5907 case KeyEvent.KEYCODE_VOLUME_MUTE: { 5908 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { 5909 if (down) { 5910 if (interactive && !mScreenshotChordVolumeDownKeyTriggered 5911 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5912 mScreenshotChordVolumeDownKeyTriggered = true; 5913 mScreenshotChordVolumeDownKeyTime = event.getDownTime(); 5914 mScreenshotChordVolumeDownKeyConsumed = false; 5915 cancelPendingPowerKeyAction(); 5916 interceptScreenshotChord(); 5917 interceptAccessibilityShortcutChord(); 5918 } 5919 } else { 5920 mScreenshotChordVolumeDownKeyTriggered = false; 5921 cancelPendingScreenshotChordAction(); 5922 cancelPendingAccessibilityShortcutAction(); 5923 } 5924 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 5925 if (down) { 5926 if (interactive && !mA11yShortcutChordVolumeUpKeyTriggered 5927 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5928 mA11yShortcutChordVolumeUpKeyTriggered = true; 5929 mA11yShortcutChordVolumeUpKeyTime = event.getDownTime(); 5930 mA11yShortcutChordVolumeUpKeyConsumed = false; 5931 cancelPendingPowerKeyAction(); 5932 cancelPendingScreenshotChordAction(); 5933 interceptAccessibilityShortcutChord(); 5934 } 5935 } else { 5936 mA11yShortcutChordVolumeUpKeyTriggered = false; 5937 cancelPendingScreenshotChordAction(); 5938 cancelPendingAccessibilityShortcutAction(); 5939 } 5940 } 5941 if (down) { 5942 TelecomManager telecomManager = getTelecommService(); 5943 if (telecomManager != null) { 5944 if (telecomManager.isRinging()) { 5945 // If an incoming call is ringing, either VOLUME key means 5946 // "silence ringer". We handle these keys here, rather than 5947 // in the InCallScreen, to make sure we'll respond to them 5948 // even if the InCallScreen hasn't come to the foreground yet. 5949 // Look for the DOWN event here, to agree with the "fallback" 5950 // behavior in the InCallScreen. 5951 Log.i(TAG, "interceptKeyBeforeQueueing:" 5952 + " VOLUME key-down while ringing: Silence ringer!"); 5953 5954 // Silence the ringer. (It's safe to call this 5955 // even if the ringer has already been silenced.) 5956 telecomManager.silenceRinger(); 5957 5958 // And *don't* pass this key thru to the current activity 5959 // (which is probably the InCallScreen.) 5960 result &= ~ACTION_PASS_TO_USER; 5961 break; 5962 } 5963 if (telecomManager.isInCall() 5964 && (result & ACTION_PASS_TO_USER) == 0) { 5965 // If we are in call but we decided not to pass the key to 5966 // the application, just pass it to the session service. 5967 MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent( 5968 event, AudioManager.USE_DEFAULT_STREAM_TYPE, false); 5969 break; 5970 } 5971 } 5972 } 5973 if (mUseTvRouting || mHandleVolumeKeysInWM) { 5974 // Defer special key handlings to 5975 // {@link interceptKeyBeforeDispatching()}. 5976 result |= ACTION_PASS_TO_USER; 5977 } else if ((result & ACTION_PASS_TO_USER) == 0) { 5978 // If we aren't passing to the user and no one else 5979 // handled it send it to the session manager to 5980 // figure out. 5981 MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent( 5982 event, AudioManager.USE_DEFAULT_STREAM_TYPE, true); 5983 } 5984 break; 5985 } 5986 5987 case KeyEvent.KEYCODE_ENDCALL: { 5988 result &= ~ACTION_PASS_TO_USER; 5989 if (down) { 5990 TelecomManager telecomManager = getTelecommService(); 5991 boolean hungUp = false; 5992 if (telecomManager != null) { 5993 hungUp = telecomManager.endCall(); 5994 } 5995 if (interactive && !hungUp) { 5996 mEndCallKeyHandled = false; 5997 mHandler.postDelayed(mEndCallLongPress, 5998 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 5999 } else { 6000 mEndCallKeyHandled = true; 6001 } 6002 } else { 6003 if (!mEndCallKeyHandled) { 6004 mHandler.removeCallbacks(mEndCallLongPress); 6005 if (!canceled) { 6006 if ((mEndcallBehavior 6007 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) { 6008 if (goHome()) { 6009 break; 6010 } 6011 } 6012 if ((mEndcallBehavior 6013 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) { 6014 mPowerManager.goToSleep(event.getEventTime(), 6015 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); 6016 isWakeKey = false; 6017 } 6018 } 6019 } 6020 } 6021 break; 6022 } 6023 6024 case KeyEvent.KEYCODE_POWER: { 6025 // Any activity on the power button stops the accessibility shortcut 6026 cancelPendingAccessibilityShortcutAction(); 6027 result &= ~ACTION_PASS_TO_USER; 6028 isWakeKey = false; // wake-up will be handled separately 6029 if (down) { 6030 interceptPowerKeyDown(event, interactive); 6031 } else { 6032 interceptPowerKeyUp(event, interactive, canceled); 6033 } 6034 break; 6035 } 6036 6037 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN: 6038 // fall through 6039 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP: 6040 // fall through 6041 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT: 6042 // fall through 6043 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: { 6044 result &= ~ACTION_PASS_TO_USER; 6045 interceptSystemNavigationKey(event); 6046 break; 6047 } 6048 6049 case KeyEvent.KEYCODE_SLEEP: { 6050 result &= ~ACTION_PASS_TO_USER; 6051 isWakeKey = false; 6052 if (!mPowerManager.isInteractive()) { 6053 useHapticFeedback = false; // suppress feedback if already non-interactive 6054 } 6055 if (down) { 6056 sleepPress(event.getEventTime()); 6057 } else { 6058 sleepRelease(event.getEventTime()); 6059 } 6060 break; 6061 } 6062 6063 case KeyEvent.KEYCODE_SOFT_SLEEP: { 6064 result &= ~ACTION_PASS_TO_USER; 6065 isWakeKey = false; 6066 if (!down) { 6067 mPowerManagerInternal.setUserInactiveOverrideFromWindowManager(); 6068 } 6069 break; 6070 } 6071 6072 case KeyEvent.KEYCODE_WAKEUP: { 6073 result &= ~ACTION_PASS_TO_USER; 6074 isWakeKey = true; 6075 break; 6076 } 6077 6078 case KeyEvent.KEYCODE_MEDIA_PLAY: 6079 case KeyEvent.KEYCODE_MEDIA_PAUSE: 6080 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 6081 case KeyEvent.KEYCODE_HEADSETHOOK: 6082 case KeyEvent.KEYCODE_MUTE: 6083 case KeyEvent.KEYCODE_MEDIA_STOP: 6084 case KeyEvent.KEYCODE_MEDIA_NEXT: 6085 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 6086 case KeyEvent.KEYCODE_MEDIA_REWIND: 6087 case KeyEvent.KEYCODE_MEDIA_RECORD: 6088 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 6089 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { 6090 if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) { 6091 // If the global session is active pass all media keys to it 6092 // instead of the active window. 6093 result &= ~ACTION_PASS_TO_USER; 6094 } 6095 if ((result & ACTION_PASS_TO_USER) == 0) { 6096 // Only do this if we would otherwise not pass it to the user. In that 6097 // case, the PhoneWindow class will do the same thing, except it will 6098 // only do it if the showing app doesn't process the key on its own. 6099 // Note that we need to make a copy of the key event here because the 6100 // original key event will be recycled when we return. 6101 mBroadcastWakeLock.acquire(); 6102 Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK, 6103 new KeyEvent(event)); 6104 msg.setAsynchronous(true); 6105 msg.sendToTarget(); 6106 } 6107 break; 6108 } 6109 6110 case KeyEvent.KEYCODE_CALL: { 6111 if (down) { 6112 TelecomManager telecomManager = getTelecommService(); 6113 if (telecomManager != null) { 6114 if (telecomManager.isRinging()) { 6115 Log.i(TAG, "interceptKeyBeforeQueueing:" 6116 + " CALL key-down while ringing: Answer the call!"); 6117 telecomManager.acceptRingingCall(); 6118 6119 // And *don't* pass this key thru to the current activity 6120 // (which is presumably the InCallScreen.) 6121 result &= ~ACTION_PASS_TO_USER; 6122 } 6123 } 6124 } 6125 break; 6126 } 6127 case KeyEvent.KEYCODE_VOICE_ASSIST: { 6128 // Only do this if we would otherwise not pass it to the user. In that case, 6129 // interceptKeyBeforeDispatching would apply a similar but different policy in 6130 // order to invoke voice assist actions. Note that we need to make a copy of the 6131 // key event here because the original key event will be recycled when we return. 6132 if ((result & ACTION_PASS_TO_USER) == 0 && !down) { 6133 mBroadcastWakeLock.acquire(); 6134 Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK, 6135 keyguardActive ? 1 : 0, 0); 6136 msg.setAsynchronous(true); 6137 msg.sendToTarget(); 6138 } 6139 break; 6140 } 6141 case KeyEvent.KEYCODE_WINDOW: { 6142 if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) { 6143 if (mPictureInPictureVisible) { 6144 // Consumes the key only if picture-in-picture is visible to show 6145 // picture-in-picture control menu. This gives a chance to the foreground 6146 // activity to customize PIP key behavior. 6147 if (!down) { 6148 showPictureInPictureMenu(event); 6149 } 6150 result &= ~ACTION_PASS_TO_USER; 6151 } 6152 } 6153 break; 6154 } 6155 } 6156 6157 if (useHapticFeedback) { 6158 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); 6159 } 6160 6161 if (isWakeKey) { 6162 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 6163 } 6164 6165 return result; 6166 } 6167 6168 /** 6169 * Handle statusbar expansion events. 6170 * @param event 6171 */ 6172 private void interceptSystemNavigationKey(KeyEvent event) { 6173 if (event.getAction() == KeyEvent.ACTION_UP) { 6174 if (!mAccessibilityManager.isEnabled() 6175 || !mAccessibilityManager.sendFingerprintGesture(event.getKeyCode())) { 6176 if (areSystemNavigationKeysEnabled()) { 6177 IStatusBarService sbar = getStatusBarService(); 6178 if (sbar != null) { 6179 try { 6180 sbar.handleSystemNavigationKey(event.getKeyCode()); 6181 } catch (RemoteException e1) { 6182 // oops, no statusbar. Ignore event. 6183 } 6184 } 6185 } 6186 } 6187 } 6188 } 6189 6190 /** 6191 * Returns true if the key can have global actions attached to it. 6192 * We reserve all power management keys for the system since they require 6193 * very careful handling. 6194 */ 6195 private static boolean isValidGlobalKey(int keyCode) { 6196 switch (keyCode) { 6197 case KeyEvent.KEYCODE_POWER: 6198 case KeyEvent.KEYCODE_WAKEUP: 6199 case KeyEvent.KEYCODE_SLEEP: 6200 return false; 6201 default: 6202 return true; 6203 } 6204 } 6205 6206 /** 6207 * When the screen is off we ignore some keys that might otherwise typically 6208 * be considered wake keys. We filter them out here. 6209 * 6210 * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it 6211 * is always considered a wake key. 6212 */ 6213 private boolean isWakeKeyWhenScreenOff(int keyCode) { 6214 switch (keyCode) { 6215 // ignore volume keys unless docked 6216 case KeyEvent.KEYCODE_VOLUME_UP: 6217 case KeyEvent.KEYCODE_VOLUME_DOWN: 6218 case KeyEvent.KEYCODE_VOLUME_MUTE: 6219 return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED; 6220 6221 // ignore media and camera keys 6222 case KeyEvent.KEYCODE_MUTE: 6223 case KeyEvent.KEYCODE_HEADSETHOOK: 6224 case KeyEvent.KEYCODE_MEDIA_PLAY: 6225 case KeyEvent.KEYCODE_MEDIA_PAUSE: 6226 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 6227 case KeyEvent.KEYCODE_MEDIA_STOP: 6228 case KeyEvent.KEYCODE_MEDIA_NEXT: 6229 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 6230 case KeyEvent.KEYCODE_MEDIA_REWIND: 6231 case KeyEvent.KEYCODE_MEDIA_RECORD: 6232 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 6233 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: 6234 case KeyEvent.KEYCODE_CAMERA: 6235 return false; 6236 } 6237 return true; 6238 } 6239 6240 6241 /** {@inheritDoc} */ 6242 @Override 6243 public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) { 6244 if ((policyFlags & FLAG_WAKE) != 0) { 6245 if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion, 6246 "android.policy:MOTION")) { 6247 return 0; 6248 } 6249 } 6250 6251 if (shouldDispatchInputWhenNonInteractive(null)) { 6252 return ACTION_PASS_TO_USER; 6253 } 6254 6255 // If we have not passed the action up and we are in theater mode without dreaming, 6256 // there will be no dream to intercept the touch and wake into ambient. The device should 6257 // wake up in this case. 6258 if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) { 6259 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming, 6260 "android.policy:MOTION"); 6261 } 6262 6263 return 0; 6264 } 6265 6266 private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) { 6267 final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF); 6268 6269 if (displayOff && !mHasFeatureWatch) { 6270 return false; 6271 } 6272 6273 // Send events to keyguard while the screen is on and it's showing. 6274 if (isKeyguardShowingAndNotOccluded() && !displayOff) { 6275 return true; 6276 } 6277 6278 // Watches handle BACK specially 6279 if (mHasFeatureWatch 6280 && event != null 6281 && (event.getKeyCode() == KeyEvent.KEYCODE_BACK 6282 || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) { 6283 return false; 6284 } 6285 6286 // Send events to a dozing dream even if the screen is off since the dream 6287 // is in control of the state of the screen. 6288 IDreamManager dreamManager = getDreamManager(); 6289 6290 try { 6291 if (dreamManager != null && dreamManager.isDreaming()) { 6292 return true; 6293 } 6294 } catch (RemoteException e) { 6295 Slog.e(TAG, "RemoteException when checking if dreaming", e); 6296 } 6297 6298 // Otherwise, consume events since the user can't see what is being 6299 // interacted with. 6300 return false; 6301 } 6302 6303 private void dispatchDirectAudioEvent(KeyEvent event) { 6304 if (event.getAction() != KeyEvent.ACTION_DOWN) { 6305 return; 6306 } 6307 int keyCode = event.getKeyCode(); 6308 int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND 6309 | AudioManager.FLAG_FROM_KEY; 6310 String pkgName = mContext.getOpPackageName(); 6311 switch (keyCode) { 6312 case KeyEvent.KEYCODE_VOLUME_UP: 6313 try { 6314 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE, 6315 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6316 } catch (RemoteException e) { 6317 Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e); 6318 } 6319 break; 6320 case KeyEvent.KEYCODE_VOLUME_DOWN: 6321 try { 6322 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER, 6323 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6324 } catch (RemoteException e) { 6325 Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e); 6326 } 6327 break; 6328 case KeyEvent.KEYCODE_VOLUME_MUTE: 6329 try { 6330 if (event.getRepeatCount() == 0) { 6331 getAudioService().adjustSuggestedStreamVolume( 6332 AudioManager.ADJUST_TOGGLE_MUTE, 6333 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6334 } 6335 } catch (RemoteException e) { 6336 Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e); 6337 } 6338 break; 6339 } 6340 } 6341 6342 void dispatchMediaKeyWithWakeLock(KeyEvent event) { 6343 if (DEBUG_INPUT) { 6344 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event); 6345 } 6346 6347 if (mHavePendingMediaKeyRepeatWithWakeLock) { 6348 if (DEBUG_INPUT) { 6349 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat"); 6350 } 6351 6352 mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK); 6353 mHavePendingMediaKeyRepeatWithWakeLock = false; 6354 mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock 6355 } 6356 6357 dispatchMediaKeyWithWakeLockToAudioService(event); 6358 6359 if (event.getAction() == KeyEvent.ACTION_DOWN 6360 && event.getRepeatCount() == 0) { 6361 mHavePendingMediaKeyRepeatWithWakeLock = true; 6362 6363 Message msg = mHandler.obtainMessage( 6364 MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event); 6365 msg.setAsynchronous(true); 6366 mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout()); 6367 } else { 6368 mBroadcastWakeLock.release(); 6369 } 6370 } 6371 6372 void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) { 6373 mHavePendingMediaKeyRepeatWithWakeLock = false; 6374 6375 KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event, 6376 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS); 6377 if (DEBUG_INPUT) { 6378 Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent); 6379 } 6380 6381 dispatchMediaKeyWithWakeLockToAudioService(repeatEvent); 6382 mBroadcastWakeLock.release(); 6383 } 6384 6385 void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) { 6386 if (mActivityManagerInternal.isSystemReady()) { 6387 MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true); 6388 } 6389 } 6390 6391 void launchVoiceAssistWithWakeLock(boolean keyguardActive) { 6392 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface( 6393 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); 6394 if (dic != null) { 6395 try { 6396 dic.exitIdle("voice-search"); 6397 } catch (RemoteException e) { 6398 } 6399 } 6400 Intent voiceIntent = 6401 new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); 6402 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive); 6403 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF); 6404 mBroadcastWakeLock.release(); 6405 } 6406 6407 BroadcastReceiver mDockReceiver = new BroadcastReceiver() { 6408 @Override 6409 public void onReceive(Context context, Intent intent) { 6410 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) { 6411 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 6412 Intent.EXTRA_DOCK_STATE_UNDOCKED); 6413 } else { 6414 try { 6415 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface( 6416 ServiceManager.getService(Context.UI_MODE_SERVICE)); 6417 mUiMode = uiModeService.getCurrentModeType(); 6418 } catch (RemoteException e) { 6419 } 6420 } 6421 updateRotation(true); 6422 synchronized (mLock) { 6423 updateOrientationListenerLp(); 6424 } 6425 } 6426 }; 6427 6428 BroadcastReceiver mDreamReceiver = new BroadcastReceiver() { 6429 @Override 6430 public void onReceive(Context context, Intent intent) { 6431 if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) { 6432 if (mKeyguardDelegate != null) { 6433 mKeyguardDelegate.onDreamingStarted(); 6434 } 6435 } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) { 6436 if (mKeyguardDelegate != null) { 6437 mKeyguardDelegate.onDreamingStopped(); 6438 } 6439 } 6440 } 6441 }; 6442 6443 BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() { 6444 @Override 6445 public void onReceive(Context context, Intent intent) { 6446 if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) { 6447 // tickle the settings observer: this first ensures that we're 6448 // observing the relevant settings for the newly-active user, 6449 // and then updates our own bookkeeping based on the now- 6450 // current user. 6451 mSettingsObserver.onChange(false); 6452 6453 // force a re-application of focused window sysui visibility. 6454 // the window may never have been shown for this user 6455 // e.g. the keyguard when going through the new-user setup flow 6456 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6457 mLastSystemUiFlags = 0; 6458 updateSystemUiVisibilityLw(); 6459 } 6460 } 6461 } 6462 }; 6463 6464 private final Runnable mHiddenNavPanic = new Runnable() { 6465 @Override 6466 public void run() { 6467 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6468 if (!isUserSetupComplete()) { 6469 // Swipe-up for navigation bar is disabled during setup 6470 return; 6471 } 6472 mPendingPanicGestureUptime = SystemClock.uptimeMillis(); 6473 if (!isNavBarEmpty(mLastSystemUiFlags)) { 6474 mNavigationBarController.showTransient(); 6475 } 6476 } 6477 } 6478 }; 6479 6480 private void requestTransientBars(WindowState swipeTarget) { 6481 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6482 if (!isUserSetupComplete()) { 6483 // Swipe-up for navigation bar is disabled during setup 6484 return; 6485 } 6486 boolean sb = mStatusBarController.checkShowTransientBarLw(); 6487 boolean nb = mNavigationBarController.checkShowTransientBarLw() 6488 && !isNavBarEmpty(mLastSystemUiFlags); 6489 if (sb || nb) { 6490 // Don't show status bar when swiping on already visible navigation bar 6491 if (!nb && swipeTarget == mNavigationBar) { 6492 if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target"); 6493 return; 6494 } 6495 if (sb) mStatusBarController.showTransient(); 6496 if (nb) mNavigationBarController.showTransient(); 6497 mImmersiveModeConfirmation.confirmCurrentPrompt(); 6498 updateSystemUiVisibilityLw(); 6499 } 6500 } 6501 } 6502 6503 // Called on the PowerManager's Notifier thread. 6504 @Override 6505 public void startedGoingToSleep(int why) { 6506 if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")"); 6507 mCameraGestureTriggeredDuringGoingToSleep = false; 6508 mGoingToSleep = true; 6509 if (mKeyguardDelegate != null) { 6510 mKeyguardDelegate.onStartedGoingToSleep(why); 6511 } 6512 } 6513 6514 // Called on the PowerManager's Notifier thread. 6515 @Override 6516 public void finishedGoingToSleep(int why) { 6517 EventLog.writeEvent(70000, 0); 6518 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")"); 6519 MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000); 6520 6521 mGoingToSleep = false; 6522 6523 // We must get this work done here because the power manager will drop 6524 // the wake lock and let the system suspend once this function returns. 6525 synchronized (mLock) { 6526 mAwake = false; 6527 updateWakeGestureListenerLp(); 6528 updateOrientationListenerLp(); 6529 updateLockScreenTimeout(); 6530 } 6531 if (mKeyguardDelegate != null) { 6532 mKeyguardDelegate.onFinishedGoingToSleep(why, 6533 mCameraGestureTriggeredDuringGoingToSleep); 6534 } 6535 mCameraGestureTriggeredDuringGoingToSleep = false; 6536 } 6537 6538 // Called on the PowerManager's Notifier thread. 6539 @Override 6540 public void startedWakingUp() { 6541 EventLog.writeEvent(70000, 1); 6542 if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up..."); 6543 6544 // Since goToSleep performs these functions synchronously, we must 6545 // do the same here. We cannot post this work to a handler because 6546 // that might cause it to become reordered with respect to what 6547 // may happen in a future call to goToSleep. 6548 synchronized (mLock) { 6549 mAwake = true; 6550 6551 updateWakeGestureListenerLp(); 6552 updateOrientationListenerLp(); 6553 updateLockScreenTimeout(); 6554 } 6555 6556 if (mKeyguardDelegate != null) { 6557 mKeyguardDelegate.onStartedWakingUp(); 6558 } 6559 } 6560 6561 // Called on the PowerManager's Notifier thread. 6562 @Override 6563 public void finishedWakingUp() { 6564 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up..."); 6565 } 6566 6567 private void wakeUpFromPowerKey(long eventTime) { 6568 wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER"); 6569 } 6570 6571 private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) { 6572 final boolean theaterModeEnabled = isTheaterModeEnabled(); 6573 if (!wakeInTheaterMode && theaterModeEnabled) { 6574 return false; 6575 } 6576 6577 if (theaterModeEnabled) { 6578 Settings.Global.putInt(mContext.getContentResolver(), 6579 Settings.Global.THEATER_MODE_ON, 0); 6580 } 6581 6582 mPowerManager.wakeUp(wakeTime, reason); 6583 return true; 6584 } 6585 6586 private void finishKeyguardDrawn() { 6587 synchronized (mLock) { 6588 if (!mScreenOnEarly || mKeyguardDrawComplete) { 6589 return; // We are not awake yet or we have already informed of this event. 6590 } 6591 6592 mKeyguardDrawComplete = true; 6593 if (mKeyguardDelegate != null) { 6594 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6595 } 6596 mWindowManagerDrawComplete = false; 6597 } 6598 6599 // ... eventually calls finishWindowsDrawn which will finalize our screen turn on 6600 // as well as enabling the orientation change logic/sensor. 6601 mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback, 6602 WAITING_FOR_DRAWN_TIMEOUT); 6603 } 6604 6605 // Called on the DisplayManager's DisplayPowerController thread. 6606 @Override 6607 public void screenTurnedOff() { 6608 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off..."); 6609 6610 updateScreenOffSleepToken(true); 6611 synchronized (mLock) { 6612 mScreenOnEarly = false; 6613 mScreenOnFully = false; 6614 mKeyguardDrawComplete = false; 6615 mWindowManagerDrawComplete = false; 6616 mScreenOnListener = null; 6617 updateOrientationListenerLp(); 6618 6619 if (mKeyguardDelegate != null) { 6620 mKeyguardDelegate.onScreenTurnedOff(); 6621 } 6622 } 6623 reportScreenStateToVrManager(false); 6624 } 6625 6626 // Called on the DisplayManager's DisplayPowerController thread. 6627 @Override 6628 public void screenTurningOn(final ScreenOnListener screenOnListener) { 6629 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on..."); 6630 6631 updateScreenOffSleepToken(false); 6632 synchronized (mLock) { 6633 mScreenOnEarly = true; 6634 mScreenOnFully = false; 6635 mKeyguardDrawComplete = false; 6636 mWindowManagerDrawComplete = false; 6637 mScreenOnListener = screenOnListener; 6638 6639 if (mKeyguardDelegate != null) { 6640 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6641 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000); 6642 mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback); 6643 } else { 6644 if (DEBUG_WAKEUP) Slog.d(TAG, 6645 "null mKeyguardDelegate: setting mKeyguardDrawComplete."); 6646 finishKeyguardDrawn(); 6647 } 6648 } 6649 } 6650 6651 // Called on the DisplayManager's DisplayPowerController thread. 6652 @Override 6653 public void screenTurnedOn() { 6654 synchronized (mLock) { 6655 if (mKeyguardDelegate != null) { 6656 mKeyguardDelegate.onScreenTurnedOn(); 6657 } 6658 } 6659 reportScreenStateToVrManager(true); 6660 } 6661 6662 private void reportScreenStateToVrManager(boolean isScreenOn) { 6663 if (mVrManagerInternal == null) { 6664 return; 6665 } 6666 mVrManagerInternal.onScreenStateChanged(isScreenOn); 6667 } 6668 6669 private void finishWindowsDrawn() { 6670 synchronized (mLock) { 6671 if (!mScreenOnEarly || mWindowManagerDrawComplete) { 6672 return; // Screen is not turned on or we did already handle this case earlier. 6673 } 6674 6675 mWindowManagerDrawComplete = true; 6676 } 6677 6678 finishScreenTurningOn(); 6679 } 6680 6681 private void finishScreenTurningOn() { 6682 synchronized (mLock) { 6683 // We have just finished drawing screen content. Since the orientation listener 6684 // gets only installed when all windows are drawn, we try to install it again. 6685 updateOrientationListenerLp(); 6686 } 6687 final ScreenOnListener listener; 6688 final boolean enableScreen; 6689 synchronized (mLock) { 6690 if (DEBUG_WAKEUP) Slog.d(TAG, 6691 "finishScreenTurningOn: mAwake=" + mAwake 6692 + ", mScreenOnEarly=" + mScreenOnEarly 6693 + ", mScreenOnFully=" + mScreenOnFully 6694 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete 6695 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete); 6696 6697 if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete 6698 || (mAwake && !mKeyguardDrawComplete)) { 6699 return; // spurious or not ready yet 6700 } 6701 6702 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on..."); 6703 listener = mScreenOnListener; 6704 mScreenOnListener = null; 6705 mScreenOnFully = true; 6706 6707 // Remember the first time we draw the keyguard so we know when we're done with 6708 // the main part of booting and can enable the screen and hide boot messages. 6709 if (!mKeyguardDrawnOnce && mAwake) { 6710 mKeyguardDrawnOnce = true; 6711 enableScreen = true; 6712 if (mBootMessageNeedsHiding) { 6713 mBootMessageNeedsHiding = false; 6714 hideBootMessages(); 6715 } 6716 } else { 6717 enableScreen = false; 6718 } 6719 } 6720 6721 if (listener != null) { 6722 listener.onScreenOn(); 6723 } 6724 6725 if (enableScreen) { 6726 try { 6727 mWindowManager.enableScreenIfNeeded(); 6728 } catch (RemoteException unhandled) { 6729 } 6730 } 6731 } 6732 6733 private void handleHideBootMessage() { 6734 synchronized (mLock) { 6735 if (!mKeyguardDrawnOnce) { 6736 mBootMessageNeedsHiding = true; 6737 return; // keyguard hasn't drawn the first time yet, not done booting 6738 } 6739 } 6740 6741 if (mBootMsgDialog != null) { 6742 if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing"); 6743 mBootMsgDialog.dismiss(); 6744 mBootMsgDialog = null; 6745 } 6746 } 6747 6748 @Override 6749 public boolean isScreenOn() { 6750 return mScreenOnFully; 6751 } 6752 6753 /** {@inheritDoc} */ 6754 @Override 6755 public void enableKeyguard(boolean enabled) { 6756 if (mKeyguardDelegate != null) { 6757 mKeyguardDelegate.setKeyguardEnabled(enabled); 6758 } 6759 } 6760 6761 /** {@inheritDoc} */ 6762 @Override 6763 public void exitKeyguardSecurely(OnKeyguardExitResult callback) { 6764 if (mKeyguardDelegate != null) { 6765 mKeyguardDelegate.verifyUnlock(callback); 6766 } 6767 } 6768 6769 @Override 6770 public boolean isKeyguardShowingAndNotOccluded() { 6771 if (mKeyguardDelegate == null) return false; 6772 return mKeyguardDelegate.isShowing() && !mKeyguardOccluded; 6773 } 6774 6775 @Override 6776 public boolean isKeyguardTrustedLw() { 6777 if (mKeyguardDelegate == null) return false; 6778 return mKeyguardDelegate.isTrusted(); 6779 } 6780 6781 /** {@inheritDoc} */ 6782 @Override 6783 public boolean isKeyguardLocked() { 6784 return keyguardOn(); 6785 } 6786 6787 /** {@inheritDoc} */ 6788 @Override 6789 public boolean isKeyguardSecure(int userId) { 6790 if (mKeyguardDelegate == null) return false; 6791 return mKeyguardDelegate.isSecure(userId); 6792 } 6793 6794 /** {@inheritDoc} */ 6795 @Override 6796 public boolean isKeyguardOccluded() { 6797 if (mKeyguardDelegate == null) return false; 6798 return mKeyguardOccluded; 6799 } 6800 6801 /** {@inheritDoc} */ 6802 @Override 6803 public boolean inKeyguardRestrictedKeyInputMode() { 6804 if (mKeyguardDelegate == null) return false; 6805 return mKeyguardDelegate.isInputRestricted(); 6806 } 6807 6808 @Override 6809 public void dismissKeyguardLw(IKeyguardDismissCallback callback) { 6810 if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) { 6811 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw"); 6812 6813 // ask the keyguard to prompt the user to authenticate if necessary 6814 mKeyguardDelegate.dismiss(callback); 6815 } else if (callback != null) { 6816 try { 6817 callback.onDismissError(); 6818 } catch (RemoteException e) { 6819 Slog.w(TAG, "Failed to call callback", e); 6820 } 6821 } 6822 } 6823 6824 @Override 6825 public boolean isKeyguardDrawnLw() { 6826 synchronized (mLock) { 6827 return mKeyguardDrawnOnce; 6828 } 6829 } 6830 6831 @Override 6832 public boolean isShowingDreamLw() { 6833 return mShowingDream; 6834 } 6835 6836 @Override 6837 public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) { 6838 if (mKeyguardDelegate != null) { 6839 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation"); 6840 mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration); 6841 } 6842 } 6843 6844 @Override 6845 public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6846 Rect outInsets) { 6847 outInsets.setEmpty(); 6848 6849 // Navigation bar and status bar. 6850 getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets); 6851 outInsets.top = mStatusBarHeight; 6852 } 6853 6854 @Override 6855 public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6856 Rect outInsets) { 6857 outInsets.setEmpty(); 6858 6859 // Only navigation bar 6860 if (mHasNavigationBar) { 6861 int position = navigationBarPosition(displayWidth, displayHeight, displayRotation); 6862 if (position == NAV_BAR_BOTTOM) { 6863 outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode); 6864 } else if (position == NAV_BAR_RIGHT) { 6865 outInsets.right = getNavigationBarWidth(displayRotation, mUiMode); 6866 } else if (position == NAV_BAR_LEFT) { 6867 outInsets.left = getNavigationBarWidth(displayRotation, mUiMode); 6868 } 6869 } 6870 } 6871 6872 @Override 6873 public boolean isNavBarForcedShownLw(WindowState windowState) { 6874 return mForceShowSystemBars; 6875 } 6876 6877 @Override 6878 public boolean isDockSideAllowed(int dockSide) { 6879 6880 // We do not allow all dock sides at which the navigation bar touches the docked stack. 6881 if (!mNavigationBarCanMove) { 6882 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT; 6883 } else { 6884 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT; 6885 } 6886 } 6887 6888 void sendCloseSystemWindows() { 6889 PhoneWindow.sendCloseSystemWindows(mContext, null); 6890 } 6891 6892 void sendCloseSystemWindows(String reason) { 6893 PhoneWindow.sendCloseSystemWindows(mContext, reason); 6894 } 6895 6896 @Override 6897 public int rotationForOrientationLw(int orientation, int lastRotation) { 6898 if (false) { 6899 Slog.v(TAG, "rotationForOrientationLw(orient=" 6900 + orientation + ", last=" + lastRotation 6901 + "); user=" + mUserRotation + " " 6902 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) 6903 ? "USER_ROTATION_LOCKED" : "") 6904 ); 6905 } 6906 6907 if (mForceDefaultOrientation) { 6908 return Surface.ROTATION_0; 6909 } 6910 6911 synchronized (mLock) { 6912 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1 6913 if (sensorRotation < 0) { 6914 sensorRotation = lastRotation; 6915 } 6916 6917 final int preferredRotation; 6918 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) { 6919 // Ignore sensor when lid switch is open and rotation is forced. 6920 preferredRotation = mLidOpenRotation; 6921 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR 6922 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) { 6923 // Ignore sensor when in car dock unless explicitly enabled. 6924 // This case can override the behavior of NOSENSOR, and can also 6925 // enable 180 degree rotation while docked. 6926 preferredRotation = mCarDockEnablesAccelerometer 6927 ? sensorRotation : mCarDockRotation; 6928 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK 6929 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK 6930 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK) 6931 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) { 6932 // Ignore sensor when in desk dock unless explicitly enabled. 6933 // This case can override the behavior of NOSENSOR, and can also 6934 // enable 180 degree rotation while docked. 6935 preferredRotation = mDeskDockEnablesAccelerometer 6936 ? sensorRotation : mDeskDockRotation; 6937 } else if (mHdmiPlugged && mDemoHdmiRotationLock) { 6938 // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled. 6939 // Note that the dock orientation overrides the HDMI orientation. 6940 preferredRotation = mDemoHdmiRotation; 6941 } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED 6942 && mUndockedHdmiRotation >= 0) { 6943 // Ignore sensor when plugged into HDMI and an undocked orientation has 6944 // been specified in the configuration (only for legacy devices without 6945 // full multi-display support). 6946 // Note that the dock orientation overrides the HDMI orientation. 6947 preferredRotation = mUndockedHdmiRotation; 6948 } else if (mDemoRotationLock) { 6949 // Ignore sensor when demo rotation lock is enabled. 6950 // Note that the dock orientation and HDMI rotation lock override this. 6951 preferredRotation = mDemoRotation; 6952 } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) { 6953 // Application just wants to remain locked in the last rotation. 6954 preferredRotation = lastRotation; 6955 } else if (!mSupportAutoRotation) { 6956 // If we don't support auto-rotation then bail out here and ignore 6957 // the sensor and any rotation lock settings. 6958 preferredRotation = -1; 6959 } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE 6960 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER 6961 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 6962 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE 6963 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT 6964 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER)) 6965 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR 6966 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6967 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE 6968 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) { 6969 // Otherwise, use sensor only if requested by the application or enabled 6970 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR. 6971 if (mAllowAllRotations < 0) { 6972 // Can't read this during init() because the context doesn't 6973 // have display metrics at that time so we cannot determine 6974 // tablet vs. phone then. 6975 mAllowAllRotations = mContext.getResources().getBoolean( 6976 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0; 6977 } 6978 if (sensorRotation != Surface.ROTATION_180 6979 || mAllowAllRotations == 1 6980 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6981 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) { 6982 // In VrMode, we report the sensor as always being in default orientation so: 6983 // 1) The orientation doesn't change as the user moves their head. 6984 // 2) 2D apps within VR show in the device's default orientation. 6985 // This only overwrites the sensor-provided orientation and does not affect any 6986 // explicit orientation preferences specified by any activities. 6987 preferredRotation = 6988 mPersistentVrModeEnabled ? Surface.ROTATION_0 : sensorRotation; 6989 } else { 6990 preferredRotation = lastRotation; 6991 } 6992 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED 6993 && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) { 6994 // Apply rotation lock. Does not apply to NOSENSOR. 6995 // The idea is that the user rotation expresses a weak preference for the direction 6996 // of gravity and as NOSENSOR is never affected by gravity, then neither should 6997 // NOSENSOR be affected by rotation lock (although it will be affected by docks). 6998 preferredRotation = mUserRotation; 6999 } else { 7000 // No overriding preference. 7001 // We will do exactly what the application asked us to do. 7002 preferredRotation = -1; 7003 } 7004 7005 switch (orientation) { 7006 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 7007 // Return portrait unless overridden. 7008 if (isAnyPortrait(preferredRotation)) { 7009 return preferredRotation; 7010 } 7011 return mPortraitRotation; 7012 7013 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 7014 // Return landscape unless overridden. 7015 if (isLandscapeOrSeascape(preferredRotation)) { 7016 return preferredRotation; 7017 } 7018 return mLandscapeRotation; 7019 7020 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 7021 // Return reverse portrait unless overridden. 7022 if (isAnyPortrait(preferredRotation)) { 7023 return preferredRotation; 7024 } 7025 return mUpsideDownRotation; 7026 7027 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 7028 // Return seascape unless overridden. 7029 if (isLandscapeOrSeascape(preferredRotation)) { 7030 return preferredRotation; 7031 } 7032 return mSeascapeRotation; 7033 7034 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 7035 case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE: 7036 // Return either landscape rotation. 7037 if (isLandscapeOrSeascape(preferredRotation)) { 7038 return preferredRotation; 7039 } 7040 if (isLandscapeOrSeascape(lastRotation)) { 7041 return lastRotation; 7042 } 7043 return mLandscapeRotation; 7044 7045 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 7046 case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT: 7047 // Return either portrait rotation. 7048 if (isAnyPortrait(preferredRotation)) { 7049 return preferredRotation; 7050 } 7051 if (isAnyPortrait(lastRotation)) { 7052 return lastRotation; 7053 } 7054 return mPortraitRotation; 7055 7056 default: 7057 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR, 7058 // just return the preferred orientation we already calculated. 7059 if (preferredRotation >= 0) { 7060 return preferredRotation; 7061 } 7062 return Surface.ROTATION_0; 7063 } 7064 } 7065 } 7066 7067 @Override 7068 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) { 7069 switch (orientation) { 7070 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 7071 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 7072 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 7073 return isAnyPortrait(rotation); 7074 7075 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 7076 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 7077 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 7078 return isLandscapeOrSeascape(rotation); 7079 7080 default: 7081 return true; 7082 } 7083 } 7084 7085 @Override 7086 public void setRotationLw(int rotation) { 7087 mOrientationListener.setCurrentRotation(rotation); 7088 } 7089 7090 private boolean isLandscapeOrSeascape(int rotation) { 7091 return rotation == mLandscapeRotation || rotation == mSeascapeRotation; 7092 } 7093 7094 private boolean isAnyPortrait(int rotation) { 7095 return rotation == mPortraitRotation || rotation == mUpsideDownRotation; 7096 } 7097 7098 @Override 7099 public int getUserRotationMode() { 7100 return Settings.System.getIntForUser(mContext.getContentResolver(), 7101 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ? 7102 WindowManagerPolicy.USER_ROTATION_FREE : 7103 WindowManagerPolicy.USER_ROTATION_LOCKED; 7104 } 7105 7106 // User rotation: to be used when all else fails in assigning an orientation to the device 7107 @Override 7108 public void setUserRotationMode(int mode, int rot) { 7109 ContentResolver res = mContext.getContentResolver(); 7110 7111 // mUserRotationMode and mUserRotation will be assigned by the content observer 7112 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) { 7113 Settings.System.putIntForUser(res, 7114 Settings.System.USER_ROTATION, 7115 rot, 7116 UserHandle.USER_CURRENT); 7117 Settings.System.putIntForUser(res, 7118 Settings.System.ACCELEROMETER_ROTATION, 7119 0, 7120 UserHandle.USER_CURRENT); 7121 } else { 7122 Settings.System.putIntForUser(res, 7123 Settings.System.ACCELEROMETER_ROTATION, 7124 1, 7125 UserHandle.USER_CURRENT); 7126 } 7127 } 7128 7129 @Override 7130 public void setSafeMode(boolean safeMode) { 7131 mSafeMode = safeMode; 7132 performHapticFeedbackLw(null, safeMode 7133 ? HapticFeedbackConstants.SAFE_MODE_ENABLED 7134 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true); 7135 } 7136 7137 static long[] getLongIntArray(Resources r, int resid) { 7138 int[] ar = r.getIntArray(resid); 7139 if (ar == null) { 7140 return null; 7141 } 7142 long[] out = new long[ar.length]; 7143 for (int i=0; i<ar.length; i++) { 7144 out[i] = ar[i]; 7145 } 7146 return out; 7147 } 7148 7149 /** {@inheritDoc} */ 7150 @Override 7151 public void systemReady() { 7152 mKeyguardDelegate = new KeyguardServiceDelegate(mContext, 7153 new StateCallback() { 7154 @Override 7155 public void onTrustedChanged() { 7156 mWindowManagerFuncs.notifyKeyguardTrustedChanged(); 7157 } 7158 }); 7159 mKeyguardDelegate.onSystemReady(); 7160 7161 mVrManagerInternal = LocalServices.getService(VrManagerInternal.class); 7162 if (mVrManagerInternal != null) { 7163 mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener); 7164 } 7165 7166 readCameraLensCoverState(); 7167 updateUiMode(); 7168 boolean bindKeyguardNow; 7169 synchronized (mLock) { 7170 updateOrientationListenerLp(); 7171 mSystemReady = true; 7172 mHandler.post(new Runnable() { 7173 @Override 7174 public void run() { 7175 updateSettings(); 7176 } 7177 }); 7178 7179 bindKeyguardNow = mDeferBindKeyguard; 7180 if (bindKeyguardNow) { 7181 // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now. 7182 mDeferBindKeyguard = false; 7183 } 7184 } 7185 7186 if (bindKeyguardNow) { 7187 mKeyguardDelegate.bindService(mContext); 7188 mKeyguardDelegate.onBootCompleted(); 7189 } 7190 mSystemGestures.systemReady(); 7191 mImmersiveModeConfirmation.systemReady(); 7192 } 7193 7194 /** {@inheritDoc} */ 7195 @Override 7196 public void systemBooted() { 7197 boolean bindKeyguardNow = false; 7198 synchronized (mLock) { 7199 // Time to bind Keyguard; take care to only bind it once, either here if ready or 7200 // in systemReady if not. 7201 if (mKeyguardDelegate != null) { 7202 bindKeyguardNow = true; 7203 } else { 7204 // Because mKeyguardDelegate is null, we know that the synchronized block in 7205 // systemReady didn't run yet and setting this will actually have an effect. 7206 mDeferBindKeyguard = true; 7207 } 7208 } 7209 if (bindKeyguardNow) { 7210 mKeyguardDelegate.bindService(mContext); 7211 mKeyguardDelegate.onBootCompleted(); 7212 } 7213 synchronized (mLock) { 7214 mSystemBooted = true; 7215 } 7216 startedWakingUp(); 7217 screenTurningOn(null); 7218 screenTurnedOn(); 7219 } 7220 7221 ProgressDialog mBootMsgDialog = null; 7222 7223 /** {@inheritDoc} */ 7224 @Override 7225 public void showBootMessage(final CharSequence msg, final boolean always) { 7226 mHandler.post(new Runnable() { 7227 @Override public void run() { 7228 if (mBootMsgDialog == null) { 7229 int theme; 7230 if (mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK)) { 7231 theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert; 7232 } else { 7233 theme = 0; 7234 } 7235 7236 mBootMsgDialog = new ProgressDialog(mContext, theme) { 7237 // This dialog will consume all events coming in to 7238 // it, to avoid it trying to do things too early in boot. 7239 @Override public boolean dispatchKeyEvent(KeyEvent event) { 7240 return true; 7241 } 7242 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { 7243 return true; 7244 } 7245 @Override public boolean dispatchTouchEvent(MotionEvent ev) { 7246 return true; 7247 } 7248 @Override public boolean dispatchTrackballEvent(MotionEvent ev) { 7249 return true; 7250 } 7251 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) { 7252 return true; 7253 } 7254 @Override public boolean dispatchPopulateAccessibilityEvent( 7255 AccessibilityEvent event) { 7256 return true; 7257 } 7258 }; 7259 if (mContext.getPackageManager().isUpgrade()) { 7260 mBootMsgDialog.setTitle(R.string.android_upgrading_title); 7261 } else { 7262 mBootMsgDialog.setTitle(R.string.android_start_title); 7263 } 7264 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 7265 mBootMsgDialog.setIndeterminate(true); 7266 mBootMsgDialog.getWindow().setType( 7267 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS); 7268 mBootMsgDialog.getWindow().addFlags( 7269 WindowManager.LayoutParams.FLAG_DIM_BEHIND 7270 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); 7271 mBootMsgDialog.getWindow().setDimAmount(1); 7272 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes(); 7273 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 7274 mBootMsgDialog.getWindow().setAttributes(lp); 7275 mBootMsgDialog.setCancelable(false); 7276 mBootMsgDialog.show(); 7277 } 7278 mBootMsgDialog.setMessage(msg); 7279 } 7280 }); 7281 } 7282 7283 /** {@inheritDoc} */ 7284 @Override 7285 public void hideBootMessages() { 7286 mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE); 7287 } 7288 7289 /** {@inheritDoc} */ 7290 @Override 7291 public void userActivity() { 7292 // *************************************** 7293 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE 7294 // *************************************** 7295 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER 7296 // WITH ITS LOCKS HELD. 7297 // 7298 // This code must be VERY careful about the locks 7299 // it acquires. 7300 // In fact, the current code acquires way too many, 7301 // and probably has lurking deadlocks. 7302 7303 synchronized (mScreenLockTimeout) { 7304 if (mLockScreenTimerActive) { 7305 // reset the timer 7306 mHandler.removeCallbacks(mScreenLockTimeout); 7307 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7308 } 7309 } 7310 } 7311 7312 class ScreenLockTimeout implements Runnable { 7313 Bundle options; 7314 7315 @Override 7316 public void run() { 7317 synchronized (this) { 7318 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard"); 7319 if (mKeyguardDelegate != null) { 7320 mKeyguardDelegate.doKeyguardTimeout(options); 7321 } 7322 mLockScreenTimerActive = false; 7323 options = null; 7324 } 7325 } 7326 7327 public void setLockOptions(Bundle options) { 7328 this.options = options; 7329 } 7330 } 7331 7332 ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout(); 7333 7334 @Override 7335 public void lockNow(Bundle options) { 7336 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 7337 mHandler.removeCallbacks(mScreenLockTimeout); 7338 if (options != null) { 7339 // In case multiple calls are made to lockNow, we don't wipe out the options 7340 // until the runnable actually executes. 7341 mScreenLockTimeout.setLockOptions(options); 7342 } 7343 mHandler.post(mScreenLockTimeout); 7344 } 7345 7346 private void updateLockScreenTimeout() { 7347 synchronized (mScreenLockTimeout) { 7348 boolean enable = (mAllowLockscreenWhenOn && mAwake && 7349 mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId)); 7350 if (mLockScreenTimerActive != enable) { 7351 if (enable) { 7352 if (localLOGV) Log.v(TAG, "setting lockscreen timer"); 7353 mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests 7354 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7355 } else { 7356 if (localLOGV) Log.v(TAG, "clearing lockscreen timer"); 7357 mHandler.removeCallbacks(mScreenLockTimeout); 7358 } 7359 mLockScreenTimerActive = enable; 7360 } 7361 } 7362 } 7363 7364 private void updateDreamingSleepToken(boolean acquire) { 7365 if (acquire) { 7366 if (mDreamingSleepToken == null) { 7367 mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream"); 7368 } 7369 } else { 7370 if (mDreamingSleepToken != null) { 7371 mDreamingSleepToken.release(); 7372 mDreamingSleepToken = null; 7373 } 7374 } 7375 } 7376 7377 private void updateScreenOffSleepToken(boolean acquire) { 7378 if (acquire) { 7379 if (mScreenOffSleepToken == null) { 7380 mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff"); 7381 } 7382 } else { 7383 if (mScreenOffSleepToken != null) { 7384 mScreenOffSleepToken.release(); 7385 mScreenOffSleepToken = null; 7386 } 7387 } 7388 } 7389 7390 /** {@inheritDoc} */ 7391 @Override 7392 public void enableScreenAfterBoot() { 7393 readLidState(); 7394 applyLidSwitchState(); 7395 updateRotation(true); 7396 } 7397 7398 private void applyLidSwitchState() { 7399 if (mLidState == LID_CLOSED && mLidControlsSleep) { 7400 mPowerManager.goToSleep(SystemClock.uptimeMillis(), 7401 PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH, 7402 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); 7403 } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) { 7404 mWindowManagerFuncs.lockDeviceNow(); 7405 } 7406 7407 synchronized (mLock) { 7408 updateWakeGestureListenerLp(); 7409 } 7410 } 7411 7412 void updateUiMode() { 7413 if (mUiModeManager == null) { 7414 mUiModeManager = IUiModeManager.Stub.asInterface( 7415 ServiceManager.getService(Context.UI_MODE_SERVICE)); 7416 } 7417 try { 7418 mUiMode = mUiModeManager.getCurrentModeType(); 7419 } catch (RemoteException e) { 7420 } 7421 } 7422 7423 void updateRotation(boolean alwaysSendConfiguration) { 7424 try { 7425 //set orientation on WindowManager 7426 mWindowManager.updateRotation(alwaysSendConfiguration, false); 7427 } catch (RemoteException e) { 7428 // Ignore 7429 } 7430 } 7431 7432 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 7433 try { 7434 //set orientation on WindowManager 7435 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout); 7436 } catch (RemoteException e) { 7437 // Ignore 7438 } 7439 } 7440 7441 /** 7442 * Return an Intent to launch the currently active dock app as home. Returns 7443 * null if the standard home should be launched, which is the case if any of the following is 7444 * true: 7445 * <ul> 7446 * <li>The device is not in either car mode or desk mode 7447 * <li>The device is in car mode but mEnableCarDockHomeCapture is false 7448 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false 7449 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME 7450 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME 7451 * </ul> 7452 * @return A dock intent. 7453 */ 7454 Intent createHomeDockIntent() { 7455 Intent intent = null; 7456 7457 // What home does is based on the mode, not the dock state. That 7458 // is, when in car mode you should be taken to car home regardless 7459 // of whether we are actually in a car dock. 7460 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) { 7461 if (mEnableCarDockHomeCapture) { 7462 intent = mCarDockIntent; 7463 } 7464 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) { 7465 if (ENABLE_DESK_DOCK_HOME_CAPTURE) { 7466 intent = mDeskDockIntent; 7467 } 7468 } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH 7469 && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK 7470 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK 7471 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) { 7472 // Always launch dock home from home when watch is docked, if it exists. 7473 intent = mDeskDockIntent; 7474 } else if (mUiMode == Configuration.UI_MODE_TYPE_VR_HEADSET) { 7475 if (ENABLE_VR_HEADSET_HOME_CAPTURE) { 7476 intent = mVrHeadsetHomeIntent; 7477 } 7478 } 7479 7480 if (intent == null) { 7481 return null; 7482 } 7483 7484 ActivityInfo ai = null; 7485 ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser( 7486 intent, 7487 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA, 7488 mCurrentUserId); 7489 if (info != null) { 7490 ai = info.activityInfo; 7491 } 7492 if (ai != null 7493 && ai.metaData != null 7494 && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) { 7495 intent = new Intent(intent); 7496 intent.setClassName(ai.packageName, ai.name); 7497 return intent; 7498 } 7499 7500 return null; 7501 } 7502 7503 void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) { 7504 if (awakenFromDreams) { 7505 awakenDreams(); 7506 } 7507 7508 Intent dock = createHomeDockIntent(); 7509 if (dock != null) { 7510 try { 7511 if (fromHomeKey) { 7512 dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7513 } 7514 startActivityAsUser(dock, UserHandle.CURRENT); 7515 return; 7516 } catch (ActivityNotFoundException e) { 7517 } 7518 } 7519 7520 Intent intent; 7521 7522 if (fromHomeKey) { 7523 intent = new Intent(mHomeIntent); 7524 intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7525 } else { 7526 intent = mHomeIntent; 7527 } 7528 7529 startActivityAsUser(intent, UserHandle.CURRENT); 7530 } 7531 7532 /** 7533 * goes to the home screen 7534 * @return whether it did anything 7535 */ 7536 boolean goHome() { 7537 if (!isUserSetupComplete()) { 7538 Slog.i(TAG, "Not going home because user setup is in progress."); 7539 return false; 7540 } 7541 if (false) { 7542 // This code always brings home to the front. 7543 try { 7544 ActivityManager.getService().stopAppSwitches(); 7545 } catch (RemoteException e) { 7546 } 7547 sendCloseSystemWindows(); 7548 startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */); 7549 } else { 7550 // This code brings home to the front or, if it is already 7551 // at the front, puts the device to sleep. 7552 try { 7553 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) { 7554 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry. 7555 Log.d(TAG, "UTS-TEST-MODE"); 7556 } else { 7557 ActivityManager.getService().stopAppSwitches(); 7558 sendCloseSystemWindows(); 7559 Intent dock = createHomeDockIntent(); 7560 if (dock != null) { 7561 int result = ActivityManager.getService() 7562 .startActivityAsUser(null, null, dock, 7563 dock.resolveTypeIfNeeded(mContext.getContentResolver()), 7564 null, null, 0, 7565 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7566 null, null, UserHandle.USER_CURRENT); 7567 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7568 return false; 7569 } 7570 } 7571 } 7572 int result = ActivityManager.getService() 7573 .startActivityAsUser(null, null, mHomeIntent, 7574 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()), 7575 null, null, 0, 7576 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7577 null, null, UserHandle.USER_CURRENT); 7578 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7579 return false; 7580 } 7581 } catch (RemoteException ex) { 7582 // bummer, the activity manager, which is in this process, is dead 7583 } 7584 } 7585 return true; 7586 } 7587 7588 @Override 7589 public void setCurrentOrientationLw(int newOrientation) { 7590 synchronized (mLock) { 7591 if (newOrientation != mCurrentAppOrientation) { 7592 mCurrentAppOrientation = newOrientation; 7593 updateOrientationListenerLp(); 7594 } 7595 } 7596 } 7597 7598 private boolean isTheaterModeEnabled() { 7599 return Settings.Global.getInt(mContext.getContentResolver(), 7600 Settings.Global.THEATER_MODE_ON, 0) == 1; 7601 } 7602 7603 private boolean areSystemNavigationKeysEnabled() { 7604 return Settings.Secure.getIntForUser(mContext.getContentResolver(), 7605 Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1; 7606 } 7607 7608 @Override 7609 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) { 7610 if (!mVibrator.hasVibrator()) { 7611 return false; 7612 } 7613 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(), 7614 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0; 7615 if (hapticsDisabled && !always) { 7616 return false; 7617 } 7618 7619 VibrationEffect effect = getVibrationEffect(effectId); 7620 if (effect == null) { 7621 return false; 7622 } 7623 7624 int owningUid; 7625 String owningPackage; 7626 if (win != null) { 7627 owningUid = win.getOwningUid(); 7628 owningPackage = win.getOwningPackage(); 7629 } else { 7630 owningUid = android.os.Process.myUid(); 7631 owningPackage = mContext.getOpPackageName(); 7632 } 7633 mVibrator.vibrate(owningUid, owningPackage, effect, VIBRATION_ATTRIBUTES); 7634 return true; 7635 } 7636 7637 private VibrationEffect getVibrationEffect(int effectId) { 7638 long[] pattern; 7639 switch (effectId) { 7640 case HapticFeedbackConstants.VIRTUAL_KEY: 7641 return VibrationEffect.get(VibrationEffect.EFFECT_CLICK); 7642 case HapticFeedbackConstants.LONG_PRESS: 7643 pattern = mLongPressVibePattern; 7644 break; 7645 case HapticFeedbackConstants.KEYBOARD_TAP: 7646 return VibrationEffect.get(VibrationEffect.EFFECT_CLICK); 7647 case HapticFeedbackConstants.CLOCK_TICK: 7648 pattern = mClockTickVibePattern; 7649 break; 7650 case HapticFeedbackConstants.CALENDAR_DATE: 7651 pattern = mCalendarDateVibePattern; 7652 break; 7653 case HapticFeedbackConstants.SAFE_MODE_DISABLED: 7654 pattern = mSafeModeDisabledVibePattern; 7655 break; 7656 case HapticFeedbackConstants.SAFE_MODE_ENABLED: 7657 pattern = mSafeModeEnabledVibePattern; 7658 break; 7659 case HapticFeedbackConstants.CONTEXT_CLICK: 7660 pattern = mContextClickVibePattern; 7661 break; 7662 default: 7663 return null; 7664 } 7665 if (pattern.length == 1) { 7666 // One-shot vibration 7667 return VibrationEffect.createOneShot(pattern[0], VibrationEffect.DEFAULT_AMPLITUDE); 7668 } else { 7669 // Pattern vibration 7670 return VibrationEffect.createWaveform(pattern, -1); 7671 } 7672 } 7673 7674 @Override 7675 public void keepScreenOnStartedLw() { 7676 } 7677 7678 @Override 7679 public void keepScreenOnStoppedLw() { 7680 if (isKeyguardShowingAndNotOccluded()) { 7681 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 7682 } 7683 } 7684 7685 private int updateSystemUiVisibilityLw() { 7686 // If there is no window focused, there will be nobody to handle the events 7687 // anyway, so just hang on in whatever state we're in until things settle down. 7688 WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow 7689 : mTopFullscreenOpaqueWindowState; 7690 if (winCandidate == null) { 7691 return 0; 7692 } 7693 if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) { 7694 // The immersive mode confirmation should never affect the system bar visibility, 7695 // otherwise it will unhide the navigation bar and hide itself. 7696 winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState; 7697 if (winCandidate == null) { 7698 return 0; 7699 } 7700 } 7701 final WindowState win = winCandidate; 7702 if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mKeyguardOccluded) { 7703 // We are updating at a point where the keyguard has gotten 7704 // focus, but we were last in a state where the top window is 7705 // hiding it. This is probably because the keyguard as been 7706 // shown while the top window was displayed, so we want to ignore 7707 // it here because this is just a very transient change and it 7708 // will quickly lose focus once it correctly gets hidden. 7709 return 0; 7710 } 7711 7712 int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null) 7713 & ~mResettingSystemUiFlags 7714 & ~mForceClearedSystemUiFlags; 7715 if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) { 7716 tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS); 7717 } 7718 7719 final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */, 7720 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState); 7721 final int dockedVisibility = updateLightStatusBarLw(0 /* vis */, 7722 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState); 7723 mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds); 7724 mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds); 7725 final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility); 7726 final int diff = visibility ^ mLastSystemUiFlags; 7727 final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags; 7728 final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags; 7729 final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState); 7730 if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu 7731 && mFocusedApp == win.getAppToken() 7732 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds) 7733 && mLastDockedStackBounds.equals(mDockedStackBounds)) { 7734 return 0; 7735 } 7736 mLastSystemUiFlags = visibility; 7737 mLastFullscreenStackSysUiFlags = fullscreenVisibility; 7738 mLastDockedStackSysUiFlags = dockedVisibility; 7739 mLastFocusNeedsMenu = needsMenu; 7740 mFocusedApp = win.getAppToken(); 7741 final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds); 7742 final Rect dockedStackBounds = new Rect(mDockedStackBounds); 7743 mHandler.post(new Runnable() { 7744 @Override 7745 public void run() { 7746 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 7747 if (statusbar != null) { 7748 statusbar.setSystemUiVisibility(visibility, fullscreenVisibility, 7749 dockedVisibility, 0xffffffff, fullscreenStackBounds, 7750 dockedStackBounds, win.toString()); 7751 statusbar.topAppWindowChanged(needsMenu); 7752 } 7753 } 7754 }); 7755 return diff; 7756 } 7757 7758 private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) { 7759 WindowState statusColorWin = isStatusBarKeyguard() && !mKeyguardOccluded 7760 ? mStatusBar 7761 : opaqueOrDimming; 7762 7763 if (statusColorWin != null) { 7764 if (statusColorWin == opaque) { 7765 // If the top fullscreen-or-dimming window is also the top fullscreen, respect 7766 // its light flag. 7767 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7768 vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null) 7769 & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7770 } else if (statusColorWin != null && statusColorWin.isDimming()) { 7771 // Otherwise if it's dimming, clear the light flag. 7772 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7773 } 7774 } 7775 return vis; 7776 } 7777 7778 private int updateLightNavigationBarLw(int vis, WindowState opaque, 7779 WindowState opaqueOrDimming) { 7780 final WindowState imeWin = mWindowManagerFuncs.getInputMethodWindowLw(); 7781 7782 final WindowState navColorWin; 7783 if (imeWin != null && imeWin.isVisibleLw()) { 7784 navColorWin = imeWin; 7785 } else { 7786 navColorWin = opaqueOrDimming; 7787 } 7788 7789 if (navColorWin != null) { 7790 if (navColorWin == opaque) { 7791 // If the top fullscreen-or-dimming window is also the top fullscreen, respect 7792 // its light flag. 7793 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; 7794 vis |= PolicyControl.getSystemUiVisibility(navColorWin, null) 7795 & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; 7796 } else if (navColorWin.isDimming() || navColorWin == imeWin) { 7797 // Otherwise if it's dimming or it's the IME window, clear the light flag. 7798 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; 7799 } 7800 } 7801 return vis; 7802 } 7803 7804 private boolean drawsSystemBarBackground(WindowState win) { 7805 return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0; 7806 } 7807 7808 private boolean forcesDrawStatusBarBackground(WindowState win) { 7809 return win == null || (win.getAttrs().privateFlags 7810 & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0; 7811 } 7812 7813 private int updateSystemBarsLw(WindowState win, int oldVis, int vis) { 7814 final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID); 7815 final boolean freeformStackVisible = 7816 mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID); 7817 final boolean resizing = mWindowManagerInternal.isDockedDividerResizing(); 7818 7819 // We need to force system bars when the docked stack is visible, when the freeform stack 7820 // is visible but also when we are resizing for the transitions when docked stack 7821 // visibility changes. 7822 mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing; 7823 final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard; 7824 7825 // apply translucent bar vis flags 7826 WindowState fullscreenTransWin = isStatusBarKeyguard() && !mKeyguardOccluded 7827 ? mStatusBar 7828 : mTopFullscreenOpaqueWindowState; 7829 vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7830 vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7831 final int dockedVis = mStatusBarController.applyTranslucentFlagLw( 7832 mTopDockedOpaqueWindowState, 0, 0); 7833 7834 final boolean fullscreenDrawsStatusBarBackground = 7835 (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState) 7836 && (vis & View.STATUS_BAR_TRANSLUCENT) == 0) 7837 || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState); 7838 final boolean dockedDrawsStatusBarBackground = 7839 (drawsSystemBarBackground(mTopDockedOpaqueWindowState) 7840 && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0) 7841 || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState); 7842 7843 // prevent status bar interaction from clearing certain flags 7844 int type = win.getAttrs().type; 7845 boolean statusBarHasFocus = type == TYPE_STATUS_BAR; 7846 if (statusBarHasFocus && !isStatusBarKeyguard()) { 7847 int flags = View.SYSTEM_UI_FLAG_FULLSCREEN 7848 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 7849 | View.SYSTEM_UI_FLAG_IMMERSIVE 7850 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 7851 | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7852 if (mKeyguardOccluded) { 7853 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT; 7854 } 7855 vis = (vis & ~flags) | (oldVis & flags); 7856 } 7857 7858 if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) { 7859 vis |= View.STATUS_BAR_TRANSPARENT; 7860 vis &= ~View.STATUS_BAR_TRANSLUCENT; 7861 } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar) 7862 || forceOpaqueStatusBar) { 7863 vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT); 7864 } 7865 7866 vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing); 7867 7868 // update status bar 7869 boolean immersiveSticky = 7870 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7871 final boolean hideStatusBarWM = 7872 mTopFullscreenOpaqueWindowState != null 7873 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null) 7874 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; 7875 final boolean hideStatusBarSysui = 7876 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 7877 final boolean hideNavBarSysui = 7878 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0; 7879 7880 final boolean transientStatusBarAllowed = mStatusBar != null 7881 && (statusBarHasFocus || (!mForceShowSystemBars 7882 && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky)))); 7883 7884 final boolean transientNavBarAllowed = mNavigationBar != null 7885 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky; 7886 7887 final long now = SystemClock.uptimeMillis(); 7888 final boolean pendingPanic = mPendingPanicGestureUptime != 0 7889 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION; 7890 if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) { 7891 // The user performed the panic gesture recently, we're about to hide the bars, 7892 // we're no longer on the Keyguard and the screen is ready. We can now request the bars. 7893 mPendingPanicGestureUptime = 0; 7894 mStatusBarController.showTransient(); 7895 if (!isNavBarEmpty(vis)) { 7896 mNavigationBarController.showTransient(); 7897 } 7898 } 7899 7900 final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested() 7901 && !transientStatusBarAllowed && hideStatusBarSysui; 7902 final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested() 7903 && !transientNavBarAllowed; 7904 if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) { 7905 // clear the clearable flags instead 7906 clearClearableFlagsLw(); 7907 vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS; 7908 } 7909 7910 final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; 7911 immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7912 final boolean navAllowedHidden = immersive || immersiveSticky; 7913 7914 if (hideNavBarSysui && !navAllowedHidden 7915 && getWindowLayerLw(win) > getWindowLayerFromTypeLw(TYPE_INPUT_CONSUMER)) { 7916 // We can't hide the navbar from this window otherwise the input consumer would not get 7917 // the input events. 7918 vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); 7919 } 7920 7921 vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis); 7922 7923 // update navigation bar 7924 boolean oldImmersiveMode = isImmersiveMode(oldVis); 7925 boolean newImmersiveMode = isImmersiveMode(vis); 7926 if (win != null && oldImmersiveMode != newImmersiveMode) { 7927 final String pkg = win.getOwningPackage(); 7928 mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode, 7929 isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility())); 7930 } 7931 7932 vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis); 7933 7934 vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState, 7935 mTopFullscreenOpaqueOrDimmingWindowState); 7936 7937 return vis; 7938 } 7939 7940 /** 7941 * @return the current visibility flags with the nav-bar opacity related flags toggled based 7942 * on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}. 7943 */ 7944 private int configureNavBarOpacity(int visibility, boolean dockedStackVisible, 7945 boolean freeformStackVisible, boolean isDockedDividerResizing) { 7946 if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) { 7947 if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) { 7948 visibility = setNavBarOpaqueFlag(visibility); 7949 } 7950 } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) { 7951 if (isDockedDividerResizing) { 7952 visibility = setNavBarOpaqueFlag(visibility); 7953 } else if (freeformStackVisible) { 7954 visibility = setNavBarTranslucentFlag(visibility); 7955 } else { 7956 visibility = setNavBarOpaqueFlag(visibility); 7957 } 7958 } 7959 7960 if (!areTranslucentBarsAllowed()) { 7961 visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT; 7962 } 7963 return visibility; 7964 } 7965 7966 private int setNavBarOpaqueFlag(int visibility) { 7967 return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT); 7968 } 7969 7970 private int setNavBarTranslucentFlag(int visibility) { 7971 visibility &= ~View.NAVIGATION_BAR_TRANSPARENT; 7972 return visibility |= View.NAVIGATION_BAR_TRANSLUCENT; 7973 } 7974 7975 private void clearClearableFlagsLw() { 7976 int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS; 7977 if (newVal != mResettingSystemUiFlags) { 7978 mResettingSystemUiFlags = newVal; 7979 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 7980 } 7981 } 7982 7983 private boolean isImmersiveMode(int vis) { 7984 final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; 7985 return mNavigationBar != null 7986 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0 7987 && (vis & flags) != 0 7988 && canHideNavigationBar(); 7989 } 7990 7991 private static boolean isNavBarEmpty(int systemUiFlags) { 7992 final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME 7993 | View.STATUS_BAR_DISABLE_BACK 7994 | View.STATUS_BAR_DISABLE_RECENT); 7995 7996 return (systemUiFlags & disableNavigationBar) == disableNavigationBar; 7997 } 7998 7999 /** 8000 * @return whether the navigation or status bar can be made translucent 8001 * 8002 * This should return true unless touch exploration is not enabled or 8003 * R.boolean.config_enableTranslucentDecor is false. 8004 */ 8005 private boolean areTranslucentBarsAllowed() { 8006 return mTranslucentDecorEnabled; 8007 } 8008 8009 // Use this instead of checking config_showNavigationBar so that it can be consistently 8010 // overridden by qemu.hw.mainkeys in the emulator. 8011 @Override 8012 public boolean hasNavigationBar() { 8013 return mHasNavigationBar; 8014 } 8015 8016 @Override 8017 public void setLastInputMethodWindowLw(WindowState ime, WindowState target) { 8018 mLastInputMethodWindow = ime; 8019 mLastInputMethodTargetWindow = target; 8020 } 8021 8022 @Override 8023 public void setDismissImeOnBackKeyPressed(boolean newValue) { 8024 mDismissImeOnBackKeyPressed = newValue; 8025 } 8026 8027 @Override 8028 public int getInputMethodWindowVisibleHeightLw() { 8029 return mDockBottom - mCurBottom; 8030 } 8031 8032 @Override 8033 public void setCurrentUserLw(int newUserId) { 8034 mCurrentUserId = newUserId; 8035 if (mKeyguardDelegate != null) { 8036 mKeyguardDelegate.setCurrentUser(newUserId); 8037 } 8038 if (mAccessibilityShortcutController != null) { 8039 mAccessibilityShortcutController.setCurrentUser(newUserId); 8040 } 8041 StatusBarManagerInternal statusBar = getStatusBarManagerInternal(); 8042 if (statusBar != null) { 8043 statusBar.setCurrentUser(newUserId); 8044 } 8045 setLastInputMethodWindowLw(null, null); 8046 } 8047 8048 @Override 8049 public void setSwitchingUser(boolean switching) { 8050 mKeyguardDelegate.setSwitchingUser(switching); 8051 } 8052 8053 @Override 8054 public boolean canMagnifyWindow(int windowType) { 8055 switch (windowType) { 8056 case WindowManager.LayoutParams.TYPE_INPUT_METHOD: 8057 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: 8058 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR: 8059 case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: { 8060 return false; 8061 } 8062 } 8063 return true; 8064 } 8065 8066 @Override 8067 public boolean isTopLevelWindow(int windowType) { 8068 if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW 8069 && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 8070 return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG); 8071 } 8072 return true; 8073 } 8074 8075 @Override 8076 public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) { 8077 // For the upside down rotation we don't rotate seamlessly as the navigation 8078 // bar moves position. 8079 // Note most apps (using orientation:sensor or user as opposed to fullSensor) 8080 // will not enter the reverse portrait orientation, so actually the 8081 // orientation won't change at all. 8082 if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) { 8083 return false; 8084 } 8085 // If the navigation bar can't change sides, then it will 8086 // jump when we change orientations and we don't rotate 8087 // seamlessly. 8088 if (!mNavigationBarCanMove) { 8089 return false; 8090 } 8091 int delta = newRotation - oldRotation; 8092 if (delta < 0) delta += 4; 8093 // Likewise we don't rotate seamlessly for 180 degree rotations 8094 // in this case the surfaces never resize, and our logic to 8095 // revert the transformations on size change will fail. We could 8096 // fix this in the future with the "tagged" frames idea. 8097 if (delta == Surface.ROTATION_180) { 8098 return false; 8099 } 8100 8101 final WindowState w = mTopFullscreenOpaqueWindowState; 8102 if (w != mFocusedWindow) { 8103 return false; 8104 } 8105 8106 // We only enable seamless rotation if the top window has requested 8107 // it and is in the fullscreen opaque state. Seamless rotation 8108 // requires freezing various Surface states and won't work well 8109 // with animations, so we disable it in the animation case for now. 8110 if (w != null && !w.isAnimatingLw() && 8111 ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) || 8112 (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) { 8113 return true; 8114 } 8115 return false; 8116 } 8117 8118 @Override 8119 public void dump(String prefix, PrintWriter pw, String[] args) { 8120 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode); 8121 pw.print(" mSystemReady="); pw.print(mSystemReady); 8122 pw.print(" mSystemBooted="); pw.println(mSystemBooted); 8123 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState); 8124 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation); 8125 pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState); 8126 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged); 8127 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0 8128 || mForceClearedSystemUiFlags != 0) { 8129 pw.print(prefix); pw.print("mLastSystemUiFlags=0x"); 8130 pw.print(Integer.toHexString(mLastSystemUiFlags)); 8131 pw.print(" mResettingSystemUiFlags=0x"); 8132 pw.print(Integer.toHexString(mResettingSystemUiFlags)); 8133 pw.print(" mForceClearedSystemUiFlags=0x"); 8134 pw.println(Integer.toHexString(mForceClearedSystemUiFlags)); 8135 } 8136 if (mLastFocusNeedsMenu) { 8137 pw.print(prefix); pw.print("mLastFocusNeedsMenu="); 8138 pw.println(mLastFocusNeedsMenu); 8139 } 8140 pw.print(prefix); pw.print("mWakeGestureEnabledSetting="); 8141 pw.println(mWakeGestureEnabledSetting); 8142 8143 pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation); 8144 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode); 8145 pw.print(" mDockMode="); pw.print(mDockMode); 8146 pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture); 8147 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation); 8148 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation); 8149 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode); 8150 pw.print(" mUserRotation="); pw.print(mUserRotation); 8151 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations); 8152 pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation); 8153 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer="); 8154 pw.print(mCarDockEnablesAccelerometer); 8155 pw.print(" mDeskDockEnablesAccelerometer="); 8156 pw.println(mDeskDockEnablesAccelerometer); 8157 pw.print(prefix); pw.print("mLidKeyboardAccessibility="); 8158 pw.print(mLidKeyboardAccessibility); 8159 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility); 8160 pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock); 8161 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep); 8162 pw.print(prefix); 8163 pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior); 8164 pw.print(prefix); 8165 pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior); 8166 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior); 8167 pw.print(prefix); 8168 pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior); 8169 pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior); 8170 pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput); 8171 pw.print(prefix); pw.print("mAwake="); pw.println(mAwake); 8172 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly); 8173 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully); 8174 pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete); 8175 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete); 8176 pw.print(prefix); pw.print("mOrientationSensorEnabled="); 8177 pw.println(mOrientationSensorEnabled); 8178 pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft); 8179 pw.print(","); pw.print(mOverscanScreenTop); 8180 pw.print(") "); pw.print(mOverscanScreenWidth); 8181 pw.print("x"); pw.println(mOverscanScreenHeight); 8182 if (mOverscanLeft != 0 || mOverscanTop != 0 8183 || mOverscanRight != 0 || mOverscanBottom != 0) { 8184 pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft); 8185 pw.print(" top="); pw.print(mOverscanTop); 8186 pw.print(" right="); pw.print(mOverscanRight); 8187 pw.print(" bottom="); pw.println(mOverscanBottom); 8188 } 8189 pw.print(prefix); pw.print("mRestrictedOverscanScreen=("); 8190 pw.print(mRestrictedOverscanScreenLeft); 8191 pw.print(","); pw.print(mRestrictedOverscanScreenTop); 8192 pw.print(") "); pw.print(mRestrictedOverscanScreenWidth); 8193 pw.print("x"); pw.println(mRestrictedOverscanScreenHeight); 8194 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft); 8195 pw.print(","); pw.print(mUnrestrictedScreenTop); 8196 pw.print(") "); pw.print(mUnrestrictedScreenWidth); 8197 pw.print("x"); pw.println(mUnrestrictedScreenHeight); 8198 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft); 8199 pw.print(","); pw.print(mRestrictedScreenTop); 8200 pw.print(") "); pw.print(mRestrictedScreenWidth); 8201 pw.print("x"); pw.println(mRestrictedScreenHeight); 8202 pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft); 8203 pw.print(","); pw.print(mStableFullscreenTop); 8204 pw.print(")-("); pw.print(mStableFullscreenRight); 8205 pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")"); 8206 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft); 8207 pw.print(","); pw.print(mStableTop); 8208 pw.print(")-("); pw.print(mStableRight); 8209 pw.print(","); pw.print(mStableBottom); pw.println(")"); 8210 pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft); 8211 pw.print(","); pw.print(mSystemTop); 8212 pw.print(")-("); pw.print(mSystemRight); 8213 pw.print(","); pw.print(mSystemBottom); pw.println(")"); 8214 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft); 8215 pw.print(","); pw.print(mCurTop); 8216 pw.print(")-("); pw.print(mCurRight); 8217 pw.print(","); pw.print(mCurBottom); pw.println(")"); 8218 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft); 8219 pw.print(","); pw.print(mContentTop); 8220 pw.print(")-("); pw.print(mContentRight); 8221 pw.print(","); pw.print(mContentBottom); pw.println(")"); 8222 pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft); 8223 pw.print(","); pw.print(mVoiceContentTop); 8224 pw.print(")-("); pw.print(mVoiceContentRight); 8225 pw.print(","); pw.print(mVoiceContentBottom); pw.println(")"); 8226 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft); 8227 pw.print(","); pw.print(mDockTop); 8228 pw.print(")-("); pw.print(mDockRight); 8229 pw.print(","); pw.print(mDockBottom); pw.println(")"); 8230 pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer); 8231 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer); 8232 pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream); 8233 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen); 8234 pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken); 8235 if (mLastInputMethodWindow != null) { 8236 pw.print(prefix); pw.print("mLastInputMethodWindow="); 8237 pw.println(mLastInputMethodWindow); 8238 } 8239 if (mLastInputMethodTargetWindow != null) { 8240 pw.print(prefix); pw.print("mLastInputMethodTargetWindow="); 8241 pw.println(mLastInputMethodTargetWindow); 8242 } 8243 pw.print(prefix); pw.print("mDismissImeOnBackKeyPressed="); 8244 pw.println(mDismissImeOnBackKeyPressed); 8245 if (mStatusBar != null) { 8246 pw.print(prefix); pw.print("mStatusBar="); 8247 pw.print(mStatusBar); pw.print(" isStatusBarKeyguard="); 8248 pw.println(isStatusBarKeyguard()); 8249 } 8250 if (mNavigationBar != null) { 8251 pw.print(prefix); pw.print("mNavigationBar="); 8252 pw.println(mNavigationBar); 8253 } 8254 if (mFocusedWindow != null) { 8255 pw.print(prefix); pw.print("mFocusedWindow="); 8256 pw.println(mFocusedWindow); 8257 } 8258 if (mFocusedApp != null) { 8259 pw.print(prefix); pw.print("mFocusedApp="); 8260 pw.println(mFocusedApp); 8261 } 8262 if (mTopFullscreenOpaqueWindowState != null) { 8263 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState="); 8264 pw.println(mTopFullscreenOpaqueWindowState); 8265 } 8266 if (mTopFullscreenOpaqueOrDimmingWindowState != null) { 8267 pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState="); 8268 pw.println(mTopFullscreenOpaqueOrDimmingWindowState); 8269 } 8270 if (mForcingShowNavBar) { 8271 pw.print(prefix); pw.print("mForcingShowNavBar="); 8272 pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer="); 8273 pw.println(mForcingShowNavBarLayer); 8274 } 8275 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen); 8276 pw.print(" mKeyguardOccluded="); pw.println(mKeyguardOccluded); 8277 pw.print(" mKeyguardOccludedChanged="); pw.println(mKeyguardOccludedChanged); 8278 pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded); 8279 pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar); 8280 pw.print(" mForceStatusBarFromKeyguard="); 8281 pw.println(mForceStatusBarFromKeyguard); 8282 pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed); 8283 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn); 8284 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout); 8285 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive); 8286 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior); 8287 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior); 8288 pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior); 8289 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior); 8290 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation); 8291 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation); 8292 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation); 8293 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation); 8294 pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation); 8295 pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock); 8296 pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation); 8297 if (mHasFeatureLeanback) { 8298 pw.print(prefix); 8299 pw.print("mAccessibilityTvKey1Pressed="); pw.println(mAccessibilityTvKey1Pressed); 8300 pw.print(prefix); 8301 pw.print("mAccessibilityTvKey2Pressed="); pw.println(mAccessibilityTvKey2Pressed); 8302 pw.print(prefix); 8303 pw.print("mAccessibilityTvScheduled="); pw.println(mAccessibilityTvScheduled); 8304 } 8305 8306 mGlobalKeyManager.dump(prefix, pw); 8307 mStatusBarController.dump(pw, prefix); 8308 mNavigationBarController.dump(pw, prefix); 8309 PolicyControl.dump(prefix, pw); 8310 8311 if (mWakeGestureListener != null) { 8312 mWakeGestureListener.dump(pw, prefix); 8313 } 8314 if (mOrientationListener != null) { 8315 mOrientationListener.dump(pw, prefix); 8316 } 8317 if (mBurnInProtectionHelper != null) { 8318 mBurnInProtectionHelper.dump(prefix, pw); 8319 } 8320 if (mKeyguardDelegate != null) { 8321 mKeyguardDelegate.dump(prefix, pw); 8322 } 8323 } 8324} 8325