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