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