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