PhoneWindowManager.java revision fb1bf69d5d7fc8c45e3ddbb8916e21ae57432ff1
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 } 3567 3568 // Toggle Caps Lock on META-ALT. 3569 boolean actionTriggered = false; 3570 if (KeyEvent.isModifierKey(keyCode)) { 3571 if (!mPendingCapsLockToggle) { 3572 // Start tracking meta state for combo. 3573 mInitialMetaState = mMetaState; 3574 mPendingCapsLockToggle = true; 3575 } else if (event.getAction() == KeyEvent.ACTION_UP) { 3576 int altOnMask = mMetaState & KeyEvent.META_ALT_MASK; 3577 int metaOnMask = mMetaState & KeyEvent.META_META_MASK; 3578 3579 // Check for Caps Lock toggle 3580 if ((metaOnMask != 0) && (altOnMask != 0)) { 3581 // Check if nothing else is pressed 3582 if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) { 3583 // Handle Caps Lock Toggle 3584 mInputManagerInternal.toggleCapsLock(event.getDeviceId()); 3585 actionTriggered = true; 3586 } 3587 } 3588 3589 // Always stop tracking when key goes up. 3590 mPendingCapsLockToggle = false; 3591 } 3592 } 3593 // Store current meta state to be able to evaluate it later. 3594 mMetaState = metaState; 3595 3596 if (actionTriggered) { 3597 return -1; 3598 } 3599 3600 if (KeyEvent.isMetaKey(keyCode)) { 3601 if (down) { 3602 mPendingMetaAction = true; 3603 } else if (mPendingMetaAction) { 3604 launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId()); 3605 } 3606 return -1; 3607 } 3608 3609 // Shortcuts are invoked through Search+key, so intercept those here 3610 // Any printing key that is chorded with Search should be consumed 3611 // even if no shortcut was invoked. This prevents text from being 3612 // inadvertently inserted when using a keyboard that has built-in macro 3613 // shortcut keys (that emit Search+x) and some of them are not registered. 3614 if (mSearchKeyShortcutPending) { 3615 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 3616 if (kcm.isPrintingKey(keyCode)) { 3617 mConsumeSearchKeyUp = true; 3618 mSearchKeyShortcutPending = false; 3619 if (down && repeatCount == 0 && !keyguardOn) { 3620 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState); 3621 if (shortcutIntent != null) { 3622 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3623 try { 3624 startActivityAsUser(shortcutIntent, UserHandle.CURRENT); 3625 dismissKeyboardShortcutsMenu(); 3626 } catch (ActivityNotFoundException ex) { 3627 Slog.w(TAG, "Dropping shortcut key combination because " 3628 + "the activity to which it is registered was not found: " 3629 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex); 3630 } 3631 } else { 3632 Slog.i(TAG, "Dropping unregistered shortcut key combination: " 3633 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode)); 3634 } 3635 } 3636 return -1; 3637 } 3638 } 3639 3640 // Invoke shortcuts using Meta. 3641 if (down && repeatCount == 0 && !keyguardOn 3642 && (metaState & KeyEvent.META_META_ON) != 0) { 3643 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 3644 if (kcm.isPrintingKey(keyCode)) { 3645 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, 3646 metaState & ~(KeyEvent.META_META_ON 3647 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON)); 3648 if (shortcutIntent != null) { 3649 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3650 try { 3651 startActivityAsUser(shortcutIntent, UserHandle.CURRENT); 3652 dismissKeyboardShortcutsMenu(); 3653 } catch (ActivityNotFoundException ex) { 3654 Slog.w(TAG, "Dropping shortcut key combination because " 3655 + "the activity to which it is registered was not found: " 3656 + "META+" + KeyEvent.keyCodeToString(keyCode), ex); 3657 } 3658 return -1; 3659 } 3660 } 3661 } 3662 3663 // Handle application launch keys. 3664 if (down && repeatCount == 0 && !keyguardOn) { 3665 String category = sApplicationLaunchKeyCategories.get(keyCode); 3666 if (category != null) { 3667 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category); 3668 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3669 try { 3670 startActivityAsUser(intent, UserHandle.CURRENT); 3671 dismissKeyboardShortcutsMenu(); 3672 } catch (ActivityNotFoundException ex) { 3673 Slog.w(TAG, "Dropping application launch key because " 3674 + "the activity to which it is registered was not found: " 3675 + "keyCode=" + keyCode + ", category=" + category, ex); 3676 } 3677 return -1; 3678 } 3679 } 3680 3681 // Display task switcher for ALT-TAB. 3682 if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) { 3683 if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) { 3684 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK; 3685 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) { 3686 mRecentAppsHeldModifiers = shiftlessModifiers; 3687 showRecentApps(true, false); 3688 return -1; 3689 } 3690 } 3691 } else if (!down && mRecentAppsHeldModifiers != 0 3692 && (metaState & mRecentAppsHeldModifiers) == 0) { 3693 mRecentAppsHeldModifiers = 0; 3694 hideRecentApps(true, false); 3695 } 3696 3697 // Handle input method switching. 3698 if (down && repeatCount == 0 3699 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH 3700 || (keyCode == KeyEvent.KEYCODE_SPACE 3701 && (metaState & KeyEvent.META_META_MASK) != 0))) { 3702 final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0; 3703 mWindowManagerFuncs.switchInputMethod(forwardDirection); 3704 return -1; 3705 } 3706 if (mLanguageSwitchKeyPressed && !down 3707 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH 3708 || keyCode == KeyEvent.KEYCODE_SPACE)) { 3709 mLanguageSwitchKeyPressed = false; 3710 return -1; 3711 } 3712 3713 if (isValidGlobalKey(keyCode) 3714 && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) { 3715 return -1; 3716 } 3717 3718 if (down) { 3719 long shortcutCode = keyCode; 3720 if (event.isCtrlPressed()) { 3721 shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE; 3722 } 3723 3724 if (event.isAltPressed()) { 3725 shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE; 3726 } 3727 3728 if (event.isShiftPressed()) { 3729 shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE; 3730 } 3731 3732 if (event.isMetaPressed()) { 3733 shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE; 3734 } 3735 3736 IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode); 3737 if (shortcutService != null) { 3738 try { 3739 if (isUserSetupComplete()) { 3740 shortcutService.notifyShortcutKeyPressed(shortcutCode); 3741 } 3742 } catch (RemoteException e) { 3743 mShortcutKeyServices.delete(shortcutCode); 3744 } 3745 return -1; 3746 } 3747 } 3748 3749 // Reserve all the META modifier combos for system behavior 3750 if ((metaState & KeyEvent.META_META_ON) != 0) { 3751 return -1; 3752 } 3753 3754 // Let the application handle the key. 3755 return 0; 3756 } 3757 3758 /** {@inheritDoc} */ 3759 @Override 3760 public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) { 3761 // Note: This method is only called if the initial down was unhandled. 3762 if (DEBUG_INPUT) { 3763 Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction() 3764 + ", flags=" + event.getFlags() 3765 + ", keyCode=" + event.getKeyCode() 3766 + ", scanCode=" + event.getScanCode() 3767 + ", metaState=" + event.getMetaState() 3768 + ", repeatCount=" + event.getRepeatCount() 3769 + ", policyFlags=" + policyFlags); 3770 } 3771 3772 KeyEvent fallbackEvent = null; 3773 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 3774 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 3775 final int keyCode = event.getKeyCode(); 3776 final int metaState = event.getMetaState(); 3777 final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN 3778 && event.getRepeatCount() == 0; 3779 3780 // Check for fallback actions specified by the key character map. 3781 final FallbackAction fallbackAction; 3782 if (initialDown) { 3783 fallbackAction = kcm.getFallbackAction(keyCode, metaState); 3784 } else { 3785 fallbackAction = mFallbackActions.get(keyCode); 3786 } 3787 3788 if (fallbackAction != null) { 3789 if (DEBUG_INPUT) { 3790 Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode 3791 + " metaState=" + Integer.toHexString(fallbackAction.metaState)); 3792 } 3793 3794 final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK; 3795 fallbackEvent = KeyEvent.obtain( 3796 event.getDownTime(), event.getEventTime(), 3797 event.getAction(), fallbackAction.keyCode, 3798 event.getRepeatCount(), fallbackAction.metaState, 3799 event.getDeviceId(), event.getScanCode(), 3800 flags, event.getSource(), null); 3801 3802 if (!interceptFallback(win, fallbackEvent, policyFlags)) { 3803 fallbackEvent.recycle(); 3804 fallbackEvent = null; 3805 } 3806 3807 if (initialDown) { 3808 mFallbackActions.put(keyCode, fallbackAction); 3809 } else if (event.getAction() == KeyEvent.ACTION_UP) { 3810 mFallbackActions.remove(keyCode); 3811 fallbackAction.recycle(); 3812 } 3813 } 3814 } 3815 3816 if (DEBUG_INPUT) { 3817 if (fallbackEvent == null) { 3818 Slog.d(TAG, "No fallback."); 3819 } else { 3820 Slog.d(TAG, "Performing fallback: " + fallbackEvent); 3821 } 3822 } 3823 return fallbackEvent; 3824 } 3825 3826 private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) { 3827 int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags); 3828 if ((actions & ACTION_PASS_TO_USER) != 0) { 3829 long delayMillis = interceptKeyBeforeDispatching( 3830 win, fallbackEvent, policyFlags); 3831 if (delayMillis == 0) { 3832 return true; 3833 } 3834 } 3835 return false; 3836 } 3837 3838 @Override 3839 public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService) 3840 throws RemoteException { 3841 synchronized (mLock) { 3842 IShortcutService service = mShortcutKeyServices.get(shortcutCode); 3843 if (service != null && service.asBinder().pingBinder()) { 3844 throw new RemoteException("Key already exists."); 3845 } 3846 3847 mShortcutKeyServices.put(shortcutCode, shortcutService); 3848 } 3849 } 3850 3851 @Override 3852 public void onKeyguardOccludedChangedLw(boolean occluded) { 3853 if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) { 3854 mPendingKeyguardOccluded = occluded; 3855 mKeyguardOccludedChanged = true; 3856 } else { 3857 setKeyguardOccludedLw(occluded); 3858 } 3859 } 3860 3861 private int handleStartTransitionForKeyguardLw(int transit, @Nullable Animation anim) { 3862 if (mKeyguardOccludedChanged) { 3863 if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded=" 3864 + mPendingKeyguardOccluded); 3865 mKeyguardOccludedChanged = false; 3866 if (setKeyguardOccludedLw(mPendingKeyguardOccluded)) { 3867 return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER; 3868 } 3869 } 3870 if (AppTransition.isKeyguardGoingAwayTransit(transit)) { 3871 if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation"); 3872 final long startTime = anim != null 3873 ? SystemClock.uptimeMillis() + anim.getStartOffset() 3874 : SystemClock.uptimeMillis(); 3875 final long duration = anim != null 3876 ? anim.getDuration() 3877 : 0; 3878 startKeyguardExitAnimation(startTime, duration); 3879 } 3880 return 0; 3881 } 3882 3883 private void launchAssistLongPressAction() { 3884 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); 3885 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST); 3886 3887 // launch the search activity 3888 Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS); 3889 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3890 try { 3891 // TODO: This only stops the factory-installed search manager. 3892 // Need to formalize an API to handle others 3893 SearchManager searchManager = getSearchManager(); 3894 if (searchManager != null) { 3895 searchManager.stopSearch(); 3896 } 3897 startActivityAsUser(intent, UserHandle.CURRENT); 3898 } catch (ActivityNotFoundException e) { 3899 Slog.w(TAG, "No activity to handle assist long press action.", e); 3900 } 3901 } 3902 3903 private void launchAssistAction(String hint, int deviceId) { 3904 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST); 3905 if (!isUserSetupComplete()) { 3906 // Disable opening assist window during setup 3907 return; 3908 } 3909 Bundle args = null; 3910 if (deviceId > Integer.MIN_VALUE) { 3911 args = new Bundle(); 3912 args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId); 3913 } 3914 if ((mContext.getResources().getConfiguration().uiMode 3915 & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) { 3916 // On TV, use legacy handling until assistants are implemented in the proper way. 3917 ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE)) 3918 .launchLegacyAssist(hint, UserHandle.myUserId(), args); 3919 } else { 3920 if (hint != null) { 3921 if (args == null) { 3922 args = new Bundle(); 3923 } 3924 args.putBoolean(hint, true); 3925 } 3926 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3927 if (statusbar != null) { 3928 statusbar.startAssist(args); 3929 } 3930 } 3931 } 3932 3933 private void startActivityAsUser(Intent intent, UserHandle handle) { 3934 if (isUserSetupComplete()) { 3935 mContext.startActivityAsUser(intent, handle); 3936 } else { 3937 Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent); 3938 } 3939 } 3940 3941 private SearchManager getSearchManager() { 3942 if (mSearchManager == null) { 3943 mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); 3944 } 3945 return mSearchManager; 3946 } 3947 3948 private void preloadRecentApps() { 3949 mPreloadedRecentApps = true; 3950 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3951 if (statusbar != null) { 3952 statusbar.preloadRecentApps(); 3953 } 3954 } 3955 3956 private void cancelPreloadRecentApps() { 3957 if (mPreloadedRecentApps) { 3958 mPreloadedRecentApps = false; 3959 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3960 if (statusbar != null) { 3961 statusbar.cancelPreloadRecentApps(); 3962 } 3963 } 3964 } 3965 3966 private void toggleRecentApps() { 3967 mPreloadedRecentApps = false; // preloading no longer needs to be canceled 3968 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3969 if (statusbar != null) { 3970 statusbar.toggleRecentApps(); 3971 } 3972 } 3973 3974 @Override 3975 public void showRecentApps(boolean fromHome) { 3976 mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS); 3977 mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget(); 3978 } 3979 3980 private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) { 3981 mPreloadedRecentApps = false; // preloading no longer needs to be canceled 3982 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3983 if (statusbar != null) { 3984 statusbar.showRecentApps(triggeredFromAltTab, fromHome); 3985 } 3986 } 3987 3988 private void toggleKeyboardShortcutsMenu(int deviceId) { 3989 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3990 if (statusbar != null) { 3991 statusbar.toggleKeyboardShortcutsMenu(deviceId); 3992 } 3993 } 3994 3995 private void dismissKeyboardShortcutsMenu() { 3996 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3997 if (statusbar != null) { 3998 statusbar.dismissKeyboardShortcutsMenu(); 3999 } 4000 } 4001 4002 private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) { 4003 mPreloadedRecentApps = false; // preloading no longer needs to be canceled 4004 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 4005 if (statusbar != null) { 4006 statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome); 4007 } 4008 } 4009 4010 void launchHomeFromHotKey() { 4011 launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/); 4012 } 4013 4014 /** 4015 * A home key -> launch home action was detected. Take the appropriate action 4016 * given the situation with the keyguard. 4017 */ 4018 void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) { 4019 if (respectKeyguard) { 4020 if (isKeyguardShowingAndNotOccluded()) { 4021 // don't launch home if keyguard showing 4022 return; 4023 } 4024 4025 if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) { 4026 // when in keyguard restricted mode, must first verify unlock 4027 // before launching home 4028 mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() { 4029 @Override 4030 public void onKeyguardExitResult(boolean success) { 4031 if (success) { 4032 try { 4033 ActivityManager.getService().stopAppSwitches(); 4034 } catch (RemoteException e) { 4035 } 4036 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY); 4037 startDockOrHome(true /*fromHomeKey*/, awakenFromDreams); 4038 } 4039 } 4040 }); 4041 return; 4042 } 4043 } 4044 4045 // no keyguard stuff to worry about, just launch home! 4046 try { 4047 ActivityManager.getService().stopAppSwitches(); 4048 } catch (RemoteException e) { 4049 } 4050 if (mRecentsVisible) { 4051 // Hide Recents and notify it to launch Home 4052 if (awakenFromDreams) { 4053 awakenDreams(); 4054 } 4055 hideRecentApps(false, true); 4056 } else { 4057 // Otherwise, just launch Home 4058 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY); 4059 startDockOrHome(true /*fromHomeKey*/, awakenFromDreams); 4060 } 4061 } 4062 4063 private final Runnable mClearHideNavigationFlag = new Runnable() { 4064 @Override 4065 public void run() { 4066 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 4067 // Clear flags. 4068 mForceClearedSystemUiFlags &= 4069 ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; 4070 } 4071 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 4072 } 4073 }; 4074 4075 /** 4076 * Input handler used while nav bar is hidden. Captures any touch on the screen, 4077 * to determine when the nav bar should be shown and prevent applications from 4078 * receiving those touches. 4079 */ 4080 final class HideNavInputEventReceiver extends InputEventReceiver { 4081 public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) { 4082 super(inputChannel, looper); 4083 } 4084 4085 @Override 4086 public void onInputEvent(InputEvent event) { 4087 boolean handled = false; 4088 try { 4089 if (event instanceof MotionEvent 4090 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { 4091 final MotionEvent motionEvent = (MotionEvent)event; 4092 if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { 4093 // When the user taps down, we re-show the nav bar. 4094 boolean changed = false; 4095 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 4096 if (mInputConsumer == null) { 4097 return; 4098 } 4099 // Any user activity always causes us to show the 4100 // navigation controls, if they had been hidden. 4101 // We also clear the low profile and only content 4102 // flags so that tapping on the screen will atomically 4103 // restore all currently hidden screen decorations. 4104 int newVal = mResettingSystemUiFlags | 4105 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | 4106 View.SYSTEM_UI_FLAG_LOW_PROFILE | 4107 View.SYSTEM_UI_FLAG_FULLSCREEN; 4108 if (mResettingSystemUiFlags != newVal) { 4109 mResettingSystemUiFlags = newVal; 4110 changed = true; 4111 } 4112 // We don't allow the system's nav bar to be hidden 4113 // again for 1 second, to prevent applications from 4114 // spamming us and keeping it from being shown. 4115 newVal = mForceClearedSystemUiFlags | 4116 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; 4117 if (mForceClearedSystemUiFlags != newVal) { 4118 mForceClearedSystemUiFlags = newVal; 4119 changed = true; 4120 mHandler.postDelayed(mClearHideNavigationFlag, 1000); 4121 } 4122 } 4123 if (changed) { 4124 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 4125 } 4126 } 4127 } 4128 } finally { 4129 finishInputEvent(event, handled); 4130 } 4131 } 4132 } 4133 4134 @Override 4135 public void setRecentsVisibilityLw(boolean visible) { 4136 mRecentsVisible = visible; 4137 } 4138 4139 @Override 4140 public void setTvPipVisibilityLw(boolean visible) { 4141 mTvPictureInPictureVisible = visible; 4142 } 4143 4144 @Override 4145 public int adjustSystemUiVisibilityLw(int visibility) { 4146 mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility); 4147 mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility); 4148 4149 // Reset any bits in mForceClearingStatusBarVisibility that 4150 // are now clear. 4151 mResettingSystemUiFlags &= visibility; 4152 // Clear any bits in the new visibility that are currently being 4153 // force cleared, before reporting it. 4154 return visibility & ~mResettingSystemUiFlags 4155 & ~mForceClearedSystemUiFlags; 4156 } 4157 4158 @Override 4159 public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds, 4160 int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets, 4161 Rect outStableInsets, Rect outOutsets) { 4162 final int fl = PolicyControl.getWindowFlags(null, attrs); 4163 final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs); 4164 final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility); 4165 4166 final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl); 4167 if (useOutsets) { 4168 int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources()); 4169 if (outset > 0) { 4170 if (displayRotation == Surface.ROTATION_0) { 4171 outOutsets.bottom += outset; 4172 } else if (displayRotation == Surface.ROTATION_90) { 4173 outOutsets.right += outset; 4174 } else if (displayRotation == Surface.ROTATION_180) { 4175 outOutsets.top += outset; 4176 } else if (displayRotation == Surface.ROTATION_270) { 4177 outOutsets.left += outset; 4178 } 4179 } 4180 } 4181 4182 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) 4183 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { 4184 int availRight, availBottom; 4185 if (canHideNavigationBar() && 4186 (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) { 4187 availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4188 availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4189 } else { 4190 availRight = mRestrictedScreenLeft + mRestrictedScreenWidth; 4191 availBottom = mRestrictedScreenTop + mRestrictedScreenHeight; 4192 } 4193 if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) { 4194 if ((fl & FLAG_FULLSCREEN) != 0) { 4195 outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop, 4196 availRight - mStableFullscreenRight, 4197 availBottom - mStableFullscreenBottom); 4198 } else { 4199 outContentInsets.set(mStableLeft, mStableTop, 4200 availRight - mStableRight, availBottom - mStableBottom); 4201 } 4202 } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) { 4203 outContentInsets.setEmpty(); 4204 } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN 4205 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) { 4206 outContentInsets.set(mCurLeft, mCurTop, 4207 availRight - mCurRight, availBottom - mCurBottom); 4208 } else { 4209 outContentInsets.set(mCurLeft, mCurTop, 4210 availRight - mCurRight, availBottom - mCurBottom); 4211 } 4212 4213 outStableInsets.set(mStableLeft, mStableTop, 4214 availRight - mStableRight, availBottom - mStableBottom); 4215 if (taskBounds != null) { 4216 calculateRelevantTaskInsets(taskBounds, outContentInsets, 4217 displayWidth, displayHeight); 4218 calculateRelevantTaskInsets(taskBounds, outStableInsets, 4219 displayWidth, displayHeight); 4220 } 4221 return mForceShowSystemBars; 4222 } 4223 outContentInsets.setEmpty(); 4224 outStableInsets.setEmpty(); 4225 return mForceShowSystemBars; 4226 } 4227 4228 /** 4229 * For any given task bounds, the insets relevant for these bounds given the insets relevant 4230 * for the entire display. 4231 */ 4232 private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth, 4233 int displayHeight) { 4234 mTmpRect.set(0, 0, displayWidth, displayHeight); 4235 mTmpRect.inset(inOutInsets); 4236 mTmpRect.intersect(taskBounds); 4237 int leftInset = mTmpRect.left - taskBounds.left; 4238 int topInset = mTmpRect.top - taskBounds.top; 4239 int rightInset = taskBounds.right - mTmpRect.right; 4240 int bottomInset = taskBounds.bottom - mTmpRect.bottom; 4241 inOutInsets.set(leftInset, topInset, rightInset, bottomInset); 4242 } 4243 4244 private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) { 4245 return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN 4246 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0; 4247 } 4248 4249 /** {@inheritDoc} */ 4250 @Override 4251 public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight, 4252 int displayRotation, int uiMode) { 4253 mDisplayRotation = displayRotation; 4254 final int overscanLeft, overscanTop, overscanRight, overscanBottom; 4255 if (isDefaultDisplay) { 4256 switch (displayRotation) { 4257 case Surface.ROTATION_90: 4258 overscanLeft = mOverscanTop; 4259 overscanTop = mOverscanRight; 4260 overscanRight = mOverscanBottom; 4261 overscanBottom = mOverscanLeft; 4262 break; 4263 case Surface.ROTATION_180: 4264 overscanLeft = mOverscanRight; 4265 overscanTop = mOverscanBottom; 4266 overscanRight = mOverscanLeft; 4267 overscanBottom = mOverscanTop; 4268 break; 4269 case Surface.ROTATION_270: 4270 overscanLeft = mOverscanBottom; 4271 overscanTop = mOverscanLeft; 4272 overscanRight = mOverscanTop; 4273 overscanBottom = mOverscanRight; 4274 break; 4275 default: 4276 overscanLeft = mOverscanLeft; 4277 overscanTop = mOverscanTop; 4278 overscanRight = mOverscanRight; 4279 overscanBottom = mOverscanBottom; 4280 break; 4281 } 4282 } else { 4283 overscanLeft = 0; 4284 overscanTop = 0; 4285 overscanRight = 0; 4286 overscanBottom = 0; 4287 } 4288 mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0; 4289 mOverscanScreenTop = mRestrictedOverscanScreenTop = 0; 4290 mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth; 4291 mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight; 4292 mSystemLeft = 0; 4293 mSystemTop = 0; 4294 mSystemRight = displayWidth; 4295 mSystemBottom = displayHeight; 4296 mUnrestrictedScreenLeft = overscanLeft; 4297 mUnrestrictedScreenTop = overscanTop; 4298 mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight; 4299 mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom; 4300 mRestrictedScreenLeft = mUnrestrictedScreenLeft; 4301 mRestrictedScreenTop = mUnrestrictedScreenTop; 4302 mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth; 4303 mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight; 4304 mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft 4305 = mCurLeft = mUnrestrictedScreenLeft; 4306 mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop 4307 = mCurTop = mUnrestrictedScreenTop; 4308 mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight 4309 = mCurRight = displayWidth - overscanRight; 4310 mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom 4311 = mCurBottom = displayHeight - overscanBottom; 4312 mDockLayer = 0x10000000; 4313 mStatusBarLayer = -1; 4314 4315 // start with the current dock rect, which will be (0,0,displayWidth,displayHeight) 4316 final Rect pf = mTmpParentFrame; 4317 final Rect df = mTmpDisplayFrame; 4318 final Rect of = mTmpOverscanFrame; 4319 final Rect vf = mTmpVisibleFrame; 4320 final Rect dcf = mTmpDecorFrame; 4321 pf.left = df.left = of.left = vf.left = mDockLeft; 4322 pf.top = df.top = of.top = vf.top = mDockTop; 4323 pf.right = df.right = of.right = vf.right = mDockRight; 4324 pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom; 4325 dcf.setEmpty(); // Decor frame N/A for system bars. 4326 4327 if (isDefaultDisplay) { 4328 // For purposes of putting out fake window up to steal focus, we will 4329 // drive nav being hidden only by whether it is requested. 4330 final int sysui = mLastSystemUiFlags; 4331 boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0; 4332 boolean navTranslucent = (sysui 4333 & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0; 4334 boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; 4335 boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 4336 boolean navAllowedHidden = immersive || immersiveSticky; 4337 navTranslucent &= !immersiveSticky; // transient trumps translucent 4338 boolean isKeyguardShowing = isStatusBarKeyguard() && !mKeyguardOccluded; 4339 if (!isKeyguardShowing) { 4340 navTranslucent &= areTranslucentBarsAllowed(); 4341 } 4342 boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null 4343 && mStatusBar.getAttrs().height == MATCH_PARENT 4344 && mStatusBar.getAttrs().width == MATCH_PARENT; 4345 4346 // When the navigation bar isn't visible, we put up a fake 4347 // input window to catch all touch events. This way we can 4348 // detect when the user presses anywhere to bring back the nav 4349 // bar and ensure the application doesn't see the event. 4350 if (navVisible || navAllowedHidden) { 4351 if (mInputConsumer != null) { 4352 mHandler.sendMessage( 4353 mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer)); 4354 mInputConsumer = null; 4355 } 4356 } else if (mInputConsumer == null) { 4357 mInputConsumer = mWindowManagerFuncs.createInputConsumer(mHandler.getLooper(), 4358 INPUT_CONSUMER_NAVIGATION, 4359 (channel, looper) -> new HideNavInputEventReceiver(channel, looper)); 4360 } 4361 4362 // For purposes of positioning and showing the nav bar, if we have 4363 // decided that it can't be hidden (because of the screen aspect ratio), 4364 // then take that into account. 4365 navVisible |= !canHideNavigationBar(); 4366 4367 boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight, 4368 displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom, dcf, navVisible, navTranslucent, 4369 navAllowedHidden, statusBarExpandedNotKeyguard); 4370 if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)", 4371 mDockLeft, mDockTop, mDockRight, mDockBottom)); 4372 updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing); 4373 if (updateSysUiVisibility) { 4374 updateSystemUiVisibilityLw(); 4375 } 4376 } 4377 } 4378 4379 private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui, 4380 boolean isKeyguardShowing) { 4381 // decide where the status bar goes ahead of time 4382 if (mStatusBar != null) { 4383 // apply any navigation bar insets 4384 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4385 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4386 pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft; 4387 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight 4388 + mUnrestrictedScreenTop; 4389 vf.left = mStableLeft; 4390 vf.top = mStableTop; 4391 vf.right = mStableRight; 4392 vf.bottom = mStableBottom; 4393 4394 mStatusBarLayer = mStatusBar.getSurfaceLayer(); 4395 4396 // Let the status bar determine its size. 4397 mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */, 4398 vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */, 4399 dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */); 4400 4401 // For layout, the status bar is always at the top with our fixed height. 4402 mStableTop = mUnrestrictedScreenTop + mStatusBarHeight; 4403 4404 boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0; 4405 boolean statusBarTranslucent = (sysui 4406 & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0; 4407 if (!isKeyguardShowing) { 4408 statusBarTranslucent &= areTranslucentBarsAllowed(); 4409 } 4410 4411 // If the status bar is hidden, we don't want to cause 4412 // windows behind it to scroll. 4413 if (mStatusBar.isVisibleLw() && !statusBarTransient) { 4414 // Status bar may go away, so the screen area it occupies 4415 // is available to apps but just covering them when the 4416 // status bar is visible. 4417 mDockTop = mUnrestrictedScreenTop + mStatusBarHeight; 4418 4419 mContentTop = mVoiceContentTop = mCurTop = mDockTop; 4420 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom; 4421 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft; 4422 mContentRight = mVoiceContentRight = mCurRight = mDockRight; 4423 4424 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " + 4425 String.format( 4426 "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]", 4427 mDockLeft, mDockTop, mDockRight, mDockBottom, 4428 mContentLeft, mContentTop, mContentRight, mContentBottom, 4429 mCurLeft, mCurTop, mCurRight, mCurBottom)); 4430 } 4431 if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw() 4432 && !statusBarTransient && !statusBarTranslucent 4433 && !mStatusBarController.wasRecentlyTranslucent()) { 4434 // If the opaque status bar is currently requested to be visible, 4435 // and not in the process of animating on or off, then 4436 // we can tell the app that it is covered by it. 4437 mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight; 4438 } 4439 if (mStatusBarController.checkHiddenLw()) { 4440 return true; 4441 } 4442 } 4443 return false; 4444 } 4445 4446 private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation, 4447 int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf, 4448 boolean navVisible, boolean navTranslucent, boolean navAllowedHidden, 4449 boolean statusBarExpandedNotKeyguard) { 4450 if (mNavigationBar != null) { 4451 boolean transientNavBarShowing = mNavigationBarController.isTransientShowing(); 4452 // Force the navigation bar to its appropriate place and 4453 // size. We need to do this directly, instead of relying on 4454 // it to bubble up from the nav bar, because this needs to 4455 // change atomically with screen rotations. 4456 mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight, 4457 displayRotation); 4458 if (mNavigationBarPosition == NAV_BAR_BOTTOM) { 4459 // It's a system nav bar or a portrait screen; nav bar goes on bottom. 4460 int top = displayHeight - overscanBottom 4461 - getNavigationBarHeight(displayRotation, uiMode); 4462 mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom); 4463 mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top; 4464 if (transientNavBarShowing) { 4465 mNavigationBarController.setBarShowingLw(true); 4466 } else if (navVisible) { 4467 mNavigationBarController.setBarShowingLw(true); 4468 mDockBottom = mTmpNavigationFrame.top; 4469 mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop; 4470 mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop; 4471 } else { 4472 // We currently want to hide the navigation UI - unless we expanded the status 4473 // bar. 4474 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); 4475 } 4476 if (navVisible && !navTranslucent && !navAllowedHidden 4477 && !mNavigationBar.isAnimatingLw() 4478 && !mNavigationBarController.wasRecentlyTranslucent()) { 4479 // If the opaque nav bar is currently requested to be visible, 4480 // and not in the process of animating on or off, then 4481 // we can tell the app that it is covered by it. 4482 mSystemBottom = mTmpNavigationFrame.top; 4483 } 4484 } else if (mNavigationBarPosition == NAV_BAR_RIGHT) { 4485 // Landscape screen; nav bar goes to the right. 4486 int left = displayWidth - overscanRight 4487 - getNavigationBarWidth(displayRotation, uiMode); 4488 mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight); 4489 mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left; 4490 if (transientNavBarShowing) { 4491 mNavigationBarController.setBarShowingLw(true); 4492 } else if (navVisible) { 4493 mNavigationBarController.setBarShowingLw(true); 4494 mDockRight = mTmpNavigationFrame.left; 4495 mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft; 4496 mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft; 4497 } else { 4498 // We currently want to hide the navigation UI - unless we expanded the status 4499 // bar. 4500 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); 4501 } 4502 if (navVisible && !navTranslucent && !navAllowedHidden 4503 && !mNavigationBar.isAnimatingLw() 4504 && !mNavigationBarController.wasRecentlyTranslucent()) { 4505 // If the nav bar is currently requested to be visible, 4506 // and not in the process of animating on or off, then 4507 // we can tell the app that it is covered by it. 4508 mSystemRight = mTmpNavigationFrame.left; 4509 } 4510 } else if (mNavigationBarPosition == NAV_BAR_LEFT) { 4511 // Seascape screen; nav bar goes to the left. 4512 int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode); 4513 mTmpNavigationFrame.set(overscanLeft, 0, right, displayHeight); 4514 mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right; 4515 if (transientNavBarShowing) { 4516 mNavigationBarController.setBarShowingLw(true); 4517 } else if (navVisible) { 4518 mNavigationBarController.setBarShowingLw(true); 4519 mDockLeft = mTmpNavigationFrame.right; 4520 // TODO: not so sure about those: 4521 mRestrictedScreenLeft = mRestrictedOverscanScreenLeft = mDockLeft; 4522 mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft; 4523 mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft; 4524 } else { 4525 // We currently want to hide the navigation UI - unless we expanded the status 4526 // bar. 4527 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); 4528 } 4529 if (navVisible && !navTranslucent && !navAllowedHidden 4530 && !mNavigationBar.isAnimatingLw() 4531 && !mNavigationBarController.wasRecentlyTranslucent()) { 4532 // If the nav bar is currently requested to be visible, 4533 // and not in the process of animating on or off, then 4534 // we can tell the app that it is covered by it. 4535 mSystemLeft = mTmpNavigationFrame.right; 4536 } 4537 } 4538 // Make sure the content and current rectangles are updated to 4539 // account for the restrictions from the navigation bar. 4540 mContentTop = mVoiceContentTop = mCurTop = mDockTop; 4541 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom; 4542 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft; 4543 mContentRight = mVoiceContentRight = mCurRight = mDockRight; 4544 mStatusBarLayer = mNavigationBar.getSurfaceLayer(); 4545 // And compute the final frame. 4546 mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame, 4547 mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf, 4548 mTmpNavigationFrame, mTmpNavigationFrame); 4549 if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame); 4550 if (mNavigationBarController.checkHiddenLw()) { 4551 return true; 4552 } 4553 } 4554 return false; 4555 } 4556 4557 private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) { 4558 if (mNavigationBarCanMove && displayWidth > displayHeight) { 4559 if (displayRotation == Surface.ROTATION_270) { 4560 return NAV_BAR_LEFT; 4561 } else { 4562 return NAV_BAR_RIGHT; 4563 } 4564 } 4565 return NAV_BAR_BOTTOM; 4566 } 4567 4568 /** {@inheritDoc} */ 4569 @Override 4570 public int getSystemDecorLayerLw() { 4571 if (mStatusBar != null && mStatusBar.isVisibleLw()) { 4572 return mStatusBar.getSurfaceLayer(); 4573 } 4574 4575 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) { 4576 return mNavigationBar.getSurfaceLayer(); 4577 } 4578 4579 return 0; 4580 } 4581 4582 @Override 4583 public void getContentRectLw(Rect r) { 4584 r.set(mContentLeft, mContentTop, mContentRight, mContentBottom); 4585 } 4586 4587 void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached, 4588 boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) { 4589 if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) { 4590 // Here's a special case: if this attached window is a panel that is 4591 // above the dock window, and the window it is attached to is below 4592 // the dock window, then the frames we computed for the window it is 4593 // attached to can not be used because the dock is effectively part 4594 // of the underlying window and the attached window is floating on top 4595 // of the whole thing. So, we ignore the attached window and explicitly 4596 // compute the frames that would be appropriate without the dock. 4597 df.left = of.left = cf.left = vf.left = mDockLeft; 4598 df.top = of.top = cf.top = vf.top = mDockTop; 4599 df.right = of.right = cf.right = vf.right = mDockRight; 4600 df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom; 4601 } else { 4602 // The effective display frame of the attached window depends on 4603 // whether it is taking care of insetting its content. If not, 4604 // we need to use the parent's content frame so that the entire 4605 // window is positioned within that content. Otherwise we can use 4606 // the overscan frame and let the attached window take care of 4607 // positioning its content appropriately. 4608 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4609 // Set the content frame of the attached window to the parent's decor frame 4610 // (same as content frame when IME isn't present) if specifically requested by 4611 // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag. 4612 // Otherwise, use the overscan frame. 4613 cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0 4614 ? attached.getContentFrameLw() : attached.getOverscanFrameLw()); 4615 } else { 4616 // If the window is resizing, then we want to base the content 4617 // frame on our attached content frame to resize... however, 4618 // things can be tricky if the attached window is NOT in resize 4619 // mode, in which case its content frame will be larger. 4620 // Ungh. So to deal with that, make sure the content frame 4621 // we end up using is not covering the IM dock. 4622 cf.set(attached.getContentFrameLw()); 4623 if (attached.isVoiceInteraction()) { 4624 if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft; 4625 if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop; 4626 if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight; 4627 if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom; 4628 } else if (attached.getSurfaceLayer() < mDockLayer) { 4629 if (cf.left < mContentLeft) cf.left = mContentLeft; 4630 if (cf.top < mContentTop) cf.top = mContentTop; 4631 if (cf.right > mContentRight) cf.right = mContentRight; 4632 if (cf.bottom > mContentBottom) cf.bottom = mContentBottom; 4633 } 4634 } 4635 df.set(insetDecors ? attached.getDisplayFrameLw() : cf); 4636 of.set(insetDecors ? attached.getOverscanFrameLw() : cf); 4637 vf.set(attached.getVisibleFrameLw()); 4638 } 4639 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached 4640 // window should be positioned relative to its parent or the entire 4641 // screen. 4642 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 4643 ? attached.getFrameLw() : df); 4644 } 4645 4646 private void applyStableConstraints(int sysui, int fl, Rect r) { 4647 if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) { 4648 // If app is requesting a stable layout, don't let the 4649 // content insets go below the stable values. 4650 if ((fl & FLAG_FULLSCREEN) != 0) { 4651 if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft; 4652 if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop; 4653 if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight; 4654 if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom; 4655 } else { 4656 if (r.left < mStableLeft) r.left = mStableLeft; 4657 if (r.top < mStableTop) r.top = mStableTop; 4658 if (r.right > mStableRight) r.right = mStableRight; 4659 if (r.bottom > mStableBottom) r.bottom = mStableBottom; 4660 } 4661 } 4662 } 4663 4664 private boolean canReceiveInput(WindowState win) { 4665 boolean notFocusable = 4666 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0; 4667 boolean altFocusableIm = 4668 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0; 4669 boolean notFocusableForIm = notFocusable ^ altFocusableIm; 4670 return !notFocusableForIm; 4671 } 4672 4673 /** {@inheritDoc} */ 4674 @Override 4675 public void layoutWindowLw(WindowState win, WindowState attached) { 4676 // We've already done the navigation bar and status bar. If the status bar can receive 4677 // input, we need to layout it again to accomodate for the IME window. 4678 if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) { 4679 return; 4680 } 4681 final WindowManager.LayoutParams attrs = win.getAttrs(); 4682 final boolean isDefaultDisplay = win.isDefaultDisplay(); 4683 final boolean needsToOffsetInputMethodTarget = isDefaultDisplay && 4684 (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null); 4685 if (needsToOffsetInputMethodTarget) { 4686 if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state"); 4687 offsetInputMethodWindowLw(mLastInputMethodWindow); 4688 } 4689 4690 final int fl = PolicyControl.getWindowFlags(win, attrs); 4691 final int pfl = attrs.privateFlags; 4692 final int sim = attrs.softInputMode; 4693 final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null); 4694 4695 final Rect pf = mTmpParentFrame; 4696 final Rect df = mTmpDisplayFrame; 4697 final Rect of = mTmpOverscanFrame; 4698 final Rect cf = mTmpContentFrame; 4699 final Rect vf = mTmpVisibleFrame; 4700 final Rect dcf = mTmpDecorFrame; 4701 final Rect sf = mTmpStableFrame; 4702 Rect osf = null; 4703 dcf.setEmpty(); 4704 4705 final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar 4706 && mNavigationBar != null && mNavigationBar.isVisibleLw()); 4707 4708 final int adjust = sim & SOFT_INPUT_MASK_ADJUST; 4709 4710 if (isDefaultDisplay) { 4711 sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom); 4712 } else { 4713 sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom); 4714 } 4715 4716 if (!isDefaultDisplay) { 4717 if (attached != null) { 4718 // If this window is attached to another, our display 4719 // frame is the same as the one we are attached to. 4720 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf); 4721 } else { 4722 // Give the window full screen. 4723 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 4724 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 4725 pf.right = df.right = of.right = cf.right 4726 = mOverscanScreenLeft + mOverscanScreenWidth; 4727 pf.bottom = df.bottom = of.bottom = cf.bottom 4728 = mOverscanScreenTop + mOverscanScreenHeight; 4729 } 4730 } else if (attrs.type == TYPE_INPUT_METHOD) { 4731 pf.left = df.left = of.left = cf.left = vf.left = mDockLeft; 4732 pf.top = df.top = of.top = cf.top = vf.top = mDockTop; 4733 pf.right = df.right = of.right = cf.right = vf.right = mDockRight; 4734 // IM dock windows layout below the nav bar... 4735 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4736 // ...with content insets above the nav bar 4737 cf.bottom = vf.bottom = mStableBottom; 4738 if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) { 4739 // The status bar forces the navigation bar while it's visible. Make sure the IME 4740 // avoids the navigation bar in that case. 4741 if (mNavigationBarPosition == NAV_BAR_RIGHT) { 4742 pf.right = df.right = of.right = cf.right = vf.right = mStableRight; 4743 } else if (mNavigationBarPosition == NAV_BAR_LEFT) { 4744 pf.left = df.left = of.left = cf.left = vf.left = mStableLeft; 4745 } 4746 } 4747 // IM dock windows always go to the bottom of the screen. 4748 attrs.gravity = Gravity.BOTTOM; 4749 mDockLayer = win.getSurfaceLayer(); 4750 } else if (attrs.type == TYPE_VOICE_INTERACTION) { 4751 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4752 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4753 pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4754 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4755 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4756 cf.left = mDockLeft; 4757 cf.top = mDockTop; 4758 cf.right = mDockRight; 4759 cf.bottom = mDockBottom; 4760 } else { 4761 cf.left = mContentLeft; 4762 cf.top = mContentTop; 4763 cf.right = mContentRight; 4764 cf.bottom = mContentBottom; 4765 } 4766 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 4767 vf.left = mCurLeft; 4768 vf.top = mCurTop; 4769 vf.right = mCurRight; 4770 vf.bottom = mCurBottom; 4771 } else { 4772 vf.set(cf); 4773 } 4774 } else if (attrs.type == TYPE_WALLPAPER) { 4775 layoutWallpaper(win, pf, df, of, cf); 4776 } else if (win == mStatusBar) { 4777 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4778 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4779 pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft; 4780 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop; 4781 cf.left = vf.left = mStableLeft; 4782 cf.top = vf.top = mStableTop; 4783 cf.right = vf.right = mStableRight; 4784 vf.bottom = mStableBottom; 4785 4786 if (adjust == SOFT_INPUT_ADJUST_RESIZE) { 4787 cf.bottom = mContentBottom; 4788 } else { 4789 cf.bottom = mDockBottom; 4790 vf.bottom = mContentBottom; 4791 } 4792 } else { 4793 4794 // Default policy decor for the default display 4795 dcf.left = mSystemLeft; 4796 dcf.top = mSystemTop; 4797 dcf.right = mSystemRight; 4798 dcf.bottom = mSystemBottom; 4799 final boolean inheritTranslucentDecor = (attrs.privateFlags 4800 & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0; 4801 final boolean isAppWindow = 4802 attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW && 4803 attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; 4804 final boolean topAtRest = 4805 win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw(); 4806 if (isAppWindow && !inheritTranslucentDecor && !topAtRest) { 4807 if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0 4808 && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0 4809 && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0 4810 && (fl & WindowManager.LayoutParams. 4811 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0 4812 && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) { 4813 // Ensure policy decor includes status bar 4814 dcf.top = mStableTop; 4815 } 4816 if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0 4817 && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0 4818 && (fl & WindowManager.LayoutParams. 4819 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) { 4820 // Ensure policy decor includes navigation bar 4821 dcf.bottom = mStableBottom; 4822 dcf.right = mStableRight; 4823 } 4824 } 4825 4826 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) 4827 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { 4828 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() 4829 + "): IN_SCREEN, INSET_DECOR"); 4830 // This is the case for a normal activity window: we want it 4831 // to cover all of the screen space, and it can take care of 4832 // moving its contents to account for screen decorations that 4833 // intrude into that space. 4834 if (attached != null) { 4835 // If this window is attached to another, our display 4836 // frame is the same as the one we are attached to. 4837 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf); 4838 } else { 4839 if (attrs.type == TYPE_STATUS_BAR_PANEL 4840 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) { 4841 // Status bar panels are the only windows who can go on top of 4842 // the status bar. They are protected by the STATUS_BAR_SERVICE 4843 // permission, so they have the same privileges as the status 4844 // bar itself. 4845 // 4846 // However, they should still dodge the navigation bar if it exists. 4847 4848 pf.left = df.left = of.left = hasNavBar 4849 ? mDockLeft : mUnrestrictedScreenLeft; 4850 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4851 pf.right = df.right = of.right = hasNavBar 4852 ? mRestrictedScreenLeft+mRestrictedScreenWidth 4853 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4854 pf.bottom = df.bottom = of.bottom = hasNavBar 4855 ? mRestrictedScreenTop+mRestrictedScreenHeight 4856 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4857 4858 if (DEBUG_LAYOUT) Slog.v(TAG, String.format( 4859 "Laying out status bar window: (%d,%d - %d,%d)", 4860 pf.left, pf.top, pf.right, pf.bottom)); 4861 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0 4862 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 4863 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 4864 // Asking to layout into the overscan region, so give it that pure 4865 // unrestricted area. 4866 pf.left = df.left = of.left = mOverscanScreenLeft; 4867 pf.top = df.top = of.top = mOverscanScreenTop; 4868 pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth; 4869 pf.bottom = df.bottom = of.bottom = mOverscanScreenTop 4870 + mOverscanScreenHeight; 4871 } else if (canHideNavigationBar() 4872 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 4873 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 4874 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 4875 // Asking for layout as if the nav bar is hidden, lets the 4876 // application extend into the unrestricted overscan screen area. We 4877 // only do this for application windows to ensure no window that 4878 // can be above the nav bar can do this. 4879 pf.left = df.left = mOverscanScreenLeft; 4880 pf.top = df.top = mOverscanScreenTop; 4881 pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth; 4882 pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight; 4883 // We need to tell the app about where the frame inside the overscan 4884 // is, so it can inset its content by that amount -- it didn't ask 4885 // to actually extend itself into the overscan region. 4886 of.left = mUnrestrictedScreenLeft; 4887 of.top = mUnrestrictedScreenTop; 4888 of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4889 of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4890 } else { 4891 pf.left = df.left = mRestrictedOverscanScreenLeft; 4892 pf.top = df.top = mRestrictedOverscanScreenTop; 4893 pf.right = df.right = mRestrictedOverscanScreenLeft 4894 + mRestrictedOverscanScreenWidth; 4895 pf.bottom = df.bottom = mRestrictedOverscanScreenTop 4896 + mRestrictedOverscanScreenHeight; 4897 // We need to tell the app about where the frame inside the overscan 4898 // is, so it can inset its content by that amount -- it didn't ask 4899 // to actually extend itself into the overscan region. 4900 of.left = mUnrestrictedScreenLeft; 4901 of.top = mUnrestrictedScreenTop; 4902 of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4903 of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4904 } 4905 4906 if ((fl & FLAG_FULLSCREEN) == 0) { 4907 if (win.isVoiceInteraction()) { 4908 cf.left = mVoiceContentLeft; 4909 cf.top = mVoiceContentTop; 4910 cf.right = mVoiceContentRight; 4911 cf.bottom = mVoiceContentBottom; 4912 } else { 4913 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4914 cf.left = mDockLeft; 4915 cf.top = mDockTop; 4916 cf.right = mDockRight; 4917 cf.bottom = mDockBottom; 4918 } else { 4919 cf.left = mContentLeft; 4920 cf.top = mContentTop; 4921 cf.right = mContentRight; 4922 cf.bottom = mContentBottom; 4923 } 4924 } 4925 } else { 4926 // Full screen windows are always given a layout that is as if the 4927 // status bar and other transient decors are gone. This is to avoid 4928 // bad states when moving from a window that is not hding the 4929 // status bar to one that is. 4930 cf.left = mRestrictedScreenLeft; 4931 cf.top = mRestrictedScreenTop; 4932 cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth; 4933 cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight; 4934 } 4935 applyStableConstraints(sysUiFl, fl, cf); 4936 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 4937 vf.left = mCurLeft; 4938 vf.top = mCurTop; 4939 vf.right = mCurRight; 4940 vf.bottom = mCurBottom; 4941 } else { 4942 vf.set(cf); 4943 } 4944 } 4945 } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl 4946 & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 4947 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) { 4948 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + 4949 "): IN_SCREEN"); 4950 // A window that has requested to fill the entire screen just 4951 // gets everything, period. 4952 if (attrs.type == TYPE_STATUS_BAR_PANEL 4953 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL 4954 || attrs.type == TYPE_VOLUME_OVERLAY) { 4955 pf.left = df.left = of.left = cf.left = hasNavBar 4956 ? mDockLeft : mUnrestrictedScreenLeft; 4957 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop; 4958 pf.right = df.right = of.right = cf.right = hasNavBar 4959 ? mRestrictedScreenLeft+mRestrictedScreenWidth 4960 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4961 pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar 4962 ? mRestrictedScreenTop+mRestrictedScreenHeight 4963 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4964 if (DEBUG_LAYOUT) Slog.v(TAG, String.format( 4965 "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)", 4966 pf.left, pf.top, pf.right, pf.bottom)); 4967 } else if (attrs.type == TYPE_NAVIGATION_BAR 4968 || attrs.type == TYPE_NAVIGATION_BAR_PANEL) { 4969 // The navigation bar has Real Ultimate Power. 4970 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4971 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4972 pf.right = df.right = of.right = mUnrestrictedScreenLeft 4973 + mUnrestrictedScreenWidth; 4974 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop 4975 + mUnrestrictedScreenHeight; 4976 if (DEBUG_LAYOUT) Slog.v(TAG, String.format( 4977 "Laying out navigation bar window: (%d,%d - %d,%d)", 4978 pf.left, pf.top, pf.right, pf.bottom)); 4979 } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY 4980 || attrs.type == TYPE_BOOT_PROGRESS 4981 || attrs.type == TYPE_SCREENSHOT) 4982 && ((fl & FLAG_FULLSCREEN) != 0)) { 4983 // Fullscreen secure system overlays get what they ask for. Screenshot region 4984 // selection overlay should also expand to full screen. 4985 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 4986 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 4987 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft 4988 + mOverscanScreenWidth; 4989 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop 4990 + mOverscanScreenHeight; 4991 } else if (attrs.type == TYPE_BOOT_PROGRESS) { 4992 // Boot progress screen always covers entire display. 4993 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 4994 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 4995 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft 4996 + mOverscanScreenWidth; 4997 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop 4998 + mOverscanScreenHeight; 4999 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0 5000 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 5001 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 5002 // Asking to layout into the overscan region, so give it that pure 5003 // unrestricted area. 5004 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 5005 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 5006 pf.right = df.right = of.right = cf.right 5007 = mOverscanScreenLeft + mOverscanScreenWidth; 5008 pf.bottom = df.bottom = of.bottom = cf.bottom 5009 = mOverscanScreenTop + mOverscanScreenHeight; 5010 } else if (canHideNavigationBar() 5011 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 5012 && (attrs.type == TYPE_STATUS_BAR 5013 || attrs.type == TYPE_TOAST 5014 || attrs.type == TYPE_DOCK_DIVIDER 5015 || attrs.type == TYPE_VOICE_INTERACTION_STARTING 5016 || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 5017 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) { 5018 // Asking for layout as if the nav bar is hidden, lets the 5019 // application extend into the unrestricted screen area. We 5020 // only do this for application windows (or toasts) to ensure no window that 5021 // can be above the nav bar can do this. 5022 // XXX This assumes that an app asking for this will also 5023 // ask for layout in only content. We can't currently figure out 5024 // what the screen would be if only laying out to hide the nav bar. 5025 pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft; 5026 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop; 5027 pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft 5028 + mUnrestrictedScreenWidth; 5029 pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop 5030 + mUnrestrictedScreenHeight; 5031 } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) { 5032 pf.left = df.left = of.left = mRestrictedScreenLeft; 5033 pf.top = df.top = of.top = mRestrictedScreenTop; 5034 pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth; 5035 pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop 5036 + mRestrictedScreenHeight; 5037 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 5038 cf.left = mDockLeft; 5039 cf.top = mDockTop; 5040 cf.right = mDockRight; 5041 cf.bottom = mDockBottom; 5042 } else { 5043 cf.left = mContentLeft; 5044 cf.top = mContentTop; 5045 cf.right = mContentRight; 5046 cf.bottom = mContentBottom; 5047 } 5048 } else { 5049 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft; 5050 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop; 5051 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft 5052 + mRestrictedScreenWidth; 5053 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop 5054 + mRestrictedScreenHeight; 5055 } 5056 5057 applyStableConstraints(sysUiFl, fl, cf); 5058 5059 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 5060 vf.left = mCurLeft; 5061 vf.top = mCurTop; 5062 vf.right = mCurRight; 5063 vf.bottom = mCurBottom; 5064 } else { 5065 vf.set(cf); 5066 } 5067 } else if (attached != null) { 5068 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + 5069 "): attached to " + attached); 5070 // A child window should be placed inside of the same visible 5071 // frame that its parent had. 5072 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf); 5073 } else { 5074 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + 5075 "): normal window"); 5076 // Otherwise, a normal window must be placed inside the content 5077 // of all screen decorations. 5078 if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) { 5079 // Status bar panels and the volume dialog are the only windows who can go on 5080 // top of the status bar. They are protected by the STATUS_BAR_SERVICE 5081 // permission, so they have the same privileges as the status 5082 // bar itself. 5083 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft; 5084 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop; 5085 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft 5086 + mRestrictedScreenWidth; 5087 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop 5088 + mRestrictedScreenHeight; 5089 } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) { 5090 // These dialogs are stable to interim decor changes. 5091 pf.left = df.left = of.left = cf.left = mStableLeft; 5092 pf.top = df.top = of.top = cf.top = mStableTop; 5093 pf.right = df.right = of.right = cf.right = mStableRight; 5094 pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom; 5095 } else { 5096 pf.left = mContentLeft; 5097 pf.top = mContentTop; 5098 pf.right = mContentRight; 5099 pf.bottom = mContentBottom; 5100 if (win.isVoiceInteraction()) { 5101 df.left = of.left = cf.left = mVoiceContentLeft; 5102 df.top = of.top = cf.top = mVoiceContentTop; 5103 df.right = of.right = cf.right = mVoiceContentRight; 5104 df.bottom = of.bottom = cf.bottom = mVoiceContentBottom; 5105 } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 5106 df.left = of.left = cf.left = mDockLeft; 5107 df.top = of.top = cf.top = mDockTop; 5108 df.right = of.right = cf.right = mDockRight; 5109 df.bottom = of.bottom = cf.bottom = mDockBottom; 5110 } else { 5111 df.left = of.left = cf.left = mContentLeft; 5112 df.top = of.top = cf.top = mContentTop; 5113 df.right = of.right = cf.right = mContentRight; 5114 df.bottom = of.bottom = cf.bottom = mContentBottom; 5115 } 5116 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 5117 vf.left = mCurLeft; 5118 vf.top = mCurTop; 5119 vf.right = mCurRight; 5120 vf.bottom = mCurBottom; 5121 } else { 5122 vf.set(cf); 5123 } 5124 } 5125 } 5126 } 5127 5128 // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it. 5129 // Also, we don't allow windows in multi-window mode to extend out of the screen. 5130 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR 5131 && !win.isInMultiWindowMode()) { 5132 df.left = df.top = -10000; 5133 df.right = df.bottom = 10000; 5134 if (attrs.type != TYPE_WALLPAPER) { 5135 of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000; 5136 of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000; 5137 } 5138 } 5139 5140 // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we 5141 // need to provide information to the clients that want to pretend that you can draw there. 5142 // We only want to apply outsets to certain types of windows. For example, we never want to 5143 // apply the outsets to floating dialogs, because they wouldn't make sense there. 5144 final boolean useOutsets = shouldUseOutsets(attrs, fl); 5145 if (isDefaultDisplay && useOutsets) { 5146 osf = mTmpOutsetFrame; 5147 osf.set(cf.left, cf.top, cf.right, cf.bottom); 5148 int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources()); 5149 if (outset > 0) { 5150 int rotation = mDisplayRotation; 5151 if (rotation == Surface.ROTATION_0) { 5152 osf.bottom += outset; 5153 } else if (rotation == Surface.ROTATION_90) { 5154 osf.right += outset; 5155 } else if (rotation == Surface.ROTATION_180) { 5156 osf.top -= outset; 5157 } else if (rotation == Surface.ROTATION_270) { 5158 osf.left -= outset; 5159 } 5160 if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset 5161 + " with rotation " + rotation + ", result: " + osf); 5162 } 5163 } 5164 5165 if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle() 5166 + ": sim=#" + Integer.toHexString(sim) 5167 + " attach=" + attached + " type=" + attrs.type 5168 + String.format(" flags=0x%08x", fl) 5169 + " pf=" + pf.toShortString() + " df=" + df.toShortString() 5170 + " of=" + of.toShortString() 5171 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString() 5172 + " dcf=" + dcf.toShortString() 5173 + " sf=" + sf.toShortString() 5174 + " osf=" + (osf == null ? "null" : osf.toShortString())); 5175 5176 win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf); 5177 5178 // Dock windows carve out the bottom of the screen, so normal windows 5179 // can't appear underneath them. 5180 if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleLw() 5181 && !win.getGivenInsetsPendingLw()) { 5182 setLastInputMethodWindowLw(null, null); 5183 offsetInputMethodWindowLw(win); 5184 } 5185 if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleLw() 5186 && !win.getGivenInsetsPendingLw()) { 5187 offsetVoiceInputWindowLw(win); 5188 } 5189 } 5190 5191 private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) { 5192 5193 // The wallpaper also has Real Ultimate Power, but we want to tell 5194 // it about the overscan area. 5195 pf.left = df.left = mOverscanScreenLeft; 5196 pf.top = df.top = mOverscanScreenTop; 5197 pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth; 5198 pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight; 5199 of.left = cf.left = mUnrestrictedScreenLeft; 5200 of.top = cf.top = mUnrestrictedScreenTop; 5201 of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 5202 of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 5203 } 5204 5205 private void offsetInputMethodWindowLw(WindowState win) { 5206 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top); 5207 top += win.getGivenContentInsetsLw().top; 5208 if (mContentBottom > top) { 5209 mContentBottom = top; 5210 } 5211 if (mVoiceContentBottom > top) { 5212 mVoiceContentBottom = top; 5213 } 5214 top = win.getVisibleFrameLw().top; 5215 top += win.getGivenVisibleInsetsLw().top; 5216 if (mCurBottom > top) { 5217 mCurBottom = top; 5218 } 5219 if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom=" 5220 + mDockBottom + " mContentBottom=" 5221 + mContentBottom + " mCurBottom=" + mCurBottom); 5222 } 5223 5224 private void offsetVoiceInputWindowLw(WindowState win) { 5225 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top); 5226 top += win.getGivenContentInsetsLw().top; 5227 if (mVoiceContentBottom > top) { 5228 mVoiceContentBottom = top; 5229 } 5230 } 5231 5232 /** {@inheritDoc} */ 5233 @Override 5234 public void finishLayoutLw() { 5235 return; 5236 } 5237 5238 /** {@inheritDoc} */ 5239 @Override 5240 public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) { 5241 mTopFullscreenOpaqueWindowState = null; 5242 mTopFullscreenOpaqueOrDimmingWindowState = null; 5243 mTopDockedOpaqueWindowState = null; 5244 mTopDockedOpaqueOrDimmingWindowState = null; 5245 mForceStatusBar = false; 5246 mForceStatusBarFromKeyguard = false; 5247 mForceStatusBarTransparent = false; 5248 mForcingShowNavBar = false; 5249 mForcingShowNavBarLayer = -1; 5250 5251 mAllowLockscreenWhenOn = false; 5252 mShowingDream = false; 5253 } 5254 5255 /** {@inheritDoc} */ 5256 @Override 5257 public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs, 5258 WindowState attached, WindowState imeTarget) { 5259 final boolean visible = !win.isGoneForLayoutLw(); 5260 if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisible=" + visible); 5261 applyKeyguardPolicyLw(win, imeTarget); 5262 final int fl = PolicyControl.getWindowFlags(win, attrs); 5263 if (mTopFullscreenOpaqueWindowState == null && visible && attrs.type == TYPE_INPUT_METHOD) { 5264 mForcingShowNavBar = true; 5265 mForcingShowNavBarLayer = win.getSurfaceLayer(); 5266 } 5267 if (attrs.type == TYPE_STATUS_BAR) { 5268 if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 5269 mForceStatusBarFromKeyguard = true; 5270 } 5271 if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) { 5272 mForceStatusBarTransparent = true; 5273 } 5274 } 5275 5276 // Don't allow snapshots to influence SystemUI visibility flags. 5277 // TODO: Revisit this once SystemUI flags for snapshots are handled correctly 5278 boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW 5279 && attrs.type < FIRST_SYSTEM_WINDOW 5280 && (attrs.privateFlags & PRIVATE_FLAG_TASK_SNAPSHOT) == 0; 5281 final int stackId = win.getStackId(); 5282 if (mTopFullscreenOpaqueWindowState == null && visible) { 5283 if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) { 5284 mForceStatusBar = true; 5285 } 5286 if (attrs.type == TYPE_DREAM) { 5287 // If the lockscreen was showing when the dream started then wait 5288 // for the dream to draw before hiding the lockscreen. 5289 if (!mDreamingLockscreen 5290 || (win.isVisibleLw() && win.hasDrawnLw())) { 5291 mShowingDream = true; 5292 appWindow = true; 5293 } 5294 } 5295 5296 // For app windows that are not attached, we decide if all windows in the app they 5297 // represent should be hidden or if we should hide the lockscreen. For attached app 5298 // windows we defer the decision to the window it is attached to. 5299 if (appWindow && attached == null) { 5300 if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) { 5301 if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win); 5302 mTopFullscreenOpaqueWindowState = win; 5303 if (mTopFullscreenOpaqueOrDimmingWindowState == null) { 5304 mTopFullscreenOpaqueOrDimmingWindowState = win; 5305 } 5306 if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) { 5307 mAllowLockscreenWhenOn = true; 5308 } 5309 } 5310 } 5311 } 5312 5313 // Voice interaction overrides both top fullscreen and top docked. 5314 if (visible && win.getAttrs().type == TYPE_VOICE_INTERACTION) { 5315 if (mTopFullscreenOpaqueWindowState == null) { 5316 mTopFullscreenOpaqueWindowState = win; 5317 if (mTopFullscreenOpaqueOrDimmingWindowState == null) { 5318 mTopFullscreenOpaqueOrDimmingWindowState = win; 5319 } 5320 } 5321 if (mTopDockedOpaqueWindowState == null) { 5322 mTopDockedOpaqueWindowState = win; 5323 if (mTopDockedOpaqueOrDimmingWindowState == null) { 5324 mTopDockedOpaqueOrDimmingWindowState = win; 5325 } 5326 } 5327 } 5328 5329 // Keep track of the window if it's dimming but not necessarily fullscreen. 5330 if (mTopFullscreenOpaqueOrDimmingWindowState == null && visible 5331 && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) { 5332 mTopFullscreenOpaqueOrDimmingWindowState = win; 5333 } 5334 5335 // We need to keep track of the top "fullscreen" opaque window for the docked stack 5336 // separately, because both the "real fullscreen" opaque window and the one for the docked 5337 // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR. 5338 if (mTopDockedOpaqueWindowState == null && visible && appWindow && attached == null 5339 && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) { 5340 mTopDockedOpaqueWindowState = win; 5341 if (mTopDockedOpaqueOrDimmingWindowState == null) { 5342 mTopDockedOpaqueOrDimmingWindowState = win; 5343 } 5344 } 5345 5346 // Also keep track of any windows that are dimming but not necessarily fullscreen in the 5347 // docked stack. 5348 if (mTopDockedOpaqueOrDimmingWindowState == null && visible && win.isDimming() 5349 && stackId == DOCKED_STACK_ID) { 5350 mTopDockedOpaqueOrDimmingWindowState = win; 5351 } 5352 } 5353 5354 private void applyKeyguardPolicyLw(WindowState win, WindowState imeTarget) { 5355 if (canBeHiddenByKeyguardLw(win)) { 5356 if (shouldBeHiddenByKeyguard(win, imeTarget)) { 5357 win.hideLw(false /* doAnimation */); 5358 } else { 5359 win.showLw(false /* doAnimation */); 5360 } 5361 } 5362 } 5363 5364 private boolean isFullscreen(WindowManager.LayoutParams attrs) { 5365 return attrs.x == 0 && attrs.y == 0 5366 && attrs.width == WindowManager.LayoutParams.MATCH_PARENT 5367 && attrs.height == WindowManager.LayoutParams.MATCH_PARENT; 5368 } 5369 5370 /** {@inheritDoc} */ 5371 @Override 5372 public int finishPostLayoutPolicyLw() { 5373 int changes = 0; 5374 boolean topIsFullscreen = false; 5375 5376 final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null) 5377 ? mTopFullscreenOpaqueWindowState.getAttrs() 5378 : null; 5379 5380 // If we are not currently showing a dream then remember the current 5381 // lockscreen state. We will use this to determine whether the dream 5382 // started while the lockscreen was showing and remember this state 5383 // while the dream is showing. 5384 if (!mShowingDream) { 5385 mDreamingLockscreen = isKeyguardShowingAndNotOccluded(); 5386 if (mDreamingSleepTokenNeeded) { 5387 mDreamingSleepTokenNeeded = false; 5388 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget(); 5389 } 5390 } else { 5391 if (!mDreamingSleepTokenNeeded) { 5392 mDreamingSleepTokenNeeded = true; 5393 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget(); 5394 } 5395 } 5396 5397 if (mStatusBar != null) { 5398 if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar 5399 + " forcefkg=" + mForceStatusBarFromKeyguard 5400 + " top=" + mTopFullscreenOpaqueWindowState); 5401 boolean shouldBeTransparent = mForceStatusBarTransparent 5402 && !mForceStatusBar 5403 && !mForceStatusBarFromKeyguard; 5404 if (!shouldBeTransparent) { 5405 mStatusBarController.setShowTransparent(false /* transparent */); 5406 } else if (!mStatusBar.isVisibleLw()) { 5407 mStatusBarController.setShowTransparent(true /* transparent */); 5408 } 5409 5410 WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs(); 5411 boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT 5412 && statusBarAttrs.width == MATCH_PARENT; 5413 if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent 5414 || statusBarExpanded) { 5415 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced"); 5416 if (mStatusBarController.setBarShowingLw(true)) { 5417 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5418 } 5419 // Maintain fullscreen layout until incoming animation is complete. 5420 topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw(); 5421 // Transient status bar on the lockscreen is not allowed 5422 if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) { 5423 mStatusBarController.updateVisibilityLw(false /*transientAllowed*/, 5424 mLastSystemUiFlags, mLastSystemUiFlags); 5425 } 5426 if (statusBarExpanded && mNavigationBar != null) { 5427 if (mNavigationBarController.setBarShowingLw(true)) { 5428 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5429 } 5430 } 5431 } else if (mTopFullscreenOpaqueWindowState != null) { 5432 final int fl = PolicyControl.getWindowFlags(null, lp); 5433 if (localLOGV) { 5434 Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() 5435 + " shown position: " 5436 + mTopFullscreenOpaqueWindowState.getShownPositionLw()); 5437 Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs() 5438 + " lp.flags=0x" + Integer.toHexString(fl)); 5439 } 5440 topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0 5441 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 5442 // The subtle difference between the window for mTopFullscreenOpaqueWindowState 5443 // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window 5444 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the 5445 // case though. 5446 if (mStatusBarController.isTransientShowing()) { 5447 if (mStatusBarController.setBarShowingLw(true)) { 5448 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5449 } 5450 } else if (topIsFullscreen 5451 && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID) 5452 && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) { 5453 if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar"); 5454 if (mStatusBarController.setBarShowingLw(false)) { 5455 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5456 } else { 5457 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding"); 5458 } 5459 } else { 5460 if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen"); 5461 if (mStatusBarController.setBarShowingLw(true)) { 5462 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5463 } 5464 } 5465 } 5466 } 5467 5468 if (mTopIsFullscreen != topIsFullscreen) { 5469 if (!topIsFullscreen) { 5470 // Force another layout when status bar becomes fully shown. 5471 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5472 } 5473 mTopIsFullscreen = topIsFullscreen; 5474 } 5475 5476 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5477 // If the navigation bar has been hidden or shown, we need to do another 5478 // layout pass to update that window. 5479 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5480 } 5481 5482 if (mShowingDream != mLastShowingDream) { 5483 mLastShowingDream = mShowingDream; 5484 mWindowManagerFuncs.notifyShowingDreamChanged(); 5485 } 5486 5487 // update since mAllowLockscreenWhenOn might have changed 5488 updateLockScreenTimeout(); 5489 return changes; 5490 } 5491 5492 /** 5493 * Updates the occluded state of the Keyguard. 5494 * 5495 * @return Whether the flags have changed and we have to redo the layout. 5496 */ 5497 private boolean setKeyguardOccludedLw(boolean isOccluded) { 5498 if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded); 5499 boolean wasOccluded = mKeyguardOccluded; 5500 boolean showing = mKeyguardDelegate.isShowing(); 5501 if (wasOccluded && !isOccluded && showing) { 5502 mKeyguardOccluded = false; 5503 mKeyguardDelegate.setOccluded(false, true /* animate */); 5504 mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD; 5505 if (!mKeyguardDelegate.hasLockscreenWallpaper()) { 5506 mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER; 5507 } 5508 return true; 5509 } else if (!wasOccluded && isOccluded && showing) { 5510 mKeyguardOccluded = true; 5511 mKeyguardDelegate.setOccluded(true, false /* animate */); 5512 mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD; 5513 mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER; 5514 return true; 5515 } else if (wasOccluded != isOccluded) { 5516 mKeyguardOccluded = isOccluded; 5517 mKeyguardDelegate.setOccluded(isOccluded, false /* animate */); 5518 return false; 5519 } else { 5520 return false; 5521 } 5522 } 5523 5524 private boolean isStatusBarKeyguard() { 5525 return mStatusBar != null 5526 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0; 5527 } 5528 5529 @Override 5530 public boolean allowAppAnimationsLw() { 5531 if (mShowingDream) { 5532 // If keyguard or dreams is currently visible, no reason to animate behind it. 5533 return false; 5534 } 5535 return true; 5536 } 5537 5538 @Override 5539 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) { 5540 mFocusedWindow = newFocus; 5541 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5542 // If the navigation bar has been hidden or shown, we need to do another 5543 // layout pass to update that window. 5544 return FINISH_LAYOUT_REDO_LAYOUT; 5545 } 5546 return 0; 5547 } 5548 5549 /** {@inheritDoc} */ 5550 @Override 5551 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { 5552 // lid changed state 5553 final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED; 5554 if (newLidState == mLidState) { 5555 return; 5556 } 5557 5558 mLidState = newLidState; 5559 applyLidSwitchState(); 5560 updateRotation(true); 5561 5562 if (lidOpen) { 5563 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch, 5564 "android.policy:LID"); 5565 } else if (!mLidControlsSleep) { 5566 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 5567 } 5568 } 5569 5570 @Override 5571 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) { 5572 int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED; 5573 if (mCameraLensCoverState == lensCoverState) { 5574 return; 5575 } 5576 if (mCameraLensCoverState == CAMERA_LENS_COVERED && 5577 lensCoverState == CAMERA_LENS_UNCOVERED) { 5578 Intent intent; 5579 final boolean keyguardActive = mKeyguardDelegate == null ? false : 5580 mKeyguardDelegate.isShowing(); 5581 if (keyguardActive) { 5582 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE); 5583 } else { 5584 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); 5585 } 5586 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens, 5587 "android.policy:CAMERA_COVER"); 5588 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); 5589 } 5590 mCameraLensCoverState = lensCoverState; 5591 } 5592 5593 void setHdmiPlugged(boolean plugged) { 5594 if (mHdmiPlugged != plugged) { 5595 mHdmiPlugged = plugged; 5596 updateRotation(true, true); 5597 Intent intent = new Intent(ACTION_HDMI_PLUGGED); 5598 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5599 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged); 5600 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 5601 } 5602 } 5603 5604 void initializeHdmiState() { 5605 boolean plugged = false; 5606 // watch for HDMI plug messages if the hdmi switch exists 5607 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) { 5608 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi"); 5609 5610 final String filename = "/sys/class/switch/hdmi/state"; 5611 FileReader reader = null; 5612 try { 5613 reader = new FileReader(filename); 5614 char[] buf = new char[15]; 5615 int n = reader.read(buf); 5616 if (n > 1) { 5617 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1)); 5618 } 5619 } catch (IOException ex) { 5620 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5621 } catch (NumberFormatException ex) { 5622 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5623 } finally { 5624 if (reader != null) { 5625 try { 5626 reader.close(); 5627 } catch (IOException ex) { 5628 } 5629 } 5630 } 5631 } 5632 // This dance forces the code in setHdmiPlugged to run. 5633 // Always do this so the sticky intent is stuck (to false) if there is no hdmi. 5634 mHdmiPlugged = !plugged; 5635 setHdmiPlugged(!mHdmiPlugged); 5636 } 5637 5638 final Object mScreenshotLock = new Object(); 5639 ServiceConnection mScreenshotConnection = null; 5640 5641 final Runnable mScreenshotTimeout = new Runnable() { 5642 @Override public void run() { 5643 synchronized (mScreenshotLock) { 5644 if (mScreenshotConnection != null) { 5645 mContext.unbindService(mScreenshotConnection); 5646 mScreenshotConnection = null; 5647 notifyScreenshotError(); 5648 } 5649 } 5650 } 5651 }; 5652 5653 // Assume this is called from the Handler thread. 5654 private void takeScreenshot(final int screenshotType) { 5655 synchronized (mScreenshotLock) { 5656 if (mScreenshotConnection != null) { 5657 return; 5658 } 5659 final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE, 5660 SYSUI_SCREENSHOT_SERVICE); 5661 final Intent serviceIntent = new Intent(); 5662 serviceIntent.setComponent(serviceComponent); 5663 ServiceConnection conn = new ServiceConnection() { 5664 @Override 5665 public void onServiceConnected(ComponentName name, IBinder service) { 5666 synchronized (mScreenshotLock) { 5667 if (mScreenshotConnection != this) { 5668 return; 5669 } 5670 Messenger messenger = new Messenger(service); 5671 Message msg = Message.obtain(null, screenshotType); 5672 final ServiceConnection myConn = this; 5673 Handler h = new Handler(mHandler.getLooper()) { 5674 @Override 5675 public void handleMessage(Message msg) { 5676 synchronized (mScreenshotLock) { 5677 if (mScreenshotConnection == myConn) { 5678 mContext.unbindService(mScreenshotConnection); 5679 mScreenshotConnection = null; 5680 mHandler.removeCallbacks(mScreenshotTimeout); 5681 } 5682 } 5683 } 5684 }; 5685 msg.replyTo = new Messenger(h); 5686 msg.arg1 = msg.arg2 = 0; 5687 if (mStatusBar != null && mStatusBar.isVisibleLw()) 5688 msg.arg1 = 1; 5689 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) 5690 msg.arg2 = 1; 5691 try { 5692 messenger.send(msg); 5693 } catch (RemoteException e) { 5694 } 5695 } 5696 } 5697 5698 @Override 5699 public void onServiceDisconnected(ComponentName name) { 5700 synchronized (mScreenshotLock) { 5701 if (mScreenshotConnection != null) { 5702 mContext.unbindService(mScreenshotConnection); 5703 mScreenshotConnection = null; 5704 mHandler.removeCallbacks(mScreenshotTimeout); 5705 notifyScreenshotError(); 5706 } 5707 } 5708 } 5709 }; 5710 if (mContext.bindServiceAsUser(serviceIntent, conn, 5711 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, 5712 UserHandle.CURRENT)) { 5713 mScreenshotConnection = conn; 5714 mHandler.postDelayed(mScreenshotTimeout, 10000); 5715 } 5716 } 5717 } 5718 5719 /** 5720 * Notifies the screenshot service to show an error. 5721 */ 5722 private void notifyScreenshotError() { 5723 // If the service process is killed, then ask it to clean up after itself 5724 final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE, 5725 SYSUI_SCREENSHOT_ERROR_RECEIVER); 5726 Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT); 5727 errorIntent.setComponent(errorComponent); 5728 errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | 5729 Intent.FLAG_RECEIVER_FOREGROUND); 5730 mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT); 5731 } 5732 5733 /** {@inheritDoc} */ 5734 @Override 5735 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { 5736 if (!mSystemBooted) { 5737 // If we have not yet booted, don't let key events do anything. 5738 return 0; 5739 } 5740 5741 final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0; 5742 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; 5743 final boolean canceled = event.isCanceled(); 5744 final int keyCode = event.getKeyCode(); 5745 5746 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; 5747 5748 // If screen is off then we treat the case where the keyguard is open but hidden 5749 // the same as if it were open and in front. 5750 // This will prevent any keys other than the power button from waking the screen 5751 // when the keyguard is hidden by another activity. 5752 final boolean keyguardActive = (mKeyguardDelegate == null ? false : 5753 (interactive ? 5754 isKeyguardShowingAndNotOccluded() : 5755 mKeyguardDelegate.isShowing())); 5756 5757 if (DEBUG_INPUT) { 5758 Log.d(TAG, "interceptKeyTq keycode=" + keyCode 5759 + " interactive=" + interactive + " keyguardActive=" + keyguardActive 5760 + " policyFlags=" + Integer.toHexString(policyFlags)); 5761 } 5762 5763 // Basic policy based on interactive state. 5764 int result; 5765 boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0 5766 || event.isWakeKey(); 5767 if (interactive || (isInjected && !isWakeKey)) { 5768 // When the device is interactive or the key is injected pass the 5769 // key to the application. 5770 result = ACTION_PASS_TO_USER; 5771 isWakeKey = false; 5772 5773 if (interactive) { 5774 // If the screen is awake, but the button pressed was the one that woke the device 5775 // then don't pass it to the application 5776 if (keyCode == mPendingWakeKey && !down) { 5777 result = 0; 5778 } 5779 // Reset the pending key 5780 mPendingWakeKey = PENDING_KEY_NULL; 5781 } 5782 } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) { 5783 // If we're currently dozing with the screen on and the keyguard showing, pass the key 5784 // to the application but preserve its wake key status to make sure we still move 5785 // from dozing to fully interactive if we would normally go from off to fully 5786 // interactive. 5787 result = ACTION_PASS_TO_USER; 5788 // Since we're dispatching the input, reset the pending key 5789 mPendingWakeKey = PENDING_KEY_NULL; 5790 } else { 5791 // When the screen is off and the key is not injected, determine whether 5792 // to wake the device but don't pass the key to the application. 5793 result = 0; 5794 if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) { 5795 isWakeKey = false; 5796 } 5797 // Cache the wake key on down event so we can also avoid sending the up event to the app 5798 if (isWakeKey && down) { 5799 mPendingWakeKey = keyCode; 5800 } 5801 } 5802 5803 // If the key would be handled globally, just return the result, don't worry about special 5804 // key processing. 5805 if (isValidGlobalKey(keyCode) 5806 && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) { 5807 if (isWakeKey) { 5808 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 5809 } 5810 return result; 5811 } 5812 5813 boolean useHapticFeedback = down 5814 && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0 5815 && event.getRepeatCount() == 0; 5816 5817 // Handle special keys. 5818 switch (keyCode) { 5819 case KeyEvent.KEYCODE_BACK: { 5820 if (down) { 5821 interceptBackKeyDown(); 5822 } else { 5823 boolean handled = interceptBackKeyUp(event); 5824 5825 // Don't pass back press to app if we've already handled it via long press 5826 if (handled) { 5827 result &= ~ACTION_PASS_TO_USER; 5828 } 5829 } 5830 break; 5831 } 5832 5833 case KeyEvent.KEYCODE_VOLUME_DOWN: 5834 case KeyEvent.KEYCODE_VOLUME_UP: 5835 case KeyEvent.KEYCODE_VOLUME_MUTE: { 5836 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { 5837 if (down) { 5838 if (interactive && !mScreenshotChordVolumeDownKeyTriggered 5839 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5840 mScreenshotChordVolumeDownKeyTriggered = true; 5841 mScreenshotChordVolumeDownKeyTime = event.getDownTime(); 5842 mScreenshotChordVolumeDownKeyConsumed = false; 5843 cancelPendingPowerKeyAction(); 5844 interceptScreenshotChord(); 5845 if (!keyguardActive) { 5846 interceptAccessibilityShortcutChord(); 5847 } 5848 } 5849 } else { 5850 mScreenshotChordVolumeDownKeyTriggered = false; 5851 cancelPendingScreenshotChordAction(); 5852 cancelPendingAccessibilityShortcutAction(); 5853 } 5854 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 5855 if (down) { 5856 if (interactive && !mA11yShortcutChordVolumeUpKeyTriggered 5857 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5858 mA11yShortcutChordVolumeUpKeyTriggered = true; 5859 mA11yShortcutChordVolumeUpKeyTime = event.getDownTime(); 5860 mA11yShortcutChordVolumeUpKeyConsumed = false; 5861 cancelPendingPowerKeyAction(); 5862 cancelPendingScreenshotChordAction(); 5863 if (!keyguardActive) { 5864 interceptAccessibilityShortcutChord(); 5865 } 5866 } 5867 } else { 5868 mA11yShortcutChordVolumeUpKeyTriggered = false; 5869 cancelPendingScreenshotChordAction(); 5870 cancelPendingAccessibilityShortcutAction(); 5871 } 5872 } 5873 if (down) { 5874 TelecomManager telecomManager = getTelecommService(); 5875 if (telecomManager != null) { 5876 if (telecomManager.isRinging()) { 5877 // If an incoming call is ringing, either VOLUME key means 5878 // "silence ringer". We handle these keys here, rather than 5879 // in the InCallScreen, to make sure we'll respond to them 5880 // even if the InCallScreen hasn't come to the foreground yet. 5881 // Look for the DOWN event here, to agree with the "fallback" 5882 // behavior in the InCallScreen. 5883 Log.i(TAG, "interceptKeyBeforeQueueing:" 5884 + " VOLUME key-down while ringing: Silence ringer!"); 5885 5886 // Silence the ringer. (It's safe to call this 5887 // even if the ringer has already been silenced.) 5888 telecomManager.silenceRinger(); 5889 5890 // And *don't* pass this key thru to the current activity 5891 // (which is probably the InCallScreen.) 5892 result &= ~ACTION_PASS_TO_USER; 5893 break; 5894 } 5895 if (telecomManager.isInCall() 5896 && (result & ACTION_PASS_TO_USER) == 0) { 5897 // If we are in call but we decided not to pass the key to 5898 // the application, just pass it to the session service. 5899 5900 MediaSessionLegacyHelper.getHelper(mContext) 5901 .sendVolumeKeyEvent(event, false); 5902 break; 5903 } 5904 } 5905 } 5906 if (mUseTvRouting) { 5907 // On TVs, defer special key handlings to 5908 // {@link interceptKeyBeforeDispatching()}. 5909 result |= ACTION_PASS_TO_USER; 5910 } else if ((result & ACTION_PASS_TO_USER) == 0) { 5911 // If we aren't passing to the user and no one else 5912 // handled it send it to the session manager to 5913 // figure out. 5914 MediaSessionLegacyHelper.getHelper(mContext) 5915 .sendVolumeKeyEvent(event, true); 5916 } 5917 break; 5918 } 5919 5920 case KeyEvent.KEYCODE_ENDCALL: { 5921 result &= ~ACTION_PASS_TO_USER; 5922 if (down) { 5923 TelecomManager telecomManager = getTelecommService(); 5924 boolean hungUp = false; 5925 if (telecomManager != null) { 5926 hungUp = telecomManager.endCall(); 5927 } 5928 if (interactive && !hungUp) { 5929 mEndCallKeyHandled = false; 5930 mHandler.postDelayed(mEndCallLongPress, 5931 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 5932 } else { 5933 mEndCallKeyHandled = true; 5934 } 5935 } else { 5936 if (!mEndCallKeyHandled) { 5937 mHandler.removeCallbacks(mEndCallLongPress); 5938 if (!canceled) { 5939 if ((mEndcallBehavior 5940 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) { 5941 if (goHome()) { 5942 break; 5943 } 5944 } 5945 if ((mEndcallBehavior 5946 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) { 5947 mPowerManager.goToSleep(event.getEventTime(), 5948 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); 5949 isWakeKey = false; 5950 } 5951 } 5952 } 5953 } 5954 break; 5955 } 5956 5957 case KeyEvent.KEYCODE_POWER: { 5958 // Any activity on the power button stops the accessibility shortcut 5959 cancelPendingAccessibilityShortcutAction(); 5960 result &= ~ACTION_PASS_TO_USER; 5961 isWakeKey = false; // wake-up will be handled separately 5962 if (down) { 5963 interceptPowerKeyDown(event, interactive); 5964 } else { 5965 interceptPowerKeyUp(event, interactive, canceled); 5966 } 5967 break; 5968 } 5969 5970 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN: 5971 // fall through 5972 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP: 5973 // fall through 5974 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT: 5975 // fall through 5976 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: { 5977 result &= ~ACTION_PASS_TO_USER; 5978 interceptSystemNavigationKey(event); 5979 break; 5980 } 5981 5982 case KeyEvent.KEYCODE_SLEEP: { 5983 result &= ~ACTION_PASS_TO_USER; 5984 isWakeKey = false; 5985 if (!mPowerManager.isInteractive()) { 5986 useHapticFeedback = false; // suppress feedback if already non-interactive 5987 } 5988 if (down) { 5989 sleepPress(event.getEventTime()); 5990 } else { 5991 sleepRelease(event.getEventTime()); 5992 } 5993 break; 5994 } 5995 5996 case KeyEvent.KEYCODE_SOFT_SLEEP: { 5997 result &= ~ACTION_PASS_TO_USER; 5998 isWakeKey = false; 5999 if (!down) { 6000 mPowerManagerInternal.setUserInactiveOverrideFromWindowManager(); 6001 } 6002 break; 6003 } 6004 6005 case KeyEvent.KEYCODE_WAKEUP: { 6006 result &= ~ACTION_PASS_TO_USER; 6007 isWakeKey = true; 6008 break; 6009 } 6010 6011 case KeyEvent.KEYCODE_MEDIA_PLAY: 6012 case KeyEvent.KEYCODE_MEDIA_PAUSE: 6013 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 6014 case KeyEvent.KEYCODE_HEADSETHOOK: 6015 case KeyEvent.KEYCODE_MUTE: 6016 case KeyEvent.KEYCODE_MEDIA_STOP: 6017 case KeyEvent.KEYCODE_MEDIA_NEXT: 6018 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 6019 case KeyEvent.KEYCODE_MEDIA_REWIND: 6020 case KeyEvent.KEYCODE_MEDIA_RECORD: 6021 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 6022 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { 6023 if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) { 6024 // If the global session is active pass all media keys to it 6025 // instead of the active window. 6026 result &= ~ACTION_PASS_TO_USER; 6027 } 6028 if ((result & ACTION_PASS_TO_USER) == 0) { 6029 // Only do this if we would otherwise not pass it to the user. In that 6030 // case, the PhoneWindow class will do the same thing, except it will 6031 // only do it if the showing app doesn't process the key on its own. 6032 // Note that we need to make a copy of the key event here because the 6033 // original key event will be recycled when we return. 6034 mBroadcastWakeLock.acquire(); 6035 Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK, 6036 new KeyEvent(event)); 6037 msg.setAsynchronous(true); 6038 msg.sendToTarget(); 6039 } 6040 break; 6041 } 6042 6043 case KeyEvent.KEYCODE_CALL: { 6044 if (down) { 6045 TelecomManager telecomManager = getTelecommService(); 6046 if (telecomManager != null) { 6047 if (telecomManager.isRinging()) { 6048 Log.i(TAG, "interceptKeyBeforeQueueing:" 6049 + " CALL key-down while ringing: Answer the call!"); 6050 telecomManager.acceptRingingCall(); 6051 6052 // And *don't* pass this key thru to the current activity 6053 // (which is presumably the InCallScreen.) 6054 result &= ~ACTION_PASS_TO_USER; 6055 } 6056 } 6057 } 6058 break; 6059 } 6060 case KeyEvent.KEYCODE_VOICE_ASSIST: { 6061 // Only do this if we would otherwise not pass it to the user. In that case, 6062 // interceptKeyBeforeDispatching would apply a similar but different policy in 6063 // order to invoke voice assist actions. Note that we need to make a copy of the 6064 // key event here because the original key event will be recycled when we return. 6065 if ((result & ACTION_PASS_TO_USER) == 0 && !down) { 6066 mBroadcastWakeLock.acquire(); 6067 Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK, 6068 keyguardActive ? 1 : 0, 0); 6069 msg.setAsynchronous(true); 6070 msg.sendToTarget(); 6071 } 6072 break; 6073 } 6074 case KeyEvent.KEYCODE_WINDOW: { 6075 if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) { 6076 if (mTvPictureInPictureVisible) { 6077 // Consumes the key only if picture-in-picture is visible 6078 // to show picture-in-picture control menu. 6079 // This gives a chance to the foreground activity 6080 // to customize PIP key behavior. 6081 if (!down) { 6082 showTvPictureInPictureMenu(event); 6083 } 6084 result &= ~ACTION_PASS_TO_USER; 6085 } 6086 } 6087 break; 6088 } 6089 } 6090 6091 if (useHapticFeedback) { 6092 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); 6093 } 6094 6095 if (isWakeKey) { 6096 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 6097 } 6098 6099 return result; 6100 } 6101 6102 /** 6103 * Handle statusbar expansion events. 6104 * @param event 6105 */ 6106 private void interceptSystemNavigationKey(KeyEvent event) { 6107 if (event.getAction() == KeyEvent.ACTION_UP && areSystemNavigationKeysEnabled()) { 6108 IStatusBarService sbar = getStatusBarService(); 6109 if (sbar != null) { 6110 try { 6111 sbar.handleSystemNavigationKey(event.getKeyCode()); 6112 } catch (RemoteException e1) { 6113 // oops, no statusbar. Ignore event. 6114 } 6115 } 6116 } 6117 } 6118 6119 /** 6120 * Returns true if the key can have global actions attached to it. 6121 * We reserve all power management keys for the system since they require 6122 * very careful handling. 6123 */ 6124 private static boolean isValidGlobalKey(int keyCode) { 6125 switch (keyCode) { 6126 case KeyEvent.KEYCODE_POWER: 6127 case KeyEvent.KEYCODE_WAKEUP: 6128 case KeyEvent.KEYCODE_SLEEP: 6129 return false; 6130 default: 6131 return true; 6132 } 6133 } 6134 6135 /** 6136 * When the screen is off we ignore some keys that might otherwise typically 6137 * be considered wake keys. We filter them out here. 6138 * 6139 * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it 6140 * is always considered a wake key. 6141 */ 6142 private boolean isWakeKeyWhenScreenOff(int keyCode) { 6143 switch (keyCode) { 6144 // ignore volume keys unless docked 6145 case KeyEvent.KEYCODE_VOLUME_UP: 6146 case KeyEvent.KEYCODE_VOLUME_DOWN: 6147 case KeyEvent.KEYCODE_VOLUME_MUTE: 6148 return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED; 6149 6150 // ignore media and camera keys 6151 case KeyEvent.KEYCODE_MUTE: 6152 case KeyEvent.KEYCODE_HEADSETHOOK: 6153 case KeyEvent.KEYCODE_MEDIA_PLAY: 6154 case KeyEvent.KEYCODE_MEDIA_PAUSE: 6155 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 6156 case KeyEvent.KEYCODE_MEDIA_STOP: 6157 case KeyEvent.KEYCODE_MEDIA_NEXT: 6158 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 6159 case KeyEvent.KEYCODE_MEDIA_REWIND: 6160 case KeyEvent.KEYCODE_MEDIA_RECORD: 6161 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 6162 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: 6163 case KeyEvent.KEYCODE_CAMERA: 6164 return false; 6165 } 6166 return true; 6167 } 6168 6169 6170 /** {@inheritDoc} */ 6171 @Override 6172 public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) { 6173 if ((policyFlags & FLAG_WAKE) != 0) { 6174 if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion, 6175 "android.policy:MOTION")) { 6176 return 0; 6177 } 6178 } 6179 6180 if (shouldDispatchInputWhenNonInteractive(null)) { 6181 return ACTION_PASS_TO_USER; 6182 } 6183 6184 // If we have not passed the action up and we are in theater mode without dreaming, 6185 // there will be no dream to intercept the touch and wake into ambient. The device should 6186 // wake up in this case. 6187 if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) { 6188 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming, 6189 "android.policy:MOTION"); 6190 } 6191 6192 return 0; 6193 } 6194 6195 private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) { 6196 final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF); 6197 6198 if (displayOff && !mHasFeatureWatch) { 6199 return false; 6200 } 6201 6202 // Send events to keyguard while the screen is on and it's showing. 6203 if (isKeyguardShowingAndNotOccluded() && !displayOff) { 6204 return true; 6205 } 6206 6207 // Watches handle BACK specially 6208 if (mHasFeatureWatch 6209 && event != null 6210 && (event.getKeyCode() == KeyEvent.KEYCODE_BACK 6211 || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) { 6212 return false; 6213 } 6214 6215 // Send events to a dozing dream even if the screen is off since the dream 6216 // is in control of the state of the screen. 6217 IDreamManager dreamManager = getDreamManager(); 6218 6219 try { 6220 if (dreamManager != null && dreamManager.isDreaming()) { 6221 return true; 6222 } 6223 } catch (RemoteException e) { 6224 Slog.e(TAG, "RemoteException when checking if dreaming", e); 6225 } 6226 6227 // Otherwise, consume events since the user can't see what is being 6228 // interacted with. 6229 return false; 6230 } 6231 6232 private void dispatchDirectAudioEvent(KeyEvent event) { 6233 if (event.getAction() != KeyEvent.ACTION_DOWN) { 6234 return; 6235 } 6236 int keyCode = event.getKeyCode(); 6237 int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND 6238 | AudioManager.FLAG_FROM_KEY; 6239 String pkgName = mContext.getOpPackageName(); 6240 switch (keyCode) { 6241 case KeyEvent.KEYCODE_VOLUME_UP: 6242 try { 6243 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE, 6244 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6245 } catch (RemoteException e) { 6246 Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e); 6247 } 6248 break; 6249 case KeyEvent.KEYCODE_VOLUME_DOWN: 6250 try { 6251 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER, 6252 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6253 } catch (RemoteException e) { 6254 Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e); 6255 } 6256 break; 6257 case KeyEvent.KEYCODE_VOLUME_MUTE: 6258 try { 6259 if (event.getRepeatCount() == 0) { 6260 getAudioService().adjustSuggestedStreamVolume( 6261 AudioManager.ADJUST_TOGGLE_MUTE, 6262 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6263 } 6264 } catch (RemoteException e) { 6265 Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e); 6266 } 6267 break; 6268 } 6269 } 6270 6271 void dispatchMediaKeyWithWakeLock(KeyEvent event) { 6272 if (DEBUG_INPUT) { 6273 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event); 6274 } 6275 6276 if (mHavePendingMediaKeyRepeatWithWakeLock) { 6277 if (DEBUG_INPUT) { 6278 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat"); 6279 } 6280 6281 mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK); 6282 mHavePendingMediaKeyRepeatWithWakeLock = false; 6283 mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock 6284 } 6285 6286 dispatchMediaKeyWithWakeLockToAudioService(event); 6287 6288 if (event.getAction() == KeyEvent.ACTION_DOWN 6289 && event.getRepeatCount() == 0) { 6290 mHavePendingMediaKeyRepeatWithWakeLock = true; 6291 6292 Message msg = mHandler.obtainMessage( 6293 MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event); 6294 msg.setAsynchronous(true); 6295 mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout()); 6296 } else { 6297 mBroadcastWakeLock.release(); 6298 } 6299 } 6300 6301 void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) { 6302 mHavePendingMediaKeyRepeatWithWakeLock = false; 6303 6304 KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event, 6305 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS); 6306 if (DEBUG_INPUT) { 6307 Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent); 6308 } 6309 6310 dispatchMediaKeyWithWakeLockToAudioService(repeatEvent); 6311 mBroadcastWakeLock.release(); 6312 } 6313 6314 void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) { 6315 if (mActivityManagerInternal.isSystemReady()) { 6316 MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true); 6317 } 6318 } 6319 6320 void launchVoiceAssistWithWakeLock(boolean keyguardActive) { 6321 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface( 6322 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); 6323 if (dic != null) { 6324 try { 6325 dic.exitIdle("voice-search"); 6326 } catch (RemoteException e) { 6327 } 6328 } 6329 Intent voiceIntent = 6330 new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); 6331 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive); 6332 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF); 6333 mBroadcastWakeLock.release(); 6334 } 6335 6336 BroadcastReceiver mDockReceiver = new BroadcastReceiver() { 6337 @Override 6338 public void onReceive(Context context, Intent intent) { 6339 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) { 6340 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 6341 Intent.EXTRA_DOCK_STATE_UNDOCKED); 6342 } else { 6343 try { 6344 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface( 6345 ServiceManager.getService(Context.UI_MODE_SERVICE)); 6346 mUiMode = uiModeService.getCurrentModeType(); 6347 } catch (RemoteException e) { 6348 } 6349 } 6350 updateRotation(true); 6351 synchronized (mLock) { 6352 updateOrientationListenerLp(); 6353 } 6354 } 6355 }; 6356 6357 BroadcastReceiver mDreamReceiver = new BroadcastReceiver() { 6358 @Override 6359 public void onReceive(Context context, Intent intent) { 6360 if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) { 6361 if (mKeyguardDelegate != null) { 6362 mKeyguardDelegate.onDreamingStarted(); 6363 } 6364 } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) { 6365 if (mKeyguardDelegate != null) { 6366 mKeyguardDelegate.onDreamingStopped(); 6367 } 6368 } 6369 } 6370 }; 6371 6372 BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() { 6373 @Override 6374 public void onReceive(Context context, Intent intent) { 6375 if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) { 6376 // tickle the settings observer: this first ensures that we're 6377 // observing the relevant settings for the newly-active user, 6378 // and then updates our own bookkeeping based on the now- 6379 // current user. 6380 mSettingsObserver.onChange(false); 6381 6382 // force a re-application of focused window sysui visibility. 6383 // the window may never have been shown for this user 6384 // e.g. the keyguard when going through the new-user setup flow 6385 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6386 mLastSystemUiFlags = 0; 6387 updateSystemUiVisibilityLw(); 6388 } 6389 } 6390 } 6391 }; 6392 6393 private final Runnable mHiddenNavPanic = new Runnable() { 6394 @Override 6395 public void run() { 6396 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6397 if (!isUserSetupComplete()) { 6398 // Swipe-up for navigation bar is disabled during setup 6399 return; 6400 } 6401 mPendingPanicGestureUptime = SystemClock.uptimeMillis(); 6402 if (!isNavBarEmpty(mLastSystemUiFlags)) { 6403 mNavigationBarController.showTransient(); 6404 } 6405 } 6406 } 6407 }; 6408 6409 private void requestTransientBars(WindowState swipeTarget) { 6410 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6411 if (!isUserSetupComplete()) { 6412 // Swipe-up for navigation bar is disabled during setup 6413 return; 6414 } 6415 boolean sb = mStatusBarController.checkShowTransientBarLw(); 6416 boolean nb = mNavigationBarController.checkShowTransientBarLw() 6417 && !isNavBarEmpty(mLastSystemUiFlags); 6418 if (sb || nb) { 6419 // Don't show status bar when swiping on already visible navigation bar 6420 if (!nb && swipeTarget == mNavigationBar) { 6421 if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target"); 6422 return; 6423 } 6424 if (sb) mStatusBarController.showTransient(); 6425 if (nb) mNavigationBarController.showTransient(); 6426 mImmersiveModeConfirmation.confirmCurrentPrompt(); 6427 updateSystemUiVisibilityLw(); 6428 } 6429 } 6430 } 6431 6432 // Called on the PowerManager's Notifier thread. 6433 @Override 6434 public void startedGoingToSleep(int why) { 6435 if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")"); 6436 mCameraGestureTriggeredDuringGoingToSleep = false; 6437 mGoingToSleep = true; 6438 if (mKeyguardDelegate != null) { 6439 mKeyguardDelegate.onStartedGoingToSleep(why); 6440 } 6441 } 6442 6443 // Called on the PowerManager's Notifier thread. 6444 @Override 6445 public void finishedGoingToSleep(int why) { 6446 EventLog.writeEvent(70000, 0); 6447 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")"); 6448 MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000); 6449 6450 mGoingToSleep = false; 6451 6452 // We must get this work done here because the power manager will drop 6453 // the wake lock and let the system suspend once this function returns. 6454 synchronized (mLock) { 6455 mAwake = false; 6456 updateWakeGestureListenerLp(); 6457 updateOrientationListenerLp(); 6458 updateLockScreenTimeout(); 6459 } 6460 if (mKeyguardDelegate != null) { 6461 mKeyguardDelegate.onFinishedGoingToSleep(why, 6462 mCameraGestureTriggeredDuringGoingToSleep); 6463 } 6464 mCameraGestureTriggeredDuringGoingToSleep = false; 6465 } 6466 6467 // Called on the PowerManager's Notifier thread. 6468 @Override 6469 public void startedWakingUp() { 6470 EventLog.writeEvent(70000, 1); 6471 if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up..."); 6472 6473 // Since goToSleep performs these functions synchronously, we must 6474 // do the same here. We cannot post this work to a handler because 6475 // that might cause it to become reordered with respect to what 6476 // may happen in a future call to goToSleep. 6477 synchronized (mLock) { 6478 mAwake = true; 6479 6480 updateWakeGestureListenerLp(); 6481 updateOrientationListenerLp(); 6482 updateLockScreenTimeout(); 6483 } 6484 6485 if (mKeyguardDelegate != null) { 6486 mKeyguardDelegate.onStartedWakingUp(); 6487 } 6488 } 6489 6490 // Called on the PowerManager's Notifier thread. 6491 @Override 6492 public void finishedWakingUp() { 6493 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up..."); 6494 } 6495 6496 private void wakeUpFromPowerKey(long eventTime) { 6497 wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER"); 6498 } 6499 6500 private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) { 6501 final boolean theaterModeEnabled = isTheaterModeEnabled(); 6502 if (!wakeInTheaterMode && theaterModeEnabled) { 6503 return false; 6504 } 6505 6506 if (theaterModeEnabled) { 6507 Settings.Global.putInt(mContext.getContentResolver(), 6508 Settings.Global.THEATER_MODE_ON, 0); 6509 } 6510 6511 mPowerManager.wakeUp(wakeTime, reason); 6512 return true; 6513 } 6514 6515 private void finishKeyguardDrawn() { 6516 synchronized (mLock) { 6517 if (!mScreenOnEarly || mKeyguardDrawComplete) { 6518 return; // We are not awake yet or we have already informed of this event. 6519 } 6520 6521 mKeyguardDrawComplete = true; 6522 if (mKeyguardDelegate != null) { 6523 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6524 } 6525 mWindowManagerDrawComplete = false; 6526 } 6527 6528 // ... eventually calls finishWindowsDrawn which will finalize our screen turn on 6529 // as well as enabling the orientation change logic/sensor. 6530 mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback, 6531 WAITING_FOR_DRAWN_TIMEOUT); 6532 } 6533 6534 // Called on the DisplayManager's DisplayPowerController thread. 6535 @Override 6536 public void screenTurnedOff() { 6537 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off..."); 6538 6539 updateScreenOffSleepToken(true); 6540 synchronized (mLock) { 6541 mScreenOnEarly = false; 6542 mScreenOnFully = false; 6543 mKeyguardDrawComplete = false; 6544 mWindowManagerDrawComplete = false; 6545 mScreenOnListener = null; 6546 updateOrientationListenerLp(); 6547 6548 if (mKeyguardDelegate != null) { 6549 mKeyguardDelegate.onScreenTurnedOff(); 6550 } 6551 } 6552 reportScreenStateToVrManager(false); 6553 } 6554 6555 // Called on the DisplayManager's DisplayPowerController thread. 6556 @Override 6557 public void screenTurningOn(final ScreenOnListener screenOnListener) { 6558 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on..."); 6559 6560 updateScreenOffSleepToken(false); 6561 synchronized (mLock) { 6562 mScreenOnEarly = true; 6563 mScreenOnFully = false; 6564 mKeyguardDrawComplete = false; 6565 mWindowManagerDrawComplete = false; 6566 mScreenOnListener = screenOnListener; 6567 6568 if (mKeyguardDelegate != null) { 6569 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6570 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000); 6571 mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback); 6572 } else { 6573 if (DEBUG_WAKEUP) Slog.d(TAG, 6574 "null mKeyguardDelegate: setting mKeyguardDrawComplete."); 6575 finishKeyguardDrawn(); 6576 } 6577 } 6578 } 6579 6580 // Called on the DisplayManager's DisplayPowerController thread. 6581 @Override 6582 public void screenTurnedOn() { 6583 synchronized (mLock) { 6584 if (mKeyguardDelegate != null) { 6585 mKeyguardDelegate.onScreenTurnedOn(); 6586 } 6587 } 6588 reportScreenStateToVrManager(true); 6589 } 6590 6591 private void reportScreenStateToVrManager(boolean isScreenOn) { 6592 VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class); 6593 if (vrService == null) { 6594 return; 6595 } 6596 vrService.onScreenStateChanged(isScreenOn); 6597 } 6598 6599 private void finishWindowsDrawn() { 6600 synchronized (mLock) { 6601 if (!mScreenOnEarly || mWindowManagerDrawComplete) { 6602 return; // Screen is not turned on or we did already handle this case earlier. 6603 } 6604 6605 mWindowManagerDrawComplete = true; 6606 } 6607 6608 finishScreenTurningOn(); 6609 } 6610 6611 private void finishScreenTurningOn() { 6612 synchronized (mLock) { 6613 // We have just finished drawing screen content. Since the orientation listener 6614 // gets only installed when all windows are drawn, we try to install it again. 6615 updateOrientationListenerLp(); 6616 } 6617 final ScreenOnListener listener; 6618 final boolean enableScreen; 6619 synchronized (mLock) { 6620 if (DEBUG_WAKEUP) Slog.d(TAG, 6621 "finishScreenTurningOn: mAwake=" + mAwake 6622 + ", mScreenOnEarly=" + mScreenOnEarly 6623 + ", mScreenOnFully=" + mScreenOnFully 6624 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete 6625 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete); 6626 6627 if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete 6628 || (mAwake && !mKeyguardDrawComplete)) { 6629 return; // spurious or not ready yet 6630 } 6631 6632 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on..."); 6633 listener = mScreenOnListener; 6634 mScreenOnListener = null; 6635 mScreenOnFully = true; 6636 6637 // Remember the first time we draw the keyguard so we know when we're done with 6638 // the main part of booting and can enable the screen and hide boot messages. 6639 if (!mKeyguardDrawnOnce && mAwake) { 6640 mKeyguardDrawnOnce = true; 6641 enableScreen = true; 6642 if (mBootMessageNeedsHiding) { 6643 mBootMessageNeedsHiding = false; 6644 hideBootMessages(); 6645 } 6646 } else { 6647 enableScreen = false; 6648 } 6649 } 6650 6651 if (listener != null) { 6652 listener.onScreenOn(); 6653 } 6654 6655 if (enableScreen) { 6656 try { 6657 mWindowManager.enableScreenIfNeeded(); 6658 } catch (RemoteException unhandled) { 6659 } 6660 } 6661 } 6662 6663 private void handleHideBootMessage() { 6664 synchronized (mLock) { 6665 if (!mKeyguardDrawnOnce) { 6666 mBootMessageNeedsHiding = true; 6667 return; // keyguard hasn't drawn the first time yet, not done booting 6668 } 6669 } 6670 6671 if (mBootMsgDialog != null) { 6672 if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing"); 6673 mBootMsgDialog.dismiss(); 6674 mBootMsgDialog = null; 6675 } 6676 } 6677 6678 @Override 6679 public boolean isScreenOn() { 6680 return mScreenOnFully; 6681 } 6682 6683 /** {@inheritDoc} */ 6684 @Override 6685 public void enableKeyguard(boolean enabled) { 6686 if (mKeyguardDelegate != null) { 6687 mKeyguardDelegate.setKeyguardEnabled(enabled); 6688 } 6689 } 6690 6691 /** {@inheritDoc} */ 6692 @Override 6693 public void exitKeyguardSecurely(OnKeyguardExitResult callback) { 6694 if (mKeyguardDelegate != null) { 6695 mKeyguardDelegate.verifyUnlock(callback); 6696 } 6697 } 6698 6699 @Override 6700 public boolean isKeyguardShowingAndNotOccluded() { 6701 if (mKeyguardDelegate == null) return false; 6702 return mKeyguardDelegate.isShowing() && !mKeyguardOccluded; 6703 } 6704 6705 @Override 6706 public boolean isKeyguardTrustedLw() { 6707 if (mKeyguardDelegate == null) return false; 6708 return mKeyguardDelegate.isTrusted(); 6709 } 6710 6711 /** {@inheritDoc} */ 6712 @Override 6713 public boolean isKeyguardLocked() { 6714 return keyguardOn(); 6715 } 6716 6717 /** {@inheritDoc} */ 6718 @Override 6719 public boolean isKeyguardSecure(int userId) { 6720 if (mKeyguardDelegate == null) return false; 6721 return mKeyguardDelegate.isSecure(userId); 6722 } 6723 6724 /** {@inheritDoc} */ 6725 @Override 6726 public boolean isKeyguardOccluded() { 6727 if (mKeyguardDelegate == null) return false; 6728 return mKeyguardOccluded; 6729 } 6730 6731 /** {@inheritDoc} */ 6732 @Override 6733 public boolean inKeyguardRestrictedKeyInputMode() { 6734 if (mKeyguardDelegate == null) return false; 6735 return mKeyguardDelegate.isInputRestricted(); 6736 } 6737 6738 @Override 6739 public void dismissKeyguardLw(IKeyguardDismissCallback callback) { 6740 if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) { 6741 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw"); 6742 6743 // ask the keyguard to prompt the user to authenticate if necessary 6744 mKeyguardDelegate.dismiss(callback); 6745 } else if (callback != null) { 6746 try { 6747 callback.onDismissError(); 6748 } catch (RemoteException e) { 6749 Slog.w(TAG, "Failed to call callback", e); 6750 } 6751 } 6752 } 6753 6754 @Override 6755 public boolean isKeyguardDrawnLw() { 6756 synchronized (mLock) { 6757 return mKeyguardDrawnOnce; 6758 } 6759 } 6760 6761 @Override 6762 public boolean isShowingDreamLw() { 6763 return mShowingDream; 6764 } 6765 6766 @Override 6767 public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) { 6768 if (mKeyguardDelegate != null) { 6769 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation"); 6770 mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration); 6771 } 6772 } 6773 6774 @Override 6775 public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6776 Rect outInsets) { 6777 outInsets.setEmpty(); 6778 6779 // Navigation bar and status bar. 6780 getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets); 6781 outInsets.top = mStatusBarHeight; 6782 } 6783 6784 @Override 6785 public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6786 Rect outInsets) { 6787 outInsets.setEmpty(); 6788 6789 // Only navigation bar 6790 if (mHasNavigationBar) { 6791 int position = navigationBarPosition(displayWidth, displayHeight, displayRotation); 6792 if (position == NAV_BAR_BOTTOM) { 6793 outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode); 6794 } else if (position == NAV_BAR_RIGHT) { 6795 outInsets.right = getNavigationBarWidth(displayRotation, mUiMode); 6796 } else if (position == NAV_BAR_LEFT) { 6797 outInsets.left = getNavigationBarWidth(displayRotation, mUiMode); 6798 } 6799 } 6800 } 6801 6802 @Override 6803 public boolean isNavBarForcedShownLw(WindowState windowState) { 6804 return mForceShowSystemBars; 6805 } 6806 6807 @Override 6808 public boolean isDockSideAllowed(int dockSide) { 6809 6810 // We do not allow all dock sides at which the navigation bar touches the docked stack. 6811 if (!mNavigationBarCanMove) { 6812 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT; 6813 } else { 6814 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT; 6815 } 6816 } 6817 6818 void sendCloseSystemWindows() { 6819 PhoneWindow.sendCloseSystemWindows(mContext, null); 6820 } 6821 6822 void sendCloseSystemWindows(String reason) { 6823 PhoneWindow.sendCloseSystemWindows(mContext, reason); 6824 } 6825 6826 @Override 6827 public int rotationForOrientationLw(int orientation, int lastRotation) { 6828 if (false) { 6829 Slog.v(TAG, "rotationForOrientationLw(orient=" 6830 + orientation + ", last=" + lastRotation 6831 + "); user=" + mUserRotation + " " 6832 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) 6833 ? "USER_ROTATION_LOCKED" : "") 6834 ); 6835 } 6836 6837 if (mForceDefaultOrientation) { 6838 return Surface.ROTATION_0; 6839 } 6840 6841 synchronized (mLock) { 6842 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1 6843 if (sensorRotation < 0) { 6844 sensorRotation = lastRotation; 6845 } 6846 6847 final int preferredRotation; 6848 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) { 6849 // Ignore sensor when lid switch is open and rotation is forced. 6850 preferredRotation = mLidOpenRotation; 6851 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR 6852 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) { 6853 // Ignore sensor when in car dock unless explicitly enabled. 6854 // This case can override the behavior of NOSENSOR, and can also 6855 // enable 180 degree rotation while docked. 6856 preferredRotation = mCarDockEnablesAccelerometer 6857 ? sensorRotation : mCarDockRotation; 6858 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK 6859 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK 6860 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK) 6861 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) { 6862 // Ignore sensor when in desk dock unless explicitly enabled. 6863 // This case can override the behavior of NOSENSOR, and can also 6864 // enable 180 degree rotation while docked. 6865 preferredRotation = mDeskDockEnablesAccelerometer 6866 ? sensorRotation : mDeskDockRotation; 6867 } else if (mHdmiPlugged && mDemoHdmiRotationLock) { 6868 // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled. 6869 // Note that the dock orientation overrides the HDMI orientation. 6870 preferredRotation = mDemoHdmiRotation; 6871 } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED 6872 && mUndockedHdmiRotation >= 0) { 6873 // Ignore sensor when plugged into HDMI and an undocked orientation has 6874 // been specified in the configuration (only for legacy devices without 6875 // full multi-display support). 6876 // Note that the dock orientation overrides the HDMI orientation. 6877 preferredRotation = mUndockedHdmiRotation; 6878 } else if (mDemoRotationLock) { 6879 // Ignore sensor when demo rotation lock is enabled. 6880 // Note that the dock orientation and HDMI rotation lock override this. 6881 preferredRotation = mDemoRotation; 6882 } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) { 6883 // Application just wants to remain locked in the last rotation. 6884 preferredRotation = lastRotation; 6885 } else if (!mSupportAutoRotation) { 6886 // If we don't support auto-rotation then bail out here and ignore 6887 // the sensor and any rotation lock settings. 6888 preferredRotation = -1; 6889 } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE 6890 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER 6891 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 6892 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE 6893 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT 6894 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER)) 6895 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR 6896 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6897 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE 6898 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) { 6899 // Otherwise, use sensor only if requested by the application or enabled 6900 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR. 6901 if (mAllowAllRotations < 0) { 6902 // Can't read this during init() because the context doesn't 6903 // have display metrics at that time so we cannot determine 6904 // tablet vs. phone then. 6905 mAllowAllRotations = mContext.getResources().getBoolean( 6906 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0; 6907 } 6908 if (sensorRotation != Surface.ROTATION_180 6909 || mAllowAllRotations == 1 6910 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6911 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) { 6912 preferredRotation = sensorRotation; 6913 } else { 6914 preferredRotation = lastRotation; 6915 } 6916 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED 6917 && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) { 6918 // Apply rotation lock. Does not apply to NOSENSOR. 6919 // The idea is that the user rotation expresses a weak preference for the direction 6920 // of gravity and as NOSENSOR is never affected by gravity, then neither should 6921 // NOSENSOR be affected by rotation lock (although it will be affected by docks). 6922 preferredRotation = mUserRotation; 6923 } else { 6924 // No overriding preference. 6925 // We will do exactly what the application asked us to do. 6926 preferredRotation = -1; 6927 } 6928 6929 switch (orientation) { 6930 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 6931 // Return portrait unless overridden. 6932 if (isAnyPortrait(preferredRotation)) { 6933 return preferredRotation; 6934 } 6935 return mPortraitRotation; 6936 6937 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 6938 // Return landscape unless overridden. 6939 if (isLandscapeOrSeascape(preferredRotation)) { 6940 return preferredRotation; 6941 } 6942 return mLandscapeRotation; 6943 6944 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 6945 // Return reverse portrait unless overridden. 6946 if (isAnyPortrait(preferredRotation)) { 6947 return preferredRotation; 6948 } 6949 return mUpsideDownRotation; 6950 6951 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 6952 // Return seascape unless overridden. 6953 if (isLandscapeOrSeascape(preferredRotation)) { 6954 return preferredRotation; 6955 } 6956 return mSeascapeRotation; 6957 6958 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 6959 case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE: 6960 // Return either landscape rotation. 6961 if (isLandscapeOrSeascape(preferredRotation)) { 6962 return preferredRotation; 6963 } 6964 if (isLandscapeOrSeascape(lastRotation)) { 6965 return lastRotation; 6966 } 6967 return mLandscapeRotation; 6968 6969 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 6970 case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT: 6971 // Return either portrait rotation. 6972 if (isAnyPortrait(preferredRotation)) { 6973 return preferredRotation; 6974 } 6975 if (isAnyPortrait(lastRotation)) { 6976 return lastRotation; 6977 } 6978 return mPortraitRotation; 6979 6980 default: 6981 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR, 6982 // just return the preferred orientation we already calculated. 6983 if (preferredRotation >= 0) { 6984 return preferredRotation; 6985 } 6986 return Surface.ROTATION_0; 6987 } 6988 } 6989 } 6990 6991 @Override 6992 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) { 6993 switch (orientation) { 6994 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 6995 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 6996 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 6997 return isAnyPortrait(rotation); 6998 6999 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 7000 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 7001 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 7002 return isLandscapeOrSeascape(rotation); 7003 7004 default: 7005 return true; 7006 } 7007 } 7008 7009 @Override 7010 public void setRotationLw(int rotation) { 7011 mOrientationListener.setCurrentRotation(rotation); 7012 } 7013 7014 private boolean isLandscapeOrSeascape(int rotation) { 7015 return rotation == mLandscapeRotation || rotation == mSeascapeRotation; 7016 } 7017 7018 private boolean isAnyPortrait(int rotation) { 7019 return rotation == mPortraitRotation || rotation == mUpsideDownRotation; 7020 } 7021 7022 @Override 7023 public int getUserRotationMode() { 7024 return Settings.System.getIntForUser(mContext.getContentResolver(), 7025 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ? 7026 WindowManagerPolicy.USER_ROTATION_FREE : 7027 WindowManagerPolicy.USER_ROTATION_LOCKED; 7028 } 7029 7030 // User rotation: to be used when all else fails in assigning an orientation to the device 7031 @Override 7032 public void setUserRotationMode(int mode, int rot) { 7033 ContentResolver res = mContext.getContentResolver(); 7034 7035 // mUserRotationMode and mUserRotation will be assigned by the content observer 7036 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) { 7037 Settings.System.putIntForUser(res, 7038 Settings.System.USER_ROTATION, 7039 rot, 7040 UserHandle.USER_CURRENT); 7041 Settings.System.putIntForUser(res, 7042 Settings.System.ACCELEROMETER_ROTATION, 7043 0, 7044 UserHandle.USER_CURRENT); 7045 } else { 7046 Settings.System.putIntForUser(res, 7047 Settings.System.ACCELEROMETER_ROTATION, 7048 1, 7049 UserHandle.USER_CURRENT); 7050 } 7051 } 7052 7053 @Override 7054 public void setSafeMode(boolean safeMode) { 7055 mSafeMode = safeMode; 7056 performHapticFeedbackLw(null, safeMode 7057 ? HapticFeedbackConstants.SAFE_MODE_ENABLED 7058 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true); 7059 } 7060 7061 static long[] getLongIntArray(Resources r, int resid) { 7062 int[] ar = r.getIntArray(resid); 7063 if (ar == null) { 7064 return null; 7065 } 7066 long[] out = new long[ar.length]; 7067 for (int i=0; i<ar.length; i++) { 7068 out[i] = ar[i]; 7069 } 7070 return out; 7071 } 7072 7073 /** {@inheritDoc} */ 7074 @Override 7075 public void systemReady() { 7076 mKeyguardDelegate = new KeyguardServiceDelegate(mContext, 7077 new StateCallback() { 7078 @Override 7079 public void onTrustedChanged() { 7080 mWindowManagerFuncs.notifyKeyguardTrustedChanged(); 7081 } 7082 }); 7083 mKeyguardDelegate.onSystemReady(); 7084 7085 readCameraLensCoverState(); 7086 updateUiMode(); 7087 boolean bindKeyguardNow; 7088 synchronized (mLock) { 7089 updateOrientationListenerLp(); 7090 mSystemReady = true; 7091 mHandler.post(new Runnable() { 7092 @Override 7093 public void run() { 7094 updateSettings(); 7095 } 7096 }); 7097 7098 bindKeyguardNow = mDeferBindKeyguard; 7099 if (bindKeyguardNow) { 7100 // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now. 7101 mDeferBindKeyguard = false; 7102 } 7103 } 7104 7105 if (bindKeyguardNow) { 7106 mKeyguardDelegate.bindService(mContext); 7107 mKeyguardDelegate.onBootCompleted(); 7108 } 7109 mSystemGestures.systemReady(); 7110 mImmersiveModeConfirmation.systemReady(); 7111 } 7112 7113 /** {@inheritDoc} */ 7114 @Override 7115 public void systemBooted() { 7116 boolean bindKeyguardNow = false; 7117 synchronized (mLock) { 7118 // Time to bind Keyguard; take care to only bind it once, either here if ready or 7119 // in systemReady if not. 7120 if (mKeyguardDelegate != null) { 7121 bindKeyguardNow = true; 7122 } else { 7123 // Because mKeyguardDelegate is null, we know that the synchronized block in 7124 // systemReady didn't run yet and setting this will actually have an effect. 7125 mDeferBindKeyguard = true; 7126 } 7127 } 7128 if (bindKeyguardNow) { 7129 mKeyguardDelegate.bindService(mContext); 7130 mKeyguardDelegate.onBootCompleted(); 7131 } 7132 synchronized (mLock) { 7133 mSystemBooted = true; 7134 } 7135 startedWakingUp(); 7136 screenTurningOn(null); 7137 screenTurnedOn(); 7138 } 7139 7140 ProgressDialog mBootMsgDialog = null; 7141 7142 /** {@inheritDoc} */ 7143 @Override 7144 public void showBootMessage(final CharSequence msg, final boolean always) { 7145 mHandler.post(new Runnable() { 7146 @Override public void run() { 7147 if (mBootMsgDialog == null) { 7148 int theme; 7149 if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) { 7150 theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert; 7151 } else { 7152 theme = 0; 7153 } 7154 7155 mBootMsgDialog = new ProgressDialog(mContext, theme) { 7156 // This dialog will consume all events coming in to 7157 // it, to avoid it trying to do things too early in boot. 7158 @Override public boolean dispatchKeyEvent(KeyEvent event) { 7159 return true; 7160 } 7161 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { 7162 return true; 7163 } 7164 @Override public boolean dispatchTouchEvent(MotionEvent ev) { 7165 return true; 7166 } 7167 @Override public boolean dispatchTrackballEvent(MotionEvent ev) { 7168 return true; 7169 } 7170 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) { 7171 return true; 7172 } 7173 @Override public boolean dispatchPopulateAccessibilityEvent( 7174 AccessibilityEvent event) { 7175 return true; 7176 } 7177 }; 7178 if (mContext.getPackageManager().isUpgrade()) { 7179 mBootMsgDialog.setTitle(R.string.android_upgrading_title); 7180 } else { 7181 mBootMsgDialog.setTitle(R.string.android_start_title); 7182 } 7183 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 7184 mBootMsgDialog.setIndeterminate(true); 7185 mBootMsgDialog.getWindow().setType( 7186 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS); 7187 mBootMsgDialog.getWindow().addFlags( 7188 WindowManager.LayoutParams.FLAG_DIM_BEHIND 7189 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); 7190 mBootMsgDialog.getWindow().setDimAmount(1); 7191 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes(); 7192 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 7193 mBootMsgDialog.getWindow().setAttributes(lp); 7194 mBootMsgDialog.setCancelable(false); 7195 mBootMsgDialog.show(); 7196 } 7197 mBootMsgDialog.setMessage(msg); 7198 } 7199 }); 7200 } 7201 7202 /** {@inheritDoc} */ 7203 @Override 7204 public void hideBootMessages() { 7205 mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE); 7206 } 7207 7208 /** {@inheritDoc} */ 7209 @Override 7210 public void userActivity() { 7211 // *************************************** 7212 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE 7213 // *************************************** 7214 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER 7215 // WITH ITS LOCKS HELD. 7216 // 7217 // This code must be VERY careful about the locks 7218 // it acquires. 7219 // In fact, the current code acquires way too many, 7220 // and probably has lurking deadlocks. 7221 7222 synchronized (mScreenLockTimeout) { 7223 if (mLockScreenTimerActive) { 7224 // reset the timer 7225 mHandler.removeCallbacks(mScreenLockTimeout); 7226 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7227 } 7228 } 7229 } 7230 7231 class ScreenLockTimeout implements Runnable { 7232 Bundle options; 7233 7234 @Override 7235 public void run() { 7236 synchronized (this) { 7237 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard"); 7238 if (mKeyguardDelegate != null) { 7239 mKeyguardDelegate.doKeyguardTimeout(options); 7240 } 7241 mLockScreenTimerActive = false; 7242 options = null; 7243 } 7244 } 7245 7246 public void setLockOptions(Bundle options) { 7247 this.options = options; 7248 } 7249 } 7250 7251 ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout(); 7252 7253 @Override 7254 public void lockNow(Bundle options) { 7255 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 7256 mHandler.removeCallbacks(mScreenLockTimeout); 7257 if (options != null) { 7258 // In case multiple calls are made to lockNow, we don't wipe out the options 7259 // until the runnable actually executes. 7260 mScreenLockTimeout.setLockOptions(options); 7261 } 7262 mHandler.post(mScreenLockTimeout); 7263 } 7264 7265 private void updateLockScreenTimeout() { 7266 synchronized (mScreenLockTimeout) { 7267 boolean enable = (mAllowLockscreenWhenOn && mAwake && 7268 mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId)); 7269 if (mLockScreenTimerActive != enable) { 7270 if (enable) { 7271 if (localLOGV) Log.v(TAG, "setting lockscreen timer"); 7272 mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests 7273 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7274 } else { 7275 if (localLOGV) Log.v(TAG, "clearing lockscreen timer"); 7276 mHandler.removeCallbacks(mScreenLockTimeout); 7277 } 7278 mLockScreenTimerActive = enable; 7279 } 7280 } 7281 } 7282 7283 private void updateDreamingSleepToken(boolean acquire) { 7284 if (acquire) { 7285 if (mDreamingSleepToken == null) { 7286 mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream"); 7287 } 7288 } else { 7289 if (mDreamingSleepToken != null) { 7290 mDreamingSleepToken.release(); 7291 mDreamingSleepToken = null; 7292 } 7293 } 7294 } 7295 7296 private void updateScreenOffSleepToken(boolean acquire) { 7297 if (acquire) { 7298 if (mScreenOffSleepToken == null) { 7299 mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff"); 7300 } 7301 } else { 7302 if (mScreenOffSleepToken != null) { 7303 mScreenOffSleepToken.release(); 7304 mScreenOffSleepToken = null; 7305 } 7306 } 7307 } 7308 7309 /** {@inheritDoc} */ 7310 @Override 7311 public void enableScreenAfterBoot() { 7312 readLidState(); 7313 applyLidSwitchState(); 7314 updateRotation(true); 7315 } 7316 7317 private void applyLidSwitchState() { 7318 if (mLidState == LID_CLOSED && mLidControlsSleep) { 7319 mPowerManager.goToSleep(SystemClock.uptimeMillis(), 7320 PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH, 7321 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); 7322 } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) { 7323 mWindowManagerFuncs.lockDeviceNow(); 7324 } 7325 7326 synchronized (mLock) { 7327 updateWakeGestureListenerLp(); 7328 } 7329 } 7330 7331 void updateUiMode() { 7332 if (mUiModeManager == null) { 7333 mUiModeManager = IUiModeManager.Stub.asInterface( 7334 ServiceManager.getService(Context.UI_MODE_SERVICE)); 7335 } 7336 try { 7337 mUiMode = mUiModeManager.getCurrentModeType(); 7338 } catch (RemoteException e) { 7339 } 7340 } 7341 7342 void updateRotation(boolean alwaysSendConfiguration) { 7343 try { 7344 //set orientation on WindowManager 7345 mWindowManager.updateRotation(alwaysSendConfiguration, false); 7346 } catch (RemoteException e) { 7347 // Ignore 7348 } 7349 } 7350 7351 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 7352 try { 7353 //set orientation on WindowManager 7354 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout); 7355 } catch (RemoteException e) { 7356 // Ignore 7357 } 7358 } 7359 7360 /** 7361 * Return an Intent to launch the currently active dock app as home. Returns 7362 * null if the standard home should be launched, which is the case if any of the following is 7363 * true: 7364 * <ul> 7365 * <li>The device is not in either car mode or desk mode 7366 * <li>The device is in car mode but mEnableCarDockHomeCapture is false 7367 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false 7368 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME 7369 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME 7370 * </ul> 7371 * @return A dock intent. 7372 */ 7373 Intent createHomeDockIntent() { 7374 Intent intent = null; 7375 7376 // What home does is based on the mode, not the dock state. That 7377 // is, when in car mode you should be taken to car home regardless 7378 // of whether we are actually in a car dock. 7379 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) { 7380 if (mEnableCarDockHomeCapture) { 7381 intent = mCarDockIntent; 7382 } 7383 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) { 7384 if (ENABLE_DESK_DOCK_HOME_CAPTURE) { 7385 intent = mDeskDockIntent; 7386 } 7387 } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH 7388 && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK 7389 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK 7390 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) { 7391 // Always launch dock home from home when watch is docked, if it exists. 7392 intent = mDeskDockIntent; 7393 } 7394 7395 if (intent == null) { 7396 return null; 7397 } 7398 7399 ActivityInfo ai = null; 7400 ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser( 7401 intent, 7402 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA, 7403 mCurrentUserId); 7404 if (info != null) { 7405 ai = info.activityInfo; 7406 } 7407 if (ai != null 7408 && ai.metaData != null 7409 && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) { 7410 intent = new Intent(intent); 7411 intent.setClassName(ai.packageName, ai.name); 7412 return intent; 7413 } 7414 7415 return null; 7416 } 7417 7418 void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) { 7419 if (awakenFromDreams) { 7420 awakenDreams(); 7421 } 7422 7423 Intent dock = createHomeDockIntent(); 7424 if (dock != null) { 7425 try { 7426 if (fromHomeKey) { 7427 dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7428 } 7429 startActivityAsUser(dock, UserHandle.CURRENT); 7430 return; 7431 } catch (ActivityNotFoundException e) { 7432 } 7433 } 7434 7435 Intent intent; 7436 7437 if (fromHomeKey) { 7438 intent = new Intent(mHomeIntent); 7439 intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7440 } else { 7441 intent = mHomeIntent; 7442 } 7443 7444 startActivityAsUser(intent, UserHandle.CURRENT); 7445 } 7446 7447 /** 7448 * goes to the home screen 7449 * @return whether it did anything 7450 */ 7451 boolean goHome() { 7452 if (!isUserSetupComplete()) { 7453 Slog.i(TAG, "Not going home because user setup is in progress."); 7454 return false; 7455 } 7456 if (false) { 7457 // This code always brings home to the front. 7458 try { 7459 ActivityManager.getService().stopAppSwitches(); 7460 } catch (RemoteException e) { 7461 } 7462 sendCloseSystemWindows(); 7463 startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */); 7464 } else { 7465 // This code brings home to the front or, if it is already 7466 // at the front, puts the device to sleep. 7467 try { 7468 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) { 7469 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry. 7470 Log.d(TAG, "UTS-TEST-MODE"); 7471 } else { 7472 ActivityManager.getService().stopAppSwitches(); 7473 sendCloseSystemWindows(); 7474 Intent dock = createHomeDockIntent(); 7475 if (dock != null) { 7476 int result = ActivityManager.getService() 7477 .startActivityAsUser(null, null, dock, 7478 dock.resolveTypeIfNeeded(mContext.getContentResolver()), 7479 null, null, 0, 7480 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7481 null, null, UserHandle.USER_CURRENT); 7482 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7483 return false; 7484 } 7485 } 7486 } 7487 int result = ActivityManager.getService() 7488 .startActivityAsUser(null, null, mHomeIntent, 7489 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()), 7490 null, null, 0, 7491 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7492 null, null, UserHandle.USER_CURRENT); 7493 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7494 return false; 7495 } 7496 } catch (RemoteException ex) { 7497 // bummer, the activity manager, which is in this process, is dead 7498 } 7499 } 7500 return true; 7501 } 7502 7503 @Override 7504 public void setCurrentOrientationLw(int newOrientation) { 7505 synchronized (mLock) { 7506 if (newOrientation != mCurrentAppOrientation) { 7507 mCurrentAppOrientation = newOrientation; 7508 updateOrientationListenerLp(); 7509 } 7510 } 7511 } 7512 7513 private boolean isTheaterModeEnabled() { 7514 return Settings.Global.getInt(mContext.getContentResolver(), 7515 Settings.Global.THEATER_MODE_ON, 0) == 1; 7516 } 7517 7518 private boolean areSystemNavigationKeysEnabled() { 7519 return Settings.Secure.getIntForUser(mContext.getContentResolver(), 7520 Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1; 7521 } 7522 7523 @Override 7524 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) { 7525 if (!mVibrator.hasVibrator()) { 7526 return false; 7527 } 7528 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(), 7529 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0; 7530 if (hapticsDisabled && !always) { 7531 return false; 7532 } 7533 long[] pattern = null; 7534 switch (effectId) { 7535 case HapticFeedbackConstants.LONG_PRESS: 7536 pattern = mLongPressVibePattern; 7537 break; 7538 case HapticFeedbackConstants.VIRTUAL_KEY: 7539 pattern = mVirtualKeyVibePattern; 7540 break; 7541 case HapticFeedbackConstants.KEYBOARD_TAP: 7542 pattern = mKeyboardTapVibePattern; 7543 break; 7544 case HapticFeedbackConstants.CLOCK_TICK: 7545 pattern = mClockTickVibePattern; 7546 break; 7547 case HapticFeedbackConstants.CALENDAR_DATE: 7548 pattern = mCalendarDateVibePattern; 7549 break; 7550 case HapticFeedbackConstants.SAFE_MODE_DISABLED: 7551 pattern = mSafeModeDisabledVibePattern; 7552 break; 7553 case HapticFeedbackConstants.SAFE_MODE_ENABLED: 7554 pattern = mSafeModeEnabledVibePattern; 7555 break; 7556 case HapticFeedbackConstants.CONTEXT_CLICK: 7557 pattern = mContextClickVibePattern; 7558 break; 7559 default: 7560 return false; 7561 } 7562 int owningUid; 7563 String owningPackage; 7564 if (win != null) { 7565 owningUid = win.getOwningUid(); 7566 owningPackage = win.getOwningPackage(); 7567 } else { 7568 owningUid = android.os.Process.myUid(); 7569 owningPackage = mContext.getOpPackageName(); 7570 } 7571 if (pattern.length == 1) { 7572 // One-shot vibration 7573 mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES); 7574 } else { 7575 // Pattern vibration 7576 mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES); 7577 } 7578 return true; 7579 } 7580 7581 @Override 7582 public void keepScreenOnStartedLw() { 7583 } 7584 7585 @Override 7586 public void keepScreenOnStoppedLw() { 7587 if (isKeyguardShowingAndNotOccluded()) { 7588 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 7589 } 7590 } 7591 7592 private int updateSystemUiVisibilityLw() { 7593 // If there is no window focused, there will be nobody to handle the events 7594 // anyway, so just hang on in whatever state we're in until things settle down. 7595 WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow 7596 : mTopFullscreenOpaqueWindowState; 7597 if (winCandidate == null) { 7598 return 0; 7599 } 7600 if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) { 7601 // The immersive mode confirmation should never affect the system bar visibility, 7602 // otherwise it will unhide the navigation bar and hide itself. 7603 winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState; 7604 if (winCandidate == null) { 7605 return 0; 7606 } 7607 } 7608 final WindowState win = winCandidate; 7609 if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mKeyguardOccluded) { 7610 // We are updating at a point where the keyguard has gotten 7611 // focus, but we were last in a state where the top window is 7612 // hiding it. This is probably because the keyguard as been 7613 // shown while the top window was displayed, so we want to ignore 7614 // it here because this is just a very transient change and it 7615 // will quickly lose focus once it correctly gets hidden. 7616 return 0; 7617 } 7618 7619 int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null) 7620 & ~mResettingSystemUiFlags 7621 & ~mForceClearedSystemUiFlags; 7622 if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) { 7623 tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS); 7624 } 7625 7626 final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */, 7627 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState); 7628 final int dockedVisibility = updateLightStatusBarLw(0 /* vis */, 7629 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState); 7630 mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds); 7631 mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds); 7632 final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility); 7633 final int diff = visibility ^ mLastSystemUiFlags; 7634 final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags; 7635 final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags; 7636 final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState); 7637 if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu 7638 && mFocusedApp == win.getAppToken() 7639 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds) 7640 && mLastDockedStackBounds.equals(mDockedStackBounds)) { 7641 return 0; 7642 } 7643 mLastSystemUiFlags = visibility; 7644 mLastFullscreenStackSysUiFlags = fullscreenVisibility; 7645 mLastDockedStackSysUiFlags = dockedVisibility; 7646 mLastFocusNeedsMenu = needsMenu; 7647 mFocusedApp = win.getAppToken(); 7648 final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds); 7649 final Rect dockedStackBounds = new Rect(mDockedStackBounds); 7650 mHandler.post(new Runnable() { 7651 @Override 7652 public void run() { 7653 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 7654 if (statusbar != null) { 7655 statusbar.setSystemUiVisibility(visibility, fullscreenVisibility, 7656 dockedVisibility, 0xffffffff, fullscreenStackBounds, 7657 dockedStackBounds, win.toString()); 7658 statusbar.topAppWindowChanged(needsMenu); 7659 } 7660 } 7661 }); 7662 return diff; 7663 } 7664 7665 private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) { 7666 WindowState statusColorWin = isStatusBarKeyguard() && !mKeyguardOccluded 7667 ? mStatusBar 7668 : opaqueOrDimming; 7669 7670 if (statusColorWin != null) { 7671 if (statusColorWin == opaque) { 7672 // If the top fullscreen-or-dimming window is also the top fullscreen, respect 7673 // its light flag. 7674 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7675 vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null) 7676 & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7677 } else if (statusColorWin != null && statusColorWin.isDimming()) { 7678 // Otherwise if it's dimming, clear the light flag. 7679 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7680 } 7681 } 7682 return vis; 7683 } 7684 7685 private int updateLightNavigationBarLw(int vis, WindowState opaque, 7686 WindowState opaqueOrDimming) { 7687 final WindowState imeWin = mWindowManagerFuncs.getInputMethodWindowLw(); 7688 7689 final WindowState navColorWin; 7690 if (imeWin != null && imeWin.isVisibleLw()) { 7691 navColorWin = imeWin; 7692 } else { 7693 navColorWin = opaqueOrDimming; 7694 } 7695 7696 if (navColorWin != null) { 7697 if (navColorWin == opaque) { 7698 // If the top fullscreen-or-dimming window is also the top fullscreen, respect 7699 // its light flag. 7700 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; 7701 vis |= PolicyControl.getSystemUiVisibility(navColorWin, null) 7702 & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; 7703 } else if (navColorWin.isDimming() || navColorWin == imeWin) { 7704 // Otherwise if it's dimming or it's the IME window, clear the light flag. 7705 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; 7706 } 7707 } 7708 return vis; 7709 } 7710 7711 private boolean drawsSystemBarBackground(WindowState win) { 7712 return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0; 7713 } 7714 7715 private boolean forcesDrawStatusBarBackground(WindowState win) { 7716 return win == null || (win.getAttrs().privateFlags 7717 & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0; 7718 } 7719 7720 private int updateSystemBarsLw(WindowState win, int oldVis, int vis) { 7721 final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID); 7722 final boolean freeformStackVisible = 7723 mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID); 7724 final boolean resizing = mWindowManagerInternal.isDockedDividerResizing(); 7725 7726 // We need to force system bars when the docked stack is visible, when the freeform stack 7727 // is visible but also when we are resizing for the transitions when docked stack 7728 // visibility changes. 7729 mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing; 7730 final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard; 7731 7732 // apply translucent bar vis flags 7733 WindowState fullscreenTransWin = isStatusBarKeyguard() && !mKeyguardOccluded 7734 ? mStatusBar 7735 : mTopFullscreenOpaqueWindowState; 7736 vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7737 vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7738 final int dockedVis = mStatusBarController.applyTranslucentFlagLw( 7739 mTopDockedOpaqueWindowState, 0, 0); 7740 7741 final boolean fullscreenDrawsStatusBarBackground = 7742 (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState) 7743 && (vis & View.STATUS_BAR_TRANSLUCENT) == 0) 7744 || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState); 7745 final boolean dockedDrawsStatusBarBackground = 7746 (drawsSystemBarBackground(mTopDockedOpaqueWindowState) 7747 && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0) 7748 || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState); 7749 7750 // prevent status bar interaction from clearing certain flags 7751 int type = win.getAttrs().type; 7752 boolean statusBarHasFocus = type == TYPE_STATUS_BAR; 7753 if (statusBarHasFocus && !isStatusBarKeyguard()) { 7754 int flags = View.SYSTEM_UI_FLAG_FULLSCREEN 7755 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 7756 | View.SYSTEM_UI_FLAG_IMMERSIVE 7757 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 7758 | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7759 if (mKeyguardOccluded) { 7760 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT; 7761 } 7762 vis = (vis & ~flags) | (oldVis & flags); 7763 } 7764 7765 if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) { 7766 vis |= View.STATUS_BAR_TRANSPARENT; 7767 vis &= ~View.STATUS_BAR_TRANSLUCENT; 7768 } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar) 7769 || forceOpaqueStatusBar) { 7770 vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT); 7771 } 7772 7773 vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing); 7774 7775 // update status bar 7776 boolean immersiveSticky = 7777 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7778 final boolean hideStatusBarWM = 7779 mTopFullscreenOpaqueWindowState != null 7780 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null) 7781 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; 7782 final boolean hideStatusBarSysui = 7783 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 7784 final boolean hideNavBarSysui = 7785 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0; 7786 7787 final boolean transientStatusBarAllowed = mStatusBar != null 7788 && (statusBarHasFocus || (!mForceShowSystemBars 7789 && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky)))); 7790 7791 final boolean transientNavBarAllowed = mNavigationBar != null 7792 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky; 7793 7794 final long now = SystemClock.uptimeMillis(); 7795 final boolean pendingPanic = mPendingPanicGestureUptime != 0 7796 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION; 7797 if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) { 7798 // The user performed the panic gesture recently, we're about to hide the bars, 7799 // we're no longer on the Keyguard and the screen is ready. We can now request the bars. 7800 mPendingPanicGestureUptime = 0; 7801 mStatusBarController.showTransient(); 7802 if (!isNavBarEmpty(vis)) { 7803 mNavigationBarController.showTransient(); 7804 } 7805 } 7806 7807 final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested() 7808 && !transientStatusBarAllowed && hideStatusBarSysui; 7809 final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested() 7810 && !transientNavBarAllowed; 7811 if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) { 7812 // clear the clearable flags instead 7813 clearClearableFlagsLw(); 7814 vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS; 7815 } 7816 7817 final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; 7818 immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7819 final boolean navAllowedHidden = immersive || immersiveSticky; 7820 7821 if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType()) 7822 > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) { 7823 // We can't hide the navbar from this window otherwise the input consumer would not get 7824 // the input events. 7825 vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); 7826 } 7827 7828 vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis); 7829 7830 // update navigation bar 7831 boolean oldImmersiveMode = isImmersiveMode(oldVis); 7832 boolean newImmersiveMode = isImmersiveMode(vis); 7833 if (win != null && oldImmersiveMode != newImmersiveMode) { 7834 final String pkg = win.getOwningPackage(); 7835 mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode, 7836 isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility())); 7837 } 7838 7839 vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis); 7840 7841 vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState, 7842 mTopFullscreenOpaqueOrDimmingWindowState); 7843 7844 return vis; 7845 } 7846 7847 /** 7848 * @return the current visibility flags with the nav-bar opacity related flags toggled based 7849 * on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}. 7850 */ 7851 private int configureNavBarOpacity(int visibility, boolean dockedStackVisible, 7852 boolean freeformStackVisible, boolean isDockedDividerResizing) { 7853 if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) { 7854 if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) { 7855 visibility = setNavBarOpaqueFlag(visibility); 7856 } 7857 } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) { 7858 if (isDockedDividerResizing) { 7859 visibility = setNavBarOpaqueFlag(visibility); 7860 } else if (freeformStackVisible) { 7861 visibility = setNavBarTranslucentFlag(visibility); 7862 } else { 7863 visibility = setNavBarOpaqueFlag(visibility); 7864 } 7865 } 7866 7867 if (!areTranslucentBarsAllowed()) { 7868 visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT; 7869 } 7870 return visibility; 7871 } 7872 7873 private int setNavBarOpaqueFlag(int visibility) { 7874 return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT); 7875 } 7876 7877 private int setNavBarTranslucentFlag(int visibility) { 7878 visibility &= ~View.NAVIGATION_BAR_TRANSPARENT; 7879 return visibility |= View.NAVIGATION_BAR_TRANSLUCENT; 7880 } 7881 7882 private void clearClearableFlagsLw() { 7883 int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS; 7884 if (newVal != mResettingSystemUiFlags) { 7885 mResettingSystemUiFlags = newVal; 7886 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 7887 } 7888 } 7889 7890 private boolean isImmersiveMode(int vis) { 7891 final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; 7892 return mNavigationBar != null 7893 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0 7894 && (vis & flags) != 0 7895 && canHideNavigationBar(); 7896 } 7897 7898 private static boolean isNavBarEmpty(int systemUiFlags) { 7899 final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME 7900 | View.STATUS_BAR_DISABLE_BACK 7901 | View.STATUS_BAR_DISABLE_RECENT); 7902 7903 return (systemUiFlags & disableNavigationBar) == disableNavigationBar; 7904 } 7905 7906 /** 7907 * @return whether the navigation or status bar can be made translucent 7908 * 7909 * This should return true unless touch exploration is not enabled or 7910 * R.boolean.config_enableTranslucentDecor is false. 7911 */ 7912 private boolean areTranslucentBarsAllowed() { 7913 return mTranslucentDecorEnabled; 7914 } 7915 7916 // Use this instead of checking config_showNavigationBar so that it can be consistently 7917 // overridden by qemu.hw.mainkeys in the emulator. 7918 @Override 7919 public boolean hasNavigationBar() { 7920 return mHasNavigationBar; 7921 } 7922 7923 @Override 7924 public void setLastInputMethodWindowLw(WindowState ime, WindowState target) { 7925 mLastInputMethodWindow = ime; 7926 mLastInputMethodTargetWindow = target; 7927 } 7928 7929 @Override 7930 public int getInputMethodWindowVisibleHeightLw() { 7931 return mDockBottom - mCurBottom; 7932 } 7933 7934 @Override 7935 public void setCurrentUserLw(int newUserId) { 7936 mCurrentUserId = newUserId; 7937 if (mKeyguardDelegate != null) { 7938 mKeyguardDelegate.setCurrentUser(newUserId); 7939 } 7940 StatusBarManagerInternal statusBar = getStatusBarManagerInternal(); 7941 if (statusBar != null) { 7942 statusBar.setCurrentUser(newUserId); 7943 } 7944 setLastInputMethodWindowLw(null, null); 7945 } 7946 7947 @Override 7948 public void setSwitchingUser(boolean switching) { 7949 mKeyguardDelegate.setSwitchingUser(switching); 7950 } 7951 7952 @Override 7953 public boolean canMagnifyWindow(int windowType) { 7954 switch (windowType) { 7955 case WindowManager.LayoutParams.TYPE_INPUT_METHOD: 7956 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: 7957 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR: 7958 case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: { 7959 return false; 7960 } 7961 } 7962 return true; 7963 } 7964 7965 @Override 7966 public boolean isTopLevelWindow(int windowType) { 7967 if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW 7968 && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 7969 return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG); 7970 } 7971 return true; 7972 } 7973 7974 @Override 7975 public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) { 7976 // For the upside down rotation we don't rotate seamlessly as the navigation 7977 // bar moves position. 7978 // Note most apps (using orientation:sensor or user as opposed to fullSensor) 7979 // will not enter the reverse portrait orientation, so actually the 7980 // orientation won't change at all. 7981 if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) { 7982 return false; 7983 } 7984 // If the navigation bar can't change sides, then it will 7985 // jump when we change orientations and we don't rotate 7986 // seamlessly. 7987 if (!mNavigationBarCanMove) { 7988 return false; 7989 } 7990 int delta = newRotation - oldRotation; 7991 if (delta < 0) delta += 4; 7992 // Likewise we don't rotate seamlessly for 180 degree rotations 7993 // in this case the surfaces never resize, and our logic to 7994 // revert the transformations on size change will fail. We could 7995 // fix this in the future with the "tagged" frames idea. 7996 if (delta == Surface.ROTATION_180) { 7997 return false; 7998 } 7999 8000 final WindowState w = mTopFullscreenOpaqueWindowState; 8001 if (w != mFocusedWindow) { 8002 return false; 8003 } 8004 8005 // We only enable seamless rotation if the top window has requested 8006 // it and is in the fullscreen opaque state. Seamless rotation 8007 // requires freezing various Surface states and won't work well 8008 // with animations, so we disable it in the animation case for now. 8009 if (w != null && !w.isAnimatingLw() && 8010 ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) || 8011 (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) { 8012 return true; 8013 } 8014 return false; 8015 } 8016 8017 @Override 8018 public void dump(String prefix, PrintWriter pw, String[] args) { 8019 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode); 8020 pw.print(" mSystemReady="); pw.print(mSystemReady); 8021 pw.print(" mSystemBooted="); pw.println(mSystemBooted); 8022 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState); 8023 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation); 8024 pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState); 8025 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged); 8026 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0 8027 || mForceClearedSystemUiFlags != 0) { 8028 pw.print(prefix); pw.print("mLastSystemUiFlags=0x"); 8029 pw.print(Integer.toHexString(mLastSystemUiFlags)); 8030 pw.print(" mResettingSystemUiFlags=0x"); 8031 pw.print(Integer.toHexString(mResettingSystemUiFlags)); 8032 pw.print(" mForceClearedSystemUiFlags=0x"); 8033 pw.println(Integer.toHexString(mForceClearedSystemUiFlags)); 8034 } 8035 if (mLastFocusNeedsMenu) { 8036 pw.print(prefix); pw.print("mLastFocusNeedsMenu="); 8037 pw.println(mLastFocusNeedsMenu); 8038 } 8039 pw.print(prefix); pw.print("mWakeGestureEnabledSetting="); 8040 pw.println(mWakeGestureEnabledSetting); 8041 8042 pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation); 8043 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode); 8044 pw.print(" mDockMode="); pw.print(mDockMode); 8045 pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture); 8046 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation); 8047 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation); 8048 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode); 8049 pw.print(" mUserRotation="); pw.print(mUserRotation); 8050 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations); 8051 pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation); 8052 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer="); 8053 pw.print(mCarDockEnablesAccelerometer); 8054 pw.print(" mDeskDockEnablesAccelerometer="); 8055 pw.println(mDeskDockEnablesAccelerometer); 8056 pw.print(prefix); pw.print("mLidKeyboardAccessibility="); 8057 pw.print(mLidKeyboardAccessibility); 8058 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility); 8059 pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock); 8060 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep); 8061 pw.print(prefix); 8062 pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior); 8063 pw.print(prefix); 8064 pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior); 8065 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior); 8066 pw.print(prefix); 8067 pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior); 8068 pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior); 8069 pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput); 8070 pw.print(prefix); pw.print("mAwake="); pw.println(mAwake); 8071 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly); 8072 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully); 8073 pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete); 8074 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete); 8075 pw.print(prefix); pw.print("mOrientationSensorEnabled="); 8076 pw.println(mOrientationSensorEnabled); 8077 pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft); 8078 pw.print(","); pw.print(mOverscanScreenTop); 8079 pw.print(") "); pw.print(mOverscanScreenWidth); 8080 pw.print("x"); pw.println(mOverscanScreenHeight); 8081 if (mOverscanLeft != 0 || mOverscanTop != 0 8082 || mOverscanRight != 0 || mOverscanBottom != 0) { 8083 pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft); 8084 pw.print(" top="); pw.print(mOverscanTop); 8085 pw.print(" right="); pw.print(mOverscanRight); 8086 pw.print(" bottom="); pw.println(mOverscanBottom); 8087 } 8088 pw.print(prefix); pw.print("mRestrictedOverscanScreen=("); 8089 pw.print(mRestrictedOverscanScreenLeft); 8090 pw.print(","); pw.print(mRestrictedOverscanScreenTop); 8091 pw.print(") "); pw.print(mRestrictedOverscanScreenWidth); 8092 pw.print("x"); pw.println(mRestrictedOverscanScreenHeight); 8093 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft); 8094 pw.print(","); pw.print(mUnrestrictedScreenTop); 8095 pw.print(") "); pw.print(mUnrestrictedScreenWidth); 8096 pw.print("x"); pw.println(mUnrestrictedScreenHeight); 8097 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft); 8098 pw.print(","); pw.print(mRestrictedScreenTop); 8099 pw.print(") "); pw.print(mRestrictedScreenWidth); 8100 pw.print("x"); pw.println(mRestrictedScreenHeight); 8101 pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft); 8102 pw.print(","); pw.print(mStableFullscreenTop); 8103 pw.print(")-("); pw.print(mStableFullscreenRight); 8104 pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")"); 8105 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft); 8106 pw.print(","); pw.print(mStableTop); 8107 pw.print(")-("); pw.print(mStableRight); 8108 pw.print(","); pw.print(mStableBottom); pw.println(")"); 8109 pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft); 8110 pw.print(","); pw.print(mSystemTop); 8111 pw.print(")-("); pw.print(mSystemRight); 8112 pw.print(","); pw.print(mSystemBottom); pw.println(")"); 8113 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft); 8114 pw.print(","); pw.print(mCurTop); 8115 pw.print(")-("); pw.print(mCurRight); 8116 pw.print(","); pw.print(mCurBottom); pw.println(")"); 8117 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft); 8118 pw.print(","); pw.print(mContentTop); 8119 pw.print(")-("); pw.print(mContentRight); 8120 pw.print(","); pw.print(mContentBottom); pw.println(")"); 8121 pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft); 8122 pw.print(","); pw.print(mVoiceContentTop); 8123 pw.print(")-("); pw.print(mVoiceContentRight); 8124 pw.print(","); pw.print(mVoiceContentBottom); pw.println(")"); 8125 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft); 8126 pw.print(","); pw.print(mDockTop); 8127 pw.print(")-("); pw.print(mDockRight); 8128 pw.print(","); pw.print(mDockBottom); pw.println(")"); 8129 pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer); 8130 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer); 8131 pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream); 8132 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen); 8133 pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken); 8134 if (mLastInputMethodWindow != null) { 8135 pw.print(prefix); pw.print("mLastInputMethodWindow="); 8136 pw.println(mLastInputMethodWindow); 8137 } 8138 if (mLastInputMethodTargetWindow != null) { 8139 pw.print(prefix); pw.print("mLastInputMethodTargetWindow="); 8140 pw.println(mLastInputMethodTargetWindow); 8141 } 8142 if (mStatusBar != null) { 8143 pw.print(prefix); pw.print("mStatusBar="); 8144 pw.print(mStatusBar); pw.print(" isStatusBarKeyguard="); 8145 pw.println(isStatusBarKeyguard()); 8146 } 8147 if (mNavigationBar != null) { 8148 pw.print(prefix); pw.print("mNavigationBar="); 8149 pw.println(mNavigationBar); 8150 } 8151 if (mFocusedWindow != null) { 8152 pw.print(prefix); pw.print("mFocusedWindow="); 8153 pw.println(mFocusedWindow); 8154 } 8155 if (mFocusedApp != null) { 8156 pw.print(prefix); pw.print("mFocusedApp="); 8157 pw.println(mFocusedApp); 8158 } 8159 if (mTopFullscreenOpaqueWindowState != null) { 8160 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState="); 8161 pw.println(mTopFullscreenOpaqueWindowState); 8162 } 8163 if (mTopFullscreenOpaqueOrDimmingWindowState != null) { 8164 pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState="); 8165 pw.println(mTopFullscreenOpaqueOrDimmingWindowState); 8166 } 8167 if (mForcingShowNavBar) { 8168 pw.print(prefix); pw.print("mForcingShowNavBar="); 8169 pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer="); 8170 pw.println(mForcingShowNavBarLayer); 8171 } 8172 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen); 8173 pw.print(" mKeyguardOccluded="); pw.println(mKeyguardOccluded); 8174 pw.print(" mKeyguardOccludedChanged="); pw.println(mKeyguardOccludedChanged); 8175 pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded); 8176 pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar); 8177 pw.print(" mForceStatusBarFromKeyguard="); 8178 pw.println(mForceStatusBarFromKeyguard); 8179 pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed); 8180 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn); 8181 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout); 8182 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive); 8183 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior); 8184 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior); 8185 pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior); 8186 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior); 8187 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation); 8188 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation); 8189 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation); 8190 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation); 8191 pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation); 8192 pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock); 8193 pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation); 8194 8195 mGlobalKeyManager.dump(prefix, pw); 8196 mStatusBarController.dump(pw, prefix); 8197 mNavigationBarController.dump(pw, prefix); 8198 PolicyControl.dump(prefix, pw); 8199 8200 if (mWakeGestureListener != null) { 8201 mWakeGestureListener.dump(pw, prefix); 8202 } 8203 if (mOrientationListener != null) { 8204 mOrientationListener.dump(pw, prefix); 8205 } 8206 if (mBurnInProtectionHelper != null) { 8207 mBurnInProtectionHelper.dump(prefix, pw); 8208 } 8209 if (mKeyguardDelegate != null) { 8210 mKeyguardDelegate.dump(prefix, pw); 8211 } 8212 } 8213} 8214