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