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