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