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