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