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