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