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