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