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