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