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