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