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