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