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