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