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