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