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