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