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