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