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