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