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