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