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