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