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