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