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