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