PhoneWindowManager.java revision 84e863e02f07415b3437295a3752a0052556836c
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 static final boolean SHOW_PROCESSES_ON_ALT_MENU = false; 181 182 // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key. 183 // No longer recommended for desk docks; 184 static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false; 185 186 static final boolean ALTERNATE_CAR_MODE_NAV_SIZE = false; 187 188 static final int SHORT_PRESS_POWER_NOTHING = 0; 189 static final int SHORT_PRESS_POWER_GO_TO_SLEEP = 1; 190 static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2; 191 static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3; 192 static final int SHORT_PRESS_POWER_GO_HOME = 4; 193 194 static final int LONG_PRESS_POWER_NOTHING = 0; 195 static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1; 196 static final int LONG_PRESS_POWER_SHUT_OFF = 2; 197 static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3; 198 199 static final int LONG_PRESS_BACK_NOTHING = 0; 200 static final int LONG_PRESS_BACK_GO_TO_VOICE_ASSIST = 1; 201 202 static final int MULTI_PRESS_POWER_NOTHING = 0; 203 static final int MULTI_PRESS_POWER_THEATER_MODE = 1; 204 static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2; 205 206 // Number of presses needed before we induce panic press behavior on the back button 207 static final int PANIC_PRESS_BACK_COUNT = 4; 208 static final int PANIC_PRESS_BACK_NOTHING = 0; 209 static final int PANIC_PRESS_BACK_HOME = 1; 210 211 // These need to match the documentation/constant in 212 // core/res/res/values/config.xml 213 static final int LONG_PRESS_HOME_NOTHING = 0; 214 static final int LONG_PRESS_HOME_RECENT_SYSTEM_UI = 1; 215 static final int LONG_PRESS_HOME_ASSIST = 2; 216 static final int LAST_LONG_PRESS_HOME_BEHAVIOR = LONG_PRESS_HOME_ASSIST; 217 218 static final int DOUBLE_TAP_HOME_NOTHING = 0; 219 static final int DOUBLE_TAP_HOME_RECENT_SYSTEM_UI = 1; 220 221 static final int SHORT_PRESS_WINDOW_NOTHING = 0; 222 static final int SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE = 1; 223 224 static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP = 0; 225 static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME = 1; 226 227 static final int PENDING_KEY_NULL = -1; 228 229 // Controls navigation bar opacity depending on which workspace stacks are currently 230 // visible. 231 // Nav bar is always opaque when either the freeform stack or docked stack is visible. 232 static final int NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED = 0; 233 // Nav bar is always translucent when the freeform stack is visible, otherwise always opaque. 234 static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1; 235 236 static final int APPLICATION_MEDIA_SUBLAYER = -2; 237 static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1; 238 static final int APPLICATION_PANEL_SUBLAYER = 1; 239 static final int APPLICATION_SUB_PANEL_SUBLAYER = 2; 240 static final int APPLICATION_ABOVE_SUB_PANEL_SUBLAYER = 3; 241 242 static public final String SYSTEM_DIALOG_REASON_KEY = "reason"; 243 static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions"; 244 static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps"; 245 static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey"; 246 static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist"; 247 248 /** 249 * These are the system UI flags that, when changing, can cause the layout 250 * of the screen to change. 251 */ 252 static final int SYSTEM_UI_CHANGING_LAYOUT = 253 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 254 | View.SYSTEM_UI_FLAG_FULLSCREEN 255 | View.STATUS_BAR_TRANSLUCENT 256 | View.NAVIGATION_BAR_TRANSLUCENT 257 | View.STATUS_BAR_TRANSPARENT 258 | View.NAVIGATION_BAR_TRANSPARENT; 259 260 private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder() 261 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) 262 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) 263 .build(); 264 265 // The panic gesture may become active only after the keyguard is dismissed and the immersive 266 // app shows again. If that doesn't happen for 30s we drop the gesture. 267 private static final long PANIC_GESTURE_EXPIRATION = 30000; 268 269 private static final String SYSUI_PACKAGE = "com.android.systemui"; 270 private static final String SYSUI_SCREENSHOT_SERVICE = 271 "com.android.systemui.screenshot.TakeScreenshotService"; 272 private static final String SYSUI_SCREENSHOT_ERROR_RECEIVER = 273 "com.android.systemui.screenshot.ScreenshotServiceErrorReceiver"; 274 275 private static final int NAV_BAR_BOTTOM = 0; 276 private static final int NAV_BAR_RIGHT = 1; 277 private static final int NAV_BAR_LEFT = 2; 278 279 /** 280 * Keyguard stuff 281 */ 282 private WindowState mKeyguardScrim; 283 private boolean mKeyguardHidden; 284 private boolean mKeyguardDrawnOnce; 285 286 /* Table of Application Launch keys. Maps from key codes to intent categories. 287 * 288 * These are special keys that are used to launch particular kinds of applications, 289 * such as a web browser. HID defines nearly a hundred of them in the Consumer (0x0C) 290 * usage page. We don't support quite that many yet... 291 */ 292 static SparseArray<String> sApplicationLaunchKeyCategories; 293 static { 294 sApplicationLaunchKeyCategories = new SparseArray<String>(); 295 sApplicationLaunchKeyCategories.append( 296 KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER); 297 sApplicationLaunchKeyCategories.append( 298 KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL); 299 sApplicationLaunchKeyCategories.append( 300 KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS); 301 sApplicationLaunchKeyCategories.append( 302 KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR); 303 sApplicationLaunchKeyCategories.append( 304 KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC); 305 sApplicationLaunchKeyCategories.append( 306 KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR); 307 } 308 309 /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */ 310 static final int WAITING_FOR_DRAWN_TIMEOUT = 1000; 311 312 /** Amount of time (in milliseconds) a toast window can be shown. */ 313 public static final int TOAST_WINDOW_TIMEOUT = 3500; // 3.5 seconds 314 315 /** 316 * Lock protecting internal state. Must not call out into window 317 * manager with lock held. (This lock will be acquired in places 318 * where the window manager is calling in with its own lock held.) 319 */ 320 private final Object mLock = new Object(); 321 322 Context mContext; 323 IWindowManager mWindowManager; 324 WindowManagerFuncs mWindowManagerFuncs; 325 WindowManagerInternal mWindowManagerInternal; 326 PowerManager mPowerManager; 327 ActivityManagerInternal mActivityManagerInternal; 328 InputManagerInternal mInputManagerInternal; 329 DreamManagerInternal mDreamManagerInternal; 330 PowerManagerInternal mPowerManagerInternal; 331 IStatusBarService mStatusBarService; 332 StatusBarManagerInternal mStatusBarManagerInternal; 333 boolean mPreloadedRecentApps; 334 final Object mServiceAquireLock = new Object(); 335 Vibrator mVibrator; // Vibrator for giving feedback of orientation changes 336 SearchManager mSearchManager; 337 AccessibilityManager mAccessibilityManager; 338 BurnInProtectionHelper mBurnInProtectionHelper; 339 AppOpsManager mAppOpsManager; 340 private boolean mHasFeatureWatch; 341 342 // Vibrator pattern for haptic feedback of a long press. 343 long[] mLongPressVibePattern; 344 345 // Vibrator pattern for haptic feedback of virtual key press. 346 long[] mVirtualKeyVibePattern; 347 348 // Vibrator pattern for a short vibration. 349 long[] mKeyboardTapVibePattern; 350 351 // Vibrator pattern for a short vibration when tapping on an hour/minute tick of a Clock. 352 long[] mClockTickVibePattern; 353 354 // Vibrator pattern for a short vibration when tapping on a day/month/year date of a Calendar. 355 long[] mCalendarDateVibePattern; 356 357 // Vibrator pattern for haptic feedback during boot when safe mode is disabled. 358 long[] mSafeModeDisabledVibePattern; 359 360 // Vibrator pattern for haptic feedback during boot when safe mode is enabled. 361 long[] mSafeModeEnabledVibePattern; 362 363 // Vibrator pattern for haptic feedback of a context click. 364 long[] mContextClickVibePattern; 365 366 /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */ 367 boolean mEnableShiftMenuBugReports = false; 368 369 boolean mSafeMode; 370 WindowState mStatusBar = null; 371 int mStatusBarHeight; 372 WindowState mNavigationBar = null; 373 boolean mHasNavigationBar = false; 374 boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side? 375 int mNavigationBarPosition = NAV_BAR_BOTTOM; 376 int[] mNavigationBarHeightForRotationDefault = new int[4]; 377 int[] mNavigationBarWidthForRotationDefault = new int[4]; 378 int[] mNavigationBarHeightForRotationInCarMode = new int[4]; 379 int[] mNavigationBarWidthForRotationInCarMode = new int[4]; 380 381 private LongSparseArray<IShortcutService> mShortcutKeyServices = new LongSparseArray<>(); 382 383 // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key. 384 // This is for car dock and this is updated from resource. 385 private boolean mEnableCarDockHomeCapture = true; 386 387 boolean mBootMessageNeedsHiding; 388 KeyguardServiceDelegate mKeyguardDelegate; 389 final Runnable mWindowManagerDrawCallback = new Runnable() { 390 @Override 391 public void run() { 392 if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!"); 393 mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE); 394 } 395 }; 396 final DrawnListener mKeyguardDrawnCallback = new DrawnListener() { 397 @Override 398 public void onDrawn() { 399 if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn."); 400 mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE); 401 } 402 }; 403 404 GlobalActions mGlobalActions; 405 Handler mHandler; 406 WindowState mLastInputMethodWindow = null; 407 WindowState mLastInputMethodTargetWindow = null; 408 409 // FIXME This state is shared between the input reader and handler thread. 410 // Technically it's broken and buggy but it has been like this for many years 411 // and we have not yet seen any problems. Someday we'll rewrite this logic 412 // so that only one thread is involved in handling input policy. Unfortunately 413 // it's on a critical path for power management so we can't just post the work to the 414 // handler thread. We'll need to resolve this someday by teaching the input dispatcher 415 // to hold wakelocks during dispatch and eliminating the critical path. 416 volatile boolean mPowerKeyHandled; 417 volatile boolean mBackKeyHandled; 418 volatile boolean mBeganFromNonInteractive; 419 volatile int mPowerKeyPressCounter; 420 volatile int mBackKeyPressCounter; 421 volatile boolean mEndCallKeyHandled; 422 volatile boolean mCameraGestureTriggeredDuringGoingToSleep; 423 volatile boolean mGoingToSleep; 424 volatile boolean mRecentsVisible; 425 volatile boolean mTvPictureInPictureVisible; 426 427 // Used to hold the last user key used to wake the device. This helps us prevent up events 428 // from being passed to the foregrounded app without a corresponding down event 429 volatile int mPendingWakeKey = PENDING_KEY_NULL; 430 431 int mRecentAppsHeldModifiers; 432 boolean mLanguageSwitchKeyPressed; 433 434 int mLidState = LID_ABSENT; 435 int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT; 436 boolean mHaveBuiltInKeyboard; 437 438 boolean mSystemReady; 439 boolean mSystemBooted; 440 private boolean mDeferBindKeyguard; 441 boolean mHdmiPlugged; 442 HdmiControl mHdmiControl; 443 IUiModeManager mUiModeManager; 444 int mUiMode; 445 int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED; 446 int mLidOpenRotation; 447 int mCarDockRotation; 448 int mDeskDockRotation; 449 int mUndockedHdmiRotation; 450 int mDemoHdmiRotation; 451 boolean mDemoHdmiRotationLock; 452 int mDemoRotation; 453 boolean mDemoRotationLock; 454 455 boolean mWakeGestureEnabledSetting; 456 MyWakeGestureListener mWakeGestureListener; 457 458 // Default display does not rotate, apps that require non-default orientation will have to 459 // have the orientation emulated. 460 private boolean mForceDefaultOrientation = false; 461 462 int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE; 463 int mUserRotation = Surface.ROTATION_0; 464 boolean mAccelerometerDefault; 465 466 boolean mSupportAutoRotation; 467 int mAllowAllRotations = -1; 468 boolean mCarDockEnablesAccelerometer; 469 boolean mDeskDockEnablesAccelerometer; 470 int mLidKeyboardAccessibility; 471 int mLidNavigationAccessibility; 472 boolean mLidControlsScreenLock; 473 boolean mLidControlsSleep; 474 int mShortPressOnPowerBehavior; 475 int mLongPressOnPowerBehavior; 476 int mDoublePressOnPowerBehavior; 477 int mTriplePressOnPowerBehavior; 478 int mLongPressOnBackBehavior; 479 int mPanicPressOnBackBehavior; 480 int mShortPressOnSleepBehavior; 481 int mShortPressWindowBehavior; 482 boolean mAwake; 483 boolean mScreenOnEarly; 484 boolean mScreenOnFully; 485 ScreenOnListener mScreenOnListener; 486 boolean mKeyguardDrawComplete; 487 boolean mWindowManagerDrawComplete; 488 boolean mOrientationSensorEnabled = false; 489 int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 490 boolean mHasSoftInput = false; 491 boolean mTranslucentDecorEnabled = true; 492 boolean mUseTvRouting; 493 494 int mPointerLocationMode = 0; // guarded by mLock 495 496 // The last window we were told about in focusChanged. 497 WindowState mFocusedWindow; 498 IApplicationToken mFocusedApp; 499 500 PointerLocationView mPointerLocationView; 501 502 // The current size of the screen; really; extends into the overscan area of 503 // the screen and doesn't account for any system elements like the status bar. 504 int mOverscanScreenLeft, mOverscanScreenTop; 505 int mOverscanScreenWidth, mOverscanScreenHeight; 506 // The current visible size of the screen; really; (ir)regardless of whether the status 507 // bar can be hidden but not extending into the overscan area. 508 int mUnrestrictedScreenLeft, mUnrestrictedScreenTop; 509 int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight; 510 // Like mOverscanScreen*, but allowed to move into the overscan region where appropriate. 511 int mRestrictedOverscanScreenLeft, mRestrictedOverscanScreenTop; 512 int mRestrictedOverscanScreenWidth, mRestrictedOverscanScreenHeight; 513 // The current size of the screen; these may be different than (0,0)-(dw,dh) 514 // if the status bar can't be hidden; in that case it effectively carves out 515 // that area of the display from all other windows. 516 int mRestrictedScreenLeft, mRestrictedScreenTop; 517 int mRestrictedScreenWidth, mRestrictedScreenHeight; 518 // During layout, the current screen borders accounting for any currently 519 // visible system UI elements. 520 int mSystemLeft, mSystemTop, mSystemRight, mSystemBottom; 521 // For applications requesting stable content insets, these are them. 522 int mStableLeft, mStableTop, mStableRight, mStableBottom; 523 // For applications requesting stable content insets but have also set the 524 // fullscreen window flag, these are the stable dimensions without the status bar. 525 int mStableFullscreenLeft, mStableFullscreenTop; 526 int mStableFullscreenRight, mStableFullscreenBottom; 527 // During layout, the current screen borders with all outer decoration 528 // (status bar, input method dock) accounted for. 529 int mCurLeft, mCurTop, mCurRight, mCurBottom; 530 // During layout, the frame in which content should be displayed 531 // to the user, accounting for all screen decoration except for any 532 // space they deem as available for other content. This is usually 533 // the same as mCur*, but may be larger if the screen decor has supplied 534 // content insets. 535 int mContentLeft, mContentTop, mContentRight, mContentBottom; 536 // During layout, the frame in which voice content should be displayed 537 // to the user, accounting for all screen decoration except for any 538 // space they deem as available for other content. 539 int mVoiceContentLeft, mVoiceContentTop, mVoiceContentRight, mVoiceContentBottom; 540 // During layout, the current screen borders along which input method 541 // windows are placed. 542 int mDockLeft, mDockTop, mDockRight, mDockBottom; 543 // During layout, the layer at which the doc window is placed. 544 int mDockLayer; 545 // During layout, this is the layer of the status bar. 546 int mStatusBarLayer; 547 int mLastSystemUiFlags; 548 // Bits that we are in the process of clearing, so we want to prevent 549 // them from being set by applications until everything has been updated 550 // to have them clear. 551 int mResettingSystemUiFlags = 0; 552 // Bits that we are currently always keeping cleared. 553 int mForceClearedSystemUiFlags = 0; 554 int mLastFullscreenStackSysUiFlags; 555 int mLastDockedStackSysUiFlags; 556 final Rect mNonDockedStackBounds = new Rect(); 557 final Rect mDockedStackBounds = new Rect(); 558 final Rect mLastNonDockedStackBounds = new Rect(); 559 final Rect mLastDockedStackBounds = new Rect(); 560 561 // What we last reported to system UI about whether the compatibility 562 // menu needs to be displayed. 563 boolean mLastFocusNeedsMenu = false; 564 // If nonzero, a panic gesture was performed at that time in uptime millis and is still pending. 565 private long mPendingPanicGestureUptime; 566 567 InputConsumer mInputConsumer = null; 568 569 static final Rect mTmpParentFrame = new Rect(); 570 static final Rect mTmpDisplayFrame = new Rect(); 571 static final Rect mTmpOverscanFrame = new Rect(); 572 static final Rect mTmpContentFrame = new Rect(); 573 static final Rect mTmpVisibleFrame = new Rect(); 574 static final Rect mTmpDecorFrame = new Rect(); 575 static final Rect mTmpStableFrame = new Rect(); 576 static final Rect mTmpNavigationFrame = new Rect(); 577 static final Rect mTmpOutsetFrame = new Rect(); 578 private static final Rect mTmpRect = new Rect(); 579 580 WindowState mTopFullscreenOpaqueWindowState; 581 WindowState mTopFullscreenOpaqueOrDimmingWindowState; 582 WindowState mTopDockedOpaqueWindowState; 583 WindowState mTopDockedOpaqueOrDimmingWindowState; 584 HashSet<IApplicationToken> mAppsToBeHidden = new HashSet<IApplicationToken>(); 585 HashSet<IApplicationToken> mAppsThatDismissKeyguard = new HashSet<IApplicationToken>(); 586 boolean mTopIsFullscreen; 587 boolean mForceStatusBar; 588 boolean mForceStatusBarFromKeyguard; 589 private boolean mForceStatusBarTransparent; 590 int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED; 591 boolean mHideLockScreen; 592 boolean mForcingShowNavBar; 593 int mForcingShowNavBarLayer; 594 595 // States of keyguard dismiss. 596 private static final int DISMISS_KEYGUARD_NONE = 0; // Keyguard not being dismissed. 597 private static final int DISMISS_KEYGUARD_START = 1; // Keyguard needs to be dismissed. 598 private static final int DISMISS_KEYGUARD_CONTINUE = 2; // Keyguard has been dismissed. 599 int mDismissKeyguard = DISMISS_KEYGUARD_NONE; 600 601 /** 602 * Indicates that we asked the Keyguard to be dismissed and we just wait for the Keyguard to 603 * dismiss itself. 604 */ 605 @GuardedBy("Lw") 606 private boolean mCurrentlyDismissingKeyguard; 607 608 /** The window that is currently dismissing the keyguard. Dismissing the keyguard must only 609 * be done once per window. */ 610 private WindowState mWinDismissingKeyguard; 611 612 /** When window is currently dismissing the keyguard, dismissing the keyguard must handle 613 * the keygaurd secure state change instantly case, e.g. the use case of inserting a PIN 614 * lock SIM card. This variable is used to record the previous keyguard secure state for 615 * monitoring secure state change on window dismissing keyguard. */ 616 private boolean mSecureDismissingKeyguard; 617 618 /** The window that is currently showing "over" the keyguard. If there is an app window 619 * belonging to another app on top of this the keyguard shows. If there is a fullscreen 620 * app window under this, still dismiss the keyguard but don't show the app underneath. Show 621 * the wallpaper. */ 622 private WindowState mWinShowWhenLocked; 623 624 boolean mShowingLockscreen; 625 boolean mShowingDream; 626 boolean mDreamingLockscreen; 627 boolean mDreamingSleepTokenNeeded; 628 SleepToken mDreamingSleepToken; 629 SleepToken mScreenOffSleepToken; 630 boolean mKeyguardSecure; 631 boolean mKeyguardSecureIncludingHidden; 632 volatile boolean mKeyguardOccluded; 633 boolean mHomePressed; 634 boolean mHomeConsumed; 635 boolean mHomeDoubleTapPending; 636 Intent mHomeIntent; 637 Intent mCarDockIntent; 638 Intent mDeskDockIntent; 639 boolean mSearchKeyShortcutPending; 640 boolean mConsumeSearchKeyUp; 641 boolean mAssistKeyLongPressed; 642 boolean mPendingMetaAction; 643 boolean mPendingCapsLockToggle; 644 int mMetaState; 645 int mInitialMetaState; 646 boolean mForceShowSystemBars; 647 648 // support for activating the lock screen while the screen is on 649 boolean mAllowLockscreenWhenOn; 650 int mLockScreenTimeout; 651 boolean mLockScreenTimerActive; 652 653 // Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.) 654 int mEndcallBehavior; 655 656 // Behavior of POWER button while in-call and screen on. 657 // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.) 658 int mIncallPowerBehavior; 659 660 // Behavior of Back button while in-call and screen on 661 int mIncallBackBehavior; 662 663 Display mDisplay; 664 665 private int mDisplayRotation; 666 667 int mLandscapeRotation = 0; // default landscape rotation 668 int mSeascapeRotation = 0; // "other" landscape rotation, 180 degrees from mLandscapeRotation 669 int mPortraitRotation = 0; // default portrait rotation 670 int mUpsideDownRotation = 0; // "other" portrait rotation 671 672 int mOverscanLeft = 0; 673 int mOverscanTop = 0; 674 int mOverscanRight = 0; 675 int mOverscanBottom = 0; 676 677 // What we do when the user long presses on home 678 private int mLongPressOnHomeBehavior; 679 680 // What we do when the user double-taps on home 681 private int mDoubleTapOnHomeBehavior; 682 683 // Allowed theater mode wake actions 684 private boolean mAllowTheaterModeWakeFromKey; 685 private boolean mAllowTheaterModeWakeFromPowerKey; 686 private boolean mAllowTheaterModeWakeFromMotion; 687 private boolean mAllowTheaterModeWakeFromMotionWhenNotDreaming; 688 private boolean mAllowTheaterModeWakeFromCameraLens; 689 private boolean mAllowTheaterModeWakeFromLidSwitch; 690 private boolean mAllowTheaterModeWakeFromWakeGesture; 691 692 // Whether to support long press from power button in non-interactive mode 693 private boolean mSupportLongPressPowerWhenNonInteractive; 694 695 // Whether to go to sleep entering theater mode from power button 696 private boolean mGoToSleepOnButtonPressTheaterMode; 697 698 // Screenshot trigger states 699 // Time to volume and power must be pressed within this interval of each other. 700 private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150; 701 // Increase the chord delay when taking a screenshot from the keyguard 702 private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f; 703 private boolean mScreenshotChordEnabled; 704 private boolean mScreenshotChordVolumeDownKeyTriggered; 705 private long mScreenshotChordVolumeDownKeyTime; 706 private boolean mScreenshotChordVolumeDownKeyConsumed; 707 private boolean mScreenshotChordVolumeUpKeyTriggered; 708 private boolean mScreenshotChordPowerKeyTriggered; 709 private long mScreenshotChordPowerKeyTime; 710 711 /* The number of steps between min and max brightness */ 712 private static final int BRIGHTNESS_STEPS = 10; 713 714 SettingsObserver mSettingsObserver; 715 ShortcutManager mShortcutManager; 716 PowerManager.WakeLock mBroadcastWakeLock; 717 PowerManager.WakeLock mPowerKeyWakeLock; 718 boolean mHavePendingMediaKeyRepeatWithWakeLock; 719 720 private int mCurrentUserId; 721 722 // Maps global key codes to the components that will handle them. 723 private GlobalKeyManager mGlobalKeyManager; 724 725 // Fallback actions by key code. 726 private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions = 727 new SparseArray<KeyCharacterMap.FallbackAction>(); 728 729 private final LogDecelerateInterpolator mLogDecelerateInterpolator 730 = new LogDecelerateInterpolator(100, 0); 731 732 private final MutableBoolean mTmpBoolean = new MutableBoolean(false); 733 734 private static final int MSG_ENABLE_POINTER_LOCATION = 1; 735 private static final int MSG_DISABLE_POINTER_LOCATION = 2; 736 private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3; 737 private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4; 738 private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5; 739 private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6; 740 private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7; 741 private static final int MSG_DISPATCH_SHOW_RECENTS = 9; 742 private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10; 743 private static final int MSG_HIDE_BOOT_MESSAGE = 11; 744 private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12; 745 private static final int MSG_POWER_DELAYED_PRESS = 13; 746 private static final int MSG_POWER_LONG_PRESS = 14; 747 private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 15; 748 private static final int MSG_REQUEST_TRANSIENT_BARS = 16; 749 private static final int MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU = 17; 750 private static final int MSG_BACK_LONG_PRESS = 18; 751 private static final int MSG_DISPOSE_INPUT_CONSUMER = 19; 752 private static final int MSG_BACK_DELAYED_PRESS = 20; 753 754 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0; 755 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1; 756 757 private class PolicyHandler extends Handler { 758 @Override 759 public void handleMessage(Message msg) { 760 switch (msg.what) { 761 case MSG_ENABLE_POINTER_LOCATION: 762 enablePointerLocation(); 763 break; 764 case MSG_DISABLE_POINTER_LOCATION: 765 disablePointerLocation(); 766 break; 767 case MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK: 768 dispatchMediaKeyWithWakeLock((KeyEvent)msg.obj); 769 break; 770 case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK: 771 dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj); 772 break; 773 case MSG_DISPATCH_SHOW_RECENTS: 774 showRecentApps(false, msg.arg1 != 0); 775 break; 776 case MSG_DISPATCH_SHOW_GLOBAL_ACTIONS: 777 showGlobalActionsInternal(); 778 break; 779 case MSG_KEYGUARD_DRAWN_COMPLETE: 780 if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete"); 781 finishKeyguardDrawn(); 782 break; 783 case MSG_KEYGUARD_DRAWN_TIMEOUT: 784 Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete"); 785 finishKeyguardDrawn(); 786 break; 787 case MSG_WINDOW_MANAGER_DRAWN_COMPLETE: 788 if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete"); 789 finishWindowsDrawn(); 790 break; 791 case MSG_HIDE_BOOT_MESSAGE: 792 handleHideBootMessage(); 793 break; 794 case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK: 795 launchVoiceAssistWithWakeLock(msg.arg1 != 0); 796 break; 797 case MSG_POWER_DELAYED_PRESS: 798 powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2); 799 finishPowerKeyPress(); 800 break; 801 case MSG_POWER_LONG_PRESS: 802 powerLongPress(); 803 break; 804 case MSG_UPDATE_DREAMING_SLEEP_TOKEN: 805 updateDreamingSleepToken(msg.arg1 != 0); 806 break; 807 case MSG_REQUEST_TRANSIENT_BARS: 808 WindowState targetBar = (msg.arg1 == MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS) ? 809 mStatusBar : mNavigationBar; 810 if (targetBar != null) { 811 requestTransientBars(targetBar); 812 } 813 break; 814 case MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU: 815 showTvPictureInPictureMenuInternal(); 816 break; 817 case MSG_BACK_LONG_PRESS: 818 backLongPress(); 819 finishBackKeyPress(); 820 break; 821 case MSG_DISPOSE_INPUT_CONSUMER: 822 disposeInputConsumer((InputConsumer) msg.obj); 823 break; 824 case MSG_BACK_DELAYED_PRESS: 825 backMultiPressAction((Long) msg.obj, msg.arg1); 826 finishBackKeyPress(); 827 break; 828 } 829 } 830 } 831 832 private UEventObserver mHDMIObserver = new UEventObserver() { 833 @Override 834 public void onUEvent(UEventObserver.UEvent event) { 835 setHdmiPlugged("1".equals(event.get("SWITCH_STATE"))); 836 } 837 }; 838 839 class SettingsObserver extends ContentObserver { 840 SettingsObserver(Handler handler) { 841 super(handler); 842 } 843 844 void observe() { 845 // Observe all users' changes 846 ContentResolver resolver = mContext.getContentResolver(); 847 resolver.registerContentObserver(Settings.System.getUriFor( 848 Settings.System.END_BUTTON_BEHAVIOR), false, this, 849 UserHandle.USER_ALL); 850 resolver.registerContentObserver(Settings.Secure.getUriFor( 851 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this, 852 UserHandle.USER_ALL); 853 resolver.registerContentObserver(Settings.Secure.getUriFor( 854 Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR), false, this, 855 UserHandle.USER_ALL); 856 resolver.registerContentObserver(Settings.Secure.getUriFor( 857 Settings.Secure.WAKE_GESTURE_ENABLED), false, this, 858 UserHandle.USER_ALL); 859 resolver.registerContentObserver(Settings.System.getUriFor( 860 Settings.System.ACCELEROMETER_ROTATION), false, this, 861 UserHandle.USER_ALL); 862 resolver.registerContentObserver(Settings.System.getUriFor( 863 Settings.System.USER_ROTATION), false, this, 864 UserHandle.USER_ALL); 865 resolver.registerContentObserver(Settings.System.getUriFor( 866 Settings.System.SCREEN_OFF_TIMEOUT), false, this, 867 UserHandle.USER_ALL); 868 resolver.registerContentObserver(Settings.System.getUriFor( 869 Settings.System.POINTER_LOCATION), false, this, 870 UserHandle.USER_ALL); 871 resolver.registerContentObserver(Settings.Secure.getUriFor( 872 Settings.Secure.DEFAULT_INPUT_METHOD), false, this, 873 UserHandle.USER_ALL); 874 resolver.registerContentObserver(Settings.Secure.getUriFor( 875 Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this, 876 UserHandle.USER_ALL); 877 resolver.registerContentObserver(Settings.Global.getUriFor( 878 Settings.Global.POLICY_CONTROL), false, this, 879 UserHandle.USER_ALL); 880 updateSettings(); 881 } 882 883 @Override public void onChange(boolean selfChange) { 884 updateSettings(); 885 updateRotation(false); 886 } 887 } 888 889 class MyWakeGestureListener extends WakeGestureListener { 890 MyWakeGestureListener(Context context, Handler handler) { 891 super(context, handler); 892 } 893 894 @Override 895 public void onWakeUp() { 896 synchronized (mLock) { 897 if (shouldEnableWakeGestureLp()) { 898 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); 899 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture, 900 "android.policy:GESTURE"); 901 } 902 } 903 } 904 } 905 906 class MyOrientationListener extends WindowOrientationListener { 907 private final Runnable mUpdateRotationRunnable = new Runnable() { 908 @Override 909 public void run() { 910 // send interaction hint to improve redraw performance 911 mPowerManagerInternal.powerHint(PowerManagerInternal.POWER_HINT_INTERACTION, 0); 912 updateRotation(false); 913 } 914 }; 915 916 MyOrientationListener(Context context, Handler handler) { 917 super(context, handler); 918 } 919 920 @Override 921 public void onProposedRotationChanged(int rotation) { 922 if (localLOGV) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation); 923 mHandler.post(mUpdateRotationRunnable); 924 } 925 } 926 MyOrientationListener mOrientationListener; 927 928 private final StatusBarController mStatusBarController = new StatusBarController(); 929 930 private final BarController mNavigationBarController = new BarController("NavigationBar", 931 View.NAVIGATION_BAR_TRANSIENT, 932 View.NAVIGATION_BAR_UNHIDE, 933 View.NAVIGATION_BAR_TRANSLUCENT, 934 StatusBarManager.WINDOW_NAVIGATION_BAR, 935 WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, 936 View.NAVIGATION_BAR_TRANSPARENT); 937 938 private ImmersiveModeConfirmation mImmersiveModeConfirmation; 939 940 private SystemGesturesPointerEventListener mSystemGestures; 941 942 IStatusBarService getStatusBarService() { 943 synchronized (mServiceAquireLock) { 944 if (mStatusBarService == null) { 945 mStatusBarService = IStatusBarService.Stub.asInterface( 946 ServiceManager.getService("statusbar")); 947 } 948 return mStatusBarService; 949 } 950 } 951 952 StatusBarManagerInternal getStatusBarManagerInternal() { 953 synchronized (mServiceAquireLock) { 954 if (mStatusBarManagerInternal == null) { 955 mStatusBarManagerInternal = 956 LocalServices.getService(StatusBarManagerInternal.class); 957 } 958 return mStatusBarManagerInternal; 959 } 960 } 961 962 /* 963 * We always let the sensor be switched on by default except when 964 * the user has explicitly disabled sensor based rotation or when the 965 * screen is switched off. 966 */ 967 boolean needSensorRunningLp() { 968 if (mSupportAutoRotation) { 969 if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR 970 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 971 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT 972 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) { 973 // If the application has explicitly requested to follow the 974 // orientation, then we need to turn the sensor on. 975 return true; 976 } 977 } 978 if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) || 979 (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK 980 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK 981 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) { 982 // enable accelerometer if we are docked in a dock that enables accelerometer 983 // orientation management, 984 return true; 985 } 986 if (mUserRotationMode == USER_ROTATION_LOCKED) { 987 // If the setting for using the sensor by default is enabled, then 988 // we will always leave it on. Note that the user could go to 989 // a window that forces an orientation that does not use the 990 // sensor and in theory we could turn it off... however, when next 991 // turning it on we won't have a good value for the current 992 // orientation for a little bit, which can cause orientation 993 // changes to lag, so we'd like to keep it always on. (It will 994 // still be turned off when the screen is off.) 995 return false; 996 } 997 return mSupportAutoRotation; 998 } 999 1000 /* 1001 * Various use cases for invoking this function 1002 * screen turning off, should always disable listeners if already enabled 1003 * screen turned on and current app has sensor based orientation, enable listeners 1004 * if not already enabled 1005 * screen turned on and current app does not have sensor orientation, disable listeners if 1006 * already enabled 1007 * screen turning on and current app has sensor based orientation, enable listeners if needed 1008 * screen turning on and current app has nosensor based orientation, do nothing 1009 */ 1010 void updateOrientationListenerLp() { 1011 if (!mOrientationListener.canDetectOrientation()) { 1012 // If sensor is turned off or nonexistent for some reason 1013 return; 1014 } 1015 // Could have been invoked due to screen turning on or off or 1016 // change of the currently visible window's orientation. 1017 if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly 1018 + ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation 1019 + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled 1020 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete 1021 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete); 1022 boolean disable = true; 1023 // Note: We postpone the rotating of the screen until the keyguard as well as the 1024 // window manager have reported a draw complete. 1025 if (mScreenOnEarly && mAwake && 1026 mKeyguardDrawComplete && mWindowManagerDrawComplete) { 1027 if (needSensorRunningLp()) { 1028 disable = false; 1029 //enable listener if not already enabled 1030 if (!mOrientationSensorEnabled) { 1031 mOrientationListener.enable(); 1032 if(localLOGV) Slog.v(TAG, "Enabling listeners"); 1033 mOrientationSensorEnabled = true; 1034 } 1035 } 1036 } 1037 //check if sensors need to be disabled 1038 if (disable && mOrientationSensorEnabled) { 1039 mOrientationListener.disable(); 1040 if(localLOGV) Slog.v(TAG, "Disabling listeners"); 1041 mOrientationSensorEnabled = false; 1042 } 1043 } 1044 1045 private void interceptBackKeyDown() { 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 } else if (SHOW_PROCESSES_ON_ALT_MENU && 3278 (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) { 3279 Intent service = new Intent(); 3280 service.setClassName(mContext, "com.android.server.LoadAverageService"); 3281 ContentResolver res = mContext.getContentResolver(); 3282 boolean shown = Settings.Global.getInt( 3283 res, Settings.Global.SHOW_PROCESSES, 0) != 0; 3284 if (!shown) { 3285 mContext.startService(service); 3286 } else { 3287 mContext.stopService(service); 3288 } 3289 Settings.Global.putInt( 3290 res, Settings.Global.SHOW_PROCESSES, shown ? 0 : 1); 3291 return -1; 3292 } 3293 } 3294 } else if (keyCode == KeyEvent.KEYCODE_SEARCH) { 3295 if (down) { 3296 if (repeatCount == 0) { 3297 mSearchKeyShortcutPending = true; 3298 mConsumeSearchKeyUp = false; 3299 } 3300 } else { 3301 mSearchKeyShortcutPending = false; 3302 if (mConsumeSearchKeyUp) { 3303 mConsumeSearchKeyUp = false; 3304 return -1; 3305 } 3306 } 3307 return 0; 3308 } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) { 3309 if (!keyguardOn) { 3310 if (down && repeatCount == 0) { 3311 preloadRecentApps(); 3312 } else if (!down) { 3313 toggleRecentApps(); 3314 } 3315 } 3316 return -1; 3317 } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) { 3318 if (down) { 3319 IStatusBarService service = getStatusBarService(); 3320 if (service != null) { 3321 try { 3322 service.expandNotificationsPanel(); 3323 } catch (RemoteException e) { 3324 // do nothing. 3325 } 3326 } 3327 } 3328 } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed() 3329 && event.isCtrlPressed()) { 3330 if (down && repeatCount == 0) { 3331 int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION 3332 : TAKE_SCREENSHOT_FULLSCREEN; 3333 mScreenshotRunnable.setScreenshotType(type); 3334 mHandler.post(mScreenshotRunnable); 3335 return -1; 3336 } 3337 } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) { 3338 if (down && repeatCount == 0 && !isKeyguardLocked()) { 3339 toggleKeyboardShortcutsMenu(event.getDeviceId()); 3340 } 3341 } else if (keyCode == KeyEvent.KEYCODE_ASSIST) { 3342 if (down) { 3343 if (repeatCount == 0) { 3344 mAssistKeyLongPressed = false; 3345 } else if (repeatCount == 1) { 3346 mAssistKeyLongPressed = true; 3347 if (!keyguardOn) { 3348 launchAssistLongPressAction(); 3349 } 3350 } 3351 } else { 3352 if (mAssistKeyLongPressed) { 3353 mAssistKeyLongPressed = false; 3354 } else { 3355 if (!keyguardOn) { 3356 launchAssistAction(null, event.getDeviceId()); 3357 } 3358 } 3359 } 3360 return -1; 3361 } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) { 3362 if (!down) { 3363 Intent voiceIntent; 3364 if (!keyguardOn) { 3365 voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH); 3366 } else { 3367 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface( 3368 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); 3369 if (dic != null) { 3370 try { 3371 dic.exitIdle("voice-search"); 3372 } catch (RemoteException e) { 3373 } 3374 } 3375 voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); 3376 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true); 3377 } 3378 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF); 3379 } 3380 } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) { 3381 if (down && repeatCount == 0) { 3382 mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN); 3383 mHandler.post(mScreenshotRunnable); 3384 } 3385 return -1; 3386 } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP 3387 || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) { 3388 if (down) { 3389 int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1; 3390 3391 // Disable autobrightness if it's on 3392 int auto = Settings.System.getIntForUser( 3393 mContext.getContentResolver(), 3394 Settings.System.SCREEN_BRIGHTNESS_MODE, 3395 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, 3396 UserHandle.USER_CURRENT_OR_SELF); 3397 if (auto != 0) { 3398 Settings.System.putIntForUser(mContext.getContentResolver(), 3399 Settings.System.SCREEN_BRIGHTNESS_MODE, 3400 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, 3401 UserHandle.USER_CURRENT_OR_SELF); 3402 } 3403 3404 int min = mPowerManager.getMinimumScreenBrightnessSetting(); 3405 int max = mPowerManager.getMaximumScreenBrightnessSetting(); 3406 int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction; 3407 int brightness = Settings.System.getIntForUser(mContext.getContentResolver(), 3408 Settings.System.SCREEN_BRIGHTNESS, 3409 mPowerManager.getDefaultScreenBrightnessSetting(), 3410 UserHandle.USER_CURRENT_OR_SELF); 3411 brightness += step; 3412 // Make sure we don't go beyond the limits. 3413 brightness = Math.min(max, brightness); 3414 brightness = Math.max(min, brightness); 3415 3416 Settings.System.putIntForUser(mContext.getContentResolver(), 3417 Settings.System.SCREEN_BRIGHTNESS, brightness, 3418 UserHandle.USER_CURRENT_OR_SELF); 3419 startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG), 3420 UserHandle.CURRENT_OR_SELF); 3421 } 3422 return -1; 3423 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP 3424 || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN 3425 || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) { 3426 if (mUseTvRouting) { 3427 // On TVs volume keys never go to the foreground app. 3428 dispatchDirectAudioEvent(event); 3429 return -1; 3430 } 3431 } 3432 3433 // Toggle Caps Lock on META-ALT. 3434 boolean actionTriggered = false; 3435 if (KeyEvent.isModifierKey(keyCode)) { 3436 if (!mPendingCapsLockToggle) { 3437 // Start tracking meta state for combo. 3438 mInitialMetaState = mMetaState; 3439 mPendingCapsLockToggle = true; 3440 } else if (event.getAction() == KeyEvent.ACTION_UP) { 3441 int altOnMask = mMetaState & KeyEvent.META_ALT_MASK; 3442 int metaOnMask = mMetaState & KeyEvent.META_META_MASK; 3443 3444 // Check for Caps Lock toggle 3445 if ((metaOnMask != 0) && (altOnMask != 0)) { 3446 // Check if nothing else is pressed 3447 if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) { 3448 // Handle Caps Lock Toggle 3449 mInputManagerInternal.toggleCapsLock(event.getDeviceId()); 3450 actionTriggered = true; 3451 } 3452 } 3453 3454 // Always stop tracking when key goes up. 3455 mPendingCapsLockToggle = false; 3456 } 3457 } 3458 // Store current meta state to be able to evaluate it later. 3459 mMetaState = metaState; 3460 3461 if (actionTriggered) { 3462 return -1; 3463 } 3464 3465 if (KeyEvent.isMetaKey(keyCode)) { 3466 if (down) { 3467 mPendingMetaAction = true; 3468 } else if (mPendingMetaAction) { 3469 launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId()); 3470 } 3471 return -1; 3472 } 3473 3474 // Shortcuts are invoked through Search+key, so intercept those here 3475 // Any printing key that is chorded with Search should be consumed 3476 // even if no shortcut was invoked. This prevents text from being 3477 // inadvertently inserted when using a keyboard that has built-in macro 3478 // shortcut keys (that emit Search+x) and some of them are not registered. 3479 if (mSearchKeyShortcutPending) { 3480 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 3481 if (kcm.isPrintingKey(keyCode)) { 3482 mConsumeSearchKeyUp = true; 3483 mSearchKeyShortcutPending = false; 3484 if (down && repeatCount == 0 && !keyguardOn) { 3485 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState); 3486 if (shortcutIntent != null) { 3487 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3488 try { 3489 startActivityAsUser(shortcutIntent, UserHandle.CURRENT); 3490 dismissKeyboardShortcutsMenu(); 3491 } catch (ActivityNotFoundException ex) { 3492 Slog.w(TAG, "Dropping shortcut key combination because " 3493 + "the activity to which it is registered was not found: " 3494 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex); 3495 } 3496 } else { 3497 Slog.i(TAG, "Dropping unregistered shortcut key combination: " 3498 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode)); 3499 } 3500 } 3501 return -1; 3502 } 3503 } 3504 3505 // Invoke shortcuts using Meta. 3506 if (down && repeatCount == 0 && !keyguardOn 3507 && (metaState & KeyEvent.META_META_ON) != 0) { 3508 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 3509 if (kcm.isPrintingKey(keyCode)) { 3510 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, 3511 metaState & ~(KeyEvent.META_META_ON 3512 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON)); 3513 if (shortcutIntent != null) { 3514 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3515 try { 3516 startActivityAsUser(shortcutIntent, UserHandle.CURRENT); 3517 dismissKeyboardShortcutsMenu(); 3518 } catch (ActivityNotFoundException ex) { 3519 Slog.w(TAG, "Dropping shortcut key combination because " 3520 + "the activity to which it is registered was not found: " 3521 + "META+" + KeyEvent.keyCodeToString(keyCode), ex); 3522 } 3523 return -1; 3524 } 3525 } 3526 } 3527 3528 // Handle application launch keys. 3529 if (down && repeatCount == 0 && !keyguardOn) { 3530 String category = sApplicationLaunchKeyCategories.get(keyCode); 3531 if (category != null) { 3532 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category); 3533 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3534 try { 3535 startActivityAsUser(intent, UserHandle.CURRENT); 3536 dismissKeyboardShortcutsMenu(); 3537 } catch (ActivityNotFoundException ex) { 3538 Slog.w(TAG, "Dropping application launch key because " 3539 + "the activity to which it is registered was not found: " 3540 + "keyCode=" + keyCode + ", category=" + category, ex); 3541 } 3542 return -1; 3543 } 3544 } 3545 3546 // Display task switcher for ALT-TAB. 3547 if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) { 3548 if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) { 3549 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK; 3550 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) { 3551 mRecentAppsHeldModifiers = shiftlessModifiers; 3552 showRecentApps(true, false); 3553 return -1; 3554 } 3555 } 3556 } else if (!down && mRecentAppsHeldModifiers != 0 3557 && (metaState & mRecentAppsHeldModifiers) == 0) { 3558 mRecentAppsHeldModifiers = 0; 3559 hideRecentApps(true, false); 3560 } 3561 3562 // Handle input method switching. 3563 if (down && repeatCount == 0 3564 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH 3565 || (keyCode == KeyEvent.KEYCODE_SPACE 3566 && (metaState & KeyEvent.META_META_MASK) != 0))) { 3567 final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0; 3568 mWindowManagerFuncs.switchInputMethod(forwardDirection); 3569 return -1; 3570 } 3571 if (mLanguageSwitchKeyPressed && !down 3572 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH 3573 || keyCode == KeyEvent.KEYCODE_SPACE)) { 3574 mLanguageSwitchKeyPressed = false; 3575 return -1; 3576 } 3577 3578 if (isValidGlobalKey(keyCode) 3579 && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) { 3580 return -1; 3581 } 3582 3583 if (down) { 3584 long shortcutCode = keyCode; 3585 if (event.isCtrlPressed()) { 3586 shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE; 3587 } 3588 3589 if (event.isAltPressed()) { 3590 shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE; 3591 } 3592 3593 if (event.isShiftPressed()) { 3594 shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE; 3595 } 3596 3597 if (event.isMetaPressed()) { 3598 shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE; 3599 } 3600 3601 IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode); 3602 if (shortcutService != null) { 3603 try { 3604 if (isUserSetupComplete()) { 3605 shortcutService.notifyShortcutKeyPressed(shortcutCode); 3606 } 3607 } catch (RemoteException e) { 3608 mShortcutKeyServices.delete(shortcutCode); 3609 } 3610 return -1; 3611 } 3612 } 3613 3614 // Reserve all the META modifier combos for system behavior 3615 if ((metaState & KeyEvent.META_META_ON) != 0) { 3616 return -1; 3617 } 3618 3619 // Let the application handle the key. 3620 return 0; 3621 } 3622 3623 /** {@inheritDoc} */ 3624 @Override 3625 public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) { 3626 // Note: This method is only called if the initial down was unhandled. 3627 if (DEBUG_INPUT) { 3628 Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction() 3629 + ", flags=" + event.getFlags() 3630 + ", keyCode=" + event.getKeyCode() 3631 + ", scanCode=" + event.getScanCode() 3632 + ", metaState=" + event.getMetaState() 3633 + ", repeatCount=" + event.getRepeatCount() 3634 + ", policyFlags=" + policyFlags); 3635 } 3636 3637 KeyEvent fallbackEvent = null; 3638 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 3639 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 3640 final int keyCode = event.getKeyCode(); 3641 final int metaState = event.getMetaState(); 3642 final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN 3643 && event.getRepeatCount() == 0; 3644 3645 // Check for fallback actions specified by the key character map. 3646 final FallbackAction fallbackAction; 3647 if (initialDown) { 3648 fallbackAction = kcm.getFallbackAction(keyCode, metaState); 3649 } else { 3650 fallbackAction = mFallbackActions.get(keyCode); 3651 } 3652 3653 if (fallbackAction != null) { 3654 if (DEBUG_INPUT) { 3655 Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode 3656 + " metaState=" + Integer.toHexString(fallbackAction.metaState)); 3657 } 3658 3659 final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK; 3660 fallbackEvent = KeyEvent.obtain( 3661 event.getDownTime(), event.getEventTime(), 3662 event.getAction(), fallbackAction.keyCode, 3663 event.getRepeatCount(), fallbackAction.metaState, 3664 event.getDeviceId(), event.getScanCode(), 3665 flags, event.getSource(), null); 3666 3667 if (!interceptFallback(win, fallbackEvent, policyFlags)) { 3668 fallbackEvent.recycle(); 3669 fallbackEvent = null; 3670 } 3671 3672 if (initialDown) { 3673 mFallbackActions.put(keyCode, fallbackAction); 3674 } else if (event.getAction() == KeyEvent.ACTION_UP) { 3675 mFallbackActions.remove(keyCode); 3676 fallbackAction.recycle(); 3677 } 3678 } 3679 } 3680 3681 if (DEBUG_INPUT) { 3682 if (fallbackEvent == null) { 3683 Slog.d(TAG, "No fallback."); 3684 } else { 3685 Slog.d(TAG, "Performing fallback: " + fallbackEvent); 3686 } 3687 } 3688 return fallbackEvent; 3689 } 3690 3691 private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) { 3692 int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags); 3693 if ((actions & ACTION_PASS_TO_USER) != 0) { 3694 long delayMillis = interceptKeyBeforeDispatching( 3695 win, fallbackEvent, policyFlags); 3696 if (delayMillis == 0) { 3697 return true; 3698 } 3699 } 3700 return false; 3701 } 3702 3703 @Override 3704 public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService) 3705 throws RemoteException { 3706 synchronized (mLock) { 3707 IShortcutService service = mShortcutKeyServices.get(shortcutCode); 3708 if (service != null && service.asBinder().pingBinder()) { 3709 throw new RemoteException("Key already exists."); 3710 } 3711 3712 mShortcutKeyServices.put(shortcutCode, shortcutService); 3713 } 3714 } 3715 3716 @Override 3717 public boolean canShowDismissingWindowWhileLockedLw() { 3718 // If the keyguard is trusted, it will unlock without a challenge. Therefore, if we are in 3719 // the process of dismissing Keyguard, we don't need to hide them as the phone will be 3720 // unlocked right away in any case. 3721 return mKeyguardDelegate != null && mKeyguardDelegate.isTrusted() 3722 && mCurrentlyDismissingKeyguard; 3723 } 3724 3725 private void launchAssistLongPressAction() { 3726 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); 3727 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST); 3728 3729 // launch the search activity 3730 Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS); 3731 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3732 try { 3733 // TODO: This only stops the factory-installed search manager. 3734 // Need to formalize an API to handle others 3735 SearchManager searchManager = getSearchManager(); 3736 if (searchManager != null) { 3737 searchManager.stopSearch(); 3738 } 3739 startActivityAsUser(intent, UserHandle.CURRENT); 3740 } catch (ActivityNotFoundException e) { 3741 Slog.w(TAG, "No activity to handle assist long press action.", e); 3742 } 3743 } 3744 3745 private void launchAssistAction(String hint, int deviceId) { 3746 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST); 3747 if (!isUserSetupComplete()) { 3748 // Disable opening assist window during setup 3749 return; 3750 } 3751 Bundle args = null; 3752 if (deviceId > Integer.MIN_VALUE) { 3753 args = new Bundle(); 3754 args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId); 3755 } 3756 if ((mContext.getResources().getConfiguration().uiMode 3757 & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) { 3758 // On TV, use legacy handling until assistants are implemented in the proper way. 3759 ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE)) 3760 .launchLegacyAssist(hint, UserHandle.myUserId(), args); 3761 } else { 3762 if (hint != null) { 3763 if (args == null) { 3764 args = new Bundle(); 3765 } 3766 args.putBoolean(hint, true); 3767 } 3768 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3769 if (statusbar != null) { 3770 statusbar.startAssist(args); 3771 } 3772 } 3773 } 3774 3775 private void startActivityAsUser(Intent intent, UserHandle handle) { 3776 if (isUserSetupComplete()) { 3777 mContext.startActivityAsUser(intent, handle); 3778 } else { 3779 Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent); 3780 } 3781 } 3782 3783 private SearchManager getSearchManager() { 3784 if (mSearchManager == null) { 3785 mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); 3786 } 3787 return mSearchManager; 3788 } 3789 3790 private void preloadRecentApps() { 3791 mPreloadedRecentApps = true; 3792 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3793 if (statusbar != null) { 3794 statusbar.preloadRecentApps(); 3795 } 3796 } 3797 3798 private void cancelPreloadRecentApps() { 3799 if (mPreloadedRecentApps) { 3800 mPreloadedRecentApps = false; 3801 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3802 if (statusbar != null) { 3803 statusbar.cancelPreloadRecentApps(); 3804 } 3805 } 3806 } 3807 3808 private void toggleRecentApps() { 3809 mPreloadedRecentApps = false; // preloading no longer needs to be canceled 3810 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3811 if (statusbar != null) { 3812 statusbar.toggleRecentApps(); 3813 } 3814 } 3815 3816 @Override 3817 public void showRecentApps(boolean fromHome) { 3818 mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS); 3819 mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget(); 3820 } 3821 3822 private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) { 3823 mPreloadedRecentApps = false; // preloading no longer needs to be canceled 3824 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3825 if (statusbar != null) { 3826 statusbar.showRecentApps(triggeredFromAltTab, fromHome); 3827 } 3828 } 3829 3830 private void toggleKeyboardShortcutsMenu(int deviceId) { 3831 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3832 if (statusbar != null) { 3833 statusbar.toggleKeyboardShortcutsMenu(deviceId); 3834 } 3835 } 3836 3837 private void dismissKeyboardShortcutsMenu() { 3838 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3839 if (statusbar != null) { 3840 statusbar.dismissKeyboardShortcutsMenu(); 3841 } 3842 } 3843 3844 private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) { 3845 mPreloadedRecentApps = false; // preloading no longer needs to be canceled 3846 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3847 if (statusbar != null) { 3848 statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome); 3849 } 3850 } 3851 3852 void launchHomeFromHotKey() { 3853 launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/); 3854 } 3855 3856 /** 3857 * A home key -> launch home action was detected. Take the appropriate action 3858 * given the situation with the keyguard. 3859 */ 3860 void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) { 3861 if (respectKeyguard) { 3862 if (isKeyguardShowingAndNotOccluded()) { 3863 // don't launch home if keyguard showing 3864 return; 3865 } 3866 3867 if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) { 3868 // when in keyguard restricted mode, must first verify unlock 3869 // before launching home 3870 mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() { 3871 @Override 3872 public void onKeyguardExitResult(boolean success) { 3873 if (success) { 3874 try { 3875 ActivityManagerNative.getDefault().stopAppSwitches(); 3876 } catch (RemoteException e) { 3877 } 3878 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY); 3879 startDockOrHome(true /*fromHomeKey*/, awakenFromDreams); 3880 } 3881 } 3882 }); 3883 return; 3884 } 3885 } 3886 3887 // no keyguard stuff to worry about, just launch home! 3888 try { 3889 ActivityManagerNative.getDefault().stopAppSwitches(); 3890 } catch (RemoteException e) { 3891 } 3892 if (mRecentsVisible) { 3893 // Hide Recents and notify it to launch Home 3894 if (awakenFromDreams) { 3895 awakenDreams(); 3896 } 3897 hideRecentApps(false, true); 3898 } else { 3899 // Otherwise, just launch Home 3900 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY); 3901 startDockOrHome(true /*fromHomeKey*/, awakenFromDreams); 3902 } 3903 } 3904 3905 private final Runnable mClearHideNavigationFlag = new Runnable() { 3906 @Override 3907 public void run() { 3908 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 3909 // Clear flags. 3910 mForceClearedSystemUiFlags &= 3911 ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; 3912 } 3913 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 3914 } 3915 }; 3916 3917 /** 3918 * Input handler used while nav bar is hidden. Captures any touch on the screen, 3919 * to determine when the nav bar should be shown and prevent applications from 3920 * receiving those touches. 3921 */ 3922 final class HideNavInputEventReceiver extends InputEventReceiver { 3923 public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) { 3924 super(inputChannel, looper); 3925 } 3926 3927 @Override 3928 public void onInputEvent(InputEvent event) { 3929 boolean handled = false; 3930 try { 3931 if (event instanceof MotionEvent 3932 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { 3933 final MotionEvent motionEvent = (MotionEvent)event; 3934 if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { 3935 // When the user taps down, we re-show the nav bar. 3936 boolean changed = false; 3937 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 3938 if (mInputConsumer == null) { 3939 return; 3940 } 3941 // Any user activity always causes us to show the 3942 // navigation controls, if they had been hidden. 3943 // We also clear the low profile and only content 3944 // flags so that tapping on the screen will atomically 3945 // restore all currently hidden screen decorations. 3946 int newVal = mResettingSystemUiFlags | 3947 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | 3948 View.SYSTEM_UI_FLAG_LOW_PROFILE | 3949 View.SYSTEM_UI_FLAG_FULLSCREEN; 3950 if (mResettingSystemUiFlags != newVal) { 3951 mResettingSystemUiFlags = newVal; 3952 changed = true; 3953 } 3954 // We don't allow the system's nav bar to be hidden 3955 // again for 1 second, to prevent applications from 3956 // spamming us and keeping it from being shown. 3957 newVal = mForceClearedSystemUiFlags | 3958 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; 3959 if (mForceClearedSystemUiFlags != newVal) { 3960 mForceClearedSystemUiFlags = newVal; 3961 changed = true; 3962 mHandler.postDelayed(mClearHideNavigationFlag, 1000); 3963 } 3964 } 3965 if (changed) { 3966 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 3967 } 3968 } 3969 } 3970 } finally { 3971 finishInputEvent(event, handled); 3972 } 3973 } 3974 } 3975 final InputEventReceiver.Factory mHideNavInputEventReceiverFactory = 3976 new InputEventReceiver.Factory() { 3977 @Override 3978 public InputEventReceiver createInputEventReceiver( 3979 InputChannel inputChannel, Looper looper) { 3980 return new HideNavInputEventReceiver(inputChannel, looper); 3981 } 3982 }; 3983 3984 @Override 3985 public void setRecentsVisibilityLw(boolean visible) { 3986 mRecentsVisible = visible; 3987 } 3988 3989 @Override 3990 public void setTvPipVisibilityLw(boolean visible) { 3991 mTvPictureInPictureVisible = visible; 3992 } 3993 3994 @Override 3995 public int adjustSystemUiVisibilityLw(int visibility) { 3996 mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility); 3997 mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility); 3998 3999 // Reset any bits in mForceClearingStatusBarVisibility that 4000 // are now clear. 4001 mResettingSystemUiFlags &= visibility; 4002 // Clear any bits in the new visibility that are currently being 4003 // force cleared, before reporting it. 4004 return visibility & ~mResettingSystemUiFlags 4005 & ~mForceClearedSystemUiFlags; 4006 } 4007 4008 @Override 4009 public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds, 4010 int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets, 4011 Rect outStableInsets, Rect outOutsets) { 4012 final int fl = PolicyControl.getWindowFlags(null, attrs); 4013 final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs); 4014 final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility); 4015 4016 final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl); 4017 if (useOutsets) { 4018 int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources()); 4019 if (outset > 0) { 4020 if (displayRotation == Surface.ROTATION_0) { 4021 outOutsets.bottom += outset; 4022 } else if (displayRotation == Surface.ROTATION_90) { 4023 outOutsets.right += outset; 4024 } else if (displayRotation == Surface.ROTATION_180) { 4025 outOutsets.top += outset; 4026 } else if (displayRotation == Surface.ROTATION_270) { 4027 outOutsets.left += outset; 4028 } 4029 } 4030 } 4031 4032 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) 4033 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { 4034 int availRight, availBottom; 4035 if (canHideNavigationBar() && 4036 (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) { 4037 availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4038 availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4039 } else { 4040 availRight = mRestrictedScreenLeft + mRestrictedScreenWidth; 4041 availBottom = mRestrictedScreenTop + mRestrictedScreenHeight; 4042 } 4043 if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) { 4044 if ((fl & FLAG_FULLSCREEN) != 0) { 4045 outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop, 4046 availRight - mStableFullscreenRight, 4047 availBottom - mStableFullscreenBottom); 4048 } else { 4049 outContentInsets.set(mStableLeft, mStableTop, 4050 availRight - mStableRight, availBottom - mStableBottom); 4051 } 4052 } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) { 4053 outContentInsets.setEmpty(); 4054 } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN 4055 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) { 4056 outContentInsets.set(mCurLeft, mCurTop, 4057 availRight - mCurRight, availBottom - mCurBottom); 4058 } else { 4059 outContentInsets.set(mCurLeft, mCurTop, 4060 availRight - mCurRight, availBottom - mCurBottom); 4061 } 4062 4063 outStableInsets.set(mStableLeft, mStableTop, 4064 availRight - mStableRight, availBottom - mStableBottom); 4065 if (taskBounds != null) { 4066 calculateRelevantTaskInsets(taskBounds, outContentInsets, 4067 displayWidth, displayHeight); 4068 calculateRelevantTaskInsets(taskBounds, outStableInsets, 4069 displayWidth, displayHeight); 4070 } 4071 return mForceShowSystemBars; 4072 } 4073 outContentInsets.setEmpty(); 4074 outStableInsets.setEmpty(); 4075 return mForceShowSystemBars; 4076 } 4077 4078 /** 4079 * For any given task bounds, the insets relevant for these bounds given the insets relevant 4080 * for the entire display. 4081 */ 4082 private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth, 4083 int displayHeight) { 4084 mTmpRect.set(0, 0, displayWidth, displayHeight); 4085 mTmpRect.inset(inOutInsets); 4086 mTmpRect.intersect(taskBounds); 4087 int leftInset = mTmpRect.left - taskBounds.left; 4088 int topInset = mTmpRect.top - taskBounds.top; 4089 int rightInset = taskBounds.right - mTmpRect.right; 4090 int bottomInset = taskBounds.bottom - mTmpRect.bottom; 4091 inOutInsets.set(leftInset, topInset, rightInset, bottomInset); 4092 } 4093 4094 private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) { 4095 return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN 4096 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0; 4097 } 4098 4099 /** {@inheritDoc} */ 4100 @Override 4101 public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight, 4102 int displayRotation, int uiMode) { 4103 mDisplayRotation = displayRotation; 4104 final int overscanLeft, overscanTop, overscanRight, overscanBottom; 4105 if (isDefaultDisplay) { 4106 switch (displayRotation) { 4107 case Surface.ROTATION_90: 4108 overscanLeft = mOverscanTop; 4109 overscanTop = mOverscanRight; 4110 overscanRight = mOverscanBottom; 4111 overscanBottom = mOverscanLeft; 4112 break; 4113 case Surface.ROTATION_180: 4114 overscanLeft = mOverscanRight; 4115 overscanTop = mOverscanBottom; 4116 overscanRight = mOverscanLeft; 4117 overscanBottom = mOverscanTop; 4118 break; 4119 case Surface.ROTATION_270: 4120 overscanLeft = mOverscanBottom; 4121 overscanTop = mOverscanLeft; 4122 overscanRight = mOverscanTop; 4123 overscanBottom = mOverscanRight; 4124 break; 4125 default: 4126 overscanLeft = mOverscanLeft; 4127 overscanTop = mOverscanTop; 4128 overscanRight = mOverscanRight; 4129 overscanBottom = mOverscanBottom; 4130 break; 4131 } 4132 } else { 4133 overscanLeft = 0; 4134 overscanTop = 0; 4135 overscanRight = 0; 4136 overscanBottom = 0; 4137 } 4138 mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0; 4139 mOverscanScreenTop = mRestrictedOverscanScreenTop = 0; 4140 mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth; 4141 mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight; 4142 mSystemLeft = 0; 4143 mSystemTop = 0; 4144 mSystemRight = displayWidth; 4145 mSystemBottom = displayHeight; 4146 mUnrestrictedScreenLeft = overscanLeft; 4147 mUnrestrictedScreenTop = overscanTop; 4148 mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight; 4149 mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom; 4150 mRestrictedScreenLeft = mUnrestrictedScreenLeft; 4151 mRestrictedScreenTop = mUnrestrictedScreenTop; 4152 mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth; 4153 mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight; 4154 mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft 4155 = mCurLeft = mUnrestrictedScreenLeft; 4156 mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop 4157 = mCurTop = mUnrestrictedScreenTop; 4158 mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight 4159 = mCurRight = displayWidth - overscanRight; 4160 mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom 4161 = mCurBottom = displayHeight - overscanBottom; 4162 mDockLayer = 0x10000000; 4163 mStatusBarLayer = -1; 4164 4165 // start with the current dock rect, which will be (0,0,displayWidth,displayHeight) 4166 final Rect pf = mTmpParentFrame; 4167 final Rect df = mTmpDisplayFrame; 4168 final Rect of = mTmpOverscanFrame; 4169 final Rect vf = mTmpVisibleFrame; 4170 final Rect dcf = mTmpDecorFrame; 4171 pf.left = df.left = of.left = vf.left = mDockLeft; 4172 pf.top = df.top = of.top = vf.top = mDockTop; 4173 pf.right = df.right = of.right = vf.right = mDockRight; 4174 pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom; 4175 dcf.setEmpty(); // Decor frame N/A for system bars. 4176 4177 if (isDefaultDisplay) { 4178 // For purposes of putting out fake window up to steal focus, we will 4179 // drive nav being hidden only by whether it is requested. 4180 final int sysui = mLastSystemUiFlags; 4181 boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0; 4182 boolean navTranslucent = (sysui 4183 & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0; 4184 boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; 4185 boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 4186 boolean navAllowedHidden = immersive || immersiveSticky; 4187 navTranslucent &= !immersiveSticky; // transient trumps translucent 4188 boolean isKeyguardShowing = isStatusBarKeyguard() && !mHideLockScreen; 4189 if (!isKeyguardShowing) { 4190 navTranslucent &= areTranslucentBarsAllowed(); 4191 } 4192 boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null 4193 && mStatusBar.getAttrs().height == MATCH_PARENT 4194 && mStatusBar.getAttrs().width == MATCH_PARENT; 4195 4196 // When the navigation bar isn't visible, we put up a fake 4197 // input window to catch all touch events. This way we can 4198 // detect when the user presses anywhere to bring back the nav 4199 // bar and ensure the application doesn't see the event. 4200 if (navVisible || navAllowedHidden) { 4201 if (mInputConsumer != null) { 4202 mHandler.sendMessage( 4203 mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer)); 4204 mInputConsumer = null; 4205 } 4206 } else if (mInputConsumer == null) { 4207 mInputConsumer = mWindowManagerFuncs.addInputConsumer(mHandler.getLooper(), 4208 mHideNavInputEventReceiverFactory); 4209 } 4210 4211 // For purposes of positioning and showing the nav bar, if we have 4212 // decided that it can't be hidden (because of the screen aspect ratio), 4213 // then take that into account. 4214 navVisible |= !canHideNavigationBar(); 4215 4216 boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight, 4217 displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom, dcf, navVisible, navTranslucent, 4218 navAllowedHidden, statusBarExpandedNotKeyguard); 4219 if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)", 4220 mDockLeft, mDockTop, mDockRight, mDockBottom)); 4221 updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing); 4222 if (updateSysUiVisibility) { 4223 updateSystemUiVisibilityLw(); 4224 } 4225 } 4226 } 4227 4228 private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui, 4229 boolean isKeyguardShowing) { 4230 // decide where the status bar goes ahead of time 4231 if (mStatusBar != null) { 4232 // apply any navigation bar insets 4233 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4234 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4235 pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft; 4236 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight 4237 + mUnrestrictedScreenTop; 4238 vf.left = mStableLeft; 4239 vf.top = mStableTop; 4240 vf.right = mStableRight; 4241 vf.bottom = mStableBottom; 4242 4243 mStatusBarLayer = mStatusBar.getSurfaceLayer(); 4244 4245 // Let the status bar determine its size. 4246 mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */, 4247 vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */, 4248 dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */); 4249 4250 // For layout, the status bar is always at the top with our fixed height. 4251 mStableTop = mUnrestrictedScreenTop + mStatusBarHeight; 4252 4253 boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0; 4254 boolean statusBarTranslucent = (sysui 4255 & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0; 4256 if (!isKeyguardShowing) { 4257 statusBarTranslucent &= areTranslucentBarsAllowed(); 4258 } 4259 4260 // If the status bar is hidden, we don't want to cause 4261 // windows behind it to scroll. 4262 if (mStatusBar.isVisibleLw() && !statusBarTransient) { 4263 // Status bar may go away, so the screen area it occupies 4264 // is available to apps but just covering them when the 4265 // status bar is visible. 4266 mDockTop = mUnrestrictedScreenTop + mStatusBarHeight; 4267 4268 mContentTop = mVoiceContentTop = mCurTop = mDockTop; 4269 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom; 4270 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft; 4271 mContentRight = mVoiceContentRight = mCurRight = mDockRight; 4272 4273 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " + 4274 String.format( 4275 "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]", 4276 mDockLeft, mDockTop, mDockRight, mDockBottom, 4277 mContentLeft, mContentTop, mContentRight, mContentBottom, 4278 mCurLeft, mCurTop, mCurRight, mCurBottom)); 4279 } 4280 if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw() 4281 && !statusBarTransient && !statusBarTranslucent 4282 && !mStatusBarController.wasRecentlyTranslucent()) { 4283 // If the opaque status bar is currently requested to be visible, 4284 // and not in the process of animating on or off, then 4285 // we can tell the app that it is covered by it. 4286 mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight; 4287 } 4288 if (mStatusBarController.checkHiddenLw()) { 4289 return true; 4290 } 4291 } 4292 return false; 4293 } 4294 4295 private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation, 4296 int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf, 4297 boolean navVisible, boolean navTranslucent, boolean navAllowedHidden, 4298 boolean statusBarExpandedNotKeyguard) { 4299 if (mNavigationBar != null) { 4300 boolean transientNavBarShowing = mNavigationBarController.isTransientShowing(); 4301 // Force the navigation bar to its appropriate place and 4302 // size. We need to do this directly, instead of relying on 4303 // it to bubble up from the nav bar, because this needs to 4304 // change atomically with screen rotations. 4305 mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight, 4306 displayRotation); 4307 if (mNavigationBarPosition == NAV_BAR_BOTTOM) { 4308 // It's a system nav bar or a portrait screen; nav bar goes on bottom. 4309 int top = displayHeight - overscanBottom 4310 - getNavigationBarHeight(displayRotation, uiMode); 4311 mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom); 4312 mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top; 4313 if (transientNavBarShowing) { 4314 mNavigationBarController.setBarShowingLw(true); 4315 } else if (navVisible) { 4316 mNavigationBarController.setBarShowingLw(true); 4317 mDockBottom = mTmpNavigationFrame.top; 4318 mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop; 4319 mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop; 4320 } else { 4321 // We currently want to hide the navigation UI - unless we expanded the status 4322 // bar. 4323 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); 4324 } 4325 if (navVisible && !navTranslucent && !navAllowedHidden 4326 && !mNavigationBar.isAnimatingLw() 4327 && !mNavigationBarController.wasRecentlyTranslucent()) { 4328 // If the opaque nav bar is currently requested to be visible, 4329 // and not in the process of animating on or off, then 4330 // we can tell the app that it is covered by it. 4331 mSystemBottom = mTmpNavigationFrame.top; 4332 } 4333 } else if (mNavigationBarPosition == NAV_BAR_RIGHT) { 4334 // Landscape screen; nav bar goes to the right. 4335 int left = displayWidth - overscanRight 4336 - getNavigationBarWidth(displayRotation, uiMode); 4337 mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight); 4338 mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left; 4339 if (transientNavBarShowing) { 4340 mNavigationBarController.setBarShowingLw(true); 4341 } else if (navVisible) { 4342 mNavigationBarController.setBarShowingLw(true); 4343 mDockRight = mTmpNavigationFrame.left; 4344 mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft; 4345 mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft; 4346 } else { 4347 // We currently want to hide the navigation UI - unless we expanded the status 4348 // bar. 4349 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); 4350 } 4351 if (navVisible && !navTranslucent && !navAllowedHidden 4352 && !mNavigationBar.isAnimatingLw() 4353 && !mNavigationBarController.wasRecentlyTranslucent()) { 4354 // If the nav bar is currently requested to be visible, 4355 // and not in the process of animating on or off, then 4356 // we can tell the app that it is covered by it. 4357 mSystemRight = mTmpNavigationFrame.left; 4358 } 4359 } else if (mNavigationBarPosition == NAV_BAR_LEFT) { 4360 // Seascape screen; nav bar goes to the left. 4361 int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode); 4362 mTmpNavigationFrame.set(overscanLeft, 0, right, displayHeight); 4363 mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right; 4364 if (transientNavBarShowing) { 4365 mNavigationBarController.setBarShowingLw(true); 4366 } else if (navVisible) { 4367 mNavigationBarController.setBarShowingLw(true); 4368 mDockLeft = mTmpNavigationFrame.right; 4369 // TODO: not so sure about those: 4370 mRestrictedScreenLeft = mRestrictedOverscanScreenLeft = mDockLeft; 4371 mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft; 4372 mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft; 4373 } else { 4374 // We currently want to hide the navigation UI - unless we expanded the status 4375 // bar. 4376 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); 4377 } 4378 if (navVisible && !navTranslucent && !navAllowedHidden 4379 && !mNavigationBar.isAnimatingLw() 4380 && !mNavigationBarController.wasRecentlyTranslucent()) { 4381 // If the nav bar is currently requested to be visible, 4382 // and not in the process of animating on or off, then 4383 // we can tell the app that it is covered by it. 4384 mSystemLeft = mTmpNavigationFrame.right; 4385 } 4386 } 4387 // Make sure the content and current rectangles are updated to 4388 // account for the restrictions from the navigation bar. 4389 mContentTop = mVoiceContentTop = mCurTop = mDockTop; 4390 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom; 4391 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft; 4392 mContentRight = mVoiceContentRight = mCurRight = mDockRight; 4393 mStatusBarLayer = mNavigationBar.getSurfaceLayer(); 4394 // And compute the final frame. 4395 mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame, 4396 mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf, 4397 mTmpNavigationFrame, mTmpNavigationFrame); 4398 if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame); 4399 if (mNavigationBarController.checkHiddenLw()) { 4400 return true; 4401 } 4402 } 4403 return false; 4404 } 4405 4406 private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) { 4407 if (mNavigationBarCanMove && displayWidth > displayHeight) { 4408 if (displayRotation == Surface.ROTATION_270) { 4409 return NAV_BAR_LEFT; 4410 } else { 4411 return NAV_BAR_RIGHT; 4412 } 4413 } 4414 return NAV_BAR_BOTTOM; 4415 } 4416 4417 /** {@inheritDoc} */ 4418 @Override 4419 public int getSystemDecorLayerLw() { 4420 if (mStatusBar != null && mStatusBar.isVisibleLw()) { 4421 return mStatusBar.getSurfaceLayer(); 4422 } 4423 4424 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) { 4425 return mNavigationBar.getSurfaceLayer(); 4426 } 4427 4428 return 0; 4429 } 4430 4431 @Override 4432 public void getContentRectLw(Rect r) { 4433 r.set(mContentLeft, mContentTop, mContentRight, mContentBottom); 4434 } 4435 4436 void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached, 4437 boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) { 4438 if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) { 4439 // Here's a special case: if this attached window is a panel that is 4440 // above the dock window, and the window it is attached to is below 4441 // the dock window, then the frames we computed for the window it is 4442 // attached to can not be used because the dock is effectively part 4443 // of the underlying window and the attached window is floating on top 4444 // of the whole thing. So, we ignore the attached window and explicitly 4445 // compute the frames that would be appropriate without the dock. 4446 df.left = of.left = cf.left = vf.left = mDockLeft; 4447 df.top = of.top = cf.top = vf.top = mDockTop; 4448 df.right = of.right = cf.right = vf.right = mDockRight; 4449 df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom; 4450 } else { 4451 // The effective display frame of the attached window depends on 4452 // whether it is taking care of insetting its content. If not, 4453 // we need to use the parent's content frame so that the entire 4454 // window is positioned within that content. Otherwise we can use 4455 // the overscan frame and let the attached window take care of 4456 // positioning its content appropriately. 4457 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4458 // Set the content frame of the attached window to the parent's decor frame 4459 // (same as content frame when IME isn't present) if specifically requested by 4460 // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag. 4461 // Otherwise, use the overscan frame. 4462 cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0 4463 ? attached.getContentFrameLw() : attached.getOverscanFrameLw()); 4464 } else { 4465 // If the window is resizing, then we want to base the content 4466 // frame on our attached content frame to resize... however, 4467 // things can be tricky if the attached window is NOT in resize 4468 // mode, in which case its content frame will be larger. 4469 // Ungh. So to deal with that, make sure the content frame 4470 // we end up using is not covering the IM dock. 4471 cf.set(attached.getContentFrameLw()); 4472 if (attached.isVoiceInteraction()) { 4473 if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft; 4474 if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop; 4475 if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight; 4476 if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom; 4477 } else if (attached.getSurfaceLayer() < mDockLayer) { 4478 if (cf.left < mContentLeft) cf.left = mContentLeft; 4479 if (cf.top < mContentTop) cf.top = mContentTop; 4480 if (cf.right > mContentRight) cf.right = mContentRight; 4481 if (cf.bottom > mContentBottom) cf.bottom = mContentBottom; 4482 } 4483 } 4484 df.set(insetDecors ? attached.getDisplayFrameLw() : cf); 4485 of.set(insetDecors ? attached.getOverscanFrameLw() : cf); 4486 vf.set(attached.getVisibleFrameLw()); 4487 } 4488 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached 4489 // window should be positioned relative to its parent or the entire 4490 // screen. 4491 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 4492 ? attached.getFrameLw() : df); 4493 } 4494 4495 private void applyStableConstraints(int sysui, int fl, Rect r) { 4496 if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) { 4497 // If app is requesting a stable layout, don't let the 4498 // content insets go below the stable values. 4499 if ((fl & FLAG_FULLSCREEN) != 0) { 4500 if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft; 4501 if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop; 4502 if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight; 4503 if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom; 4504 } else { 4505 if (r.left < mStableLeft) r.left = mStableLeft; 4506 if (r.top < mStableTop) r.top = mStableTop; 4507 if (r.right > mStableRight) r.right = mStableRight; 4508 if (r.bottom > mStableBottom) r.bottom = mStableBottom; 4509 } 4510 } 4511 } 4512 4513 private boolean canReceiveInput(WindowState win) { 4514 boolean notFocusable = 4515 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0; 4516 boolean altFocusableIm = 4517 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0; 4518 boolean notFocusableForIm = notFocusable ^ altFocusableIm; 4519 return !notFocusableForIm; 4520 } 4521 4522 /** {@inheritDoc} */ 4523 @Override 4524 public void layoutWindowLw(WindowState win, WindowState attached) { 4525 // We've already done the navigation bar and status bar. If the status bar can receive 4526 // input, we need to layout it again to accomodate for the IME window. 4527 if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) { 4528 return; 4529 } 4530 final WindowManager.LayoutParams attrs = win.getAttrs(); 4531 final boolean isDefaultDisplay = win.isDefaultDisplay(); 4532 final boolean needsToOffsetInputMethodTarget = isDefaultDisplay && 4533 (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null); 4534 if (needsToOffsetInputMethodTarget) { 4535 if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state"); 4536 offsetInputMethodWindowLw(mLastInputMethodWindow); 4537 } 4538 4539 final int fl = PolicyControl.getWindowFlags(win, attrs); 4540 final int pfl = attrs.privateFlags; 4541 final int sim = attrs.softInputMode; 4542 final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null); 4543 4544 final Rect pf = mTmpParentFrame; 4545 final Rect df = mTmpDisplayFrame; 4546 final Rect of = mTmpOverscanFrame; 4547 final Rect cf = mTmpContentFrame; 4548 final Rect vf = mTmpVisibleFrame; 4549 final Rect dcf = mTmpDecorFrame; 4550 final Rect sf = mTmpStableFrame; 4551 Rect osf = null; 4552 dcf.setEmpty(); 4553 4554 final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar 4555 && mNavigationBar != null && mNavigationBar.isVisibleLw()); 4556 4557 final int adjust = sim & SOFT_INPUT_MASK_ADJUST; 4558 4559 if (isDefaultDisplay) { 4560 sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom); 4561 } else { 4562 sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom); 4563 } 4564 4565 if (!isDefaultDisplay) { 4566 if (attached != null) { 4567 // If this window is attached to another, our display 4568 // frame is the same as the one we are attached to. 4569 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf); 4570 } else { 4571 // Give the window full screen. 4572 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 4573 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 4574 pf.right = df.right = of.right = cf.right 4575 = mOverscanScreenLeft + mOverscanScreenWidth; 4576 pf.bottom = df.bottom = of.bottom = cf.bottom 4577 = mOverscanScreenTop + mOverscanScreenHeight; 4578 } 4579 } else if (attrs.type == TYPE_INPUT_METHOD) { 4580 pf.left = df.left = of.left = cf.left = vf.left = mDockLeft; 4581 pf.top = df.top = of.top = cf.top = vf.top = mDockTop; 4582 pf.right = df.right = of.right = cf.right = vf.right = mDockRight; 4583 // IM dock windows layout below the nav bar... 4584 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4585 // ...with content insets above the nav bar 4586 cf.bottom = vf.bottom = mStableBottom; 4587 if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) { 4588 // The status bar forces the navigation bar while it's visible. Make sure the IME 4589 // avoids the navigation bar in that case. 4590 if (mNavigationBarPosition == NAV_BAR_RIGHT) { 4591 pf.right = df.right = of.right = cf.right = vf.right = mStableRight; 4592 } else if (mNavigationBarPosition == NAV_BAR_LEFT) { 4593 pf.left = df.left = of.left = cf.left = vf.left = mStableLeft; 4594 } 4595 } 4596 // IM dock windows always go to the bottom of the screen. 4597 attrs.gravity = Gravity.BOTTOM; 4598 mDockLayer = win.getSurfaceLayer(); 4599 } else if (attrs.type == TYPE_VOICE_INTERACTION) { 4600 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4601 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4602 pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4603 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4604 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4605 cf.left = mDockLeft; 4606 cf.top = mDockTop; 4607 cf.right = mDockRight; 4608 cf.bottom = mDockBottom; 4609 } else { 4610 cf.left = mContentLeft; 4611 cf.top = mContentTop; 4612 cf.right = mContentRight; 4613 cf.bottom = mContentBottom; 4614 } 4615 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 4616 vf.left = mCurLeft; 4617 vf.top = mCurTop; 4618 vf.right = mCurRight; 4619 vf.bottom = mCurBottom; 4620 } else { 4621 vf.set(cf); 4622 } 4623 } else if (attrs.type == TYPE_WALLPAPER) { 4624 layoutWallpaper(win, pf, df, of, cf); 4625 } else if (win == mStatusBar) { 4626 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4627 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4628 pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft; 4629 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop; 4630 cf.left = vf.left = mStableLeft; 4631 cf.top = vf.top = mStableTop; 4632 cf.right = vf.right = mStableRight; 4633 vf.bottom = mStableBottom; 4634 4635 if (adjust == SOFT_INPUT_ADJUST_RESIZE) { 4636 cf.bottom = mContentBottom; 4637 } else { 4638 cf.bottom = mDockBottom; 4639 vf.bottom = mContentBottom; 4640 } 4641 } else { 4642 4643 // Default policy decor for the default display 4644 dcf.left = mSystemLeft; 4645 dcf.top = mSystemTop; 4646 dcf.right = mSystemRight; 4647 dcf.bottom = mSystemBottom; 4648 final boolean inheritTranslucentDecor = (attrs.privateFlags 4649 & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0; 4650 final boolean isAppWindow = 4651 attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW && 4652 attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; 4653 final boolean topAtRest = 4654 win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw(); 4655 if (isAppWindow && !inheritTranslucentDecor && !topAtRest) { 4656 if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0 4657 && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0 4658 && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0 4659 && (fl & WindowManager.LayoutParams. 4660 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0 4661 && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) { 4662 // Ensure policy decor includes status bar 4663 dcf.top = mStableTop; 4664 } 4665 if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0 4666 && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0 4667 && (fl & WindowManager.LayoutParams. 4668 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) { 4669 // Ensure policy decor includes navigation bar 4670 dcf.bottom = mStableBottom; 4671 dcf.right = mStableRight; 4672 } 4673 } 4674 4675 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) 4676 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { 4677 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() 4678 + "): IN_SCREEN, INSET_DECOR"); 4679 // This is the case for a normal activity window: we want it 4680 // to cover all of the screen space, and it can take care of 4681 // moving its contents to account for screen decorations that 4682 // intrude into that space. 4683 if (attached != null) { 4684 // If this window is attached to another, our display 4685 // frame is the same as the one we are attached to. 4686 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf); 4687 } else { 4688 if (attrs.type == TYPE_STATUS_BAR_PANEL 4689 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) { 4690 // Status bar panels are the only windows who can go on top of 4691 // the status bar. They are protected by the STATUS_BAR_SERVICE 4692 // permission, so they have the same privileges as the status 4693 // bar itself. 4694 // 4695 // However, they should still dodge the navigation bar if it exists. 4696 4697 pf.left = df.left = of.left = hasNavBar 4698 ? mDockLeft : mUnrestrictedScreenLeft; 4699 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4700 pf.right = df.right = of.right = hasNavBar 4701 ? mRestrictedScreenLeft+mRestrictedScreenWidth 4702 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4703 pf.bottom = df.bottom = of.bottom = hasNavBar 4704 ? mRestrictedScreenTop+mRestrictedScreenHeight 4705 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4706 4707 if (DEBUG_LAYOUT) Slog.v(TAG, String.format( 4708 "Laying out status bar window: (%d,%d - %d,%d)", 4709 pf.left, pf.top, pf.right, pf.bottom)); 4710 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0 4711 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 4712 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 4713 // Asking to layout into the overscan region, so give it that pure 4714 // unrestricted area. 4715 pf.left = df.left = of.left = mOverscanScreenLeft; 4716 pf.top = df.top = of.top = mOverscanScreenTop; 4717 pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth; 4718 pf.bottom = df.bottom = of.bottom = mOverscanScreenTop 4719 + mOverscanScreenHeight; 4720 } else if (canHideNavigationBar() 4721 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 4722 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 4723 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 4724 // Asking for layout as if the nav bar is hidden, lets the 4725 // application extend into the unrestricted overscan screen area. We 4726 // only do this for application windows to ensure no window that 4727 // can be above the nav bar can do this. 4728 pf.left = df.left = mOverscanScreenLeft; 4729 pf.top = df.top = mOverscanScreenTop; 4730 pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth; 4731 pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight; 4732 // We need to tell the app about where the frame inside the overscan 4733 // is, so it can inset its content by that amount -- it didn't ask 4734 // to actually extend itself into the overscan region. 4735 of.left = mUnrestrictedScreenLeft; 4736 of.top = mUnrestrictedScreenTop; 4737 of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4738 of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4739 } else { 4740 pf.left = df.left = mRestrictedOverscanScreenLeft; 4741 pf.top = df.top = mRestrictedOverscanScreenTop; 4742 pf.right = df.right = mRestrictedOverscanScreenLeft 4743 + mRestrictedOverscanScreenWidth; 4744 pf.bottom = df.bottom = mRestrictedOverscanScreenTop 4745 + mRestrictedOverscanScreenHeight; 4746 // We need to tell the app about where the frame inside the overscan 4747 // is, so it can inset its content by that amount -- it didn't ask 4748 // to actually extend itself into the overscan region. 4749 of.left = mUnrestrictedScreenLeft; 4750 of.top = mUnrestrictedScreenTop; 4751 of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4752 of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4753 } 4754 4755 if ((fl & FLAG_FULLSCREEN) == 0) { 4756 if (win.isVoiceInteraction()) { 4757 cf.left = mVoiceContentLeft; 4758 cf.top = mVoiceContentTop; 4759 cf.right = mVoiceContentRight; 4760 cf.bottom = mVoiceContentBottom; 4761 } else { 4762 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4763 cf.left = mDockLeft; 4764 cf.top = mDockTop; 4765 cf.right = mDockRight; 4766 cf.bottom = mDockBottom; 4767 } else { 4768 cf.left = mContentLeft; 4769 cf.top = mContentTop; 4770 cf.right = mContentRight; 4771 cf.bottom = mContentBottom; 4772 } 4773 } 4774 } else { 4775 // Full screen windows are always given a layout that is as if the 4776 // status bar and other transient decors are gone. This is to avoid 4777 // bad states when moving from a window that is not hding the 4778 // status bar to one that is. 4779 cf.left = mRestrictedScreenLeft; 4780 cf.top = mRestrictedScreenTop; 4781 cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth; 4782 cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight; 4783 } 4784 applyStableConstraints(sysUiFl, fl, cf); 4785 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 4786 vf.left = mCurLeft; 4787 vf.top = mCurTop; 4788 vf.right = mCurRight; 4789 vf.bottom = mCurBottom; 4790 } else { 4791 vf.set(cf); 4792 } 4793 } 4794 } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl 4795 & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 4796 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) { 4797 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + 4798 "): IN_SCREEN"); 4799 // A window that has requested to fill the entire screen just 4800 // gets everything, period. 4801 if (attrs.type == TYPE_STATUS_BAR_PANEL 4802 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL 4803 || attrs.type == TYPE_VOLUME_OVERLAY) { 4804 pf.left = df.left = of.left = cf.left = hasNavBar 4805 ? mDockLeft : mUnrestrictedScreenLeft; 4806 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop; 4807 pf.right = df.right = of.right = cf.right = hasNavBar 4808 ? mRestrictedScreenLeft+mRestrictedScreenWidth 4809 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4810 pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar 4811 ? mRestrictedScreenTop+mRestrictedScreenHeight 4812 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4813 if (DEBUG_LAYOUT) Slog.v(TAG, String.format( 4814 "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)", 4815 pf.left, pf.top, pf.right, pf.bottom)); 4816 } else if (attrs.type == TYPE_NAVIGATION_BAR 4817 || attrs.type == TYPE_NAVIGATION_BAR_PANEL) { 4818 // The navigation bar has Real Ultimate Power. 4819 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4820 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4821 pf.right = df.right = of.right = mUnrestrictedScreenLeft 4822 + mUnrestrictedScreenWidth; 4823 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop 4824 + mUnrestrictedScreenHeight; 4825 if (DEBUG_LAYOUT) Slog.v(TAG, String.format( 4826 "Laying out navigation bar window: (%d,%d - %d,%d)", 4827 pf.left, pf.top, pf.right, pf.bottom)); 4828 } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY 4829 || attrs.type == TYPE_BOOT_PROGRESS 4830 || attrs.type == TYPE_SCREENSHOT) 4831 && ((fl & FLAG_FULLSCREEN) != 0)) { 4832 // Fullscreen secure system overlays get what they ask for. Screenshot region 4833 // selection overlay should also expand to full screen. 4834 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 4835 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 4836 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft 4837 + mOverscanScreenWidth; 4838 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop 4839 + mOverscanScreenHeight; 4840 } else if (attrs.type == TYPE_BOOT_PROGRESS) { 4841 // Boot progress screen always covers entire display. 4842 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 4843 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 4844 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft 4845 + mOverscanScreenWidth; 4846 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop 4847 + mOverscanScreenHeight; 4848 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0 4849 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 4850 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 4851 // Asking to layout into the overscan region, so give it that pure 4852 // unrestricted area. 4853 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 4854 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 4855 pf.right = df.right = of.right = cf.right 4856 = mOverscanScreenLeft + mOverscanScreenWidth; 4857 pf.bottom = df.bottom = of.bottom = cf.bottom 4858 = mOverscanScreenTop + mOverscanScreenHeight; 4859 } else if (canHideNavigationBar() 4860 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 4861 && (attrs.type == TYPE_STATUS_BAR 4862 || attrs.type == TYPE_TOAST 4863 || attrs.type == TYPE_DOCK_DIVIDER 4864 || attrs.type == TYPE_VOICE_INTERACTION_STARTING 4865 || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 4866 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) { 4867 // Asking for layout as if the nav bar is hidden, lets the 4868 // application extend into the unrestricted screen area. We 4869 // only do this for application windows (or toasts) to ensure no window that 4870 // can be above the nav bar can do this. 4871 // XXX This assumes that an app asking for this will also 4872 // ask for layout in only content. We can't currently figure out 4873 // what the screen would be if only laying out to hide the nav bar. 4874 pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft; 4875 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop; 4876 pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft 4877 + mUnrestrictedScreenWidth; 4878 pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop 4879 + mUnrestrictedScreenHeight; 4880 } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) { 4881 pf.left = df.left = of.left = mRestrictedScreenLeft; 4882 pf.top = df.top = of.top = mRestrictedScreenTop; 4883 pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth; 4884 pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop 4885 + mRestrictedScreenHeight; 4886 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4887 cf.left = mDockLeft; 4888 cf.top = mDockTop; 4889 cf.right = mDockRight; 4890 cf.bottom = mDockBottom; 4891 } else { 4892 cf.left = mContentLeft; 4893 cf.top = mContentTop; 4894 cf.right = mContentRight; 4895 cf.bottom = mContentBottom; 4896 } 4897 } else { 4898 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft; 4899 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop; 4900 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft 4901 + mRestrictedScreenWidth; 4902 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop 4903 + mRestrictedScreenHeight; 4904 } 4905 4906 applyStableConstraints(sysUiFl, fl, cf); 4907 4908 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 4909 vf.left = mCurLeft; 4910 vf.top = mCurTop; 4911 vf.right = mCurRight; 4912 vf.bottom = mCurBottom; 4913 } else { 4914 vf.set(cf); 4915 } 4916 } else if (attached != null) { 4917 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + 4918 "): attached to " + attached); 4919 // A child window should be placed inside of the same visible 4920 // frame that its parent had. 4921 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf); 4922 } else { 4923 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + 4924 "): normal window"); 4925 // Otherwise, a normal window must be placed inside the content 4926 // of all screen decorations. 4927 if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) { 4928 // Status bar panels and the volume dialog are the only windows who can go on 4929 // top of the status bar. They are protected by the STATUS_BAR_SERVICE 4930 // permission, so they have the same privileges as the status 4931 // bar itself. 4932 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft; 4933 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop; 4934 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft 4935 + mRestrictedScreenWidth; 4936 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop 4937 + mRestrictedScreenHeight; 4938 } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) { 4939 // These dialogs are stable to interim decor changes. 4940 pf.left = df.left = of.left = cf.left = mStableLeft; 4941 pf.top = df.top = of.top = cf.top = mStableTop; 4942 pf.right = df.right = of.right = cf.right = mStableRight; 4943 pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom; 4944 } else { 4945 pf.left = mContentLeft; 4946 pf.top = mContentTop; 4947 pf.right = mContentRight; 4948 pf.bottom = mContentBottom; 4949 if (win.isVoiceInteraction()) { 4950 df.left = of.left = cf.left = mVoiceContentLeft; 4951 df.top = of.top = cf.top = mVoiceContentTop; 4952 df.right = of.right = cf.right = mVoiceContentRight; 4953 df.bottom = of.bottom = cf.bottom = mVoiceContentBottom; 4954 } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4955 df.left = of.left = cf.left = mDockLeft; 4956 df.top = of.top = cf.top = mDockTop; 4957 df.right = of.right = cf.right = mDockRight; 4958 df.bottom = of.bottom = cf.bottom = mDockBottom; 4959 } else { 4960 df.left = of.left = cf.left = mContentLeft; 4961 df.top = of.top = cf.top = mContentTop; 4962 df.right = of.right = cf.right = mContentRight; 4963 df.bottom = of.bottom = cf.bottom = mContentBottom; 4964 } 4965 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 4966 vf.left = mCurLeft; 4967 vf.top = mCurTop; 4968 vf.right = mCurRight; 4969 vf.bottom = mCurBottom; 4970 } else { 4971 vf.set(cf); 4972 } 4973 } 4974 } 4975 } 4976 4977 // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it. 4978 // Also, we don't allow windows in multi-window mode to extend out of the screen. 4979 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR 4980 && !win.isInMultiWindowMode()) { 4981 df.left = df.top = -10000; 4982 df.right = df.bottom = 10000; 4983 if (attrs.type != TYPE_WALLPAPER) { 4984 of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000; 4985 of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000; 4986 } 4987 } 4988 4989 // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we 4990 // need to provide information to the clients that want to pretend that you can draw there. 4991 // We only want to apply outsets to certain types of windows. For example, we never want to 4992 // apply the outsets to floating dialogs, because they wouldn't make sense there. 4993 final boolean useOutsets = shouldUseOutsets(attrs, fl); 4994 if (isDefaultDisplay && useOutsets) { 4995 osf = mTmpOutsetFrame; 4996 osf.set(cf.left, cf.top, cf.right, cf.bottom); 4997 int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources()); 4998 if (outset > 0) { 4999 int rotation = mDisplayRotation; 5000 if (rotation == Surface.ROTATION_0) { 5001 osf.bottom += outset; 5002 } else if (rotation == Surface.ROTATION_90) { 5003 osf.right += outset; 5004 } else if (rotation == Surface.ROTATION_180) { 5005 osf.top -= outset; 5006 } else if (rotation == Surface.ROTATION_270) { 5007 osf.left -= outset; 5008 } 5009 if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset 5010 + " with rotation " + rotation + ", result: " + osf); 5011 } 5012 } 5013 5014 if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle() 5015 + ": sim=#" + Integer.toHexString(sim) 5016 + " attach=" + attached + " type=" + attrs.type 5017 + String.format(" flags=0x%08x", fl) 5018 + " pf=" + pf.toShortString() + " df=" + df.toShortString() 5019 + " of=" + of.toShortString() 5020 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString() 5021 + " dcf=" + dcf.toShortString() 5022 + " sf=" + sf.toShortString() 5023 + " osf=" + (osf == null ? "null" : osf.toShortString())); 5024 5025 win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf); 5026 5027 // Dock windows carve out the bottom of the screen, so normal windows 5028 // can't appear underneath them. 5029 if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleOrBehindKeyguardLw() 5030 && win.isDisplayedLw() && !win.getGivenInsetsPendingLw()) { 5031 setLastInputMethodWindowLw(null, null); 5032 offsetInputMethodWindowLw(win); 5033 } 5034 if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleOrBehindKeyguardLw() 5035 && !win.getGivenInsetsPendingLw()) { 5036 offsetVoiceInputWindowLw(win); 5037 } 5038 } 5039 5040 private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) { 5041 5042 // The wallpaper also has Real Ultimate Power, but we want to tell 5043 // it about the overscan area. 5044 pf.left = df.left = mOverscanScreenLeft; 5045 pf.top = df.top = mOverscanScreenTop; 5046 pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth; 5047 pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight; 5048 of.left = cf.left = mUnrestrictedScreenLeft; 5049 of.top = cf.top = mUnrestrictedScreenTop; 5050 of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 5051 of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 5052 } 5053 5054 private void offsetInputMethodWindowLw(WindowState win) { 5055 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top); 5056 top += win.getGivenContentInsetsLw().top; 5057 if (mContentBottom > top) { 5058 mContentBottom = top; 5059 } 5060 if (mVoiceContentBottom > top) { 5061 mVoiceContentBottom = top; 5062 } 5063 top = win.getVisibleFrameLw().top; 5064 top += win.getGivenVisibleInsetsLw().top; 5065 if (mCurBottom > top) { 5066 mCurBottom = top; 5067 } 5068 if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom=" 5069 + mDockBottom + " mContentBottom=" 5070 + mContentBottom + " mCurBottom=" + mCurBottom); 5071 } 5072 5073 private void offsetVoiceInputWindowLw(WindowState win) { 5074 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top); 5075 top += win.getGivenContentInsetsLw().top; 5076 if (mVoiceContentBottom > top) { 5077 mVoiceContentBottom = top; 5078 } 5079 } 5080 5081 /** {@inheritDoc} */ 5082 @Override 5083 public void finishLayoutLw() { 5084 return; 5085 } 5086 5087 /** {@inheritDoc} */ 5088 @Override 5089 public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) { 5090 mTopFullscreenOpaqueWindowState = null; 5091 mTopFullscreenOpaqueOrDimmingWindowState = null; 5092 mTopDockedOpaqueWindowState = null; 5093 mTopDockedOpaqueOrDimmingWindowState = null; 5094 mAppsToBeHidden.clear(); 5095 mAppsThatDismissKeyguard.clear(); 5096 mForceStatusBar = false; 5097 mForceStatusBarFromKeyguard = false; 5098 mForceStatusBarTransparent = false; 5099 mForcingShowNavBar = false; 5100 mForcingShowNavBarLayer = -1; 5101 5102 mHideLockScreen = false; 5103 mAllowLockscreenWhenOn = false; 5104 mDismissKeyguard = DISMISS_KEYGUARD_NONE; 5105 mShowingLockscreen = false; 5106 mShowingDream = false; 5107 mWinShowWhenLocked = null; 5108 mKeyguardSecure = isKeyguardSecure(mCurrentUserId); 5109 mKeyguardSecureIncludingHidden = mKeyguardSecure 5110 && (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()); 5111 } 5112 5113 /** {@inheritDoc} */ 5114 @Override 5115 public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs, 5116 WindowState attached) { 5117 if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw=" 5118 + win.isVisibleOrBehindKeyguardLw()); 5119 final int fl = PolicyControl.getWindowFlags(win, attrs); 5120 if (mTopFullscreenOpaqueWindowState == null 5121 && win.isVisibleLw() && attrs.type == TYPE_INPUT_METHOD) { 5122 mForcingShowNavBar = true; 5123 mForcingShowNavBarLayer = win.getSurfaceLayer(); 5124 } 5125 if (attrs.type == TYPE_STATUS_BAR) { 5126 if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 5127 mForceStatusBarFromKeyguard = true; 5128 mShowingLockscreen = true; 5129 } 5130 if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) { 5131 mForceStatusBarTransparent = true; 5132 } 5133 } 5134 5135 boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW 5136 && attrs.type < FIRST_SYSTEM_WINDOW; 5137 final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0; 5138 final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0; 5139 final int stackId = win.getStackId(); 5140 if (mTopFullscreenOpaqueWindowState == null && 5141 win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) { 5142 if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) { 5143 if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 5144 mForceStatusBarFromKeyguard = true; 5145 } else { 5146 mForceStatusBar = true; 5147 } 5148 } 5149 if (attrs.type == TYPE_DREAM) { 5150 // If the lockscreen was showing when the dream started then wait 5151 // for the dream to draw before hiding the lockscreen. 5152 if (!mDreamingLockscreen 5153 || (win.isVisibleLw() && win.hasDrawnLw())) { 5154 mShowingDream = true; 5155 appWindow = true; 5156 } 5157 } 5158 5159 final IApplicationToken appToken = win.getAppToken(); 5160 5161 // For app windows that are not attached, we decide if all windows in the app they 5162 // represent should be hidden or if we should hide the lockscreen. For attached app 5163 // windows we defer the decision to the window it is attached to. 5164 if (appWindow && attached == null) { 5165 if (showWhenLocked) { 5166 // Remove any previous windows with the same appToken. 5167 mAppsToBeHidden.remove(appToken); 5168 mAppsThatDismissKeyguard.remove(appToken); 5169 if (mAppsToBeHidden.isEmpty()) { 5170 if (dismissKeyguard && !mKeyguardSecure) { 5171 mAppsThatDismissKeyguard.add(appToken); 5172 } else if (win.isDrawnLw() || win.hasAppShownWindows()) { 5173 mWinShowWhenLocked = win; 5174 mHideLockScreen = true; 5175 mForceStatusBarFromKeyguard = false; 5176 } 5177 } 5178 } else if (dismissKeyguard) { 5179 if (mKeyguardSecure) { 5180 mAppsToBeHidden.add(appToken); 5181 } else { 5182 mAppsToBeHidden.remove(appToken); 5183 } 5184 mAppsThatDismissKeyguard.add(appToken); 5185 } else { 5186 mAppsToBeHidden.add(appToken); 5187 } 5188 if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) { 5189 if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win); 5190 mTopFullscreenOpaqueWindowState = win; 5191 if (mTopFullscreenOpaqueOrDimmingWindowState == null) { 5192 mTopFullscreenOpaqueOrDimmingWindowState = win; 5193 } 5194 if (!mAppsThatDismissKeyguard.isEmpty() && 5195 mDismissKeyguard == DISMISS_KEYGUARD_NONE) { 5196 if (DEBUG_LAYOUT) Slog.v(TAG, 5197 "Setting mDismissKeyguard true by win " + win); 5198 mDismissKeyguard = (mWinDismissingKeyguard == win 5199 && mSecureDismissingKeyguard == mKeyguardSecure) 5200 ? DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START; 5201 mWinDismissingKeyguard = win; 5202 mSecureDismissingKeyguard = mKeyguardSecure; 5203 mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure; 5204 } else if (mAppsToBeHidden.isEmpty() && showWhenLocked 5205 && (win.isDrawnLw() || win.hasAppShownWindows())) { 5206 if (DEBUG_LAYOUT) Slog.v(TAG, 5207 "Setting mHideLockScreen to true by win " + win); 5208 mHideLockScreen = true; 5209 mForceStatusBarFromKeyguard = false; 5210 } 5211 if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) { 5212 mAllowLockscreenWhenOn = true; 5213 } 5214 } 5215 5216 if (!mKeyguardHidden && mWinShowWhenLocked != null && 5217 mWinShowWhenLocked.getAppToken() != win.getAppToken() && 5218 (attrs.flags & FLAG_SHOW_WHEN_LOCKED) == 0) { 5219 win.hideLw(false); 5220 } 5221 } 5222 } else if (mTopFullscreenOpaqueWindowState == null && mWinShowWhenLocked == null) { 5223 // No TopFullscreenOpaqueWindow is showing, but we found a SHOW_WHEN_LOCKED window 5224 // that is being hidden in an animation - keep the 5225 // keyguard hidden until the new window shows up and 5226 // we know whether to show the keyguard or not. 5227 if (win.isAnimatingLw() && appWindow && showWhenLocked && mKeyguardHidden) { 5228 mHideLockScreen = true; 5229 mWinShowWhenLocked = win; 5230 } 5231 } 5232 5233 final boolean reallyVisible = win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw(); 5234 5235 // Voice interaction overrides both top fullscreen and top docked. 5236 if (reallyVisible && win.getAttrs().type == TYPE_VOICE_INTERACTION) { 5237 if (mTopFullscreenOpaqueWindowState == null) { 5238 mTopFullscreenOpaqueWindowState = win; 5239 if (mTopFullscreenOpaqueOrDimmingWindowState == null) { 5240 mTopFullscreenOpaqueOrDimmingWindowState = win; 5241 } 5242 } 5243 if (mTopDockedOpaqueWindowState == null) { 5244 mTopDockedOpaqueWindowState = win; 5245 if (mTopDockedOpaqueOrDimmingWindowState == null) { 5246 mTopDockedOpaqueOrDimmingWindowState = win; 5247 } 5248 } 5249 } 5250 5251 // Keep track of the window if it's dimming but not necessarily fullscreen. 5252 if (mTopFullscreenOpaqueOrDimmingWindowState == null && reallyVisible 5253 && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) { 5254 mTopFullscreenOpaqueOrDimmingWindowState = win; 5255 } 5256 5257 // We need to keep track of the top "fullscreen" opaque window for the docked stack 5258 // separately, because both the "real fullscreen" opaque window and the one for the docked 5259 // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR. 5260 if (mTopDockedOpaqueWindowState == null && reallyVisible && appWindow && attached == null 5261 && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) { 5262 mTopDockedOpaqueWindowState = win; 5263 if (mTopDockedOpaqueOrDimmingWindowState == null) { 5264 mTopDockedOpaqueOrDimmingWindowState = win; 5265 } 5266 } 5267 5268 // Also keep track of any windows that are dimming but not necessarily fullscreen in the 5269 // docked stack. 5270 if (mTopDockedOpaqueOrDimmingWindowState == null && reallyVisible && win.isDimming() 5271 && stackId == DOCKED_STACK_ID) { 5272 mTopDockedOpaqueOrDimmingWindowState = win; 5273 } 5274 } 5275 5276 private boolean isFullscreen(WindowManager.LayoutParams attrs) { 5277 return attrs.x == 0 && attrs.y == 0 5278 && attrs.width == WindowManager.LayoutParams.MATCH_PARENT 5279 && attrs.height == WindowManager.LayoutParams.MATCH_PARENT; 5280 } 5281 5282 /** {@inheritDoc} */ 5283 @Override 5284 public int finishPostLayoutPolicyLw() { 5285 if (mWinShowWhenLocked != null && mTopFullscreenOpaqueWindowState != null && 5286 mWinShowWhenLocked.getAppToken() != mTopFullscreenOpaqueWindowState.getAppToken() 5287 && isKeyguardLocked()) { 5288 // A dialog is dismissing the keyguard. Put the wallpaper behind it and hide the 5289 // fullscreen window. 5290 // TODO: Make sure FLAG_SHOW_WALLPAPER is restored when dialog is dismissed. Or not. 5291 mWinShowWhenLocked.getAttrs().flags |= FLAG_SHOW_WALLPAPER; 5292 mTopFullscreenOpaqueWindowState.hideLw(false); 5293 mTopFullscreenOpaqueWindowState = mWinShowWhenLocked; 5294 } 5295 5296 int changes = 0; 5297 boolean topIsFullscreen = false; 5298 5299 final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null) 5300 ? mTopFullscreenOpaqueWindowState.getAttrs() 5301 : null; 5302 5303 // If we are not currently showing a dream then remember the current 5304 // lockscreen state. We will use this to determine whether the dream 5305 // started while the lockscreen was showing and remember this state 5306 // while the dream is showing. 5307 if (!mShowingDream) { 5308 mDreamingLockscreen = mShowingLockscreen; 5309 if (mDreamingSleepTokenNeeded) { 5310 mDreamingSleepTokenNeeded = false; 5311 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget(); 5312 } 5313 } else { 5314 if (!mDreamingSleepTokenNeeded) { 5315 mDreamingSleepTokenNeeded = true; 5316 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget(); 5317 } 5318 } 5319 5320 if (mStatusBar != null) { 5321 if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar 5322 + " forcefkg=" + mForceStatusBarFromKeyguard 5323 + " top=" + mTopFullscreenOpaqueWindowState); 5324 boolean shouldBeTransparent = mForceStatusBarTransparent 5325 && !mForceStatusBar 5326 && !mForceStatusBarFromKeyguard; 5327 if (!shouldBeTransparent) { 5328 mStatusBarController.setShowTransparent(false /* transparent */); 5329 } else if (!mStatusBar.isVisibleLw()) { 5330 mStatusBarController.setShowTransparent(true /* transparent */); 5331 } 5332 5333 WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs(); 5334 boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT 5335 && statusBarAttrs.width == MATCH_PARENT; 5336 if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent 5337 || statusBarExpanded) { 5338 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced"); 5339 if (mStatusBarController.setBarShowingLw(true)) { 5340 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5341 } 5342 // Maintain fullscreen layout until incoming animation is complete. 5343 topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw(); 5344 // Transient status bar on the lockscreen is not allowed 5345 if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) { 5346 mStatusBarController.updateVisibilityLw(false /*transientAllowed*/, 5347 mLastSystemUiFlags, mLastSystemUiFlags); 5348 } 5349 if (statusBarExpanded && mNavigationBar != null) { 5350 if (mNavigationBarController.setBarShowingLw(true)) { 5351 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5352 } 5353 } 5354 } else if (mTopFullscreenOpaqueWindowState != null) { 5355 final int fl = PolicyControl.getWindowFlags(null, lp); 5356 if (localLOGV) { 5357 Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() 5358 + " shown position: " 5359 + mTopFullscreenOpaqueWindowState.getShownPositionLw()); 5360 Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs() 5361 + " lp.flags=0x" + Integer.toHexString(fl)); 5362 } 5363 topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0 5364 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 5365 // The subtle difference between the window for mTopFullscreenOpaqueWindowState 5366 // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window 5367 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the 5368 // case though. 5369 if (mStatusBarController.isTransientShowing()) { 5370 if (mStatusBarController.setBarShowingLw(true)) { 5371 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5372 } 5373 } else if (topIsFullscreen 5374 && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID) 5375 && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) { 5376 if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar"); 5377 if (mStatusBarController.setBarShowingLw(false)) { 5378 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5379 } else { 5380 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding"); 5381 } 5382 } else { 5383 if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen"); 5384 if (mStatusBarController.setBarShowingLw(true)) { 5385 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5386 } 5387 } 5388 } 5389 } 5390 5391 if (mTopIsFullscreen != topIsFullscreen) { 5392 if (!topIsFullscreen) { 5393 // Force another layout when status bar becomes fully shown. 5394 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5395 } 5396 mTopIsFullscreen = topIsFullscreen; 5397 } 5398 5399 // Hide the key guard if a visible window explicitly specifies that it wants to be 5400 // displayed when the screen is locked. 5401 if (mKeyguardDelegate != null && mStatusBar != null) { 5402 if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard=" 5403 + mHideLockScreen); 5404 if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardSecure) { 5405 mKeyguardHidden = true; 5406 if (setKeyguardOccludedLw(true)) { 5407 changes |= FINISH_LAYOUT_REDO_LAYOUT 5408 | FINISH_LAYOUT_REDO_CONFIG 5409 | FINISH_LAYOUT_REDO_WALLPAPER; 5410 } 5411 if (mKeyguardDelegate.isShowing()) { 5412 mHandler.post(new Runnable() { 5413 @Override 5414 public void run() { 5415 mKeyguardDelegate.keyguardDone(false, false); 5416 } 5417 }); 5418 } 5419 } else if (mHideLockScreen) { 5420 mKeyguardHidden = true; 5421 mWinDismissingKeyguard = null; 5422 if (setKeyguardOccludedLw(true)) { 5423 changes |= FINISH_LAYOUT_REDO_LAYOUT 5424 | FINISH_LAYOUT_REDO_CONFIG 5425 | FINISH_LAYOUT_REDO_WALLPAPER; 5426 } 5427 } else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) { 5428 mKeyguardHidden = false; 5429 boolean willDismiss = false; 5430 if (mDismissKeyguard == DISMISS_KEYGUARD_START) { 5431 final boolean trusted = mKeyguardDelegate.isTrusted(); 5432 willDismiss = trusted && mKeyguardOccluded && mKeyguardDelegate != null 5433 && mKeyguardDelegate.isShowing(); 5434 if (willDismiss) { 5435 mCurrentlyDismissingKeyguard = true; 5436 } 5437 5438 // Only launch the next keyguard unlock window once per window. 5439 mHandler.post(() -> mKeyguardDelegate.dismiss( 5440 trusted /* allowWhileOccluded */)); 5441 } 5442 5443 // If we are currently dismissing Keyguard, there is no need to unocclude it. 5444 if (!mCurrentlyDismissingKeyguard) { 5445 if (setKeyguardOccludedLw(false)) { 5446 changes |= FINISH_LAYOUT_REDO_LAYOUT 5447 | FINISH_LAYOUT_REDO_CONFIG 5448 | FINISH_LAYOUT_REDO_WALLPAPER; 5449 } 5450 } 5451 } else { 5452 mWinDismissingKeyguard = null; 5453 mSecureDismissingKeyguard = false; 5454 mKeyguardHidden = false; 5455 if (setKeyguardOccludedLw(false)) { 5456 changes |= FINISH_LAYOUT_REDO_LAYOUT 5457 | FINISH_LAYOUT_REDO_CONFIG 5458 | FINISH_LAYOUT_REDO_WALLPAPER; 5459 } 5460 } 5461 } 5462 5463 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5464 // If the navigation bar has been hidden or shown, we need to do another 5465 // layout pass to update that window. 5466 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5467 } 5468 5469 // update since mAllowLockscreenWhenOn might have changed 5470 updateLockScreenTimeout(); 5471 return changes; 5472 } 5473 5474 /** 5475 * Updates the occluded state of the Keyguard. 5476 * 5477 * @return Whether the flags have changed and we have to redo the layout. 5478 */ 5479 private boolean setKeyguardOccludedLw(boolean isOccluded) { 5480 boolean wasOccluded = mKeyguardOccluded; 5481 boolean showing = mKeyguardDelegate.isShowing(); 5482 if (wasOccluded && !isOccluded && showing) { 5483 mKeyguardOccluded = false; 5484 mKeyguardDelegate.setOccluded(false, true /* animate */); 5485 mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD; 5486 if (!mKeyguardDelegate.hasLockscreenWallpaper()) { 5487 mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER; 5488 } 5489 Animation anim = AnimationUtils.loadAnimation(mContext, 5490 com.android.internal.R.anim.wallpaper_open_exit); 5491 mWindowManagerFuncs.overridePlayingAppAnimationsLw(anim); 5492 return true; 5493 } else if (!wasOccluded && isOccluded && showing) { 5494 mKeyguardOccluded = true; 5495 mKeyguardDelegate.setOccluded(true, false /* animate */); 5496 mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD; 5497 mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER; 5498 return true; 5499 } else { 5500 return false; 5501 } 5502 } 5503 5504 private void onKeyguardShowingStateChanged(boolean showing) { 5505 if (!showing) { 5506 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 5507 mCurrentlyDismissingKeyguard = false; 5508 } 5509 } 5510 } 5511 5512 private boolean isStatusBarKeyguard() { 5513 return mStatusBar != null 5514 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0; 5515 } 5516 5517 @Override 5518 public boolean allowAppAnimationsLw() { 5519 if (isStatusBarKeyguard() || mShowingDream) { 5520 // If keyguard or dreams is currently visible, no reason to animate behind it. 5521 return false; 5522 } 5523 return true; 5524 } 5525 5526 @Override 5527 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) { 5528 mFocusedWindow = newFocus; 5529 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5530 // If the navigation bar has been hidden or shown, we need to do another 5531 // layout pass to update that window. 5532 return FINISH_LAYOUT_REDO_LAYOUT; 5533 } 5534 return 0; 5535 } 5536 5537 /** {@inheritDoc} */ 5538 @Override 5539 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { 5540 // lid changed state 5541 final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED; 5542 if (newLidState == mLidState) { 5543 return; 5544 } 5545 5546 mLidState = newLidState; 5547 applyLidSwitchState(); 5548 updateRotation(true); 5549 5550 if (lidOpen) { 5551 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch, 5552 "android.policy:LID"); 5553 } else if (!mLidControlsSleep) { 5554 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 5555 } 5556 } 5557 5558 @Override 5559 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) { 5560 int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED; 5561 if (mCameraLensCoverState == lensCoverState) { 5562 return; 5563 } 5564 if (mCameraLensCoverState == CAMERA_LENS_COVERED && 5565 lensCoverState == CAMERA_LENS_UNCOVERED) { 5566 Intent intent; 5567 final boolean keyguardActive = mKeyguardDelegate == null ? false : 5568 mKeyguardDelegate.isShowing(); 5569 if (keyguardActive) { 5570 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE); 5571 } else { 5572 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); 5573 } 5574 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens, 5575 "android.policy:CAMERA_COVER"); 5576 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); 5577 } 5578 mCameraLensCoverState = lensCoverState; 5579 } 5580 5581 void setHdmiPlugged(boolean plugged) { 5582 if (mHdmiPlugged != plugged) { 5583 mHdmiPlugged = plugged; 5584 updateRotation(true, true); 5585 Intent intent = new Intent(ACTION_HDMI_PLUGGED); 5586 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5587 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged); 5588 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 5589 } 5590 } 5591 5592 void initializeHdmiState() { 5593 boolean plugged = false; 5594 // watch for HDMI plug messages if the hdmi switch exists 5595 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) { 5596 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi"); 5597 5598 final String filename = "/sys/class/switch/hdmi/state"; 5599 FileReader reader = null; 5600 try { 5601 reader = new FileReader(filename); 5602 char[] buf = new char[15]; 5603 int n = reader.read(buf); 5604 if (n > 1) { 5605 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1)); 5606 } 5607 } catch (IOException ex) { 5608 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5609 } catch (NumberFormatException ex) { 5610 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5611 } finally { 5612 if (reader != null) { 5613 try { 5614 reader.close(); 5615 } catch (IOException ex) { 5616 } 5617 } 5618 } 5619 } 5620 // This dance forces the code in setHdmiPlugged to run. 5621 // Always do this so the sticky intent is stuck (to false) if there is no hdmi. 5622 mHdmiPlugged = !plugged; 5623 setHdmiPlugged(!mHdmiPlugged); 5624 } 5625 5626 final Object mScreenshotLock = new Object(); 5627 ServiceConnection mScreenshotConnection = null; 5628 5629 final Runnable mScreenshotTimeout = new Runnable() { 5630 @Override public void run() { 5631 synchronized (mScreenshotLock) { 5632 if (mScreenshotConnection != null) { 5633 mContext.unbindService(mScreenshotConnection); 5634 mScreenshotConnection = null; 5635 notifyScreenshotError(); 5636 } 5637 } 5638 } 5639 }; 5640 5641 // Assume this is called from the Handler thread. 5642 private void takeScreenshot(final int screenshotType) { 5643 synchronized (mScreenshotLock) { 5644 if (mScreenshotConnection != null) { 5645 return; 5646 } 5647 final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE, 5648 SYSUI_SCREENSHOT_SERVICE); 5649 final Intent serviceIntent = new Intent(); 5650 serviceIntent.setComponent(serviceComponent); 5651 ServiceConnection conn = new ServiceConnection() { 5652 @Override 5653 public void onServiceConnected(ComponentName name, IBinder service) { 5654 synchronized (mScreenshotLock) { 5655 if (mScreenshotConnection != this) { 5656 return; 5657 } 5658 Messenger messenger = new Messenger(service); 5659 Message msg = Message.obtain(null, screenshotType); 5660 final ServiceConnection myConn = this; 5661 Handler h = new Handler(mHandler.getLooper()) { 5662 @Override 5663 public void handleMessage(Message msg) { 5664 synchronized (mScreenshotLock) { 5665 if (mScreenshotConnection == myConn) { 5666 mContext.unbindService(mScreenshotConnection); 5667 mScreenshotConnection = null; 5668 mHandler.removeCallbacks(mScreenshotTimeout); 5669 } 5670 } 5671 } 5672 }; 5673 msg.replyTo = new Messenger(h); 5674 msg.arg1 = msg.arg2 = 0; 5675 if (mStatusBar != null && mStatusBar.isVisibleLw()) 5676 msg.arg1 = 1; 5677 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) 5678 msg.arg2 = 1; 5679 try { 5680 messenger.send(msg); 5681 } catch (RemoteException e) { 5682 } 5683 } 5684 } 5685 5686 @Override 5687 public void onServiceDisconnected(ComponentName name) { 5688 synchronized (mScreenshotLock) { 5689 if (mScreenshotConnection != null) { 5690 mContext.unbindService(mScreenshotConnection); 5691 mScreenshotConnection = null; 5692 mHandler.removeCallbacks(mScreenshotTimeout); 5693 notifyScreenshotError(); 5694 } 5695 } 5696 } 5697 }; 5698 if (mContext.bindServiceAsUser(serviceIntent, conn, 5699 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, 5700 UserHandle.CURRENT)) { 5701 mScreenshotConnection = conn; 5702 mHandler.postDelayed(mScreenshotTimeout, 10000); 5703 } 5704 } 5705 } 5706 5707 /** 5708 * Notifies the screenshot service to show an error. 5709 */ 5710 private void notifyScreenshotError() { 5711 // If the service process is killed, then ask it to clean up after itself 5712 final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE, 5713 SYSUI_SCREENSHOT_ERROR_RECEIVER); 5714 Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT); 5715 errorIntent.setComponent(errorComponent); 5716 errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | 5717 Intent.FLAG_RECEIVER_FOREGROUND); 5718 mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT); 5719 } 5720 5721 /** {@inheritDoc} */ 5722 @Override 5723 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { 5724 if (!mSystemBooted) { 5725 // If we have not yet booted, don't let key events do anything. 5726 return 0; 5727 } 5728 5729 final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0; 5730 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; 5731 final boolean canceled = event.isCanceled(); 5732 final int keyCode = event.getKeyCode(); 5733 5734 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; 5735 5736 // If screen is off then we treat the case where the keyguard is open but hidden 5737 // the same as if it were open and in front. 5738 // This will prevent any keys other than the power button from waking the screen 5739 // when the keyguard is hidden by another activity. 5740 final boolean keyguardActive = (mKeyguardDelegate == null ? false : 5741 (interactive ? 5742 isKeyguardShowingAndNotOccluded() : 5743 mKeyguardDelegate.isShowing())); 5744 5745 if (DEBUG_INPUT) { 5746 Log.d(TAG, "interceptKeyTq keycode=" + keyCode 5747 + " interactive=" + interactive + " keyguardActive=" + keyguardActive 5748 + " policyFlags=" + Integer.toHexString(policyFlags)); 5749 } 5750 5751 // Basic policy based on interactive state. 5752 int result; 5753 boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0 5754 || event.isWakeKey(); 5755 if (interactive || (isInjected && !isWakeKey)) { 5756 // When the device is interactive or the key is injected pass the 5757 // key to the application. 5758 result = ACTION_PASS_TO_USER; 5759 isWakeKey = false; 5760 5761 if (interactive) { 5762 // If the screen is awake, but the button pressed was the one that woke the device 5763 // then don't pass it to the application 5764 if (keyCode == mPendingWakeKey && !down) { 5765 result = 0; 5766 } 5767 // Reset the pending key 5768 mPendingWakeKey = PENDING_KEY_NULL; 5769 } 5770 } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) { 5771 // If we're currently dozing with the screen on and the keyguard showing, pass the key 5772 // to the application but preserve its wake key status to make sure we still move 5773 // from dozing to fully interactive if we would normally go from off to fully 5774 // interactive. 5775 result = ACTION_PASS_TO_USER; 5776 // Since we're dispatching the input, reset the pending key 5777 mPendingWakeKey = PENDING_KEY_NULL; 5778 } else { 5779 // When the screen is off and the key is not injected, determine whether 5780 // to wake the device but don't pass the key to the application. 5781 result = 0; 5782 if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) { 5783 isWakeKey = false; 5784 } 5785 // Cache the wake key on down event so we can also avoid sending the up event to the app 5786 if (isWakeKey && down) { 5787 mPendingWakeKey = keyCode; 5788 } 5789 } 5790 5791 // If the key would be handled globally, just return the result, don't worry about special 5792 // key processing. 5793 if (isValidGlobalKey(keyCode) 5794 && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) { 5795 if (isWakeKey) { 5796 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 5797 } 5798 return result; 5799 } 5800 5801 boolean useHapticFeedback = down 5802 && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0 5803 && event.getRepeatCount() == 0; 5804 5805 // Handle special keys. 5806 switch (keyCode) { 5807 case KeyEvent.KEYCODE_BACK: { 5808 if (down) { 5809 interceptBackKeyDown(); 5810 } else { 5811 boolean handled = interceptBackKeyUp(event); 5812 5813 // Don't pass back press to app if we've already handled it via long press 5814 if (handled) { 5815 result &= ~ACTION_PASS_TO_USER; 5816 } 5817 } 5818 break; 5819 } 5820 5821 case KeyEvent.KEYCODE_VOLUME_DOWN: 5822 case KeyEvent.KEYCODE_VOLUME_UP: 5823 case KeyEvent.KEYCODE_VOLUME_MUTE: { 5824 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { 5825 if (down) { 5826 if (interactive && !mScreenshotChordVolumeDownKeyTriggered 5827 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5828 mScreenshotChordVolumeDownKeyTriggered = true; 5829 mScreenshotChordVolumeDownKeyTime = event.getDownTime(); 5830 mScreenshotChordVolumeDownKeyConsumed = false; 5831 cancelPendingPowerKeyAction(); 5832 interceptScreenshotChord(); 5833 } 5834 } else { 5835 mScreenshotChordVolumeDownKeyTriggered = false; 5836 cancelPendingScreenshotChordAction(); 5837 } 5838 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 5839 if (down) { 5840 if (interactive && !mScreenshotChordVolumeUpKeyTriggered 5841 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5842 mScreenshotChordVolumeUpKeyTriggered = true; 5843 cancelPendingPowerKeyAction(); 5844 cancelPendingScreenshotChordAction(); 5845 } 5846 } else { 5847 mScreenshotChordVolumeUpKeyTriggered = false; 5848 cancelPendingScreenshotChordAction(); 5849 } 5850 } 5851 if (down) { 5852 TelecomManager telecomManager = getTelecommService(); 5853 if (telecomManager != null) { 5854 if (telecomManager.isRinging()) { 5855 // If an incoming call is ringing, either VOLUME key means 5856 // "silence ringer". We handle these keys here, rather than 5857 // in the InCallScreen, to make sure we'll respond to them 5858 // even if the InCallScreen hasn't come to the foreground yet. 5859 // Look for the DOWN event here, to agree with the "fallback" 5860 // behavior in the InCallScreen. 5861 Log.i(TAG, "interceptKeyBeforeQueueing:" 5862 + " VOLUME key-down while ringing: Silence ringer!"); 5863 5864 // Silence the ringer. (It's safe to call this 5865 // even if the ringer has already been silenced.) 5866 telecomManager.silenceRinger(); 5867 5868 // And *don't* pass this key thru to the current activity 5869 // (which is probably the InCallScreen.) 5870 result &= ~ACTION_PASS_TO_USER; 5871 break; 5872 } 5873 if (telecomManager.isInCall() 5874 && (result & ACTION_PASS_TO_USER) == 0) { 5875 // If we are in call but we decided not to pass the key to 5876 // the application, just pass it to the session service. 5877 5878 MediaSessionLegacyHelper.getHelper(mContext) 5879 .sendVolumeKeyEvent(event, false); 5880 break; 5881 } 5882 } 5883 } 5884 if (mUseTvRouting) { 5885 // On TVs, defer special key handlings to 5886 // {@link interceptKeyBeforeDispatching()}. 5887 result |= ACTION_PASS_TO_USER; 5888 } else if ((result & ACTION_PASS_TO_USER) == 0) { 5889 // If we aren't passing to the user and no one else 5890 // handled it send it to the session manager to 5891 // figure out. 5892 MediaSessionLegacyHelper.getHelper(mContext) 5893 .sendVolumeKeyEvent(event, true); 5894 } 5895 break; 5896 } 5897 5898 case KeyEvent.KEYCODE_ENDCALL: { 5899 result &= ~ACTION_PASS_TO_USER; 5900 if (down) { 5901 TelecomManager telecomManager = getTelecommService(); 5902 boolean hungUp = false; 5903 if (telecomManager != null) { 5904 hungUp = telecomManager.endCall(); 5905 } 5906 if (interactive && !hungUp) { 5907 mEndCallKeyHandled = false; 5908 mHandler.postDelayed(mEndCallLongPress, 5909 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 5910 } else { 5911 mEndCallKeyHandled = true; 5912 } 5913 } else { 5914 if (!mEndCallKeyHandled) { 5915 mHandler.removeCallbacks(mEndCallLongPress); 5916 if (!canceled) { 5917 if ((mEndcallBehavior 5918 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) { 5919 if (goHome()) { 5920 break; 5921 } 5922 } 5923 if ((mEndcallBehavior 5924 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) { 5925 mPowerManager.goToSleep(event.getEventTime(), 5926 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); 5927 isWakeKey = false; 5928 } 5929 } 5930 } 5931 } 5932 break; 5933 } 5934 5935 case KeyEvent.KEYCODE_POWER: { 5936 result &= ~ACTION_PASS_TO_USER; 5937 isWakeKey = false; // wake-up will be handled separately 5938 if (down) { 5939 interceptPowerKeyDown(event, interactive); 5940 } else { 5941 interceptPowerKeyUp(event, interactive, canceled); 5942 } 5943 break; 5944 } 5945 5946 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN: 5947 // fall through 5948 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP: 5949 // fall through 5950 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT: 5951 // fall through 5952 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: { 5953 result &= ~ACTION_PASS_TO_USER; 5954 interceptSystemNavigationKey(event); 5955 break; 5956 } 5957 5958 case KeyEvent.KEYCODE_SLEEP: { 5959 result &= ~ACTION_PASS_TO_USER; 5960 isWakeKey = false; 5961 if (!mPowerManager.isInteractive()) { 5962 useHapticFeedback = false; // suppress feedback if already non-interactive 5963 } 5964 if (down) { 5965 sleepPress(event.getEventTime()); 5966 } else { 5967 sleepRelease(event.getEventTime()); 5968 } 5969 break; 5970 } 5971 5972 case KeyEvent.KEYCODE_SOFT_SLEEP: { 5973 result &= ~ACTION_PASS_TO_USER; 5974 isWakeKey = false; 5975 if (!down) { 5976 mPowerManagerInternal.setUserInactiveOverrideFromWindowManager(); 5977 } 5978 break; 5979 } 5980 5981 case KeyEvent.KEYCODE_WAKEUP: { 5982 result &= ~ACTION_PASS_TO_USER; 5983 isWakeKey = true; 5984 break; 5985 } 5986 5987 case KeyEvent.KEYCODE_MEDIA_PLAY: 5988 case KeyEvent.KEYCODE_MEDIA_PAUSE: 5989 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 5990 case KeyEvent.KEYCODE_HEADSETHOOK: 5991 case KeyEvent.KEYCODE_MUTE: 5992 case KeyEvent.KEYCODE_MEDIA_STOP: 5993 case KeyEvent.KEYCODE_MEDIA_NEXT: 5994 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 5995 case KeyEvent.KEYCODE_MEDIA_REWIND: 5996 case KeyEvent.KEYCODE_MEDIA_RECORD: 5997 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 5998 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { 5999 if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) { 6000 // If the global session is active pass all media keys to it 6001 // instead of the active window. 6002 result &= ~ACTION_PASS_TO_USER; 6003 } 6004 if ((result & ACTION_PASS_TO_USER) == 0) { 6005 // Only do this if we would otherwise not pass it to the user. In that 6006 // case, the PhoneWindow class will do the same thing, except it will 6007 // only do it if the showing app doesn't process the key on its own. 6008 // Note that we need to make a copy of the key event here because the 6009 // original key event will be recycled when we return. 6010 mBroadcastWakeLock.acquire(); 6011 Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK, 6012 new KeyEvent(event)); 6013 msg.setAsynchronous(true); 6014 msg.sendToTarget(); 6015 } 6016 break; 6017 } 6018 6019 case KeyEvent.KEYCODE_CALL: { 6020 if (down) { 6021 TelecomManager telecomManager = getTelecommService(); 6022 if (telecomManager != null) { 6023 if (telecomManager.isRinging()) { 6024 Log.i(TAG, "interceptKeyBeforeQueueing:" 6025 + " CALL key-down while ringing: Answer the call!"); 6026 telecomManager.acceptRingingCall(); 6027 6028 // And *don't* pass this key thru to the current activity 6029 // (which is presumably the InCallScreen.) 6030 result &= ~ACTION_PASS_TO_USER; 6031 } 6032 } 6033 } 6034 break; 6035 } 6036 case KeyEvent.KEYCODE_VOICE_ASSIST: { 6037 // Only do this if we would otherwise not pass it to the user. In that case, 6038 // interceptKeyBeforeDispatching would apply a similar but different policy in 6039 // order to invoke voice assist actions. Note that we need to make a copy of the 6040 // key event here because the original key event will be recycled when we return. 6041 if ((result & ACTION_PASS_TO_USER) == 0 && !down) { 6042 mBroadcastWakeLock.acquire(); 6043 Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK, 6044 keyguardActive ? 1 : 0, 0); 6045 msg.setAsynchronous(true); 6046 msg.sendToTarget(); 6047 } 6048 break; 6049 } 6050 case KeyEvent.KEYCODE_WINDOW: { 6051 if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) { 6052 if (mTvPictureInPictureVisible) { 6053 // Consumes the key only if picture-in-picture is visible 6054 // to show picture-in-picture control menu. 6055 // This gives a chance to the foreground activity 6056 // to customize PIP key behavior. 6057 if (!down) { 6058 showTvPictureInPictureMenu(event); 6059 } 6060 result &= ~ACTION_PASS_TO_USER; 6061 } 6062 } 6063 break; 6064 } 6065 } 6066 6067 if (useHapticFeedback) { 6068 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); 6069 } 6070 6071 if (isWakeKey) { 6072 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 6073 } 6074 6075 return result; 6076 } 6077 6078 /** 6079 * Handle statusbar expansion events. 6080 * @param event 6081 */ 6082 private void interceptSystemNavigationKey(KeyEvent event) { 6083 if (event.getAction() == KeyEvent.ACTION_UP && areSystemNavigationKeysEnabled()) { 6084 IStatusBarService sbar = getStatusBarService(); 6085 if (sbar != null) { 6086 try { 6087 sbar.handleSystemNavigationKey(event.getKeyCode()); 6088 } catch (RemoteException e1) { 6089 // oops, no statusbar. Ignore event. 6090 } 6091 } 6092 } 6093 } 6094 6095 /** 6096 * Returns true if the key can have global actions attached to it. 6097 * We reserve all power management keys for the system since they require 6098 * very careful handling. 6099 */ 6100 private static boolean isValidGlobalKey(int keyCode) { 6101 switch (keyCode) { 6102 case KeyEvent.KEYCODE_POWER: 6103 case KeyEvent.KEYCODE_WAKEUP: 6104 case KeyEvent.KEYCODE_SLEEP: 6105 return false; 6106 default: 6107 return true; 6108 } 6109 } 6110 6111 /** 6112 * When the screen is off we ignore some keys that might otherwise typically 6113 * be considered wake keys. We filter them out here. 6114 * 6115 * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it 6116 * is always considered a wake key. 6117 */ 6118 private boolean isWakeKeyWhenScreenOff(int keyCode) { 6119 switch (keyCode) { 6120 // ignore volume keys unless docked 6121 case KeyEvent.KEYCODE_VOLUME_UP: 6122 case KeyEvent.KEYCODE_VOLUME_DOWN: 6123 case KeyEvent.KEYCODE_VOLUME_MUTE: 6124 return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED; 6125 6126 // ignore media and camera keys 6127 case KeyEvent.KEYCODE_MUTE: 6128 case KeyEvent.KEYCODE_HEADSETHOOK: 6129 case KeyEvent.KEYCODE_MEDIA_PLAY: 6130 case KeyEvent.KEYCODE_MEDIA_PAUSE: 6131 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 6132 case KeyEvent.KEYCODE_MEDIA_STOP: 6133 case KeyEvent.KEYCODE_MEDIA_NEXT: 6134 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 6135 case KeyEvent.KEYCODE_MEDIA_REWIND: 6136 case KeyEvent.KEYCODE_MEDIA_RECORD: 6137 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 6138 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: 6139 case KeyEvent.KEYCODE_CAMERA: 6140 return false; 6141 } 6142 return true; 6143 } 6144 6145 6146 /** {@inheritDoc} */ 6147 @Override 6148 public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) { 6149 if ((policyFlags & FLAG_WAKE) != 0) { 6150 if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion, 6151 "android.policy:MOTION")) { 6152 return 0; 6153 } 6154 } 6155 6156 if (shouldDispatchInputWhenNonInteractive(null)) { 6157 return ACTION_PASS_TO_USER; 6158 } 6159 6160 // If we have not passed the action up and we are in theater mode without dreaming, 6161 // there will be no dream to intercept the touch and wake into ambient. The device should 6162 // wake up in this case. 6163 if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) { 6164 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming, 6165 "android.policy:MOTION"); 6166 } 6167 6168 return 0; 6169 } 6170 6171 private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) { 6172 final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF); 6173 6174 if (displayOff && !mHasFeatureWatch) { 6175 return false; 6176 } 6177 6178 // Send events to keyguard while the screen is on and it's showing. 6179 if (isKeyguardShowingAndNotOccluded() && !displayOff) { 6180 return true; 6181 } 6182 6183 // Watches handle BACK specially 6184 if (mHasFeatureWatch 6185 && event != null 6186 && (event.getKeyCode() == KeyEvent.KEYCODE_BACK 6187 || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) { 6188 return false; 6189 } 6190 6191 // Send events to a dozing dream even if the screen is off since the dream 6192 // is in control of the state of the screen. 6193 IDreamManager dreamManager = getDreamManager(); 6194 6195 try { 6196 if (dreamManager != null && dreamManager.isDreaming()) { 6197 return true; 6198 } 6199 } catch (RemoteException e) { 6200 Slog.e(TAG, "RemoteException when checking if dreaming", e); 6201 } 6202 6203 // Otherwise, consume events since the user can't see what is being 6204 // interacted with. 6205 return false; 6206 } 6207 6208 private void dispatchDirectAudioEvent(KeyEvent event) { 6209 if (event.getAction() != KeyEvent.ACTION_DOWN) { 6210 return; 6211 } 6212 int keyCode = event.getKeyCode(); 6213 int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND 6214 | AudioManager.FLAG_FROM_KEY; 6215 String pkgName = mContext.getOpPackageName(); 6216 switch (keyCode) { 6217 case KeyEvent.KEYCODE_VOLUME_UP: 6218 try { 6219 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE, 6220 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6221 } catch (RemoteException e) { 6222 Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e); 6223 } 6224 break; 6225 case KeyEvent.KEYCODE_VOLUME_DOWN: 6226 try { 6227 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER, 6228 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6229 } catch (RemoteException e) { 6230 Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e); 6231 } 6232 break; 6233 case KeyEvent.KEYCODE_VOLUME_MUTE: 6234 try { 6235 if (event.getRepeatCount() == 0) { 6236 getAudioService().adjustSuggestedStreamVolume( 6237 AudioManager.ADJUST_TOGGLE_MUTE, 6238 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6239 } 6240 } catch (RemoteException e) { 6241 Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e); 6242 } 6243 break; 6244 } 6245 } 6246 6247 void dispatchMediaKeyWithWakeLock(KeyEvent event) { 6248 if (DEBUG_INPUT) { 6249 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event); 6250 } 6251 6252 if (mHavePendingMediaKeyRepeatWithWakeLock) { 6253 if (DEBUG_INPUT) { 6254 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat"); 6255 } 6256 6257 mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK); 6258 mHavePendingMediaKeyRepeatWithWakeLock = false; 6259 mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock 6260 } 6261 6262 dispatchMediaKeyWithWakeLockToAudioService(event); 6263 6264 if (event.getAction() == KeyEvent.ACTION_DOWN 6265 && event.getRepeatCount() == 0) { 6266 mHavePendingMediaKeyRepeatWithWakeLock = true; 6267 6268 Message msg = mHandler.obtainMessage( 6269 MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event); 6270 msg.setAsynchronous(true); 6271 mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout()); 6272 } else { 6273 mBroadcastWakeLock.release(); 6274 } 6275 } 6276 6277 void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) { 6278 mHavePendingMediaKeyRepeatWithWakeLock = false; 6279 6280 KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event, 6281 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS); 6282 if (DEBUG_INPUT) { 6283 Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent); 6284 } 6285 6286 dispatchMediaKeyWithWakeLockToAudioService(repeatEvent); 6287 mBroadcastWakeLock.release(); 6288 } 6289 6290 void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) { 6291 if (ActivityManagerNative.isSystemReady()) { 6292 MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true); 6293 } 6294 } 6295 6296 void launchVoiceAssistWithWakeLock(boolean keyguardActive) { 6297 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface( 6298 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); 6299 if (dic != null) { 6300 try { 6301 dic.exitIdle("voice-search"); 6302 } catch (RemoteException e) { 6303 } 6304 } 6305 Intent voiceIntent = 6306 new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); 6307 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive); 6308 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF); 6309 mBroadcastWakeLock.release(); 6310 } 6311 6312 BroadcastReceiver mDockReceiver = new BroadcastReceiver() { 6313 @Override 6314 public void onReceive(Context context, Intent intent) { 6315 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) { 6316 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 6317 Intent.EXTRA_DOCK_STATE_UNDOCKED); 6318 } else { 6319 try { 6320 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface( 6321 ServiceManager.getService(Context.UI_MODE_SERVICE)); 6322 mUiMode = uiModeService.getCurrentModeType(); 6323 } catch (RemoteException e) { 6324 } 6325 } 6326 updateRotation(true); 6327 synchronized (mLock) { 6328 updateOrientationListenerLp(); 6329 } 6330 } 6331 }; 6332 6333 BroadcastReceiver mDreamReceiver = new BroadcastReceiver() { 6334 @Override 6335 public void onReceive(Context context, Intent intent) { 6336 if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) { 6337 if (mKeyguardDelegate != null) { 6338 mKeyguardDelegate.onDreamingStarted(); 6339 } 6340 } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) { 6341 if (mKeyguardDelegate != null) { 6342 mKeyguardDelegate.onDreamingStopped(); 6343 } 6344 } 6345 } 6346 }; 6347 6348 BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() { 6349 @Override 6350 public void onReceive(Context context, Intent intent) { 6351 if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) { 6352 // tickle the settings observer: this first ensures that we're 6353 // observing the relevant settings for the newly-active user, 6354 // and then updates our own bookkeeping based on the now- 6355 // current user. 6356 mSettingsObserver.onChange(false); 6357 6358 // force a re-application of focused window sysui visibility. 6359 // the window may never have been shown for this user 6360 // e.g. the keyguard when going through the new-user setup flow 6361 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6362 mLastSystemUiFlags = 0; 6363 updateSystemUiVisibilityLw(); 6364 } 6365 } 6366 } 6367 }; 6368 6369 private final Runnable mHiddenNavPanic = new Runnable() { 6370 @Override 6371 public void run() { 6372 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6373 if (!isUserSetupComplete()) { 6374 // Swipe-up for navigation bar is disabled during setup 6375 return; 6376 } 6377 mPendingPanicGestureUptime = SystemClock.uptimeMillis(); 6378 if (!isNavBarEmpty(mLastSystemUiFlags)) { 6379 mNavigationBarController.showTransient(); 6380 } 6381 } 6382 } 6383 }; 6384 6385 private void requestTransientBars(WindowState swipeTarget) { 6386 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6387 if (!isUserSetupComplete()) { 6388 // Swipe-up for navigation bar is disabled during setup 6389 return; 6390 } 6391 boolean sb = mStatusBarController.checkShowTransientBarLw(); 6392 boolean nb = mNavigationBarController.checkShowTransientBarLw() 6393 && !isNavBarEmpty(mLastSystemUiFlags); 6394 if (sb || nb) { 6395 // Don't show status bar when swiping on already visible navigation bar 6396 if (!nb && swipeTarget == mNavigationBar) { 6397 if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target"); 6398 return; 6399 } 6400 if (sb) mStatusBarController.showTransient(); 6401 if (nb) mNavigationBarController.showTransient(); 6402 mImmersiveModeConfirmation.confirmCurrentPrompt(); 6403 updateSystemUiVisibilityLw(); 6404 } 6405 } 6406 } 6407 6408 // Called on the PowerManager's Notifier thread. 6409 @Override 6410 public void startedGoingToSleep(int why) { 6411 if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")"); 6412 mCameraGestureTriggeredDuringGoingToSleep = false; 6413 mGoingToSleep = true; 6414 if (mKeyguardDelegate != null) { 6415 mKeyguardDelegate.onStartedGoingToSleep(why); 6416 } 6417 } 6418 6419 // Called on the PowerManager's Notifier thread. 6420 @Override 6421 public void finishedGoingToSleep(int why) { 6422 EventLog.writeEvent(70000, 0); 6423 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")"); 6424 MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000); 6425 6426 mGoingToSleep = false; 6427 6428 // We must get this work done here because the power manager will drop 6429 // the wake lock and let the system suspend once this function returns. 6430 synchronized (mLock) { 6431 mAwake = false; 6432 updateWakeGestureListenerLp(); 6433 updateOrientationListenerLp(); 6434 updateLockScreenTimeout(); 6435 } 6436 if (mKeyguardDelegate != null) { 6437 mKeyguardDelegate.onFinishedGoingToSleep(why, 6438 mCameraGestureTriggeredDuringGoingToSleep); 6439 } 6440 mCameraGestureTriggeredDuringGoingToSleep = false; 6441 } 6442 6443 // Called on the PowerManager's Notifier thread. 6444 @Override 6445 public void startedWakingUp() { 6446 EventLog.writeEvent(70000, 1); 6447 if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up..."); 6448 6449 // Since goToSleep performs these functions synchronously, we must 6450 // do the same here. We cannot post this work to a handler because 6451 // that might cause it to become reordered with respect to what 6452 // may happen in a future call to goToSleep. 6453 synchronized (mLock) { 6454 mAwake = true; 6455 6456 updateWakeGestureListenerLp(); 6457 updateOrientationListenerLp(); 6458 updateLockScreenTimeout(); 6459 } 6460 6461 if (mKeyguardDelegate != null) { 6462 mKeyguardDelegate.onStartedWakingUp(); 6463 } 6464 } 6465 6466 // Called on the PowerManager's Notifier thread. 6467 @Override 6468 public void finishedWakingUp() { 6469 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up..."); 6470 } 6471 6472 private void wakeUpFromPowerKey(long eventTime) { 6473 wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER"); 6474 } 6475 6476 private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) { 6477 final boolean theaterModeEnabled = isTheaterModeEnabled(); 6478 if (!wakeInTheaterMode && theaterModeEnabled) { 6479 return false; 6480 } 6481 6482 if (theaterModeEnabled) { 6483 Settings.Global.putInt(mContext.getContentResolver(), 6484 Settings.Global.THEATER_MODE_ON, 0); 6485 } 6486 6487 mPowerManager.wakeUp(wakeTime, reason); 6488 return true; 6489 } 6490 6491 private void finishKeyguardDrawn() { 6492 synchronized (mLock) { 6493 if (!mScreenOnEarly || mKeyguardDrawComplete) { 6494 return; // We are not awake yet or we have already informed of this event. 6495 } 6496 6497 mKeyguardDrawComplete = true; 6498 if (mKeyguardDelegate != null) { 6499 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6500 } 6501 mWindowManagerDrawComplete = false; 6502 } 6503 6504 // ... eventually calls finishWindowsDrawn which will finalize our screen turn on 6505 // as well as enabling the orientation change logic/sensor. 6506 mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback, 6507 WAITING_FOR_DRAWN_TIMEOUT); 6508 } 6509 6510 // Called on the DisplayManager's DisplayPowerController thread. 6511 @Override 6512 public void screenTurnedOff() { 6513 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off..."); 6514 6515 updateScreenOffSleepToken(true); 6516 synchronized (mLock) { 6517 mScreenOnEarly = false; 6518 mScreenOnFully = false; 6519 mKeyguardDrawComplete = false; 6520 mWindowManagerDrawComplete = false; 6521 mScreenOnListener = null; 6522 updateOrientationListenerLp(); 6523 6524 if (mKeyguardDelegate != null) { 6525 mKeyguardDelegate.onScreenTurnedOff(); 6526 } 6527 } 6528 } 6529 6530 // Called on the DisplayManager's DisplayPowerController thread. 6531 @Override 6532 public void screenTurningOn(final ScreenOnListener screenOnListener) { 6533 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on..."); 6534 6535 updateScreenOffSleepToken(false); 6536 synchronized (mLock) { 6537 mScreenOnEarly = true; 6538 mScreenOnFully = false; 6539 mKeyguardDrawComplete = false; 6540 mWindowManagerDrawComplete = false; 6541 mScreenOnListener = screenOnListener; 6542 6543 if (mKeyguardDelegate != null) { 6544 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6545 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000); 6546 mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback); 6547 } else { 6548 if (DEBUG_WAKEUP) Slog.d(TAG, 6549 "null mKeyguardDelegate: setting mKeyguardDrawComplete."); 6550 finishKeyguardDrawn(); 6551 } 6552 } 6553 } 6554 6555 // Called on the DisplayManager's DisplayPowerController thread. 6556 @Override 6557 public void screenTurnedOn() { 6558 synchronized (mLock) { 6559 if (mKeyguardDelegate != null) { 6560 mKeyguardDelegate.onScreenTurnedOn(); 6561 } 6562 } 6563 } 6564 6565 private void finishWindowsDrawn() { 6566 synchronized (mLock) { 6567 if (!mScreenOnEarly || mWindowManagerDrawComplete) { 6568 return; // Screen is not turned on or we did already handle this case earlier. 6569 } 6570 6571 mWindowManagerDrawComplete = true; 6572 } 6573 6574 finishScreenTurningOn(); 6575 } 6576 6577 private void finishScreenTurningOn() { 6578 synchronized (mLock) { 6579 // We have just finished drawing screen content. Since the orientation listener 6580 // gets only installed when all windows are drawn, we try to install it again. 6581 updateOrientationListenerLp(); 6582 } 6583 final ScreenOnListener listener; 6584 final boolean enableScreen; 6585 synchronized (mLock) { 6586 if (DEBUG_WAKEUP) Slog.d(TAG, 6587 "finishScreenTurningOn: mAwake=" + mAwake 6588 + ", mScreenOnEarly=" + mScreenOnEarly 6589 + ", mScreenOnFully=" + mScreenOnFully 6590 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete 6591 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete); 6592 6593 if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete 6594 || (mAwake && !mKeyguardDrawComplete)) { 6595 return; // spurious or not ready yet 6596 } 6597 6598 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on..."); 6599 listener = mScreenOnListener; 6600 mScreenOnListener = null; 6601 mScreenOnFully = true; 6602 6603 // Remember the first time we draw the keyguard so we know when we're done with 6604 // the main part of booting and can enable the screen and hide boot messages. 6605 if (!mKeyguardDrawnOnce && mAwake) { 6606 mKeyguardDrawnOnce = true; 6607 enableScreen = true; 6608 if (mBootMessageNeedsHiding) { 6609 mBootMessageNeedsHiding = false; 6610 hideBootMessages(); 6611 } 6612 } else { 6613 enableScreen = false; 6614 } 6615 } 6616 6617 if (listener != null) { 6618 listener.onScreenOn(); 6619 } 6620 6621 if (enableScreen) { 6622 try { 6623 mWindowManager.enableScreenIfNeeded(); 6624 } catch (RemoteException unhandled) { 6625 } 6626 } 6627 } 6628 6629 private void handleHideBootMessage() { 6630 synchronized (mLock) { 6631 if (!mKeyguardDrawnOnce) { 6632 mBootMessageNeedsHiding = true; 6633 return; // keyguard hasn't drawn the first time yet, not done booting 6634 } 6635 } 6636 6637 if (mBootMsgDialog != null) { 6638 if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing"); 6639 mBootMsgDialog.dismiss(); 6640 mBootMsgDialog = null; 6641 } 6642 } 6643 6644 @Override 6645 public boolean isScreenOn() { 6646 return mScreenOnFully; 6647 } 6648 6649 /** {@inheritDoc} */ 6650 @Override 6651 public void enableKeyguard(boolean enabled) { 6652 if (mKeyguardDelegate != null) { 6653 mKeyguardDelegate.setKeyguardEnabled(enabled); 6654 } 6655 } 6656 6657 /** {@inheritDoc} */ 6658 @Override 6659 public void exitKeyguardSecurely(OnKeyguardExitResult callback) { 6660 if (mKeyguardDelegate != null) { 6661 mKeyguardDelegate.verifyUnlock(callback); 6662 } 6663 } 6664 6665 private boolean isKeyguardShowingAndNotOccluded() { 6666 if (mKeyguardDelegate == null) return false; 6667 return mKeyguardDelegate.isShowing() && !mKeyguardOccluded; 6668 } 6669 6670 /** {@inheritDoc} */ 6671 @Override 6672 public boolean isKeyguardLocked() { 6673 return keyguardOn(); 6674 } 6675 6676 /** {@inheritDoc} */ 6677 @Override 6678 public boolean isKeyguardSecure(int userId) { 6679 if (mKeyguardDelegate == null) return false; 6680 return mKeyguardDelegate.isSecure(userId); 6681 } 6682 6683 /** {@inheritDoc} */ 6684 @Override 6685 public boolean isKeyguardShowingOrOccluded() { 6686 return mKeyguardDelegate == null ? false : mKeyguardDelegate.isShowing(); 6687 } 6688 6689 /** {@inheritDoc} */ 6690 @Override 6691 public boolean inKeyguardRestrictedKeyInputMode() { 6692 if (mKeyguardDelegate == null) return false; 6693 return mKeyguardDelegate.isInputRestricted(); 6694 } 6695 6696 @Override 6697 public void dismissKeyguardLw() { 6698 if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) { 6699 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw"); 6700 mHandler.post(new Runnable() { 6701 @Override 6702 public void run() { 6703 // ask the keyguard to prompt the user to authenticate if necessary 6704 mKeyguardDelegate.dismiss(false /* allowWhileOccluded */); 6705 } 6706 }); 6707 } 6708 } 6709 6710 @Override 6711 public void notifyActivityDrawnForKeyguardLw() { 6712 if (mKeyguardDelegate != null) { 6713 mHandler.post(new Runnable() { 6714 @Override 6715 public void run() { 6716 mKeyguardDelegate.onActivityDrawn(); 6717 } 6718 }); 6719 } 6720 } 6721 6722 @Override 6723 public boolean isKeyguardDrawnLw() { 6724 synchronized (mLock) { 6725 return mKeyguardDrawnOnce; 6726 } 6727 } 6728 6729 @Override 6730 public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) { 6731 if (mKeyguardDelegate != null) { 6732 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation"); 6733 mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration); 6734 } 6735 } 6736 6737 @Override 6738 public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6739 Rect outInsets) { 6740 outInsets.setEmpty(); 6741 6742 // Navigation bar and status bar. 6743 getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets); 6744 if (mStatusBar != null) { 6745 outInsets.top = mStatusBarHeight; 6746 } 6747 } 6748 6749 @Override 6750 public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6751 Rect outInsets) { 6752 outInsets.setEmpty(); 6753 6754 // Only navigation bar 6755 if (mNavigationBar != null) { 6756 int position = navigationBarPosition(displayWidth, displayHeight, displayRotation); 6757 if (position == NAV_BAR_BOTTOM) { 6758 outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode); 6759 } else if (position == NAV_BAR_RIGHT) { 6760 outInsets.right = getNavigationBarWidth(displayRotation, mUiMode); 6761 } else if (position == NAV_BAR_LEFT) { 6762 outInsets.left = getNavigationBarWidth(displayRotation, mUiMode); 6763 } 6764 } 6765 } 6766 6767 @Override 6768 public boolean isNavBarForcedShownLw(WindowState windowState) { 6769 return mForceShowSystemBars; 6770 } 6771 6772 @Override 6773 public boolean isDockSideAllowed(int dockSide) { 6774 6775 // We do not allow all dock sides at which the navigation bar touches the docked stack. 6776 if (!mNavigationBarCanMove) { 6777 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT; 6778 } else { 6779 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT; 6780 } 6781 } 6782 6783 void sendCloseSystemWindows() { 6784 PhoneWindow.sendCloseSystemWindows(mContext, null); 6785 } 6786 6787 void sendCloseSystemWindows(String reason) { 6788 PhoneWindow.sendCloseSystemWindows(mContext, reason); 6789 } 6790 6791 @Override 6792 public int rotationForOrientationLw(int orientation, int lastRotation) { 6793 if (false) { 6794 Slog.v(TAG, "rotationForOrientationLw(orient=" 6795 + orientation + ", last=" + lastRotation 6796 + "); user=" + mUserRotation + " " 6797 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) 6798 ? "USER_ROTATION_LOCKED" : "") 6799 ); 6800 } 6801 6802 if (mForceDefaultOrientation) { 6803 return Surface.ROTATION_0; 6804 } 6805 6806 synchronized (mLock) { 6807 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1 6808 if (sensorRotation < 0) { 6809 sensorRotation = lastRotation; 6810 } 6811 6812 final int preferredRotation; 6813 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) { 6814 // Ignore sensor when lid switch is open and rotation is forced. 6815 preferredRotation = mLidOpenRotation; 6816 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR 6817 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) { 6818 // Ignore sensor when in car dock unless explicitly enabled. 6819 // This case can override the behavior of NOSENSOR, and can also 6820 // enable 180 degree rotation while docked. 6821 preferredRotation = mCarDockEnablesAccelerometer 6822 ? sensorRotation : mCarDockRotation; 6823 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK 6824 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK 6825 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK) 6826 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) { 6827 // Ignore sensor when in desk dock unless explicitly enabled. 6828 // This case can override the behavior of NOSENSOR, and can also 6829 // enable 180 degree rotation while docked. 6830 preferredRotation = mDeskDockEnablesAccelerometer 6831 ? sensorRotation : mDeskDockRotation; 6832 } else if (mHdmiPlugged && mDemoHdmiRotationLock) { 6833 // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled. 6834 // Note that the dock orientation overrides the HDMI orientation. 6835 preferredRotation = mDemoHdmiRotation; 6836 } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED 6837 && mUndockedHdmiRotation >= 0) { 6838 // Ignore sensor when plugged into HDMI and an undocked orientation has 6839 // been specified in the configuration (only for legacy devices without 6840 // full multi-display support). 6841 // Note that the dock orientation overrides the HDMI orientation. 6842 preferredRotation = mUndockedHdmiRotation; 6843 } else if (mDemoRotationLock) { 6844 // Ignore sensor when demo rotation lock is enabled. 6845 // Note that the dock orientation and HDMI rotation lock override this. 6846 preferredRotation = mDemoRotation; 6847 } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) { 6848 // Application just wants to remain locked in the last rotation. 6849 preferredRotation = lastRotation; 6850 } else if (!mSupportAutoRotation) { 6851 // If we don't support auto-rotation then bail out here and ignore 6852 // the sensor and any rotation lock settings. 6853 preferredRotation = -1; 6854 } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE 6855 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER 6856 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 6857 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE 6858 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT 6859 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER)) 6860 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR 6861 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6862 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE 6863 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) { 6864 // Otherwise, use sensor only if requested by the application or enabled 6865 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR. 6866 if (mAllowAllRotations < 0) { 6867 // Can't read this during init() because the context doesn't 6868 // have display metrics at that time so we cannot determine 6869 // tablet vs. phone then. 6870 mAllowAllRotations = mContext.getResources().getBoolean( 6871 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0; 6872 } 6873 if (sensorRotation != Surface.ROTATION_180 6874 || mAllowAllRotations == 1 6875 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6876 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) { 6877 preferredRotation = sensorRotation; 6878 } else { 6879 preferredRotation = lastRotation; 6880 } 6881 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED 6882 && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) { 6883 // Apply rotation lock. Does not apply to NOSENSOR. 6884 // The idea is that the user rotation expresses a weak preference for the direction 6885 // of gravity and as NOSENSOR is never affected by gravity, then neither should 6886 // NOSENSOR be affected by rotation lock (although it will be affected by docks). 6887 preferredRotation = mUserRotation; 6888 } else { 6889 // No overriding preference. 6890 // We will do exactly what the application asked us to do. 6891 preferredRotation = -1; 6892 } 6893 6894 switch (orientation) { 6895 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 6896 // Return portrait unless overridden. 6897 if (isAnyPortrait(preferredRotation)) { 6898 return preferredRotation; 6899 } 6900 return mPortraitRotation; 6901 6902 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 6903 // Return landscape unless overridden. 6904 if (isLandscapeOrSeascape(preferredRotation)) { 6905 return preferredRotation; 6906 } 6907 return mLandscapeRotation; 6908 6909 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 6910 // Return reverse portrait unless overridden. 6911 if (isAnyPortrait(preferredRotation)) { 6912 return preferredRotation; 6913 } 6914 return mUpsideDownRotation; 6915 6916 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 6917 // Return seascape unless overridden. 6918 if (isLandscapeOrSeascape(preferredRotation)) { 6919 return preferredRotation; 6920 } 6921 return mSeascapeRotation; 6922 6923 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 6924 case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE: 6925 // Return either landscape rotation. 6926 if (isLandscapeOrSeascape(preferredRotation)) { 6927 return preferredRotation; 6928 } 6929 if (isLandscapeOrSeascape(lastRotation)) { 6930 return lastRotation; 6931 } 6932 return mLandscapeRotation; 6933 6934 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 6935 case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT: 6936 // Return either portrait rotation. 6937 if (isAnyPortrait(preferredRotation)) { 6938 return preferredRotation; 6939 } 6940 if (isAnyPortrait(lastRotation)) { 6941 return lastRotation; 6942 } 6943 return mPortraitRotation; 6944 6945 default: 6946 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR, 6947 // just return the preferred orientation we already calculated. 6948 if (preferredRotation >= 0) { 6949 return preferredRotation; 6950 } 6951 return Surface.ROTATION_0; 6952 } 6953 } 6954 } 6955 6956 @Override 6957 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) { 6958 switch (orientation) { 6959 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 6960 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 6961 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 6962 return isAnyPortrait(rotation); 6963 6964 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 6965 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 6966 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 6967 return isLandscapeOrSeascape(rotation); 6968 6969 default: 6970 return true; 6971 } 6972 } 6973 6974 @Override 6975 public void setRotationLw(int rotation) { 6976 mOrientationListener.setCurrentRotation(rotation); 6977 } 6978 6979 private boolean isLandscapeOrSeascape(int rotation) { 6980 return rotation == mLandscapeRotation || rotation == mSeascapeRotation; 6981 } 6982 6983 private boolean isAnyPortrait(int rotation) { 6984 return rotation == mPortraitRotation || rotation == mUpsideDownRotation; 6985 } 6986 6987 @Override 6988 public int getUserRotationMode() { 6989 return Settings.System.getIntForUser(mContext.getContentResolver(), 6990 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ? 6991 WindowManagerPolicy.USER_ROTATION_FREE : 6992 WindowManagerPolicy.USER_ROTATION_LOCKED; 6993 } 6994 6995 // User rotation: to be used when all else fails in assigning an orientation to the device 6996 @Override 6997 public void setUserRotationMode(int mode, int rot) { 6998 ContentResolver res = mContext.getContentResolver(); 6999 7000 // mUserRotationMode and mUserRotation will be assigned by the content observer 7001 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) { 7002 Settings.System.putIntForUser(res, 7003 Settings.System.USER_ROTATION, 7004 rot, 7005 UserHandle.USER_CURRENT); 7006 Settings.System.putIntForUser(res, 7007 Settings.System.ACCELEROMETER_ROTATION, 7008 0, 7009 UserHandle.USER_CURRENT); 7010 } else { 7011 Settings.System.putIntForUser(res, 7012 Settings.System.ACCELEROMETER_ROTATION, 7013 1, 7014 UserHandle.USER_CURRENT); 7015 } 7016 } 7017 7018 @Override 7019 public void setSafeMode(boolean safeMode) { 7020 mSafeMode = safeMode; 7021 performHapticFeedbackLw(null, safeMode 7022 ? HapticFeedbackConstants.SAFE_MODE_ENABLED 7023 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true); 7024 } 7025 7026 static long[] getLongIntArray(Resources r, int resid) { 7027 int[] ar = r.getIntArray(resid); 7028 if (ar == null) { 7029 return null; 7030 } 7031 long[] out = new long[ar.length]; 7032 for (int i=0; i<ar.length; i++) { 7033 out[i] = ar[i]; 7034 } 7035 return out; 7036 } 7037 7038 /** {@inheritDoc} */ 7039 @Override 7040 public void systemReady() { 7041 mKeyguardDelegate = new KeyguardServiceDelegate(mContext, 7042 this::onKeyguardShowingStateChanged); 7043 mKeyguardDelegate.onSystemReady(); 7044 7045 readCameraLensCoverState(); 7046 updateUiMode(); 7047 boolean bindKeyguardNow; 7048 synchronized (mLock) { 7049 updateOrientationListenerLp(); 7050 mSystemReady = true; 7051 mHandler.post(new Runnable() { 7052 @Override 7053 public void run() { 7054 updateSettings(); 7055 } 7056 }); 7057 7058 bindKeyguardNow = mDeferBindKeyguard; 7059 if (bindKeyguardNow) { 7060 // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now. 7061 mDeferBindKeyguard = false; 7062 } 7063 } 7064 7065 if (bindKeyguardNow) { 7066 mKeyguardDelegate.bindService(mContext); 7067 mKeyguardDelegate.onBootCompleted(); 7068 } 7069 mSystemGestures.systemReady(); 7070 mImmersiveModeConfirmation.systemReady(); 7071 } 7072 7073 /** {@inheritDoc} */ 7074 @Override 7075 public void systemBooted() { 7076 boolean bindKeyguardNow = false; 7077 synchronized (mLock) { 7078 // Time to bind Keyguard; take care to only bind it once, either here if ready or 7079 // in systemReady if not. 7080 if (mKeyguardDelegate != null) { 7081 bindKeyguardNow = true; 7082 } else { 7083 // Because mKeyguardDelegate is null, we know that the synchronized block in 7084 // systemReady didn't run yet and setting this will actually have an effect. 7085 mDeferBindKeyguard = true; 7086 } 7087 } 7088 if (bindKeyguardNow) { 7089 mKeyguardDelegate.bindService(mContext); 7090 mKeyguardDelegate.onBootCompleted(); 7091 } 7092 synchronized (mLock) { 7093 mSystemBooted = true; 7094 } 7095 startedWakingUp(); 7096 screenTurningOn(null); 7097 screenTurnedOn(); 7098 } 7099 7100 ProgressDialog mBootMsgDialog = null; 7101 7102 /** {@inheritDoc} */ 7103 @Override 7104 public void showBootMessage(final CharSequence msg, final boolean always) { 7105 mHandler.post(new Runnable() { 7106 @Override public void run() { 7107 if (mBootMsgDialog == null) { 7108 int theme; 7109 if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) { 7110 theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert; 7111 } else { 7112 theme = 0; 7113 } 7114 7115 mBootMsgDialog = new ProgressDialog(mContext, theme) { 7116 // This dialog will consume all events coming in to 7117 // it, to avoid it trying to do things too early in boot. 7118 @Override public boolean dispatchKeyEvent(KeyEvent event) { 7119 return true; 7120 } 7121 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { 7122 return true; 7123 } 7124 @Override public boolean dispatchTouchEvent(MotionEvent ev) { 7125 return true; 7126 } 7127 @Override public boolean dispatchTrackballEvent(MotionEvent ev) { 7128 return true; 7129 } 7130 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) { 7131 return true; 7132 } 7133 @Override public boolean dispatchPopulateAccessibilityEvent( 7134 AccessibilityEvent event) { 7135 return true; 7136 } 7137 }; 7138 if (mContext.getPackageManager().isUpgrade()) { 7139 mBootMsgDialog.setTitle(R.string.android_upgrading_title); 7140 } else { 7141 mBootMsgDialog.setTitle(R.string.android_start_title); 7142 } 7143 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 7144 mBootMsgDialog.setIndeterminate(true); 7145 mBootMsgDialog.getWindow().setType( 7146 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS); 7147 mBootMsgDialog.getWindow().addFlags( 7148 WindowManager.LayoutParams.FLAG_DIM_BEHIND 7149 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); 7150 mBootMsgDialog.getWindow().setDimAmount(1); 7151 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes(); 7152 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 7153 mBootMsgDialog.getWindow().setAttributes(lp); 7154 mBootMsgDialog.setCancelable(false); 7155 mBootMsgDialog.show(); 7156 } 7157 mBootMsgDialog.setMessage(msg); 7158 } 7159 }); 7160 } 7161 7162 /** {@inheritDoc} */ 7163 @Override 7164 public void hideBootMessages() { 7165 mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE); 7166 } 7167 7168 /** {@inheritDoc} */ 7169 @Override 7170 public void userActivity() { 7171 // *************************************** 7172 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE 7173 // *************************************** 7174 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER 7175 // WITH ITS LOCKS HELD. 7176 // 7177 // This code must be VERY careful about the locks 7178 // it acquires. 7179 // In fact, the current code acquires way too many, 7180 // and probably has lurking deadlocks. 7181 7182 synchronized (mScreenLockTimeout) { 7183 if (mLockScreenTimerActive) { 7184 // reset the timer 7185 mHandler.removeCallbacks(mScreenLockTimeout); 7186 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7187 } 7188 } 7189 } 7190 7191 class ScreenLockTimeout implements Runnable { 7192 Bundle options; 7193 7194 @Override 7195 public void run() { 7196 synchronized (this) { 7197 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard"); 7198 if (mKeyguardDelegate != null) { 7199 mKeyguardDelegate.doKeyguardTimeout(options); 7200 } 7201 mLockScreenTimerActive = false; 7202 options = null; 7203 } 7204 } 7205 7206 public void setLockOptions(Bundle options) { 7207 this.options = options; 7208 } 7209 } 7210 7211 ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout(); 7212 7213 @Override 7214 public void lockNow(Bundle options) { 7215 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 7216 mHandler.removeCallbacks(mScreenLockTimeout); 7217 if (options != null) { 7218 // In case multiple calls are made to lockNow, we don't wipe out the options 7219 // until the runnable actually executes. 7220 mScreenLockTimeout.setLockOptions(options); 7221 } 7222 mHandler.post(mScreenLockTimeout); 7223 } 7224 7225 private void updateLockScreenTimeout() { 7226 synchronized (mScreenLockTimeout) { 7227 boolean enable = (mAllowLockscreenWhenOn && mAwake && 7228 mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId)); 7229 if (mLockScreenTimerActive != enable) { 7230 if (enable) { 7231 if (localLOGV) Log.v(TAG, "setting lockscreen timer"); 7232 mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests 7233 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7234 } else { 7235 if (localLOGV) Log.v(TAG, "clearing lockscreen timer"); 7236 mHandler.removeCallbacks(mScreenLockTimeout); 7237 } 7238 mLockScreenTimerActive = enable; 7239 } 7240 } 7241 } 7242 7243 private void updateDreamingSleepToken(boolean acquire) { 7244 if (acquire) { 7245 if (mDreamingSleepToken == null) { 7246 mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream"); 7247 } 7248 } else { 7249 if (mDreamingSleepToken != null) { 7250 mDreamingSleepToken.release(); 7251 mDreamingSleepToken = null; 7252 } 7253 } 7254 } 7255 7256 private void updateScreenOffSleepToken(boolean acquire) { 7257 if (acquire) { 7258 if (mScreenOffSleepToken == null) { 7259 mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff"); 7260 } 7261 } else { 7262 if (mScreenOffSleepToken != null) { 7263 mScreenOffSleepToken.release(); 7264 mScreenOffSleepToken = null; 7265 } 7266 } 7267 } 7268 7269 /** {@inheritDoc} */ 7270 @Override 7271 public void enableScreenAfterBoot() { 7272 readLidState(); 7273 applyLidSwitchState(); 7274 updateRotation(true); 7275 } 7276 7277 private void applyLidSwitchState() { 7278 if (mLidState == LID_CLOSED && mLidControlsSleep) { 7279 mPowerManager.goToSleep(SystemClock.uptimeMillis(), 7280 PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH, 7281 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); 7282 } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) { 7283 mWindowManagerFuncs.lockDeviceNow(); 7284 } 7285 7286 synchronized (mLock) { 7287 updateWakeGestureListenerLp(); 7288 } 7289 } 7290 7291 void updateUiMode() { 7292 if (mUiModeManager == null) { 7293 mUiModeManager = IUiModeManager.Stub.asInterface( 7294 ServiceManager.getService(Context.UI_MODE_SERVICE)); 7295 } 7296 try { 7297 mUiMode = mUiModeManager.getCurrentModeType(); 7298 } catch (RemoteException e) { 7299 } 7300 } 7301 7302 void updateRotation(boolean alwaysSendConfiguration) { 7303 try { 7304 //set orientation on WindowManager 7305 mWindowManager.updateRotation(alwaysSendConfiguration, false); 7306 } catch (RemoteException e) { 7307 // Ignore 7308 } 7309 } 7310 7311 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 7312 try { 7313 //set orientation on WindowManager 7314 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout); 7315 } catch (RemoteException e) { 7316 // Ignore 7317 } 7318 } 7319 7320 /** 7321 * Return an Intent to launch the currently active dock app as home. Returns 7322 * null if the standard home should be launched, which is the case if any of the following is 7323 * true: 7324 * <ul> 7325 * <li>The device is not in either car mode or desk mode 7326 * <li>The device is in car mode but mEnableCarDockHomeCapture is false 7327 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false 7328 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME 7329 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME 7330 * </ul> 7331 * @return A dock intent. 7332 */ 7333 Intent createHomeDockIntent() { 7334 Intent intent = null; 7335 7336 // What home does is based on the mode, not the dock state. That 7337 // is, when in car mode you should be taken to car home regardless 7338 // of whether we are actually in a car dock. 7339 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) { 7340 if (mEnableCarDockHomeCapture) { 7341 intent = mCarDockIntent; 7342 } 7343 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) { 7344 if (ENABLE_DESK_DOCK_HOME_CAPTURE) { 7345 intent = mDeskDockIntent; 7346 } 7347 } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH 7348 && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK 7349 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK 7350 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) { 7351 // Always launch dock home from home when watch is docked, if it exists. 7352 intent = mDeskDockIntent; 7353 } 7354 7355 if (intent == null) { 7356 return null; 7357 } 7358 7359 ActivityInfo ai = null; 7360 ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser( 7361 intent, 7362 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA, 7363 mCurrentUserId); 7364 if (info != null) { 7365 ai = info.activityInfo; 7366 } 7367 if (ai != null 7368 && ai.metaData != null 7369 && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) { 7370 intent = new Intent(intent); 7371 intent.setClassName(ai.packageName, ai.name); 7372 return intent; 7373 } 7374 7375 return null; 7376 } 7377 7378 void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) { 7379 if (awakenFromDreams) { 7380 awakenDreams(); 7381 } 7382 7383 Intent dock = createHomeDockIntent(); 7384 if (dock != null) { 7385 try { 7386 if (fromHomeKey) { 7387 dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7388 } 7389 startActivityAsUser(dock, UserHandle.CURRENT); 7390 return; 7391 } catch (ActivityNotFoundException e) { 7392 } 7393 } 7394 7395 Intent intent; 7396 7397 if (fromHomeKey) { 7398 intent = new Intent(mHomeIntent); 7399 intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7400 } else { 7401 intent = mHomeIntent; 7402 } 7403 7404 startActivityAsUser(intent, UserHandle.CURRENT); 7405 } 7406 7407 /** 7408 * goes to the home screen 7409 * @return whether it did anything 7410 */ 7411 boolean goHome() { 7412 if (!isUserSetupComplete()) { 7413 Slog.i(TAG, "Not going home because user setup is in progress."); 7414 return false; 7415 } 7416 if (false) { 7417 // This code always brings home to the front. 7418 try { 7419 ActivityManagerNative.getDefault().stopAppSwitches(); 7420 } catch (RemoteException e) { 7421 } 7422 sendCloseSystemWindows(); 7423 startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */); 7424 } else { 7425 // This code brings home to the front or, if it is already 7426 // at the front, puts the device to sleep. 7427 try { 7428 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) { 7429 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry. 7430 Log.d(TAG, "UTS-TEST-MODE"); 7431 } else { 7432 ActivityManagerNative.getDefault().stopAppSwitches(); 7433 sendCloseSystemWindows(); 7434 Intent dock = createHomeDockIntent(); 7435 if (dock != null) { 7436 int result = ActivityManagerNative.getDefault() 7437 .startActivityAsUser(null, null, dock, 7438 dock.resolveTypeIfNeeded(mContext.getContentResolver()), 7439 null, null, 0, 7440 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7441 null, null, UserHandle.USER_CURRENT); 7442 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7443 return false; 7444 } 7445 } 7446 } 7447 int result = ActivityManagerNative.getDefault() 7448 .startActivityAsUser(null, null, mHomeIntent, 7449 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()), 7450 null, null, 0, 7451 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7452 null, null, UserHandle.USER_CURRENT); 7453 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7454 return false; 7455 } 7456 } catch (RemoteException ex) { 7457 // bummer, the activity manager, which is in this process, is dead 7458 } 7459 } 7460 return true; 7461 } 7462 7463 @Override 7464 public void setCurrentOrientationLw(int newOrientation) { 7465 synchronized (mLock) { 7466 if (newOrientation != mCurrentAppOrientation) { 7467 mCurrentAppOrientation = newOrientation; 7468 updateOrientationListenerLp(); 7469 } 7470 } 7471 } 7472 7473 private void performAuditoryFeedbackForAccessibilityIfNeed() { 7474 if (!isGlobalAccessibilityGestureEnabled()) { 7475 return; 7476 } 7477 AudioManager audioManager = (AudioManager) mContext.getSystemService( 7478 Context.AUDIO_SERVICE); 7479 if (audioManager.isSilentMode()) { 7480 return; 7481 } 7482 Ringtone ringTone = RingtoneManager.getRingtone(mContext, 7483 Settings.System.DEFAULT_NOTIFICATION_URI); 7484 ringTone.setStreamType(AudioManager.STREAM_MUSIC); 7485 ringTone.play(); 7486 } 7487 7488 private boolean isTheaterModeEnabled() { 7489 return Settings.Global.getInt(mContext.getContentResolver(), 7490 Settings.Global.THEATER_MODE_ON, 0) == 1; 7491 } 7492 7493 private boolean isGlobalAccessibilityGestureEnabled() { 7494 return Settings.Global.getInt(mContext.getContentResolver(), 7495 Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1; 7496 } 7497 7498 private boolean areSystemNavigationKeysEnabled() { 7499 return Settings.Secure.getIntForUser(mContext.getContentResolver(), 7500 Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1; 7501 } 7502 7503 @Override 7504 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) { 7505 if (!mVibrator.hasVibrator()) { 7506 return false; 7507 } 7508 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(), 7509 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0; 7510 if (hapticsDisabled && !always) { 7511 return false; 7512 } 7513 long[] pattern = null; 7514 switch (effectId) { 7515 case HapticFeedbackConstants.LONG_PRESS: 7516 pattern = mLongPressVibePattern; 7517 break; 7518 case HapticFeedbackConstants.VIRTUAL_KEY: 7519 pattern = mVirtualKeyVibePattern; 7520 break; 7521 case HapticFeedbackConstants.KEYBOARD_TAP: 7522 pattern = mKeyboardTapVibePattern; 7523 break; 7524 case HapticFeedbackConstants.CLOCK_TICK: 7525 pattern = mClockTickVibePattern; 7526 break; 7527 case HapticFeedbackConstants.CALENDAR_DATE: 7528 pattern = mCalendarDateVibePattern; 7529 break; 7530 case HapticFeedbackConstants.SAFE_MODE_DISABLED: 7531 pattern = mSafeModeDisabledVibePattern; 7532 break; 7533 case HapticFeedbackConstants.SAFE_MODE_ENABLED: 7534 pattern = mSafeModeEnabledVibePattern; 7535 break; 7536 case HapticFeedbackConstants.CONTEXT_CLICK: 7537 pattern = mContextClickVibePattern; 7538 break; 7539 default: 7540 return false; 7541 } 7542 int owningUid; 7543 String owningPackage; 7544 if (win != null) { 7545 owningUid = win.getOwningUid(); 7546 owningPackage = win.getOwningPackage(); 7547 } else { 7548 owningUid = android.os.Process.myUid(); 7549 owningPackage = mContext.getOpPackageName(); 7550 } 7551 if (pattern.length == 1) { 7552 // One-shot vibration 7553 mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES); 7554 } else { 7555 // Pattern vibration 7556 mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES); 7557 } 7558 return true; 7559 } 7560 7561 @Override 7562 public void keepScreenOnStartedLw() { 7563 } 7564 7565 @Override 7566 public void keepScreenOnStoppedLw() { 7567 if (isKeyguardShowingAndNotOccluded()) { 7568 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 7569 } 7570 } 7571 7572 private int updateSystemUiVisibilityLw() { 7573 // If there is no window focused, there will be nobody to handle the events 7574 // anyway, so just hang on in whatever state we're in until things settle down. 7575 WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow 7576 : mTopFullscreenOpaqueWindowState; 7577 if (winCandidate == null) { 7578 return 0; 7579 } 7580 if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) { 7581 // The immersive mode confirmation should never affect the system bar visibility, 7582 // otherwise it will unhide the navigation bar and hide itself. 7583 winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState; 7584 if (winCandidate == null) { 7585 return 0; 7586 } 7587 } 7588 final WindowState win = winCandidate; 7589 if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) { 7590 // We are updating at a point where the keyguard has gotten 7591 // focus, but we were last in a state where the top window is 7592 // hiding it. This is probably because the keyguard as been 7593 // shown while the top window was displayed, so we want to ignore 7594 // it here because this is just a very transient change and it 7595 // will quickly lose focus once it correctly gets hidden. 7596 return 0; 7597 } 7598 7599 int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null) 7600 & ~mResettingSystemUiFlags 7601 & ~mForceClearedSystemUiFlags; 7602 if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) { 7603 tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS); 7604 } 7605 7606 final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */, 7607 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState); 7608 final int dockedVisibility = updateLightStatusBarLw(0 /* vis */, 7609 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState); 7610 mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds); 7611 mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds); 7612 final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility); 7613 final int diff = visibility ^ mLastSystemUiFlags; 7614 final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags; 7615 final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags; 7616 final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState); 7617 if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu 7618 && mFocusedApp == win.getAppToken() 7619 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds) 7620 && mLastDockedStackBounds.equals(mDockedStackBounds)) { 7621 return 0; 7622 } 7623 mLastSystemUiFlags = visibility; 7624 mLastFullscreenStackSysUiFlags = fullscreenVisibility; 7625 mLastDockedStackSysUiFlags = dockedVisibility; 7626 mLastFocusNeedsMenu = needsMenu; 7627 mFocusedApp = win.getAppToken(); 7628 final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds); 7629 final Rect dockedStackBounds = new Rect(mDockedStackBounds); 7630 mHandler.post(new Runnable() { 7631 @Override 7632 public void run() { 7633 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 7634 if (statusbar != null) { 7635 statusbar.setSystemUiVisibility(visibility, fullscreenVisibility, 7636 dockedVisibility, 0xffffffff, fullscreenStackBounds, 7637 dockedStackBounds, win.toString()); 7638 statusbar.topAppWindowChanged(needsMenu); 7639 } 7640 } 7641 }); 7642 return diff; 7643 } 7644 7645 private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) { 7646 WindowState statusColorWin = isStatusBarKeyguard() && !mHideLockScreen 7647 ? mStatusBar 7648 : opaqueOrDimming; 7649 7650 if (statusColorWin != null) { 7651 if (statusColorWin == opaque) { 7652 // If the top fullscreen-or-dimming window is also the top fullscreen, respect 7653 // its light flag. 7654 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7655 vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null) 7656 & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7657 } else if (statusColorWin != null && statusColorWin.isDimming()) { 7658 // Otherwise if it's dimming, clear the light flag. 7659 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7660 } 7661 } 7662 return vis; 7663 } 7664 7665 private boolean drawsSystemBarBackground(WindowState win) { 7666 return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0; 7667 } 7668 7669 private boolean forcesDrawStatusBarBackground(WindowState win) { 7670 return win == null || (win.getAttrs().privateFlags 7671 & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0; 7672 } 7673 7674 private int updateSystemBarsLw(WindowState win, int oldVis, int vis) { 7675 final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID); 7676 final boolean freeformStackVisible = 7677 mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID); 7678 final boolean resizing = mWindowManagerInternal.isDockedDividerResizing(); 7679 7680 // We need to force system bars when the docked stack is visible, when the freeform stack 7681 // is visible but also when we are resizing for the transitions when docked stack 7682 // visibility changes. 7683 mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing; 7684 final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard; 7685 7686 // apply translucent bar vis flags 7687 WindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen 7688 ? mStatusBar 7689 : mTopFullscreenOpaqueWindowState; 7690 vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7691 vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7692 final int dockedVis = mStatusBarController.applyTranslucentFlagLw( 7693 mTopDockedOpaqueWindowState, 0, 0); 7694 7695 final boolean fullscreenDrawsStatusBarBackground = 7696 (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState) 7697 && (vis & View.STATUS_BAR_TRANSLUCENT) == 0) 7698 || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState); 7699 final boolean dockedDrawsStatusBarBackground = 7700 (drawsSystemBarBackground(mTopDockedOpaqueWindowState) 7701 && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0) 7702 || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState); 7703 7704 // prevent status bar interaction from clearing certain flags 7705 int type = win.getAttrs().type; 7706 boolean statusBarHasFocus = type == TYPE_STATUS_BAR; 7707 if (statusBarHasFocus && !isStatusBarKeyguard()) { 7708 int flags = View.SYSTEM_UI_FLAG_FULLSCREEN 7709 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 7710 | View.SYSTEM_UI_FLAG_IMMERSIVE 7711 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 7712 | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7713 if (mHideLockScreen) { 7714 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT; 7715 } 7716 vis = (vis & ~flags) | (oldVis & flags); 7717 } 7718 7719 if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) { 7720 vis |= View.STATUS_BAR_TRANSPARENT; 7721 vis &= ~View.STATUS_BAR_TRANSLUCENT; 7722 } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar) 7723 || forceOpaqueStatusBar) { 7724 vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT); 7725 } 7726 7727 vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing); 7728 7729 // update status bar 7730 boolean immersiveSticky = 7731 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7732 final boolean hideStatusBarWM = 7733 mTopFullscreenOpaqueWindowState != null 7734 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null) 7735 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; 7736 final boolean hideStatusBarSysui = 7737 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 7738 final boolean hideNavBarSysui = 7739 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0; 7740 7741 final boolean transientStatusBarAllowed = mStatusBar != null 7742 && (statusBarHasFocus || (!mForceShowSystemBars 7743 && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky)))); 7744 7745 final boolean transientNavBarAllowed = mNavigationBar != null 7746 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky; 7747 7748 final long now = SystemClock.uptimeMillis(); 7749 final boolean pendingPanic = mPendingPanicGestureUptime != 0 7750 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION; 7751 if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) { 7752 // The user performed the panic gesture recently, we're about to hide the bars, 7753 // we're no longer on the Keyguard and the screen is ready. We can now request the bars. 7754 mPendingPanicGestureUptime = 0; 7755 mStatusBarController.showTransient(); 7756 if (!isNavBarEmpty(vis)) { 7757 mNavigationBarController.showTransient(); 7758 } 7759 } 7760 7761 final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested() 7762 && !transientStatusBarAllowed && hideStatusBarSysui; 7763 final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested() 7764 && !transientNavBarAllowed; 7765 if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) { 7766 // clear the clearable flags instead 7767 clearClearableFlagsLw(); 7768 vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS; 7769 } 7770 7771 final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; 7772 immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7773 final boolean navAllowedHidden = immersive || immersiveSticky; 7774 7775 if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType()) 7776 > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) { 7777 // We can't hide the navbar from this window otherwise the input consumer would not get 7778 // the input events. 7779 vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); 7780 } 7781 7782 vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis); 7783 7784 // update navigation bar 7785 boolean oldImmersiveMode = isImmersiveMode(oldVis); 7786 boolean newImmersiveMode = isImmersiveMode(vis); 7787 if (win != null && oldImmersiveMode != newImmersiveMode) { 7788 final String pkg = win.getOwningPackage(); 7789 mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode, 7790 isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility())); 7791 } 7792 7793 vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis); 7794 7795 return vis; 7796 } 7797 7798 /** 7799 * @return the current visibility flags with the nav-bar opacity related flags toggled based 7800 * on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}. 7801 */ 7802 private int configureNavBarOpacity(int visibility, boolean dockedStackVisible, 7803 boolean freeformStackVisible, boolean isDockedDividerResizing) { 7804 if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) { 7805 if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) { 7806 visibility = setNavBarOpaqueFlag(visibility); 7807 } 7808 } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) { 7809 if (isDockedDividerResizing) { 7810 visibility = setNavBarOpaqueFlag(visibility); 7811 } else if (freeformStackVisible) { 7812 visibility = setNavBarTranslucentFlag(visibility); 7813 } else { 7814 visibility = setNavBarOpaqueFlag(visibility); 7815 } 7816 } 7817 7818 if (!areTranslucentBarsAllowed()) { 7819 visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT; 7820 } 7821 return visibility; 7822 } 7823 7824 private int setNavBarOpaqueFlag(int visibility) { 7825 return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT); 7826 } 7827 7828 private int setNavBarTranslucentFlag(int visibility) { 7829 visibility &= ~View.NAVIGATION_BAR_TRANSPARENT; 7830 return visibility |= View.NAVIGATION_BAR_TRANSLUCENT; 7831 } 7832 7833 private void clearClearableFlagsLw() { 7834 int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS; 7835 if (newVal != mResettingSystemUiFlags) { 7836 mResettingSystemUiFlags = newVal; 7837 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 7838 } 7839 } 7840 7841 private boolean isImmersiveMode(int vis) { 7842 final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; 7843 return mNavigationBar != null 7844 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0 7845 && (vis & flags) != 0 7846 && canHideNavigationBar(); 7847 } 7848 7849 private static boolean isNavBarEmpty(int systemUiFlags) { 7850 final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME 7851 | View.STATUS_BAR_DISABLE_BACK 7852 | View.STATUS_BAR_DISABLE_RECENT); 7853 7854 return (systemUiFlags & disableNavigationBar) == disableNavigationBar; 7855 } 7856 7857 /** 7858 * @return whether the navigation or status bar can be made translucent 7859 * 7860 * This should return true unless touch exploration is not enabled or 7861 * R.boolean.config_enableTranslucentDecor is false. 7862 */ 7863 private boolean areTranslucentBarsAllowed() { 7864 return mTranslucentDecorEnabled; 7865 } 7866 7867 // Use this instead of checking config_showNavigationBar so that it can be consistently 7868 // overridden by qemu.hw.mainkeys in the emulator. 7869 @Override 7870 public boolean hasNavigationBar() { 7871 return mHasNavigationBar; 7872 } 7873 7874 @Override 7875 public void setLastInputMethodWindowLw(WindowState ime, WindowState target) { 7876 mLastInputMethodWindow = ime; 7877 mLastInputMethodTargetWindow = target; 7878 } 7879 7880 @Override 7881 public int getInputMethodWindowVisibleHeightLw() { 7882 return mDockBottom - mCurBottom; 7883 } 7884 7885 @Override 7886 public void setCurrentUserLw(int newUserId) { 7887 mCurrentUserId = newUserId; 7888 if (mKeyguardDelegate != null) { 7889 mKeyguardDelegate.setCurrentUser(newUserId); 7890 } 7891 StatusBarManagerInternal statusBar = getStatusBarManagerInternal(); 7892 if (statusBar != null) { 7893 statusBar.setCurrentUser(newUserId); 7894 } 7895 setLastInputMethodWindowLw(null, null); 7896 } 7897 7898 @Override 7899 public boolean canMagnifyWindow(int windowType) { 7900 switch (windowType) { 7901 case WindowManager.LayoutParams.TYPE_INPUT_METHOD: 7902 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: 7903 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR: 7904 case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: { 7905 return false; 7906 } 7907 } 7908 return true; 7909 } 7910 7911 @Override 7912 public boolean isTopLevelWindow(int windowType) { 7913 if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW 7914 && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 7915 return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG); 7916 } 7917 return true; 7918 } 7919 7920 @Override 7921 public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) { 7922 // For the upside down rotation we don't rotate seamlessly as the navigation 7923 // bar moves position. 7924 // Note most apps (using orientation:sensor or user as opposed to fullSensor) 7925 // will not enter the reverse portrait orientation, so actually the 7926 // orientation won't change at all. 7927 if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) { 7928 return false; 7929 } 7930 int delta = newRotation - oldRotation; 7931 if (delta < 0) delta += 4; 7932 // Likewise we don't rotate seamlessly for 180 degree rotations 7933 // in this case the surfaces never resize, and our logic to 7934 // revert the transformations on size change will fail. We could 7935 // fix this in the future with the "tagged" frames idea. 7936 if (delta == Surface.ROTATION_180) { 7937 return false; 7938 } 7939 7940 final WindowState w = mTopFullscreenOpaqueWindowState; 7941 if (w != mFocusedWindow) { 7942 return false; 7943 } 7944 7945 // We only enable seamless rotation if the top window has requested 7946 // it and is in the fullscreen opaque state. Seamless rotation 7947 // requires freezing various Surface states and won't work well 7948 // with animations, so we disable it in the animation case for now. 7949 if (w != null && !w.isAnimatingLw() && 7950 ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) || 7951 (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) { 7952 return true; 7953 } 7954 return false; 7955 } 7956 7957 @Override 7958 public void dump(String prefix, PrintWriter pw, String[] args) { 7959 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode); 7960 pw.print(" mSystemReady="); pw.print(mSystemReady); 7961 pw.print(" mSystemBooted="); pw.println(mSystemBooted); 7962 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState); 7963 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation); 7964 pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState); 7965 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged); 7966 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0 7967 || mForceClearedSystemUiFlags != 0) { 7968 pw.print(prefix); pw.print("mLastSystemUiFlags=0x"); 7969 pw.print(Integer.toHexString(mLastSystemUiFlags)); 7970 pw.print(" mResettingSystemUiFlags=0x"); 7971 pw.print(Integer.toHexString(mResettingSystemUiFlags)); 7972 pw.print(" mForceClearedSystemUiFlags=0x"); 7973 pw.println(Integer.toHexString(mForceClearedSystemUiFlags)); 7974 } 7975 if (mLastFocusNeedsMenu) { 7976 pw.print(prefix); pw.print("mLastFocusNeedsMenu="); 7977 pw.println(mLastFocusNeedsMenu); 7978 } 7979 pw.print(prefix); pw.print("mWakeGestureEnabledSetting="); 7980 pw.println(mWakeGestureEnabledSetting); 7981 7982 pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation); 7983 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode); 7984 pw.print(" mDockMode="); pw.print(mDockMode); 7985 pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture); 7986 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation); 7987 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation); 7988 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode); 7989 pw.print(" mUserRotation="); pw.print(mUserRotation); 7990 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations); 7991 pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation); 7992 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer="); 7993 pw.print(mCarDockEnablesAccelerometer); 7994 pw.print(" mDeskDockEnablesAccelerometer="); 7995 pw.println(mDeskDockEnablesAccelerometer); 7996 pw.print(prefix); pw.print("mLidKeyboardAccessibility="); 7997 pw.print(mLidKeyboardAccessibility); 7998 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility); 7999 pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock); 8000 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep); 8001 pw.print(prefix); 8002 pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior); 8003 pw.print(prefix); 8004 pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior); 8005 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior); 8006 pw.print(prefix); 8007 pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior); 8008 pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior); 8009 pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput); 8010 pw.print(prefix); pw.print("mAwake="); pw.println(mAwake); 8011 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly); 8012 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully); 8013 pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete); 8014 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete); 8015 pw.print(prefix); pw.print("mOrientationSensorEnabled="); 8016 pw.println(mOrientationSensorEnabled); 8017 pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft); 8018 pw.print(","); pw.print(mOverscanScreenTop); 8019 pw.print(") "); pw.print(mOverscanScreenWidth); 8020 pw.print("x"); pw.println(mOverscanScreenHeight); 8021 if (mOverscanLeft != 0 || mOverscanTop != 0 8022 || mOverscanRight != 0 || mOverscanBottom != 0) { 8023 pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft); 8024 pw.print(" top="); pw.print(mOverscanTop); 8025 pw.print(" right="); pw.print(mOverscanRight); 8026 pw.print(" bottom="); pw.println(mOverscanBottom); 8027 } 8028 pw.print(prefix); pw.print("mRestrictedOverscanScreen=("); 8029 pw.print(mRestrictedOverscanScreenLeft); 8030 pw.print(","); pw.print(mRestrictedOverscanScreenTop); 8031 pw.print(") "); pw.print(mRestrictedOverscanScreenWidth); 8032 pw.print("x"); pw.println(mRestrictedOverscanScreenHeight); 8033 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft); 8034 pw.print(","); pw.print(mUnrestrictedScreenTop); 8035 pw.print(") "); pw.print(mUnrestrictedScreenWidth); 8036 pw.print("x"); pw.println(mUnrestrictedScreenHeight); 8037 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft); 8038 pw.print(","); pw.print(mRestrictedScreenTop); 8039 pw.print(") "); pw.print(mRestrictedScreenWidth); 8040 pw.print("x"); pw.println(mRestrictedScreenHeight); 8041 pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft); 8042 pw.print(","); pw.print(mStableFullscreenTop); 8043 pw.print(")-("); pw.print(mStableFullscreenRight); 8044 pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")"); 8045 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft); 8046 pw.print(","); pw.print(mStableTop); 8047 pw.print(")-("); pw.print(mStableRight); 8048 pw.print(","); pw.print(mStableBottom); pw.println(")"); 8049 pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft); 8050 pw.print(","); pw.print(mSystemTop); 8051 pw.print(")-("); pw.print(mSystemRight); 8052 pw.print(","); pw.print(mSystemBottom); pw.println(")"); 8053 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft); 8054 pw.print(","); pw.print(mCurTop); 8055 pw.print(")-("); pw.print(mCurRight); 8056 pw.print(","); pw.print(mCurBottom); pw.println(")"); 8057 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft); 8058 pw.print(","); pw.print(mContentTop); 8059 pw.print(")-("); pw.print(mContentRight); 8060 pw.print(","); pw.print(mContentBottom); pw.println(")"); 8061 pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft); 8062 pw.print(","); pw.print(mVoiceContentTop); 8063 pw.print(")-("); pw.print(mVoiceContentRight); 8064 pw.print(","); pw.print(mVoiceContentBottom); pw.println(")"); 8065 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft); 8066 pw.print(","); pw.print(mDockTop); 8067 pw.print(")-("); pw.print(mDockRight); 8068 pw.print(","); pw.print(mDockBottom); pw.println(")"); 8069 pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer); 8070 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer); 8071 pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen); 8072 pw.print(" mShowingDream="); pw.print(mShowingDream); 8073 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen); 8074 pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken); 8075 if (mLastInputMethodWindow != null) { 8076 pw.print(prefix); pw.print("mLastInputMethodWindow="); 8077 pw.println(mLastInputMethodWindow); 8078 } 8079 if (mLastInputMethodTargetWindow != null) { 8080 pw.print(prefix); pw.print("mLastInputMethodTargetWindow="); 8081 pw.println(mLastInputMethodTargetWindow); 8082 } 8083 if (mStatusBar != null) { 8084 pw.print(prefix); pw.print("mStatusBar="); 8085 pw.print(mStatusBar); pw.print(" isStatusBarKeyguard="); 8086 pw.println(isStatusBarKeyguard()); 8087 } 8088 if (mNavigationBar != null) { 8089 pw.print(prefix); pw.print("mNavigationBar="); 8090 pw.println(mNavigationBar); 8091 } 8092 if (mFocusedWindow != null) { 8093 pw.print(prefix); pw.print("mFocusedWindow="); 8094 pw.println(mFocusedWindow); 8095 } 8096 if (mFocusedApp != null) { 8097 pw.print(prefix); pw.print("mFocusedApp="); 8098 pw.println(mFocusedApp); 8099 } 8100 if (mWinDismissingKeyguard != null) { 8101 pw.print(prefix); pw.print("mWinDismissingKeyguard="); 8102 pw.println(mWinDismissingKeyguard); 8103 } 8104 if (mTopFullscreenOpaqueWindowState != null) { 8105 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState="); 8106 pw.println(mTopFullscreenOpaqueWindowState); 8107 } 8108 if (mTopFullscreenOpaqueOrDimmingWindowState != null) { 8109 pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState="); 8110 pw.println(mTopFullscreenOpaqueOrDimmingWindowState); 8111 } 8112 if (mForcingShowNavBar) { 8113 pw.print(prefix); pw.print("mForcingShowNavBar="); 8114 pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer="); 8115 pw.println(mForcingShowNavBarLayer); 8116 } 8117 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen); 8118 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen); 8119 pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar); 8120 pw.print(" mForceStatusBarFromKeyguard="); 8121 pw.println(mForceStatusBarFromKeyguard); 8122 pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard); 8123 pw.print(" mCurrentlyDismissingKeyguard="); pw.println(mCurrentlyDismissingKeyguard); 8124 pw.print(" mWinDismissingKeyguard="); pw.print(mWinDismissingKeyguard); 8125 pw.print(" mHomePressed="); pw.println(mHomePressed); 8126 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn); 8127 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout); 8128 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive); 8129 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior); 8130 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior); 8131 pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior); 8132 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior); 8133 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation); 8134 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation); 8135 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation); 8136 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation); 8137 pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation); 8138 pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock); 8139 pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation); 8140 8141 mGlobalKeyManager.dump(prefix, pw); 8142 mStatusBarController.dump(pw, prefix); 8143 mNavigationBarController.dump(pw, prefix); 8144 PolicyControl.dump(prefix, pw); 8145 8146 if (mWakeGestureListener != null) { 8147 mWakeGestureListener.dump(pw, prefix); 8148 } 8149 if (mOrientationListener != null) { 8150 mOrientationListener.dump(pw, prefix); 8151 } 8152 if (mBurnInProtectionHelper != null) { 8153 mBurnInProtectionHelper.dump(prefix, pw); 8154 } 8155 if (mKeyguardDelegate != null) { 8156 mKeyguardDelegate.dump(prefix, pw); 8157 } 8158 } 8159} 8160