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