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