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