PhoneWindowManager.java revision f0c0188a8a7732a0acc3822ddde0a2c19b25639b
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 if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) { 1950 return; 1951 } 1952 mDisplay = display; 1953 1954 final Resources res = mContext.getResources(); 1955 int shortSize, longSize; 1956 if (width > height) { 1957 shortSize = height; 1958 longSize = width; 1959 mLandscapeRotation = Surface.ROTATION_0; 1960 mSeascapeRotation = Surface.ROTATION_180; 1961 if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) { 1962 mPortraitRotation = Surface.ROTATION_90; 1963 mUpsideDownRotation = Surface.ROTATION_270; 1964 } else { 1965 mPortraitRotation = Surface.ROTATION_270; 1966 mUpsideDownRotation = Surface.ROTATION_90; 1967 } 1968 } else { 1969 shortSize = width; 1970 longSize = height; 1971 mPortraitRotation = Surface.ROTATION_0; 1972 mUpsideDownRotation = Surface.ROTATION_180; 1973 if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) { 1974 mLandscapeRotation = Surface.ROTATION_270; 1975 mSeascapeRotation = Surface.ROTATION_90; 1976 } else { 1977 mLandscapeRotation = Surface.ROTATION_90; 1978 mSeascapeRotation = Surface.ROTATION_270; 1979 } 1980 } 1981 1982 // SystemUI (status bar) layout policy 1983 int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density; 1984 int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density; 1985 1986 // Allow the navigation bar to move on non-square small devices (phones). 1987 mNavigationBarCanMove = width != height && shortSizeDp < 600; 1988 1989 mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar); 1990 1991 // Allow a system property to override this. Used by the emulator. 1992 // See also hasNavigationBar(). 1993 String navBarOverride = SystemProperties.get("qemu.hw.mainkeys"); 1994 if ("1".equals(navBarOverride)) { 1995 mHasNavigationBar = false; 1996 } else if ("0".equals(navBarOverride)) { 1997 mHasNavigationBar = true; 1998 } 1999 2000 // For demo purposes, allow the rotation of the HDMI display to be controlled. 2001 // By default, HDMI locks rotation to landscape. 2002 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) { 2003 mDemoHdmiRotation = mPortraitRotation; 2004 } else { 2005 mDemoHdmiRotation = mLandscapeRotation; 2006 } 2007 mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false); 2008 2009 // For demo purposes, allow the rotation of the remote display to be controlled. 2010 // By default, remote display locks rotation to landscape. 2011 if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) { 2012 mDemoRotation = mPortraitRotation; 2013 } else { 2014 mDemoRotation = mLandscapeRotation; 2015 } 2016 mDemoRotationLock = SystemProperties.getBoolean( 2017 "persist.demo.rotationlock", false); 2018 2019 // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per 2020 // http://developer.android.com/guide/practices/screens_support.html#range 2021 mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 && 2022 res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) && 2023 // For debug purposes the next line turns this feature off with: 2024 // $ adb shell setprop config.override_forced_orient true 2025 // $ adb shell wm size reset 2026 !"true".equals(SystemProperties.get("config.override_forced_orient")); 2027 } 2028 2029 /** 2030 * @return whether the navigation bar can be hidden, e.g. the device has a 2031 * navigation bar and touch exploration is not enabled 2032 */ 2033 private boolean canHideNavigationBar() { 2034 return mHasNavigationBar; 2035 } 2036 2037 @Override 2038 public boolean isDefaultOrientationForced() { 2039 return mForceDefaultOrientation; 2040 } 2041 2042 @Override 2043 public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) { 2044 if (display.getDisplayId() == Display.DEFAULT_DISPLAY) { 2045 mOverscanLeft = left; 2046 mOverscanTop = top; 2047 mOverscanRight = right; 2048 mOverscanBottom = bottom; 2049 } 2050 } 2051 2052 public void updateSettings() { 2053 ContentResolver resolver = mContext.getContentResolver(); 2054 boolean updateRotation = false; 2055 synchronized (mLock) { 2056 mEndcallBehavior = Settings.System.getIntForUser(resolver, 2057 Settings.System.END_BUTTON_BEHAVIOR, 2058 Settings.System.END_BUTTON_BEHAVIOR_DEFAULT, 2059 UserHandle.USER_CURRENT); 2060 mIncallPowerBehavior = Settings.Secure.getIntForUser(resolver, 2061 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR, 2062 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT, 2063 UserHandle.USER_CURRENT); 2064 mIncallBackBehavior = Settings.Secure.getIntForUser(resolver, 2065 Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR, 2066 Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_DEFAULT, 2067 UserHandle.USER_CURRENT); 2068 2069 // Configure wake gesture. 2070 boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver, 2071 Settings.Secure.WAKE_GESTURE_ENABLED, 0, 2072 UserHandle.USER_CURRENT) != 0; 2073 if (mWakeGestureEnabledSetting != wakeGestureEnabledSetting) { 2074 mWakeGestureEnabledSetting = wakeGestureEnabledSetting; 2075 updateWakeGestureListenerLp(); 2076 } 2077 2078 // Configure rotation lock. 2079 int userRotation = Settings.System.getIntForUser(resolver, 2080 Settings.System.USER_ROTATION, Surface.ROTATION_0, 2081 UserHandle.USER_CURRENT); 2082 if (mUserRotation != userRotation) { 2083 mUserRotation = userRotation; 2084 updateRotation = true; 2085 } 2086 int userRotationMode = Settings.System.getIntForUser(resolver, 2087 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ? 2088 WindowManagerPolicy.USER_ROTATION_FREE : 2089 WindowManagerPolicy.USER_ROTATION_LOCKED; 2090 if (mUserRotationMode != userRotationMode) { 2091 mUserRotationMode = userRotationMode; 2092 updateRotation = true; 2093 updateOrientationListenerLp(); 2094 } 2095 2096 if (mSystemReady) { 2097 int pointerLocation = Settings.System.getIntForUser(resolver, 2098 Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT); 2099 if (mPointerLocationMode != pointerLocation) { 2100 mPointerLocationMode = pointerLocation; 2101 mHandler.sendEmptyMessage(pointerLocation != 0 ? 2102 MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION); 2103 } 2104 } 2105 // use screen off timeout setting as the timeout for the lockscreen 2106 mLockScreenTimeout = Settings.System.getIntForUser(resolver, 2107 Settings.System.SCREEN_OFF_TIMEOUT, 0, UserHandle.USER_CURRENT); 2108 String imId = Settings.Secure.getStringForUser(resolver, 2109 Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.USER_CURRENT); 2110 boolean hasSoftInput = imId != null && imId.length() > 0; 2111 if (mHasSoftInput != hasSoftInput) { 2112 mHasSoftInput = hasSoftInput; 2113 updateRotation = true; 2114 } 2115 if (mImmersiveModeConfirmation != null) { 2116 mImmersiveModeConfirmation.loadSetting(mCurrentUserId); 2117 } 2118 } 2119 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 2120 PolicyControl.reloadFromSetting(mContext); 2121 } 2122 if (updateRotation) { 2123 updateRotation(true); 2124 } 2125 } 2126 2127 private void updateWakeGestureListenerLp() { 2128 if (shouldEnableWakeGestureLp()) { 2129 mWakeGestureListener.requestWakeUpTrigger(); 2130 } else { 2131 mWakeGestureListener.cancelWakeUpTrigger(); 2132 } 2133 } 2134 2135 private boolean shouldEnableWakeGestureLp() { 2136 return mWakeGestureEnabledSetting && !mAwake 2137 && (!mLidControlsSleep || mLidState != LID_CLOSED) 2138 && mWakeGestureListener.isSupported(); 2139 } 2140 2141 private void enablePointerLocation() { 2142 if (mPointerLocationView == null) { 2143 mPointerLocationView = new PointerLocationView(mContext); 2144 mPointerLocationView.setPrintCoords(false); 2145 WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 2146 WindowManager.LayoutParams.MATCH_PARENT, 2147 WindowManager.LayoutParams.MATCH_PARENT); 2148 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY; 2149 lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN 2150 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE 2151 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 2152 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; 2153 if (ActivityManager.isHighEndGfx()) { 2154 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; 2155 lp.privateFlags |= 2156 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED; 2157 } 2158 lp.format = PixelFormat.TRANSLUCENT; 2159 lp.setTitle("PointerLocation"); 2160 WindowManager wm = (WindowManager) 2161 mContext.getSystemService(Context.WINDOW_SERVICE); 2162 lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; 2163 wm.addView(mPointerLocationView, lp); 2164 mWindowManagerFuncs.registerPointerEventListener(mPointerLocationView); 2165 } 2166 } 2167 2168 private void disablePointerLocation() { 2169 if (mPointerLocationView != null) { 2170 mWindowManagerFuncs.unregisterPointerEventListener(mPointerLocationView); 2171 WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); 2172 wm.removeView(mPointerLocationView); 2173 mPointerLocationView = null; 2174 } 2175 } 2176 2177 private int readRotation(int resID) { 2178 try { 2179 int rotation = mContext.getResources().getInteger(resID); 2180 switch (rotation) { 2181 case 0: 2182 return Surface.ROTATION_0; 2183 case 90: 2184 return Surface.ROTATION_90; 2185 case 180: 2186 return Surface.ROTATION_180; 2187 case 270: 2188 return Surface.ROTATION_270; 2189 } 2190 } catch (Resources.NotFoundException e) { 2191 // fall through 2192 } 2193 return -1; 2194 } 2195 2196 /** {@inheritDoc} */ 2197 @Override 2198 public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) { 2199 int type = attrs.type; 2200 2201 outAppOp[0] = AppOpsManager.OP_NONE; 2202 2203 if (!((type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) 2204 || (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) 2205 || (type >= FIRST_SYSTEM_WINDOW && type <= LAST_SYSTEM_WINDOW))) { 2206 return WindowManagerGlobal.ADD_INVALID_TYPE; 2207 } 2208 2209 if (type < FIRST_SYSTEM_WINDOW || type > LAST_SYSTEM_WINDOW) { 2210 // Window manager will make sure these are okay. 2211 return WindowManagerGlobal.ADD_OKAY; 2212 } 2213 String permission = null; 2214 switch (type) { 2215 case TYPE_TOAST: 2216 // XXX right now the app process has complete control over 2217 // this... should introduce a token to let the system 2218 // monitor/control what they are doing. 2219 outAppOp[0] = AppOpsManager.OP_TOAST_WINDOW; 2220 break; 2221 case TYPE_DREAM: 2222 case TYPE_INPUT_METHOD: 2223 case TYPE_WALLPAPER: 2224 case TYPE_PRIVATE_PRESENTATION: 2225 case TYPE_VOICE_INTERACTION: 2226 case TYPE_ACCESSIBILITY_OVERLAY: 2227 case TYPE_QS_DIALOG: 2228 // The window manager will check these. 2229 break; 2230 case TYPE_PHONE: 2231 case TYPE_PRIORITY_PHONE: 2232 case TYPE_SYSTEM_ALERT: 2233 case TYPE_SYSTEM_ERROR: 2234 case TYPE_SYSTEM_OVERLAY: 2235 permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW; 2236 outAppOp[0] = AppOpsManager.OP_SYSTEM_ALERT_WINDOW; 2237 break; 2238 default: 2239 permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; 2240 } 2241 if (permission != null) { 2242 if (android.Manifest.permission.SYSTEM_ALERT_WINDOW.equals(permission)) { 2243 final int callingUid = Binder.getCallingUid(); 2244 // system processes will be automatically allowed privilege to draw 2245 if (callingUid == Process.SYSTEM_UID) { 2246 return WindowManagerGlobal.ADD_OKAY; 2247 } 2248 2249 // check if user has enabled this operation. SecurityException will be thrown if 2250 // this app has not been allowed by the user 2251 final int mode = mAppOpsManager.checkOpNoThrow(outAppOp[0], callingUid, 2252 attrs.packageName); 2253 switch (mode) { 2254 case AppOpsManager.MODE_ALLOWED: 2255 case AppOpsManager.MODE_IGNORED: 2256 // although we return ADD_OKAY for MODE_IGNORED, the added window will 2257 // actually be hidden in WindowManagerService 2258 return WindowManagerGlobal.ADD_OKAY; 2259 case AppOpsManager.MODE_ERRORED: 2260 try { 2261 ApplicationInfo appInfo = mContext.getPackageManager() 2262 .getApplicationInfo(attrs.packageName, 2263 UserHandle.getUserId(callingUid)); 2264 // Don't crash legacy apps 2265 if (appInfo.targetSdkVersion < Build.VERSION_CODES.M) { 2266 return WindowManagerGlobal.ADD_OKAY; 2267 } 2268 } catch (PackageManager.NameNotFoundException e) { 2269 /* ignore */ 2270 } 2271 return WindowManagerGlobal.ADD_PERMISSION_DENIED; 2272 default: 2273 // in the default mode, we will make a decision here based on 2274 // checkCallingPermission() 2275 if (mContext.checkCallingPermission(permission) != 2276 PackageManager.PERMISSION_GRANTED) { 2277 return WindowManagerGlobal.ADD_PERMISSION_DENIED; 2278 } else { 2279 return WindowManagerGlobal.ADD_OKAY; 2280 } 2281 } 2282 } 2283 2284 if (mContext.checkCallingOrSelfPermission(permission) 2285 != PackageManager.PERMISSION_GRANTED) { 2286 return WindowManagerGlobal.ADD_PERMISSION_DENIED; 2287 } 2288 } 2289 return WindowManagerGlobal.ADD_OKAY; 2290 } 2291 2292 @Override 2293 public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) { 2294 2295 // If this switch statement is modified, modify the comment in the declarations of 2296 // the type in {@link WindowManager.LayoutParams} as well. 2297 switch (attrs.type) { 2298 default: 2299 // These are the windows that by default are shown only to the user that created 2300 // them. If this needs to be overridden, set 2301 // {@link WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS} in 2302 // {@link WindowManager.LayoutParams}. Note that permission 2303 // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well. 2304 if ((attrs.privateFlags & PRIVATE_FLAG_SHOW_FOR_ALL_USERS) == 0) { 2305 return true; 2306 } 2307 break; 2308 2309 // These are the windows that by default are shown to all users. However, to 2310 // protect against spoofing, check permissions below. 2311 case TYPE_APPLICATION_STARTING: 2312 case TYPE_BOOT_PROGRESS: 2313 case TYPE_DISPLAY_OVERLAY: 2314 case TYPE_INPUT_CONSUMER: 2315 case TYPE_KEYGUARD_SCRIM: 2316 case TYPE_KEYGUARD_DIALOG: 2317 case TYPE_MAGNIFICATION_OVERLAY: 2318 case TYPE_NAVIGATION_BAR: 2319 case TYPE_NAVIGATION_BAR_PANEL: 2320 case TYPE_PHONE: 2321 case TYPE_POINTER: 2322 case TYPE_PRIORITY_PHONE: 2323 case TYPE_SEARCH_BAR: 2324 case TYPE_STATUS_BAR: 2325 case TYPE_STATUS_BAR_PANEL: 2326 case TYPE_STATUS_BAR_SUB_PANEL: 2327 case TYPE_SYSTEM_DIALOG: 2328 case TYPE_VOLUME_OVERLAY: 2329 case TYPE_PRIVATE_PRESENTATION: 2330 case TYPE_DOCK_DIVIDER: 2331 break; 2332 } 2333 2334 // Check if third party app has set window to system window type. 2335 return mContext.checkCallingOrSelfPermission( 2336 android.Manifest.permission.INTERNAL_SYSTEM_WINDOW) 2337 != PackageManager.PERMISSION_GRANTED; 2338 } 2339 2340 @Override 2341 public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) { 2342 switch (attrs.type) { 2343 case TYPE_SYSTEM_OVERLAY: 2344 case TYPE_SECURE_SYSTEM_OVERLAY: 2345 // These types of windows can't receive input events. 2346 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 2347 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 2348 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; 2349 break; 2350 case TYPE_STATUS_BAR: 2351 2352 // If the Keyguard is in a hidden state (occluded by another window), we force to 2353 // remove the wallpaper and keyguard flag so that any change in-flight after setting 2354 // the keyguard as occluded wouldn't set these flags again. 2355 // See {@link #processKeyguardSetHiddenResultLw}. 2356 if (mKeyguardHidden) { 2357 attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 2358 attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 2359 } 2360 break; 2361 2362 case TYPE_SCREENSHOT: 2363 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 2364 break; 2365 2366 case TYPE_TOAST: 2367 // While apps should use the dedicated toast APIs to add such windows 2368 // it possible legacy apps to add the window directly. Therefore, we 2369 // make windows added directly by the app behave as a toast as much 2370 // as possible in terms of timeout and animation. 2371 if (attrs.hideTimeoutMilliseconds < 0 2372 || attrs.hideTimeoutMilliseconds > TOAST_WINDOW_TIMEOUT) { 2373 attrs.hideTimeoutMilliseconds = TOAST_WINDOW_TIMEOUT; 2374 } 2375 attrs.windowAnimations = com.android.internal.R.style.Animation_Toast; 2376 break; 2377 } 2378 2379 if (attrs.type != TYPE_STATUS_BAR) { 2380 // The status bar is the only window allowed to exhibit keyguard behavior. 2381 attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 2382 } 2383 2384 if (ActivityManager.isHighEndGfx()) { 2385 if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) { 2386 attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; 2387 } 2388 final boolean forceWindowDrawsStatusBarBackground = 2389 (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) 2390 != 0; 2391 if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 2392 || forceWindowDrawsStatusBarBackground 2393 && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) { 2394 attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 2395 } 2396 } 2397 } 2398 2399 void readLidState() { 2400 mLidState = mWindowManagerFuncs.getLidState(); 2401 } 2402 2403 private void readCameraLensCoverState() { 2404 mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState(); 2405 } 2406 2407 private boolean isHidden(int accessibilityMode) { 2408 switch (accessibilityMode) { 2409 case 1: 2410 return mLidState == LID_CLOSED; 2411 case 2: 2412 return mLidState == LID_OPEN; 2413 default: 2414 return false; 2415 } 2416 } 2417 2418 /** {@inheritDoc} */ 2419 @Override 2420 public void adjustConfigurationLw(Configuration config, int keyboardPresence, 2421 int navigationPresence) { 2422 mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0; 2423 2424 readConfigurationDependentBehaviors(); 2425 readLidState(); 2426 2427 if (config.keyboard == Configuration.KEYBOARD_NOKEYS 2428 || (keyboardPresence == PRESENCE_INTERNAL 2429 && isHidden(mLidKeyboardAccessibility))) { 2430 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES; 2431 if (!mHasSoftInput) { 2432 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES; 2433 } 2434 } 2435 2436 if (config.navigation == Configuration.NAVIGATION_NONAV 2437 || (navigationPresence == PRESENCE_INTERNAL 2438 && isHidden(mLidNavigationAccessibility))) { 2439 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES; 2440 } 2441 } 2442 2443 @Override 2444 public void onConfigurationChanged() { 2445 final Resources res = mContext.getResources(); 2446 2447 mStatusBarHeight = 2448 res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); 2449 2450 // Height of the navigation bar when presented horizontally at bottom 2451 mNavigationBarHeightForRotationDefault[mPortraitRotation] = 2452 mNavigationBarHeightForRotationDefault[mUpsideDownRotation] = 2453 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height); 2454 mNavigationBarHeightForRotationDefault[mLandscapeRotation] = 2455 mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize( 2456 com.android.internal.R.dimen.navigation_bar_height_landscape); 2457 2458 // Width of the navigation bar when presented vertically along one side 2459 mNavigationBarWidthForRotationDefault[mPortraitRotation] = 2460 mNavigationBarWidthForRotationDefault[mUpsideDownRotation] = 2461 mNavigationBarWidthForRotationDefault[mLandscapeRotation] = 2462 mNavigationBarWidthForRotationDefault[mSeascapeRotation] = 2463 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width); 2464 2465 if (ALTERNATE_CAR_MODE_NAV_SIZE) { 2466 // Height of the navigation bar when presented horizontally at bottom 2467 mNavigationBarHeightForRotationInCarMode[mPortraitRotation] = 2468 mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] = 2469 res.getDimensionPixelSize( 2470 com.android.internal.R.dimen.navigation_bar_height_car_mode); 2471 mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] = 2472 mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize( 2473 com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode); 2474 2475 // Width of the navigation bar when presented vertically along one side 2476 mNavigationBarWidthForRotationInCarMode[mPortraitRotation] = 2477 mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] = 2478 mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] = 2479 mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] = 2480 res.getDimensionPixelSize( 2481 com.android.internal.R.dimen.navigation_bar_width_car_mode); 2482 } 2483 } 2484 2485 /** {@inheritDoc} */ 2486 @Override 2487 public int windowTypeToLayerLw(int type) { 2488 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 2489 return 2; 2490 } 2491 switch (type) { 2492 case TYPE_PRIVATE_PRESENTATION: 2493 return 2; 2494 case TYPE_WALLPAPER: 2495 // wallpaper is at the bottom, though the window manager may move it. 2496 return 2; 2497 case TYPE_DOCK_DIVIDER: 2498 return 2; 2499 case TYPE_QS_DIALOG: 2500 return 2; 2501 case TYPE_PHONE: 2502 return 3; 2503 case TYPE_SEARCH_BAR: 2504 case TYPE_VOICE_INTERACTION_STARTING: 2505 return 4; 2506 case TYPE_VOICE_INTERACTION: 2507 // voice interaction layer is almost immediately above apps. 2508 return 5; 2509 case TYPE_INPUT_CONSUMER: 2510 return 6; 2511 case TYPE_SYSTEM_DIALOG: 2512 return 7; 2513 case TYPE_TOAST: 2514 // toasts and the plugged-in battery thing 2515 return 8; 2516 case TYPE_PRIORITY_PHONE: 2517 // SIM errors and unlock. Not sure if this really should be in a high layer. 2518 return 9; 2519 case TYPE_DREAM: 2520 // used for Dreams (screensavers with TYPE_DREAM windows) 2521 return 10; 2522 case TYPE_SYSTEM_ALERT: 2523 // like the ANR / app crashed dialogs 2524 return 11; 2525 case TYPE_INPUT_METHOD: 2526 // on-screen keyboards and other such input method user interfaces go here. 2527 return 12; 2528 case TYPE_INPUT_METHOD_DIALOG: 2529 // on-screen keyboards and other such input method user interfaces go here. 2530 return 13; 2531 case TYPE_KEYGUARD_SCRIM: 2532 // the safety window that shows behind keyguard while keyguard is starting 2533 return 14; 2534 case TYPE_STATUS_BAR_SUB_PANEL: 2535 return 15; 2536 case TYPE_STATUS_BAR: 2537 return 16; 2538 case TYPE_STATUS_BAR_PANEL: 2539 return 17; 2540 case TYPE_KEYGUARD_DIALOG: 2541 return 18; 2542 case TYPE_VOLUME_OVERLAY: 2543 // the on-screen volume indicator and controller shown when the user 2544 // changes the device volume 2545 return 19; 2546 case TYPE_SYSTEM_OVERLAY: 2547 // the on-screen volume indicator and controller shown when the user 2548 // changes the device volume 2549 return 20; 2550 case TYPE_NAVIGATION_BAR: 2551 // the navigation bar, if available, shows atop most things 2552 return 21; 2553 case TYPE_NAVIGATION_BAR_PANEL: 2554 // some panels (e.g. search) need to show on top of the navigation bar 2555 return 22; 2556 case TYPE_SCREENSHOT: 2557 // screenshot selection layer shouldn't go above system error, but it should cover 2558 // navigation bars at the very least. 2559 return 23; 2560 case TYPE_SYSTEM_ERROR: 2561 // system-level error dialogs 2562 return 24; 2563 case TYPE_MAGNIFICATION_OVERLAY: 2564 // used to highlight the magnified portion of a display 2565 return 25; 2566 case TYPE_DISPLAY_OVERLAY: 2567 // used to simulate secondary display devices 2568 return 26; 2569 case TYPE_DRAG: 2570 // the drag layer: input for drag-and-drop is associated with this window, 2571 // which sits above all other focusable windows 2572 return 27; 2573 case TYPE_ACCESSIBILITY_OVERLAY: 2574 // overlay put by accessibility services to intercept user interaction 2575 return 28; 2576 case TYPE_SECURE_SYSTEM_OVERLAY: 2577 return 29; 2578 case TYPE_BOOT_PROGRESS: 2579 return 30; 2580 case TYPE_POINTER: 2581 // the (mouse) pointer layer 2582 return 31; 2583 } 2584 Log.e(TAG, "Unknown window type: " + type); 2585 return 2; 2586 } 2587 2588 /** {@inheritDoc} */ 2589 @Override 2590 public int subWindowTypeToLayerLw(int type) { 2591 switch (type) { 2592 case TYPE_APPLICATION_PANEL: 2593 case TYPE_APPLICATION_ATTACHED_DIALOG: 2594 return APPLICATION_PANEL_SUBLAYER; 2595 case TYPE_APPLICATION_MEDIA: 2596 return APPLICATION_MEDIA_SUBLAYER; 2597 case TYPE_APPLICATION_MEDIA_OVERLAY: 2598 return APPLICATION_MEDIA_OVERLAY_SUBLAYER; 2599 case TYPE_APPLICATION_SUB_PANEL: 2600 return APPLICATION_SUB_PANEL_SUBLAYER; 2601 case TYPE_APPLICATION_ABOVE_SUB_PANEL: 2602 return APPLICATION_ABOVE_SUB_PANEL_SUBLAYER; 2603 } 2604 Log.e(TAG, "Unknown sub-window type: " + type); 2605 return 0; 2606 } 2607 2608 @Override 2609 public int getMaxWallpaperLayer() { 2610 return windowTypeToLayerLw(TYPE_STATUS_BAR); 2611 } 2612 2613 private int getNavigationBarWidth(int rotation, int uiMode) { 2614 if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) { 2615 return mNavigationBarWidthForRotationInCarMode[rotation]; 2616 } else { 2617 return mNavigationBarWidthForRotationDefault[rotation]; 2618 } 2619 } 2620 2621 @Override 2622 public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, 2623 int uiMode) { 2624 if (mHasNavigationBar) { 2625 // For a basic navigation bar, when we are in landscape mode we place 2626 // the navigation bar to the side. 2627 if (mNavigationBarCanMove && fullWidth > fullHeight) { 2628 return fullWidth - getNavigationBarWidth(rotation, uiMode); 2629 } 2630 } 2631 return fullWidth; 2632 } 2633 2634 private int getNavigationBarHeight(int rotation, int uiMode) { 2635 if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) { 2636 return mNavigationBarHeightForRotationInCarMode[rotation]; 2637 } else { 2638 return mNavigationBarHeightForRotationDefault[rotation]; 2639 } 2640 } 2641 2642 @Override 2643 public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, 2644 int uiMode) { 2645 if (mHasNavigationBar) { 2646 // For a basic navigation bar, when we are in portrait mode we place 2647 // the navigation bar to the bottom. 2648 if (!mNavigationBarCanMove || fullWidth < fullHeight) { 2649 return fullHeight - getNavigationBarHeight(rotation, uiMode); 2650 } 2651 } 2652 return fullHeight; 2653 } 2654 2655 @Override 2656 public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode) { 2657 return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode); 2658 } 2659 2660 @Override 2661 public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode) { 2662 // There is a separate status bar at the top of the display. We don't count that as part 2663 // of the fixed decor, since it can hide; however, for purposes of configurations, 2664 // we do want to exclude it since applications can't generally use that part 2665 // of the screen. 2666 return getNonDecorDisplayHeight( 2667 fullWidth, fullHeight, rotation, uiMode) - mStatusBarHeight; 2668 } 2669 2670 @Override 2671 public boolean isForceHiding(WindowManager.LayoutParams attrs) { 2672 return (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 || 2673 (isKeyguardHostWindow(attrs) && 2674 (mKeyguardDelegate != null && mKeyguardDelegate.isShowing())) || 2675 (attrs.type == TYPE_KEYGUARD_SCRIM); 2676 } 2677 2678 @Override 2679 public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) { 2680 return attrs.type == TYPE_STATUS_BAR; 2681 } 2682 2683 @Override 2684 public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) { 2685 switch (attrs.type) { 2686 case TYPE_STATUS_BAR: 2687 case TYPE_NAVIGATION_BAR: 2688 case TYPE_WALLPAPER: 2689 case TYPE_DREAM: 2690 case TYPE_KEYGUARD_SCRIM: 2691 return false; 2692 default: 2693 // Hide only windows below the keyguard host window. 2694 return windowTypeToLayerLw(win.getBaseType()) 2695 < windowTypeToLayerLw(TYPE_STATUS_BAR); 2696 } 2697 } 2698 2699 @Override 2700 public WindowState getWinShowWhenLockedLw() { 2701 return mWinShowWhenLocked; 2702 } 2703 2704 /** {@inheritDoc} */ 2705 @Override 2706 public View addStartingWindow(IBinder appToken, String packageName, int theme, 2707 CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, 2708 int icon, int logo, int windowFlags, Configuration overrideConfig) { 2709 if (!SHOW_STARTING_ANIMATIONS) { 2710 return null; 2711 } 2712 if (packageName == null) { 2713 return null; 2714 } 2715 2716 WindowManager wm = null; 2717 View view = null; 2718 2719 try { 2720 Context context = mContext; 2721 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow " + packageName 2722 + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme=" 2723 + Integer.toHexString(theme)); 2724 if (theme != context.getThemeResId() || labelRes != 0) { 2725 try { 2726 context = context.createPackageContext(packageName, 0); 2727 context.setTheme(theme); 2728 } catch (PackageManager.NameNotFoundException e) { 2729 // Ignore 2730 } 2731 } 2732 2733 if (overrideConfig != null && overrideConfig != EMPTY) { 2734 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: creating context based" 2735 + " on overrideConfig" + overrideConfig + " for starting window"); 2736 final Context overrideContext = context.createConfigurationContext(overrideConfig); 2737 overrideContext.setTheme(theme); 2738 final TypedArray typedArray = overrideContext.obtainStyledAttributes( 2739 com.android.internal.R.styleable.Window); 2740 final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0); 2741 if (resId != 0 && overrideContext.getDrawable(resId) != null) { 2742 // We want to use the windowBackground for the override context if it is 2743 // available, otherwise we use the default one to make sure a themed starting 2744 // window is displayed for the app. 2745 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: apply overrideConfig" 2746 + overrideConfig + " to starting window resId=" + resId); 2747 context = overrideContext; 2748 } 2749 } 2750 2751 final PhoneWindow win = new PhoneWindow(context); 2752 win.setIsStartingWindow(true); 2753 2754 CharSequence label = context.getResources().getText(labelRes, null); 2755 // Only change the accessibility title if the label is localized 2756 if (label != null) { 2757 win.setTitle(label, true); 2758 } else { 2759 win.setTitle(nonLocalizedLabel, false); 2760 } 2761 2762 win.setType( 2763 WindowManager.LayoutParams.TYPE_APPLICATION_STARTING); 2764 2765 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 2766 // Assumes it's safe to show starting windows of launched apps while 2767 // the keyguard is being hidden. This is okay because starting windows never show 2768 // secret information. 2769 if (mKeyguardHidden) { 2770 windowFlags |= FLAG_SHOW_WHEN_LOCKED; 2771 } 2772 } 2773 2774 // Force the window flags: this is a fake window, so it is not really 2775 // touchable or focusable by the user. We also add in the ALT_FOCUSABLE_IM 2776 // flag because we do know that the next window will take input 2777 // focus, so we want to get the IME window up on top of us right away. 2778 win.setFlags( 2779 windowFlags| 2780 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE| 2781 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| 2782 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, 2783 windowFlags| 2784 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE| 2785 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| 2786 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 2787 2788 win.setDefaultIcon(icon); 2789 win.setDefaultLogo(logo); 2790 2791 win.setLayout(WindowManager.LayoutParams.MATCH_PARENT, 2792 WindowManager.LayoutParams.MATCH_PARENT); 2793 2794 final WindowManager.LayoutParams params = win.getAttributes(); 2795 params.token = appToken; 2796 params.packageName = packageName; 2797 params.windowAnimations = win.getWindowStyle().getResourceId( 2798 com.android.internal.R.styleable.Window_windowAnimationStyle, 0); 2799 params.privateFlags |= 2800 WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED; 2801 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; 2802 2803 if (!compatInfo.supportsScreen()) { 2804 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; 2805 } 2806 2807 params.setTitle("Starting " + packageName); 2808 2809 wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); 2810 view = win.getDecorView(); 2811 2812 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Adding starting window for " 2813 + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null)); 2814 2815 wm.addView(view, params); 2816 2817 // Only return the view if it was successfully added to the 2818 // window manager... which we can tell by it having a parent. 2819 return view.getParent() != null ? view : null; 2820 } catch (WindowManager.BadTokenException e) { 2821 // ignore 2822 Log.w(TAG, appToken + " already running, starting window not displayed. " + 2823 e.getMessage()); 2824 } catch (RuntimeException e) { 2825 // don't crash if something else bad happens, for example a 2826 // failure loading resources because we are loading from an app 2827 // on external storage that has been unmounted. 2828 Log.w(TAG, appToken + " failed creating starting window", e); 2829 } finally { 2830 if (view != null && view.getParent() == null) { 2831 Log.w(TAG, "view not successfully added to wm, removing view"); 2832 wm.removeViewImmediate(view); 2833 } 2834 } 2835 2836 return null; 2837 } 2838 2839 /** {@inheritDoc} */ 2840 @Override 2841 public void removeStartingWindow(IBinder appToken, View window) { 2842 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Removing starting window for " + appToken + ": " 2843 + window + " Callers=" + Debug.getCallers(4)); 2844 2845 if (window != null) { 2846 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); 2847 wm.removeView(window); 2848 } 2849 } 2850 2851 /** 2852 * Preflight adding a window to the system. 2853 * 2854 * Currently enforces that three window types are singletons: 2855 * <ul> 2856 * <li>STATUS_BAR_TYPE</li> 2857 * <li>KEYGUARD_TYPE</li> 2858 * </ul> 2859 * 2860 * @param win The window to be added 2861 * @param attrs Information about the window to be added 2862 * 2863 * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons, 2864 * WindowManagerImpl.ADD_MULTIPLE_SINGLETON 2865 */ 2866 @Override 2867 public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) { 2868 switch (attrs.type) { 2869 case TYPE_STATUS_BAR: 2870 mContext.enforceCallingOrSelfPermission( 2871 android.Manifest.permission.STATUS_BAR_SERVICE, 2872 "PhoneWindowManager"); 2873 if (mStatusBar != null) { 2874 if (mStatusBar.isAlive()) { 2875 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON; 2876 } 2877 } 2878 mStatusBar = win; 2879 mStatusBarController.setWindow(win); 2880 break; 2881 case TYPE_NAVIGATION_BAR: 2882 mContext.enforceCallingOrSelfPermission( 2883 android.Manifest.permission.STATUS_BAR_SERVICE, 2884 "PhoneWindowManager"); 2885 if (mNavigationBar != null) { 2886 if (mNavigationBar.isAlive()) { 2887 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON; 2888 } 2889 } 2890 mNavigationBar = win; 2891 mNavigationBarController.setWindow(win); 2892 if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar); 2893 break; 2894 case TYPE_NAVIGATION_BAR_PANEL: 2895 case TYPE_STATUS_BAR_PANEL: 2896 case TYPE_STATUS_BAR_SUB_PANEL: 2897 case TYPE_VOICE_INTERACTION_STARTING: 2898 mContext.enforceCallingOrSelfPermission( 2899 android.Manifest.permission.STATUS_BAR_SERVICE, 2900 "PhoneWindowManager"); 2901 break; 2902 case TYPE_KEYGUARD_SCRIM: 2903 if (mKeyguardScrim != null) { 2904 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON; 2905 } 2906 mKeyguardScrim = win; 2907 break; 2908 } 2909 return WindowManagerGlobal.ADD_OKAY; 2910 } 2911 2912 /** {@inheritDoc} */ 2913 @Override 2914 public void removeWindowLw(WindowState win) { 2915 if (mStatusBar == win) { 2916 mStatusBar = null; 2917 mStatusBarController.setWindow(null); 2918 mKeyguardDelegate.showScrim(); 2919 } else if (mKeyguardScrim == win) { 2920 Log.v(TAG, "Removing keyguard scrim"); 2921 mKeyguardScrim = null; 2922 } if (mNavigationBar == win) { 2923 mNavigationBar = null; 2924 mNavigationBarController.setWindow(null); 2925 } 2926 } 2927 2928 static final boolean PRINT_ANIM = false; 2929 2930 /** {@inheritDoc} */ 2931 @Override 2932 public int selectAnimationLw(WindowState win, int transit) { 2933 if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win 2934 + ": transit=" + transit); 2935 if (win == mStatusBar) { 2936 boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0; 2937 if (transit == TRANSIT_EXIT 2938 || transit == TRANSIT_HIDE) { 2939 return isKeyguard ? -1 : R.anim.dock_top_exit; 2940 } else if (transit == TRANSIT_ENTER 2941 || transit == TRANSIT_SHOW) { 2942 return isKeyguard ? -1 : R.anim.dock_top_enter; 2943 } 2944 } else if (win == mNavigationBar) { 2945 if (win.getAttrs().windowAnimations != 0) { 2946 return 0; 2947 } 2948 // This can be on either the bottom or the right or the left. 2949 if (mNavigationBarPosition == NAV_BAR_BOTTOM) { 2950 if (transit == TRANSIT_EXIT 2951 || transit == TRANSIT_HIDE) { 2952 if (isKeyguardShowingAndNotOccluded()) { 2953 return R.anim.dock_bottom_exit_keyguard; 2954 } else { 2955 return R.anim.dock_bottom_exit; 2956 } 2957 } else if (transit == TRANSIT_ENTER 2958 || transit == TRANSIT_SHOW) { 2959 return R.anim.dock_bottom_enter; 2960 } 2961 } else if (mNavigationBarPosition == NAV_BAR_RIGHT) { 2962 if (transit == TRANSIT_EXIT 2963 || transit == TRANSIT_HIDE) { 2964 return R.anim.dock_right_exit; 2965 } else if (transit == TRANSIT_ENTER 2966 || transit == TRANSIT_SHOW) { 2967 return R.anim.dock_right_enter; 2968 } 2969 } else if (mNavigationBarPosition == NAV_BAR_LEFT) { 2970 if (transit == TRANSIT_EXIT 2971 || transit == TRANSIT_HIDE) { 2972 return R.anim.dock_left_exit; 2973 } else if (transit == TRANSIT_ENTER 2974 || transit == TRANSIT_SHOW) { 2975 return R.anim.dock_left_enter; 2976 } 2977 } 2978 } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) { 2979 return selectDockedDividerAnimationLw(win, transit); 2980 } 2981 2982 if (transit == TRANSIT_PREVIEW_DONE) { 2983 if (win.hasAppShownWindows()) { 2984 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT"); 2985 return com.android.internal.R.anim.app_starting_exit; 2986 } 2987 } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen 2988 && transit == TRANSIT_ENTER) { 2989 // Special case: we are animating in a dream, while the keyguard 2990 // is shown. We don't want an animation on the dream, because 2991 // we need it shown immediately with the keyguard animating away 2992 // to reveal it. 2993 return -1; 2994 } 2995 2996 return 0; 2997 } 2998 2999 private int selectDockedDividerAnimationLw(WindowState win, int transit) { 3000 int insets = mWindowManagerFuncs.getDockedDividerInsetsLw(); 3001 3002 // If the divider is behind the navigation bar, don't animate. 3003 final Rect frame = win.getFrameLw(); 3004 final boolean behindNavBar = mNavigationBar != null 3005 && ((mNavigationBarPosition == NAV_BAR_BOTTOM 3006 && frame.top + insets >= mNavigationBar.getFrameLw().top) 3007 || (mNavigationBarPosition == NAV_BAR_RIGHT 3008 && frame.left + insets >= mNavigationBar.getFrameLw().left) 3009 || (mNavigationBarPosition == NAV_BAR_LEFT 3010 && frame.right - insets <= mNavigationBar.getFrameLw().right)); 3011 final boolean landscape = frame.height() > frame.width(); 3012 final boolean offscreenLandscape = landscape && (frame.right - insets <= 0 3013 || frame.left + insets >= win.getDisplayFrameLw().right); 3014 final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0 3015 || frame.bottom + insets >= win.getDisplayFrameLw().bottom); 3016 final boolean offscreen = offscreenLandscape || offscreenPortrait; 3017 if (behindNavBar || offscreen) { 3018 return 0; 3019 } 3020 if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) { 3021 return R.anim.fade_in; 3022 } else if (transit == TRANSIT_EXIT) { 3023 return R.anim.fade_out; 3024 } else { 3025 return 0; 3026 } 3027 } 3028 3029 @Override 3030 public void selectRotationAnimationLw(int anim[]) { 3031 if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen=" 3032 + mTopFullscreenOpaqueWindowState + " rotationAnimation=" 3033 + (mTopFullscreenOpaqueWindowState == null ? 3034 "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation)); 3035 if (mTopFullscreenOpaqueWindowState != null) { 3036 int animationHint = mTopFullscreenOpaqueWindowState.getRotationAnimationHint(); 3037 if (animationHint < 0 && mTopIsFullscreen) { 3038 animationHint = mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation; 3039 } 3040 switch (animationHint) { 3041 case ROTATION_ANIMATION_CROSSFADE: 3042 case ROTATION_ANIMATION_SEAMLESS: // Crossfade is fallback for seamless. 3043 anim[0] = R.anim.rotation_animation_xfade_exit; 3044 anim[1] = R.anim.rotation_animation_enter; 3045 break; 3046 case ROTATION_ANIMATION_JUMPCUT: 3047 anim[0] = R.anim.rotation_animation_jump_exit; 3048 anim[1] = R.anim.rotation_animation_enter; 3049 break; 3050 case ROTATION_ANIMATION_ROTATE: 3051 default: 3052 anim[0] = anim[1] = 0; 3053 break; 3054 } 3055 } else { 3056 anim[0] = anim[1] = 0; 3057 } 3058 } 3059 3060 @Override 3061 public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId, 3062 boolean forceDefault) { 3063 switch (exitAnimId) { 3064 case R.anim.rotation_animation_xfade_exit: 3065 case R.anim.rotation_animation_jump_exit: 3066 // These are the only cases that matter. 3067 if (forceDefault) { 3068 return false; 3069 } 3070 int anim[] = new int[2]; 3071 selectRotationAnimationLw(anim); 3072 return (exitAnimId == anim[0] && enterAnimId == anim[1]); 3073 default: 3074 return true; 3075 } 3076 } 3077 3078 @Override 3079 public Animation createForceHideEnterAnimation(boolean onWallpaper, 3080 boolean goingToNotificationShade) { 3081 if (goingToNotificationShade) { 3082 return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in); 3083 } 3084 3085 AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ? 3086 R.anim.lock_screen_behind_enter_wallpaper : 3087 R.anim.lock_screen_behind_enter); 3088 3089 // TODO: Use XML interpolators when we have log interpolators available in XML. 3090 final List<Animation> animations = set.getAnimations(); 3091 for (int i = animations.size() - 1; i >= 0; --i) { 3092 animations.get(i).setInterpolator(mLogDecelerateInterpolator); 3093 } 3094 3095 return set; 3096 } 3097 3098 3099 @Override 3100 public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade) { 3101 if (goingToNotificationShade) { 3102 return null; 3103 } else { 3104 return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit); 3105 } 3106 } 3107 3108 private static void awakenDreams() { 3109 IDreamManager dreamManager = getDreamManager(); 3110 if (dreamManager != null) { 3111 try { 3112 dreamManager.awaken(); 3113 } catch (RemoteException e) { 3114 // fine, stay asleep then 3115 } 3116 } 3117 } 3118 3119 static IDreamManager getDreamManager() { 3120 return IDreamManager.Stub.asInterface( 3121 ServiceManager.checkService(DreamService.DREAM_SERVICE)); 3122 } 3123 3124 TelecomManager getTelecommService() { 3125 return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); 3126 } 3127 3128 static IAudioService getAudioService() { 3129 IAudioService audioService = IAudioService.Stub.asInterface( 3130 ServiceManager.checkService(Context.AUDIO_SERVICE)); 3131 if (audioService == null) { 3132 Log.w(TAG, "Unable to find IAudioService interface."); 3133 } 3134 return audioService; 3135 } 3136 3137 boolean keyguardOn() { 3138 return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode(); 3139 } 3140 3141 private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = { 3142 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, 3143 WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, 3144 }; 3145 3146 /** {@inheritDoc} */ 3147 @Override 3148 public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) { 3149 final boolean keyguardOn = keyguardOn(); 3150 final int keyCode = event.getKeyCode(); 3151 final int repeatCount = event.getRepeatCount(); 3152 final int metaState = event.getMetaState(); 3153 final int flags = event.getFlags(); 3154 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; 3155 final boolean canceled = event.isCanceled(); 3156 3157 if (DEBUG_INPUT) { 3158 Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount=" 3159 + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed 3160 + " canceled=" + canceled); 3161 } 3162 3163 // If we think we might have a volume down & power key chord on the way 3164 // but we're not sure, then tell the dispatcher to wait a little while and 3165 // try again later before dispatching. 3166 if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) { 3167 if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) { 3168 final long now = SystemClock.uptimeMillis(); 3169 final long timeoutTime = mScreenshotChordVolumeDownKeyTime 3170 + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS; 3171 if (now < timeoutTime) { 3172 return timeoutTime - now; 3173 } 3174 } 3175 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN 3176 && mScreenshotChordVolumeDownKeyConsumed) { 3177 if (!down) { 3178 mScreenshotChordVolumeDownKeyConsumed = false; 3179 } 3180 return -1; 3181 } 3182 } 3183 3184 // Cancel any pending meta actions if we see any other keys being pressed between the down 3185 // of the meta key and its corresponding up. 3186 if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) { 3187 mPendingMetaAction = false; 3188 } 3189 // Any key that is not Alt or Meta cancels Caps Lock combo tracking. 3190 if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) { 3191 mPendingCapsLockToggle = false; 3192 } 3193 3194 // First we always handle the home key here, so applications 3195 // can never break it, although if keyguard is on, we do let 3196 // it handle it, because that gives us the correct 5 second 3197 // timeout. 3198 if (keyCode == KeyEvent.KEYCODE_HOME) { 3199 3200 // If we have released the home key, and didn't do anything else 3201 // while it was pressed, then it is time to go home! 3202 if (!down) { 3203 cancelPreloadRecentApps(); 3204 3205 mHomePressed = false; 3206 if (mHomeConsumed) { 3207 mHomeConsumed = false; 3208 return -1; 3209 } 3210 3211 if (canceled) { 3212 Log.i(TAG, "Ignoring HOME; event canceled."); 3213 return -1; 3214 } 3215 3216 // Delay handling home if a double-tap is possible. 3217 if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) { 3218 mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case 3219 mHomeDoubleTapPending = true; 3220 mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable, 3221 ViewConfiguration.getDoubleTapTimeout()); 3222 return -1; 3223 } 3224 3225 handleShortPressOnHome(); 3226 return -1; 3227 } 3228 3229 // If a system window has focus, then it doesn't make sense 3230 // right now to interact with applications. 3231 WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null; 3232 if (attrs != null) { 3233 final int type = attrs.type; 3234 if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM 3235 || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG 3236 || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 3237 // the "app" is keyguard, so give it the key 3238 return 0; 3239 } 3240 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length; 3241 for (int i=0; i<typeCount; i++) { 3242 if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) { 3243 // don't do anything, but also don't pass it to the app 3244 return -1; 3245 } 3246 } 3247 } 3248 3249 // Remember that home is pressed and handle special actions. 3250 if (repeatCount == 0) { 3251 mHomePressed = true; 3252 if (mHomeDoubleTapPending) { 3253 mHomeDoubleTapPending = false; 3254 mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); 3255 handleDoubleTapOnHome(); 3256 } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI 3257 || mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) { 3258 preloadRecentApps(); 3259 } 3260 } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { 3261 if (!keyguardOn) { 3262 handleLongPressOnHome(event.getDeviceId()); 3263 } 3264 } 3265 return -1; 3266 } else if (keyCode == KeyEvent.KEYCODE_MENU) { 3267 // Hijack modified menu keys for debugging features 3268 final int chordBug = KeyEvent.META_SHIFT_ON; 3269 3270 if (down && repeatCount == 0) { 3271 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) { 3272 Intent intent = new Intent(Intent.ACTION_BUG_REPORT); 3273 mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, 3274 null, null, null, 0, null, null); 3275 return -1; 3276 } 3277 } 3278 } else if (keyCode == KeyEvent.KEYCODE_SEARCH) { 3279 if (down) { 3280 if (repeatCount == 0) { 3281 mSearchKeyShortcutPending = true; 3282 mConsumeSearchKeyUp = false; 3283 } 3284 } else { 3285 mSearchKeyShortcutPending = false; 3286 if (mConsumeSearchKeyUp) { 3287 mConsumeSearchKeyUp = false; 3288 return -1; 3289 } 3290 } 3291 return 0; 3292 } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) { 3293 if (!keyguardOn) { 3294 if (down && repeatCount == 0) { 3295 preloadRecentApps(); 3296 } else if (!down) { 3297 toggleRecentApps(); 3298 } 3299 } 3300 return -1; 3301 } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) { 3302 if (down) { 3303 IStatusBarService service = getStatusBarService(); 3304 if (service != null) { 3305 try { 3306 service.expandNotificationsPanel(); 3307 } catch (RemoteException e) { 3308 // do nothing. 3309 } 3310 } 3311 } 3312 } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed() 3313 && event.isCtrlPressed()) { 3314 if (down && repeatCount == 0) { 3315 int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION 3316 : TAKE_SCREENSHOT_FULLSCREEN; 3317 mScreenshotRunnable.setScreenshotType(type); 3318 mHandler.post(mScreenshotRunnable); 3319 return -1; 3320 } 3321 } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) { 3322 if (down && repeatCount == 0 && !isKeyguardLocked()) { 3323 toggleKeyboardShortcutsMenu(event.getDeviceId()); 3324 } 3325 } else if (keyCode == KeyEvent.KEYCODE_ASSIST) { 3326 if (down) { 3327 if (repeatCount == 0) { 3328 mAssistKeyLongPressed = false; 3329 } else if (repeatCount == 1) { 3330 mAssistKeyLongPressed = true; 3331 if (!keyguardOn) { 3332 launchAssistLongPressAction(); 3333 } 3334 } 3335 } else { 3336 if (mAssistKeyLongPressed) { 3337 mAssistKeyLongPressed = false; 3338 } else { 3339 if (!keyguardOn) { 3340 launchAssistAction(null, event.getDeviceId()); 3341 } 3342 } 3343 } 3344 return -1; 3345 } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) { 3346 if (!down) { 3347 Intent voiceIntent; 3348 if (!keyguardOn) { 3349 voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH); 3350 } else { 3351 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface( 3352 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); 3353 if (dic != null) { 3354 try { 3355 dic.exitIdle("voice-search"); 3356 } catch (RemoteException e) { 3357 } 3358 } 3359 voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); 3360 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true); 3361 } 3362 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF); 3363 } 3364 } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) { 3365 if (down && repeatCount == 0) { 3366 mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN); 3367 mHandler.post(mScreenshotRunnable); 3368 } 3369 return -1; 3370 } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP 3371 || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) { 3372 if (down) { 3373 int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1; 3374 3375 // Disable autobrightness if it's on 3376 int auto = Settings.System.getIntForUser( 3377 mContext.getContentResolver(), 3378 Settings.System.SCREEN_BRIGHTNESS_MODE, 3379 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, 3380 UserHandle.USER_CURRENT_OR_SELF); 3381 if (auto != 0) { 3382 Settings.System.putIntForUser(mContext.getContentResolver(), 3383 Settings.System.SCREEN_BRIGHTNESS_MODE, 3384 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, 3385 UserHandle.USER_CURRENT_OR_SELF); 3386 } 3387 3388 int min = mPowerManager.getMinimumScreenBrightnessSetting(); 3389 int max = mPowerManager.getMaximumScreenBrightnessSetting(); 3390 int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction; 3391 int brightness = Settings.System.getIntForUser(mContext.getContentResolver(), 3392 Settings.System.SCREEN_BRIGHTNESS, 3393 mPowerManager.getDefaultScreenBrightnessSetting(), 3394 UserHandle.USER_CURRENT_OR_SELF); 3395 brightness += step; 3396 // Make sure we don't go beyond the limits. 3397 brightness = Math.min(max, brightness); 3398 brightness = Math.max(min, brightness); 3399 3400 Settings.System.putIntForUser(mContext.getContentResolver(), 3401 Settings.System.SCREEN_BRIGHTNESS, brightness, 3402 UserHandle.USER_CURRENT_OR_SELF); 3403 startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG), 3404 UserHandle.CURRENT_OR_SELF); 3405 } 3406 return -1; 3407 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP 3408 || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN 3409 || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) { 3410 if (mUseTvRouting) { 3411 // On TVs volume keys never go to the foreground app. 3412 dispatchDirectAudioEvent(event); 3413 return -1; 3414 } 3415 } 3416 3417 // Toggle Caps Lock on META-ALT. 3418 boolean actionTriggered = false; 3419 if (KeyEvent.isModifierKey(keyCode)) { 3420 if (!mPendingCapsLockToggle) { 3421 // Start tracking meta state for combo. 3422 mInitialMetaState = mMetaState; 3423 mPendingCapsLockToggle = true; 3424 } else if (event.getAction() == KeyEvent.ACTION_UP) { 3425 int altOnMask = mMetaState & KeyEvent.META_ALT_MASK; 3426 int metaOnMask = mMetaState & KeyEvent.META_META_MASK; 3427 3428 // Check for Caps Lock toggle 3429 if ((metaOnMask != 0) && (altOnMask != 0)) { 3430 // Check if nothing else is pressed 3431 if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) { 3432 // Handle Caps Lock Toggle 3433 mInputManagerInternal.toggleCapsLock(event.getDeviceId()); 3434 actionTriggered = true; 3435 } 3436 } 3437 3438 // Always stop tracking when key goes up. 3439 mPendingCapsLockToggle = false; 3440 } 3441 } 3442 // Store current meta state to be able to evaluate it later. 3443 mMetaState = metaState; 3444 3445 if (actionTriggered) { 3446 return -1; 3447 } 3448 3449 if (KeyEvent.isMetaKey(keyCode)) { 3450 if (down) { 3451 mPendingMetaAction = true; 3452 } else if (mPendingMetaAction) { 3453 launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId()); 3454 } 3455 return -1; 3456 } 3457 3458 // Shortcuts are invoked through Search+key, so intercept those here 3459 // Any printing key that is chorded with Search should be consumed 3460 // even if no shortcut was invoked. This prevents text from being 3461 // inadvertently inserted when using a keyboard that has built-in macro 3462 // shortcut keys (that emit Search+x) and some of them are not registered. 3463 if (mSearchKeyShortcutPending) { 3464 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 3465 if (kcm.isPrintingKey(keyCode)) { 3466 mConsumeSearchKeyUp = true; 3467 mSearchKeyShortcutPending = false; 3468 if (down && repeatCount == 0 && !keyguardOn) { 3469 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState); 3470 if (shortcutIntent != null) { 3471 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3472 try { 3473 startActivityAsUser(shortcutIntent, UserHandle.CURRENT); 3474 dismissKeyboardShortcutsMenu(); 3475 } catch (ActivityNotFoundException ex) { 3476 Slog.w(TAG, "Dropping shortcut key combination because " 3477 + "the activity to which it is registered was not found: " 3478 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex); 3479 } 3480 } else { 3481 Slog.i(TAG, "Dropping unregistered shortcut key combination: " 3482 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode)); 3483 } 3484 } 3485 return -1; 3486 } 3487 } 3488 3489 // Invoke shortcuts using Meta. 3490 if (down && repeatCount == 0 && !keyguardOn 3491 && (metaState & KeyEvent.META_META_ON) != 0) { 3492 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 3493 if (kcm.isPrintingKey(keyCode)) { 3494 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, 3495 metaState & ~(KeyEvent.META_META_ON 3496 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON)); 3497 if (shortcutIntent != null) { 3498 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3499 try { 3500 startActivityAsUser(shortcutIntent, UserHandle.CURRENT); 3501 dismissKeyboardShortcutsMenu(); 3502 } catch (ActivityNotFoundException ex) { 3503 Slog.w(TAG, "Dropping shortcut key combination because " 3504 + "the activity to which it is registered was not found: " 3505 + "META+" + KeyEvent.keyCodeToString(keyCode), ex); 3506 } 3507 return -1; 3508 } 3509 } 3510 } 3511 3512 // Handle application launch keys. 3513 if (down && repeatCount == 0 && !keyguardOn) { 3514 String category = sApplicationLaunchKeyCategories.get(keyCode); 3515 if (category != null) { 3516 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category); 3517 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3518 try { 3519 startActivityAsUser(intent, UserHandle.CURRENT); 3520 dismissKeyboardShortcutsMenu(); 3521 } catch (ActivityNotFoundException ex) { 3522 Slog.w(TAG, "Dropping application launch key because " 3523 + "the activity to which it is registered was not found: " 3524 + "keyCode=" + keyCode + ", category=" + category, ex); 3525 } 3526 return -1; 3527 } 3528 } 3529 3530 // Display task switcher for ALT-TAB. 3531 if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) { 3532 if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) { 3533 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK; 3534 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) { 3535 mRecentAppsHeldModifiers = shiftlessModifiers; 3536 showRecentApps(true, false); 3537 return -1; 3538 } 3539 } 3540 } else if (!down && mRecentAppsHeldModifiers != 0 3541 && (metaState & mRecentAppsHeldModifiers) == 0) { 3542 mRecentAppsHeldModifiers = 0; 3543 hideRecentApps(true, false); 3544 } 3545 3546 // Handle input method switching. 3547 if (down && repeatCount == 0 3548 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH 3549 || (keyCode == KeyEvent.KEYCODE_SPACE 3550 && (metaState & KeyEvent.META_META_MASK) != 0))) { 3551 final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0; 3552 mWindowManagerFuncs.switchInputMethod(forwardDirection); 3553 return -1; 3554 } 3555 if (mLanguageSwitchKeyPressed && !down 3556 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH 3557 || keyCode == KeyEvent.KEYCODE_SPACE)) { 3558 mLanguageSwitchKeyPressed = false; 3559 return -1; 3560 } 3561 3562 if (isValidGlobalKey(keyCode) 3563 && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) { 3564 return -1; 3565 } 3566 3567 if (down) { 3568 long shortcutCode = keyCode; 3569 if (event.isCtrlPressed()) { 3570 shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE; 3571 } 3572 3573 if (event.isAltPressed()) { 3574 shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE; 3575 } 3576 3577 if (event.isShiftPressed()) { 3578 shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE; 3579 } 3580 3581 if (event.isMetaPressed()) { 3582 shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE; 3583 } 3584 3585 IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode); 3586 if (shortcutService != null) { 3587 try { 3588 if (isUserSetupComplete()) { 3589 shortcutService.notifyShortcutKeyPressed(shortcutCode); 3590 } 3591 } catch (RemoteException e) { 3592 mShortcutKeyServices.delete(shortcutCode); 3593 } 3594 return -1; 3595 } 3596 } 3597 3598 // Reserve all the META modifier combos for system behavior 3599 if ((metaState & KeyEvent.META_META_ON) != 0) { 3600 return -1; 3601 } 3602 3603 // Let the application handle the key. 3604 return 0; 3605 } 3606 3607 /** {@inheritDoc} */ 3608 @Override 3609 public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) { 3610 // Note: This method is only called if the initial down was unhandled. 3611 if (DEBUG_INPUT) { 3612 Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction() 3613 + ", flags=" + event.getFlags() 3614 + ", keyCode=" + event.getKeyCode() 3615 + ", scanCode=" + event.getScanCode() 3616 + ", metaState=" + event.getMetaState() 3617 + ", repeatCount=" + event.getRepeatCount() 3618 + ", policyFlags=" + policyFlags); 3619 } 3620 3621 KeyEvent fallbackEvent = null; 3622 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 3623 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 3624 final int keyCode = event.getKeyCode(); 3625 final int metaState = event.getMetaState(); 3626 final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN 3627 && event.getRepeatCount() == 0; 3628 3629 // Check for fallback actions specified by the key character map. 3630 final FallbackAction fallbackAction; 3631 if (initialDown) { 3632 fallbackAction = kcm.getFallbackAction(keyCode, metaState); 3633 } else { 3634 fallbackAction = mFallbackActions.get(keyCode); 3635 } 3636 3637 if (fallbackAction != null) { 3638 if (DEBUG_INPUT) { 3639 Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode 3640 + " metaState=" + Integer.toHexString(fallbackAction.metaState)); 3641 } 3642 3643 final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK; 3644 fallbackEvent = KeyEvent.obtain( 3645 event.getDownTime(), event.getEventTime(), 3646 event.getAction(), fallbackAction.keyCode, 3647 event.getRepeatCount(), fallbackAction.metaState, 3648 event.getDeviceId(), event.getScanCode(), 3649 flags, event.getSource(), null); 3650 3651 if (!interceptFallback(win, fallbackEvent, policyFlags)) { 3652 fallbackEvent.recycle(); 3653 fallbackEvent = null; 3654 } 3655 3656 if (initialDown) { 3657 mFallbackActions.put(keyCode, fallbackAction); 3658 } else if (event.getAction() == KeyEvent.ACTION_UP) { 3659 mFallbackActions.remove(keyCode); 3660 fallbackAction.recycle(); 3661 } 3662 } 3663 } 3664 3665 if (DEBUG_INPUT) { 3666 if (fallbackEvent == null) { 3667 Slog.d(TAG, "No fallback."); 3668 } else { 3669 Slog.d(TAG, "Performing fallback: " + fallbackEvent); 3670 } 3671 } 3672 return fallbackEvent; 3673 } 3674 3675 private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) { 3676 int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags); 3677 if ((actions & ACTION_PASS_TO_USER) != 0) { 3678 long delayMillis = interceptKeyBeforeDispatching( 3679 win, fallbackEvent, policyFlags); 3680 if (delayMillis == 0) { 3681 return true; 3682 } 3683 } 3684 return false; 3685 } 3686 3687 @Override 3688 public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService) 3689 throws RemoteException { 3690 synchronized (mLock) { 3691 IShortcutService service = mShortcutKeyServices.get(shortcutCode); 3692 if (service != null && service.asBinder().pingBinder()) { 3693 throw new RemoteException("Key already exists."); 3694 } 3695 3696 mShortcutKeyServices.put(shortcutCode, shortcutService); 3697 } 3698 } 3699 3700 @Override 3701 public boolean canShowDismissingWindowWhileLockedLw() { 3702 // If the keyguard is trusted, it will unlock without a challenge. Therefore, if we are in 3703 // the process of dismissing Keyguard, we don't need to hide them as the phone will be 3704 // unlocked right away in any case. 3705 return mKeyguardDelegate != null && mKeyguardDelegate.isTrusted() 3706 && mCurrentlyDismissingKeyguard; 3707 } 3708 3709 private void launchAssistLongPressAction() { 3710 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); 3711 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST); 3712 3713 // launch the search activity 3714 Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS); 3715 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3716 try { 3717 // TODO: This only stops the factory-installed search manager. 3718 // Need to formalize an API to handle others 3719 SearchManager searchManager = getSearchManager(); 3720 if (searchManager != null) { 3721 searchManager.stopSearch(); 3722 } 3723 startActivityAsUser(intent, UserHandle.CURRENT); 3724 } catch (ActivityNotFoundException e) { 3725 Slog.w(TAG, "No activity to handle assist long press action.", e); 3726 } 3727 } 3728 3729 private void launchAssistAction(String hint, int deviceId) { 3730 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST); 3731 if (!isUserSetupComplete()) { 3732 // Disable opening assist window during setup 3733 return; 3734 } 3735 Bundle args = null; 3736 if (deviceId > Integer.MIN_VALUE) { 3737 args = new Bundle(); 3738 args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId); 3739 } 3740 if ((mContext.getResources().getConfiguration().uiMode 3741 & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) { 3742 // On TV, use legacy handling until assistants are implemented in the proper way. 3743 ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE)) 3744 .launchLegacyAssist(hint, UserHandle.myUserId(), args); 3745 } else { 3746 if (hint != null) { 3747 if (args == null) { 3748 args = new Bundle(); 3749 } 3750 args.putBoolean(hint, true); 3751 } 3752 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3753 if (statusbar != null) { 3754 statusbar.startAssist(args); 3755 } 3756 } 3757 } 3758 3759 private void startActivityAsUser(Intent intent, UserHandle handle) { 3760 if (isUserSetupComplete()) { 3761 mContext.startActivityAsUser(intent, handle); 3762 } else { 3763 Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent); 3764 } 3765 } 3766 3767 private SearchManager getSearchManager() { 3768 if (mSearchManager == null) { 3769 mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); 3770 } 3771 return mSearchManager; 3772 } 3773 3774 private void preloadRecentApps() { 3775 mPreloadedRecentApps = true; 3776 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3777 if (statusbar != null) { 3778 statusbar.preloadRecentApps(); 3779 } 3780 } 3781 3782 private void cancelPreloadRecentApps() { 3783 if (mPreloadedRecentApps) { 3784 mPreloadedRecentApps = false; 3785 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3786 if (statusbar != null) { 3787 statusbar.cancelPreloadRecentApps(); 3788 } 3789 } 3790 } 3791 3792 private void toggleRecentApps() { 3793 mPreloadedRecentApps = false; // preloading no longer needs to be canceled 3794 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3795 if (statusbar != null) { 3796 statusbar.toggleRecentApps(); 3797 } 3798 } 3799 3800 @Override 3801 public void showRecentApps(boolean fromHome) { 3802 mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS); 3803 mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget(); 3804 } 3805 3806 private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) { 3807 mPreloadedRecentApps = false; // preloading no longer needs to be canceled 3808 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3809 if (statusbar != null) { 3810 statusbar.showRecentApps(triggeredFromAltTab, fromHome); 3811 } 3812 } 3813 3814 private void toggleKeyboardShortcutsMenu(int deviceId) { 3815 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3816 if (statusbar != null) { 3817 statusbar.toggleKeyboardShortcutsMenu(deviceId); 3818 } 3819 } 3820 3821 private void dismissKeyboardShortcutsMenu() { 3822 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3823 if (statusbar != null) { 3824 statusbar.dismissKeyboardShortcutsMenu(); 3825 } 3826 } 3827 3828 private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) { 3829 mPreloadedRecentApps = false; // preloading no longer needs to be canceled 3830 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3831 if (statusbar != null) { 3832 statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome); 3833 } 3834 } 3835 3836 void launchHomeFromHotKey() { 3837 launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/); 3838 } 3839 3840 /** 3841 * A home key -> launch home action was detected. Take the appropriate action 3842 * given the situation with the keyguard. 3843 */ 3844 void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) { 3845 if (respectKeyguard) { 3846 if (isKeyguardShowingAndNotOccluded()) { 3847 // don't launch home if keyguard showing 3848 return; 3849 } 3850 3851 if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) { 3852 // when in keyguard restricted mode, must first verify unlock 3853 // before launching home 3854 mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() { 3855 @Override 3856 public void onKeyguardExitResult(boolean success) { 3857 if (success) { 3858 try { 3859 ActivityManagerNative.getDefault().stopAppSwitches(); 3860 } catch (RemoteException e) { 3861 } 3862 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY); 3863 startDockOrHome(true /*fromHomeKey*/, awakenFromDreams); 3864 } 3865 } 3866 }); 3867 return; 3868 } 3869 } 3870 3871 // no keyguard stuff to worry about, just launch home! 3872 try { 3873 ActivityManagerNative.getDefault().stopAppSwitches(); 3874 } catch (RemoteException e) { 3875 } 3876 if (mRecentsVisible) { 3877 // Hide Recents and notify it to launch Home 3878 if (awakenFromDreams) { 3879 awakenDreams(); 3880 } 3881 hideRecentApps(false, true); 3882 } else { 3883 // Otherwise, just launch Home 3884 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY); 3885 startDockOrHome(true /*fromHomeKey*/, awakenFromDreams); 3886 } 3887 } 3888 3889 private final Runnable mClearHideNavigationFlag = new Runnable() { 3890 @Override 3891 public void run() { 3892 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 3893 // Clear flags. 3894 mForceClearedSystemUiFlags &= 3895 ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; 3896 } 3897 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 3898 } 3899 }; 3900 3901 /** 3902 * Input handler used while nav bar is hidden. Captures any touch on the screen, 3903 * to determine when the nav bar should be shown and prevent applications from 3904 * receiving those touches. 3905 */ 3906 final class HideNavInputEventReceiver extends InputEventReceiver { 3907 public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) { 3908 super(inputChannel, looper); 3909 } 3910 3911 @Override 3912 public void onInputEvent(InputEvent event) { 3913 boolean handled = false; 3914 try { 3915 if (event instanceof MotionEvent 3916 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { 3917 final MotionEvent motionEvent = (MotionEvent)event; 3918 if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { 3919 // When the user taps down, we re-show the nav bar. 3920 boolean changed = false; 3921 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 3922 if (mInputConsumer == null) { 3923 return; 3924 } 3925 // Any user activity always causes us to show the 3926 // navigation controls, if they had been hidden. 3927 // We also clear the low profile and only content 3928 // flags so that tapping on the screen will atomically 3929 // restore all currently hidden screen decorations. 3930 int newVal = mResettingSystemUiFlags | 3931 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | 3932 View.SYSTEM_UI_FLAG_LOW_PROFILE | 3933 View.SYSTEM_UI_FLAG_FULLSCREEN; 3934 if (mResettingSystemUiFlags != newVal) { 3935 mResettingSystemUiFlags = newVal; 3936 changed = true; 3937 } 3938 // We don't allow the system's nav bar to be hidden 3939 // again for 1 second, to prevent applications from 3940 // spamming us and keeping it from being shown. 3941 newVal = mForceClearedSystemUiFlags | 3942 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; 3943 if (mForceClearedSystemUiFlags != newVal) { 3944 mForceClearedSystemUiFlags = newVal; 3945 changed = true; 3946 mHandler.postDelayed(mClearHideNavigationFlag, 1000); 3947 } 3948 } 3949 if (changed) { 3950 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 3951 } 3952 } 3953 } 3954 } finally { 3955 finishInputEvent(event, handled); 3956 } 3957 } 3958 } 3959 final InputEventReceiver.Factory mHideNavInputEventReceiverFactory = 3960 new InputEventReceiver.Factory() { 3961 @Override 3962 public InputEventReceiver createInputEventReceiver( 3963 InputChannel inputChannel, Looper looper) { 3964 return new HideNavInputEventReceiver(inputChannel, looper); 3965 } 3966 }; 3967 3968 @Override 3969 public void setRecentsVisibilityLw(boolean visible) { 3970 mRecentsVisible = visible; 3971 } 3972 3973 @Override 3974 public void setTvPipVisibilityLw(boolean visible) { 3975 mTvPictureInPictureVisible = visible; 3976 } 3977 3978 @Override 3979 public int adjustSystemUiVisibilityLw(int visibility) { 3980 mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility); 3981 mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility); 3982 3983 // Reset any bits in mForceClearingStatusBarVisibility that 3984 // are now clear. 3985 mResettingSystemUiFlags &= visibility; 3986 // Clear any bits in the new visibility that are currently being 3987 // force cleared, before reporting it. 3988 return visibility & ~mResettingSystemUiFlags 3989 & ~mForceClearedSystemUiFlags; 3990 } 3991 3992 @Override 3993 public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds, 3994 int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets, 3995 Rect outStableInsets, Rect outOutsets) { 3996 final int fl = PolicyControl.getWindowFlags(null, attrs); 3997 final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs); 3998 final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility); 3999 4000 final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl); 4001 if (useOutsets) { 4002 int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources()); 4003 if (outset > 0) { 4004 if (displayRotation == Surface.ROTATION_0) { 4005 outOutsets.bottom += outset; 4006 } else if (displayRotation == Surface.ROTATION_90) { 4007 outOutsets.right += outset; 4008 } else if (displayRotation == Surface.ROTATION_180) { 4009 outOutsets.top += outset; 4010 } else if (displayRotation == Surface.ROTATION_270) { 4011 outOutsets.left += outset; 4012 } 4013 } 4014 } 4015 4016 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) 4017 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { 4018 int availRight, availBottom; 4019 if (canHideNavigationBar() && 4020 (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) { 4021 availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4022 availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4023 } else { 4024 availRight = mRestrictedScreenLeft + mRestrictedScreenWidth; 4025 availBottom = mRestrictedScreenTop + mRestrictedScreenHeight; 4026 } 4027 if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) { 4028 if ((fl & FLAG_FULLSCREEN) != 0) { 4029 outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop, 4030 availRight - mStableFullscreenRight, 4031 availBottom - mStableFullscreenBottom); 4032 } else { 4033 outContentInsets.set(mStableLeft, mStableTop, 4034 availRight - mStableRight, availBottom - mStableBottom); 4035 } 4036 } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) { 4037 outContentInsets.setEmpty(); 4038 } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN 4039 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) { 4040 outContentInsets.set(mCurLeft, mCurTop, 4041 availRight - mCurRight, availBottom - mCurBottom); 4042 } else { 4043 outContentInsets.set(mCurLeft, mCurTop, 4044 availRight - mCurRight, availBottom - mCurBottom); 4045 } 4046 4047 outStableInsets.set(mStableLeft, mStableTop, 4048 availRight - mStableRight, availBottom - mStableBottom); 4049 if (taskBounds != null) { 4050 calculateRelevantTaskInsets(taskBounds, outContentInsets, 4051 displayWidth, displayHeight); 4052 calculateRelevantTaskInsets(taskBounds, outStableInsets, 4053 displayWidth, displayHeight); 4054 } 4055 return mForceShowSystemBars; 4056 } 4057 outContentInsets.setEmpty(); 4058 outStableInsets.setEmpty(); 4059 return mForceShowSystemBars; 4060 } 4061 4062 /** 4063 * For any given task bounds, the insets relevant for these bounds given the insets relevant 4064 * for the entire display. 4065 */ 4066 private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth, 4067 int displayHeight) { 4068 mTmpRect.set(0, 0, displayWidth, displayHeight); 4069 mTmpRect.inset(inOutInsets); 4070 mTmpRect.intersect(taskBounds); 4071 int leftInset = mTmpRect.left - taskBounds.left; 4072 int topInset = mTmpRect.top - taskBounds.top; 4073 int rightInset = taskBounds.right - mTmpRect.right; 4074 int bottomInset = taskBounds.bottom - mTmpRect.bottom; 4075 inOutInsets.set(leftInset, topInset, rightInset, bottomInset); 4076 } 4077 4078 private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) { 4079 return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN 4080 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0; 4081 } 4082 4083 /** {@inheritDoc} */ 4084 @Override 4085 public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight, 4086 int displayRotation, int uiMode) { 4087 mDisplayRotation = displayRotation; 4088 final int overscanLeft, overscanTop, overscanRight, overscanBottom; 4089 if (isDefaultDisplay) { 4090 switch (displayRotation) { 4091 case Surface.ROTATION_90: 4092 overscanLeft = mOverscanTop; 4093 overscanTop = mOverscanRight; 4094 overscanRight = mOverscanBottom; 4095 overscanBottom = mOverscanLeft; 4096 break; 4097 case Surface.ROTATION_180: 4098 overscanLeft = mOverscanRight; 4099 overscanTop = mOverscanBottom; 4100 overscanRight = mOverscanLeft; 4101 overscanBottom = mOverscanTop; 4102 break; 4103 case Surface.ROTATION_270: 4104 overscanLeft = mOverscanBottom; 4105 overscanTop = mOverscanLeft; 4106 overscanRight = mOverscanTop; 4107 overscanBottom = mOverscanRight; 4108 break; 4109 default: 4110 overscanLeft = mOverscanLeft; 4111 overscanTop = mOverscanTop; 4112 overscanRight = mOverscanRight; 4113 overscanBottom = mOverscanBottom; 4114 break; 4115 } 4116 } else { 4117 overscanLeft = 0; 4118 overscanTop = 0; 4119 overscanRight = 0; 4120 overscanBottom = 0; 4121 } 4122 mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0; 4123 mOverscanScreenTop = mRestrictedOverscanScreenTop = 0; 4124 mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth; 4125 mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight; 4126 mSystemLeft = 0; 4127 mSystemTop = 0; 4128 mSystemRight = displayWidth; 4129 mSystemBottom = displayHeight; 4130 mUnrestrictedScreenLeft = overscanLeft; 4131 mUnrestrictedScreenTop = overscanTop; 4132 mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight; 4133 mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom; 4134 mRestrictedScreenLeft = mUnrestrictedScreenLeft; 4135 mRestrictedScreenTop = mUnrestrictedScreenTop; 4136 mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth; 4137 mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight; 4138 mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft 4139 = mCurLeft = mUnrestrictedScreenLeft; 4140 mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop 4141 = mCurTop = mUnrestrictedScreenTop; 4142 mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight 4143 = mCurRight = displayWidth - overscanRight; 4144 mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom 4145 = mCurBottom = displayHeight - overscanBottom; 4146 mDockLayer = 0x10000000; 4147 mStatusBarLayer = -1; 4148 4149 // start with the current dock rect, which will be (0,0,displayWidth,displayHeight) 4150 final Rect pf = mTmpParentFrame; 4151 final Rect df = mTmpDisplayFrame; 4152 final Rect of = mTmpOverscanFrame; 4153 final Rect vf = mTmpVisibleFrame; 4154 final Rect dcf = mTmpDecorFrame; 4155 pf.left = df.left = of.left = vf.left = mDockLeft; 4156 pf.top = df.top = of.top = vf.top = mDockTop; 4157 pf.right = df.right = of.right = vf.right = mDockRight; 4158 pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom; 4159 dcf.setEmpty(); // Decor frame N/A for system bars. 4160 4161 if (isDefaultDisplay) { 4162 // For purposes of putting out fake window up to steal focus, we will 4163 // drive nav being hidden only by whether it is requested. 4164 final int sysui = mLastSystemUiFlags; 4165 boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0; 4166 boolean navTranslucent = (sysui 4167 & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0; 4168 boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; 4169 boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 4170 boolean navAllowedHidden = immersive || immersiveSticky; 4171 navTranslucent &= !immersiveSticky; // transient trumps translucent 4172 boolean isKeyguardShowing = isStatusBarKeyguard() && !mHideLockScreen; 4173 if (!isKeyguardShowing) { 4174 navTranslucent &= areTranslucentBarsAllowed(); 4175 } 4176 boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null 4177 && mStatusBar.getAttrs().height == MATCH_PARENT 4178 && mStatusBar.getAttrs().width == MATCH_PARENT; 4179 4180 // When the navigation bar isn't visible, we put up a fake 4181 // input window to catch all touch events. This way we can 4182 // detect when the user presses anywhere to bring back the nav 4183 // bar and ensure the application doesn't see the event. 4184 if (navVisible || navAllowedHidden) { 4185 if (mInputConsumer != null) { 4186 mHandler.sendMessage( 4187 mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer)); 4188 mInputConsumer = null; 4189 } 4190 } else if (mInputConsumer == null) { 4191 mInputConsumer = mWindowManagerFuncs.addInputConsumer(mHandler.getLooper(), 4192 mHideNavInputEventReceiverFactory); 4193 } 4194 4195 // For purposes of positioning and showing the nav bar, if we have 4196 // decided that it can't be hidden (because of the screen aspect ratio), 4197 // then take that into account. 4198 navVisible |= !canHideNavigationBar(); 4199 4200 boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight, 4201 displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom, dcf, navVisible, navTranslucent, 4202 navAllowedHidden, statusBarExpandedNotKeyguard); 4203 if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)", 4204 mDockLeft, mDockTop, mDockRight, mDockBottom)); 4205 updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing); 4206 if (updateSysUiVisibility) { 4207 updateSystemUiVisibilityLw(); 4208 } 4209 } 4210 } 4211 4212 private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui, 4213 boolean isKeyguardShowing) { 4214 // decide where the status bar goes ahead of time 4215 if (mStatusBar != null) { 4216 // apply any navigation bar insets 4217 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4218 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4219 pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft; 4220 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight 4221 + mUnrestrictedScreenTop; 4222 vf.left = mStableLeft; 4223 vf.top = mStableTop; 4224 vf.right = mStableRight; 4225 vf.bottom = mStableBottom; 4226 4227 mStatusBarLayer = mStatusBar.getSurfaceLayer(); 4228 4229 // Let the status bar determine its size. 4230 mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */, 4231 vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */, 4232 dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */); 4233 4234 // For layout, the status bar is always at the top with our fixed height. 4235 mStableTop = mUnrestrictedScreenTop + mStatusBarHeight; 4236 4237 boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0; 4238 boolean statusBarTranslucent = (sysui 4239 & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0; 4240 if (!isKeyguardShowing) { 4241 statusBarTranslucent &= areTranslucentBarsAllowed(); 4242 } 4243 4244 // If the status bar is hidden, we don't want to cause 4245 // windows behind it to scroll. 4246 if (mStatusBar.isVisibleLw() && !statusBarTransient) { 4247 // Status bar may go away, so the screen area it occupies 4248 // is available to apps but just covering them when the 4249 // status bar is visible. 4250 mDockTop = mUnrestrictedScreenTop + mStatusBarHeight; 4251 4252 mContentTop = mVoiceContentTop = mCurTop = mDockTop; 4253 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom; 4254 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft; 4255 mContentRight = mVoiceContentRight = mCurRight = mDockRight; 4256 4257 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " + 4258 String.format( 4259 "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]", 4260 mDockLeft, mDockTop, mDockRight, mDockBottom, 4261 mContentLeft, mContentTop, mContentRight, mContentBottom, 4262 mCurLeft, mCurTop, mCurRight, mCurBottom)); 4263 } 4264 if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw() 4265 && !statusBarTransient && !statusBarTranslucent 4266 && !mStatusBarController.wasRecentlyTranslucent()) { 4267 // If the opaque status bar is currently requested to be visible, 4268 // and not in the process of animating on or off, then 4269 // we can tell the app that it is covered by it. 4270 mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight; 4271 } 4272 if (mStatusBarController.checkHiddenLw()) { 4273 return true; 4274 } 4275 } 4276 return false; 4277 } 4278 4279 private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation, 4280 int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf, 4281 boolean navVisible, boolean navTranslucent, boolean navAllowedHidden, 4282 boolean statusBarExpandedNotKeyguard) { 4283 if (mNavigationBar != null) { 4284 boolean transientNavBarShowing = mNavigationBarController.isTransientShowing(); 4285 // Force the navigation bar to its appropriate place and 4286 // size. We need to do this directly, instead of relying on 4287 // it to bubble up from the nav bar, because this needs to 4288 // change atomically with screen rotations. 4289 mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight, 4290 displayRotation); 4291 if (mNavigationBarPosition == NAV_BAR_BOTTOM) { 4292 // It's a system nav bar or a portrait screen; nav bar goes on bottom. 4293 int top = displayHeight - overscanBottom 4294 - getNavigationBarHeight(displayRotation, uiMode); 4295 mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom); 4296 mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top; 4297 if (transientNavBarShowing) { 4298 mNavigationBarController.setBarShowingLw(true); 4299 } else if (navVisible) { 4300 mNavigationBarController.setBarShowingLw(true); 4301 mDockBottom = mTmpNavigationFrame.top; 4302 mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop; 4303 mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop; 4304 } else { 4305 // We currently want to hide the navigation UI - unless we expanded the status 4306 // bar. 4307 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); 4308 } 4309 if (navVisible && !navTranslucent && !navAllowedHidden 4310 && !mNavigationBar.isAnimatingLw() 4311 && !mNavigationBarController.wasRecentlyTranslucent()) { 4312 // If the opaque nav bar is currently requested to be visible, 4313 // and not in the process of animating on or off, then 4314 // we can tell the app that it is covered by it. 4315 mSystemBottom = mTmpNavigationFrame.top; 4316 } 4317 } else if (mNavigationBarPosition == NAV_BAR_RIGHT) { 4318 // Landscape screen; nav bar goes to the right. 4319 int left = displayWidth - overscanRight 4320 - getNavigationBarWidth(displayRotation, uiMode); 4321 mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight); 4322 mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left; 4323 if (transientNavBarShowing) { 4324 mNavigationBarController.setBarShowingLw(true); 4325 } else if (navVisible) { 4326 mNavigationBarController.setBarShowingLw(true); 4327 mDockRight = mTmpNavigationFrame.left; 4328 mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft; 4329 mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft; 4330 } else { 4331 // We currently want to hide the navigation UI - unless we expanded the status 4332 // bar. 4333 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); 4334 } 4335 if (navVisible && !navTranslucent && !navAllowedHidden 4336 && !mNavigationBar.isAnimatingLw() 4337 && !mNavigationBarController.wasRecentlyTranslucent()) { 4338 // If the nav bar is currently requested to be visible, 4339 // and not in the process of animating on or off, then 4340 // we can tell the app that it is covered by it. 4341 mSystemRight = mTmpNavigationFrame.left; 4342 } 4343 } else if (mNavigationBarPosition == NAV_BAR_LEFT) { 4344 // Seascape screen; nav bar goes to the left. 4345 int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode); 4346 mTmpNavigationFrame.set(overscanLeft, 0, right, displayHeight); 4347 mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right; 4348 if (transientNavBarShowing) { 4349 mNavigationBarController.setBarShowingLw(true); 4350 } else if (navVisible) { 4351 mNavigationBarController.setBarShowingLw(true); 4352 mDockLeft = mTmpNavigationFrame.right; 4353 // TODO: not so sure about those: 4354 mRestrictedScreenLeft = mRestrictedOverscanScreenLeft = mDockLeft; 4355 mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft; 4356 mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft; 4357 } else { 4358 // We currently want to hide the navigation UI - unless we expanded the status 4359 // bar. 4360 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); 4361 } 4362 if (navVisible && !navTranslucent && !navAllowedHidden 4363 && !mNavigationBar.isAnimatingLw() 4364 && !mNavigationBarController.wasRecentlyTranslucent()) { 4365 // If the nav bar is currently requested to be visible, 4366 // and not in the process of animating on or off, then 4367 // we can tell the app that it is covered by it. 4368 mSystemLeft = mTmpNavigationFrame.right; 4369 } 4370 } 4371 // Make sure the content and current rectangles are updated to 4372 // account for the restrictions from the navigation bar. 4373 mContentTop = mVoiceContentTop = mCurTop = mDockTop; 4374 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom; 4375 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft; 4376 mContentRight = mVoiceContentRight = mCurRight = mDockRight; 4377 mStatusBarLayer = mNavigationBar.getSurfaceLayer(); 4378 // And compute the final frame. 4379 mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame, 4380 mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf, 4381 mTmpNavigationFrame, mTmpNavigationFrame); 4382 if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame); 4383 if (mNavigationBarController.checkHiddenLw()) { 4384 return true; 4385 } 4386 } 4387 return false; 4388 } 4389 4390 private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) { 4391 if (mNavigationBarCanMove && displayWidth > displayHeight) { 4392 if (displayRotation == Surface.ROTATION_270) { 4393 return NAV_BAR_LEFT; 4394 } else { 4395 return NAV_BAR_RIGHT; 4396 } 4397 } 4398 return NAV_BAR_BOTTOM; 4399 } 4400 4401 /** {@inheritDoc} */ 4402 @Override 4403 public int getSystemDecorLayerLw() { 4404 if (mStatusBar != null && mStatusBar.isVisibleLw()) { 4405 return mStatusBar.getSurfaceLayer(); 4406 } 4407 4408 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) { 4409 return mNavigationBar.getSurfaceLayer(); 4410 } 4411 4412 return 0; 4413 } 4414 4415 @Override 4416 public void getContentRectLw(Rect r) { 4417 r.set(mContentLeft, mContentTop, mContentRight, mContentBottom); 4418 } 4419 4420 void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached, 4421 boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) { 4422 if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) { 4423 // Here's a special case: if this attached window is a panel that is 4424 // above the dock window, and the window it is attached to is below 4425 // the dock window, then the frames we computed for the window it is 4426 // attached to can not be used because the dock is effectively part 4427 // of the underlying window and the attached window is floating on top 4428 // of the whole thing. So, we ignore the attached window and explicitly 4429 // compute the frames that would be appropriate without the dock. 4430 df.left = of.left = cf.left = vf.left = mDockLeft; 4431 df.top = of.top = cf.top = vf.top = mDockTop; 4432 df.right = of.right = cf.right = vf.right = mDockRight; 4433 df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom; 4434 } else { 4435 // The effective display frame of the attached window depends on 4436 // whether it is taking care of insetting its content. If not, 4437 // we need to use the parent's content frame so that the entire 4438 // window is positioned within that content. Otherwise we can use 4439 // the overscan frame and let the attached window take care of 4440 // positioning its content appropriately. 4441 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4442 // Set the content frame of the attached window to the parent's decor frame 4443 // (same as content frame when IME isn't present) if specifically requested by 4444 // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag. 4445 // Otherwise, use the overscan frame. 4446 cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0 4447 ? attached.getContentFrameLw() : attached.getOverscanFrameLw()); 4448 } else { 4449 // If the window is resizing, then we want to base the content 4450 // frame on our attached content frame to resize... however, 4451 // things can be tricky if the attached window is NOT in resize 4452 // mode, in which case its content frame will be larger. 4453 // Ungh. So to deal with that, make sure the content frame 4454 // we end up using is not covering the IM dock. 4455 cf.set(attached.getContentFrameLw()); 4456 if (attached.isVoiceInteraction()) { 4457 if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft; 4458 if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop; 4459 if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight; 4460 if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom; 4461 } else if (attached.getSurfaceLayer() < mDockLayer) { 4462 if (cf.left < mContentLeft) cf.left = mContentLeft; 4463 if (cf.top < mContentTop) cf.top = mContentTop; 4464 if (cf.right > mContentRight) cf.right = mContentRight; 4465 if (cf.bottom > mContentBottom) cf.bottom = mContentBottom; 4466 } 4467 } 4468 df.set(insetDecors ? attached.getDisplayFrameLw() : cf); 4469 of.set(insetDecors ? attached.getOverscanFrameLw() : cf); 4470 vf.set(attached.getVisibleFrameLw()); 4471 } 4472 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached 4473 // window should be positioned relative to its parent or the entire 4474 // screen. 4475 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 4476 ? attached.getFrameLw() : df); 4477 } 4478 4479 private void applyStableConstraints(int sysui, int fl, Rect r) { 4480 if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) { 4481 // If app is requesting a stable layout, don't let the 4482 // content insets go below the stable values. 4483 if ((fl & FLAG_FULLSCREEN) != 0) { 4484 if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft; 4485 if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop; 4486 if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight; 4487 if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom; 4488 } else { 4489 if (r.left < mStableLeft) r.left = mStableLeft; 4490 if (r.top < mStableTop) r.top = mStableTop; 4491 if (r.right > mStableRight) r.right = mStableRight; 4492 if (r.bottom > mStableBottom) r.bottom = mStableBottom; 4493 } 4494 } 4495 } 4496 4497 private boolean canReceiveInput(WindowState win) { 4498 boolean notFocusable = 4499 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0; 4500 boolean altFocusableIm = 4501 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0; 4502 boolean notFocusableForIm = notFocusable ^ altFocusableIm; 4503 return !notFocusableForIm; 4504 } 4505 4506 /** {@inheritDoc} */ 4507 @Override 4508 public void layoutWindowLw(WindowState win, WindowState attached) { 4509 // We've already done the navigation bar and status bar. If the status bar can receive 4510 // input, we need to layout it again to accomodate for the IME window. 4511 if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) { 4512 return; 4513 } 4514 final WindowManager.LayoutParams attrs = win.getAttrs(); 4515 final boolean isDefaultDisplay = win.isDefaultDisplay(); 4516 final boolean needsToOffsetInputMethodTarget = isDefaultDisplay && 4517 (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null); 4518 if (needsToOffsetInputMethodTarget) { 4519 if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state"); 4520 offsetInputMethodWindowLw(mLastInputMethodWindow); 4521 } 4522 4523 final int fl = PolicyControl.getWindowFlags(win, attrs); 4524 final int pfl = attrs.privateFlags; 4525 final int sim = attrs.softInputMode; 4526 final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null); 4527 4528 final Rect pf = mTmpParentFrame; 4529 final Rect df = mTmpDisplayFrame; 4530 final Rect of = mTmpOverscanFrame; 4531 final Rect cf = mTmpContentFrame; 4532 final Rect vf = mTmpVisibleFrame; 4533 final Rect dcf = mTmpDecorFrame; 4534 final Rect sf = mTmpStableFrame; 4535 Rect osf = null; 4536 dcf.setEmpty(); 4537 4538 final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar 4539 && mNavigationBar != null && mNavigationBar.isVisibleLw()); 4540 4541 final int adjust = sim & SOFT_INPUT_MASK_ADJUST; 4542 4543 if (isDefaultDisplay) { 4544 sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom); 4545 } else { 4546 sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom); 4547 } 4548 4549 if (!isDefaultDisplay) { 4550 if (attached != null) { 4551 // If this window is attached to another, our display 4552 // frame is the same as the one we are attached to. 4553 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf); 4554 } else { 4555 // Give the window full screen. 4556 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 4557 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 4558 pf.right = df.right = of.right = cf.right 4559 = mOverscanScreenLeft + mOverscanScreenWidth; 4560 pf.bottom = df.bottom = of.bottom = cf.bottom 4561 = mOverscanScreenTop + mOverscanScreenHeight; 4562 } 4563 } else if (attrs.type == TYPE_INPUT_METHOD) { 4564 pf.left = df.left = of.left = cf.left = vf.left = mDockLeft; 4565 pf.top = df.top = of.top = cf.top = vf.top = mDockTop; 4566 pf.right = df.right = of.right = cf.right = vf.right = mDockRight; 4567 // IM dock windows layout below the nav bar... 4568 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4569 // ...with content insets above the nav bar 4570 cf.bottom = vf.bottom = mStableBottom; 4571 if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) { 4572 // The status bar forces the navigation bar while it's visible. Make sure the IME 4573 // avoids the navigation bar in that case. 4574 if (mNavigationBarPosition == NAV_BAR_RIGHT) { 4575 pf.right = df.right = of.right = cf.right = vf.right = mStableRight; 4576 } else if (mNavigationBarPosition == NAV_BAR_LEFT) { 4577 pf.left = df.left = of.left = cf.left = vf.left = mStableLeft; 4578 } 4579 } 4580 // IM dock windows always go to the bottom of the screen. 4581 attrs.gravity = Gravity.BOTTOM; 4582 mDockLayer = win.getSurfaceLayer(); 4583 } else if (attrs.type == TYPE_VOICE_INTERACTION) { 4584 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4585 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4586 pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4587 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4588 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4589 cf.left = mDockLeft; 4590 cf.top = mDockTop; 4591 cf.right = mDockRight; 4592 cf.bottom = mDockBottom; 4593 } else { 4594 cf.left = mContentLeft; 4595 cf.top = mContentTop; 4596 cf.right = mContentRight; 4597 cf.bottom = mContentBottom; 4598 } 4599 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 4600 vf.left = mCurLeft; 4601 vf.top = mCurTop; 4602 vf.right = mCurRight; 4603 vf.bottom = mCurBottom; 4604 } else { 4605 vf.set(cf); 4606 } 4607 } else if (attrs.type == TYPE_WALLPAPER) { 4608 layoutWallpaper(win, pf, df, of, cf); 4609 } else if (win == mStatusBar) { 4610 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4611 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4612 pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft; 4613 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop; 4614 cf.left = vf.left = mStableLeft; 4615 cf.top = vf.top = mStableTop; 4616 cf.right = vf.right = mStableRight; 4617 vf.bottom = mStableBottom; 4618 4619 if (adjust == SOFT_INPUT_ADJUST_RESIZE) { 4620 cf.bottom = mContentBottom; 4621 } else { 4622 cf.bottom = mDockBottom; 4623 vf.bottom = mContentBottom; 4624 } 4625 } else { 4626 4627 // Default policy decor for the default display 4628 dcf.left = mSystemLeft; 4629 dcf.top = mSystemTop; 4630 dcf.right = mSystemRight; 4631 dcf.bottom = mSystemBottom; 4632 final boolean inheritTranslucentDecor = (attrs.privateFlags 4633 & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0; 4634 final boolean isAppWindow = 4635 attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW && 4636 attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; 4637 final boolean topAtRest = 4638 win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw(); 4639 if (isAppWindow && !inheritTranslucentDecor && !topAtRest) { 4640 if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0 4641 && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0 4642 && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0 4643 && (fl & WindowManager.LayoutParams. 4644 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0 4645 && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) { 4646 // Ensure policy decor includes status bar 4647 dcf.top = mStableTop; 4648 } 4649 if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0 4650 && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0 4651 && (fl & WindowManager.LayoutParams. 4652 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) { 4653 // Ensure policy decor includes navigation bar 4654 dcf.bottom = mStableBottom; 4655 dcf.right = mStableRight; 4656 } 4657 } 4658 4659 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) 4660 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { 4661 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() 4662 + "): IN_SCREEN, INSET_DECOR"); 4663 // This is the case for a normal activity window: we want it 4664 // to cover all of the screen space, and it can take care of 4665 // moving its contents to account for screen decorations that 4666 // intrude into that space. 4667 if (attached != null) { 4668 // If this window is attached to another, our display 4669 // frame is the same as the one we are attached to. 4670 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf); 4671 } else { 4672 if (attrs.type == TYPE_STATUS_BAR_PANEL 4673 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) { 4674 // Status bar panels are the only windows who can go on top of 4675 // the status bar. They are protected by the STATUS_BAR_SERVICE 4676 // permission, so they have the same privileges as the status 4677 // bar itself. 4678 // 4679 // However, they should still dodge the navigation bar if it exists. 4680 4681 pf.left = df.left = of.left = hasNavBar 4682 ? mDockLeft : mUnrestrictedScreenLeft; 4683 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4684 pf.right = df.right = of.right = hasNavBar 4685 ? mRestrictedScreenLeft+mRestrictedScreenWidth 4686 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4687 pf.bottom = df.bottom = of.bottom = hasNavBar 4688 ? mRestrictedScreenTop+mRestrictedScreenHeight 4689 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4690 4691 if (DEBUG_LAYOUT) Slog.v(TAG, String.format( 4692 "Laying out status bar window: (%d,%d - %d,%d)", 4693 pf.left, pf.top, pf.right, pf.bottom)); 4694 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0 4695 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 4696 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 4697 // Asking to layout into the overscan region, so give it that pure 4698 // unrestricted area. 4699 pf.left = df.left = of.left = mOverscanScreenLeft; 4700 pf.top = df.top = of.top = mOverscanScreenTop; 4701 pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth; 4702 pf.bottom = df.bottom = of.bottom = mOverscanScreenTop 4703 + mOverscanScreenHeight; 4704 } else if (canHideNavigationBar() 4705 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 4706 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 4707 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 4708 // Asking for layout as if the nav bar is hidden, lets the 4709 // application extend into the unrestricted overscan screen area. We 4710 // only do this for application windows to ensure no window that 4711 // can be above the nav bar can do this. 4712 pf.left = df.left = mOverscanScreenLeft; 4713 pf.top = df.top = mOverscanScreenTop; 4714 pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth; 4715 pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight; 4716 // We need to tell the app about where the frame inside the overscan 4717 // is, so it can inset its content by that amount -- it didn't ask 4718 // to actually extend itself into the overscan region. 4719 of.left = mUnrestrictedScreenLeft; 4720 of.top = mUnrestrictedScreenTop; 4721 of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4722 of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4723 } else { 4724 pf.left = df.left = mRestrictedOverscanScreenLeft; 4725 pf.top = df.top = mRestrictedOverscanScreenTop; 4726 pf.right = df.right = mRestrictedOverscanScreenLeft 4727 + mRestrictedOverscanScreenWidth; 4728 pf.bottom = df.bottom = mRestrictedOverscanScreenTop 4729 + mRestrictedOverscanScreenHeight; 4730 // We need to tell the app about where the frame inside the overscan 4731 // is, so it can inset its content by that amount -- it didn't ask 4732 // to actually extend itself into the overscan region. 4733 of.left = mUnrestrictedScreenLeft; 4734 of.top = mUnrestrictedScreenTop; 4735 of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4736 of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4737 } 4738 4739 if ((fl & FLAG_FULLSCREEN) == 0) { 4740 if (win.isVoiceInteraction()) { 4741 cf.left = mVoiceContentLeft; 4742 cf.top = mVoiceContentTop; 4743 cf.right = mVoiceContentRight; 4744 cf.bottom = mVoiceContentBottom; 4745 } else { 4746 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4747 cf.left = mDockLeft; 4748 cf.top = mDockTop; 4749 cf.right = mDockRight; 4750 cf.bottom = mDockBottom; 4751 } else { 4752 cf.left = mContentLeft; 4753 cf.top = mContentTop; 4754 cf.right = mContentRight; 4755 cf.bottom = mContentBottom; 4756 } 4757 } 4758 } else { 4759 // Full screen windows are always given a layout that is as if the 4760 // status bar and other transient decors are gone. This is to avoid 4761 // bad states when moving from a window that is not hding the 4762 // status bar to one that is. 4763 cf.left = mRestrictedScreenLeft; 4764 cf.top = mRestrictedScreenTop; 4765 cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth; 4766 cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight; 4767 } 4768 applyStableConstraints(sysUiFl, fl, cf); 4769 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 4770 vf.left = mCurLeft; 4771 vf.top = mCurTop; 4772 vf.right = mCurRight; 4773 vf.bottom = mCurBottom; 4774 } else { 4775 vf.set(cf); 4776 } 4777 } 4778 } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl 4779 & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 4780 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) { 4781 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + 4782 "): IN_SCREEN"); 4783 // A window that has requested to fill the entire screen just 4784 // gets everything, period. 4785 if (attrs.type == TYPE_STATUS_BAR_PANEL 4786 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL 4787 || attrs.type == TYPE_VOLUME_OVERLAY) { 4788 pf.left = df.left = of.left = cf.left = hasNavBar 4789 ? mDockLeft : mUnrestrictedScreenLeft; 4790 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop; 4791 pf.right = df.right = of.right = cf.right = hasNavBar 4792 ? mRestrictedScreenLeft+mRestrictedScreenWidth 4793 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4794 pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar 4795 ? mRestrictedScreenTop+mRestrictedScreenHeight 4796 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4797 if (DEBUG_LAYOUT) Slog.v(TAG, String.format( 4798 "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)", 4799 pf.left, pf.top, pf.right, pf.bottom)); 4800 } else if (attrs.type == TYPE_NAVIGATION_BAR 4801 || attrs.type == TYPE_NAVIGATION_BAR_PANEL) { 4802 // The navigation bar has Real Ultimate Power. 4803 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4804 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4805 pf.right = df.right = of.right = mUnrestrictedScreenLeft 4806 + mUnrestrictedScreenWidth; 4807 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop 4808 + mUnrestrictedScreenHeight; 4809 if (DEBUG_LAYOUT) Slog.v(TAG, String.format( 4810 "Laying out navigation bar window: (%d,%d - %d,%d)", 4811 pf.left, pf.top, pf.right, pf.bottom)); 4812 } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY 4813 || attrs.type == TYPE_BOOT_PROGRESS 4814 || attrs.type == TYPE_SCREENSHOT) 4815 && ((fl & FLAG_FULLSCREEN) != 0)) { 4816 // Fullscreen secure system overlays get what they ask for. Screenshot region 4817 // selection overlay should also expand to full screen. 4818 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 4819 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 4820 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft 4821 + mOverscanScreenWidth; 4822 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop 4823 + mOverscanScreenHeight; 4824 } else if (attrs.type == TYPE_BOOT_PROGRESS) { 4825 // Boot progress screen always covers entire display. 4826 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 4827 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 4828 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft 4829 + mOverscanScreenWidth; 4830 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop 4831 + mOverscanScreenHeight; 4832 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0 4833 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 4834 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 4835 // Asking to layout into the overscan region, so give it that pure 4836 // unrestricted area. 4837 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 4838 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 4839 pf.right = df.right = of.right = cf.right 4840 = mOverscanScreenLeft + mOverscanScreenWidth; 4841 pf.bottom = df.bottom = of.bottom = cf.bottom 4842 = mOverscanScreenTop + mOverscanScreenHeight; 4843 } else if (canHideNavigationBar() 4844 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 4845 && (attrs.type == TYPE_STATUS_BAR 4846 || attrs.type == TYPE_TOAST 4847 || attrs.type == TYPE_DOCK_DIVIDER 4848 || attrs.type == TYPE_VOICE_INTERACTION_STARTING 4849 || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 4850 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) { 4851 // Asking for layout as if the nav bar is hidden, lets the 4852 // application extend into the unrestricted screen area. We 4853 // only do this for application windows (or toasts) to ensure no window that 4854 // can be above the nav bar can do this. 4855 // XXX This assumes that an app asking for this will also 4856 // ask for layout in only content. We can't currently figure out 4857 // what the screen would be if only laying out to hide the nav bar. 4858 pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft; 4859 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop; 4860 pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft 4861 + mUnrestrictedScreenWidth; 4862 pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop 4863 + mUnrestrictedScreenHeight; 4864 } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) { 4865 pf.left = df.left = of.left = mRestrictedScreenLeft; 4866 pf.top = df.top = of.top = mRestrictedScreenTop; 4867 pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth; 4868 pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop 4869 + mRestrictedScreenHeight; 4870 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4871 cf.left = mDockLeft; 4872 cf.top = mDockTop; 4873 cf.right = mDockRight; 4874 cf.bottom = mDockBottom; 4875 } else { 4876 cf.left = mContentLeft; 4877 cf.top = mContentTop; 4878 cf.right = mContentRight; 4879 cf.bottom = mContentBottom; 4880 } 4881 } else { 4882 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft; 4883 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop; 4884 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft 4885 + mRestrictedScreenWidth; 4886 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop 4887 + mRestrictedScreenHeight; 4888 } 4889 4890 applyStableConstraints(sysUiFl, fl, cf); 4891 4892 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 4893 vf.left = mCurLeft; 4894 vf.top = mCurTop; 4895 vf.right = mCurRight; 4896 vf.bottom = mCurBottom; 4897 } else { 4898 vf.set(cf); 4899 } 4900 } else if (attached != null) { 4901 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + 4902 "): attached to " + attached); 4903 // A child window should be placed inside of the same visible 4904 // frame that its parent had. 4905 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf); 4906 } else { 4907 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + 4908 "): normal window"); 4909 // Otherwise, a normal window must be placed inside the content 4910 // of all screen decorations. 4911 if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) { 4912 // Status bar panels and the volume dialog are the only windows who can go on 4913 // top of the status bar. They are protected by the STATUS_BAR_SERVICE 4914 // permission, so they have the same privileges as the status 4915 // bar itself. 4916 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft; 4917 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop; 4918 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft 4919 + mRestrictedScreenWidth; 4920 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop 4921 + mRestrictedScreenHeight; 4922 } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) { 4923 // These dialogs are stable to interim decor changes. 4924 pf.left = df.left = of.left = cf.left = mStableLeft; 4925 pf.top = df.top = of.top = cf.top = mStableTop; 4926 pf.right = df.right = of.right = cf.right = mStableRight; 4927 pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom; 4928 } else { 4929 pf.left = mContentLeft; 4930 pf.top = mContentTop; 4931 pf.right = mContentRight; 4932 pf.bottom = mContentBottom; 4933 if (win.isVoiceInteraction()) { 4934 df.left = of.left = cf.left = mVoiceContentLeft; 4935 df.top = of.top = cf.top = mVoiceContentTop; 4936 df.right = of.right = cf.right = mVoiceContentRight; 4937 df.bottom = of.bottom = cf.bottom = mVoiceContentBottom; 4938 } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4939 df.left = of.left = cf.left = mDockLeft; 4940 df.top = of.top = cf.top = mDockTop; 4941 df.right = of.right = cf.right = mDockRight; 4942 df.bottom = of.bottom = cf.bottom = mDockBottom; 4943 } else { 4944 df.left = of.left = cf.left = mContentLeft; 4945 df.top = of.top = cf.top = mContentTop; 4946 df.right = of.right = cf.right = mContentRight; 4947 df.bottom = of.bottom = cf.bottom = mContentBottom; 4948 } 4949 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 4950 vf.left = mCurLeft; 4951 vf.top = mCurTop; 4952 vf.right = mCurRight; 4953 vf.bottom = mCurBottom; 4954 } else { 4955 vf.set(cf); 4956 } 4957 } 4958 } 4959 } 4960 4961 // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it. 4962 // Also, we don't allow windows in multi-window mode to extend out of the screen. 4963 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR 4964 && !win.isInMultiWindowMode()) { 4965 df.left = df.top = -10000; 4966 df.right = df.bottom = 10000; 4967 if (attrs.type != TYPE_WALLPAPER) { 4968 of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000; 4969 of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000; 4970 } 4971 } 4972 4973 // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we 4974 // need to provide information to the clients that want to pretend that you can draw there. 4975 // We only want to apply outsets to certain types of windows. For example, we never want to 4976 // apply the outsets to floating dialogs, because they wouldn't make sense there. 4977 final boolean useOutsets = shouldUseOutsets(attrs, fl); 4978 if (isDefaultDisplay && useOutsets) { 4979 osf = mTmpOutsetFrame; 4980 osf.set(cf.left, cf.top, cf.right, cf.bottom); 4981 int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources()); 4982 if (outset > 0) { 4983 int rotation = mDisplayRotation; 4984 if (rotation == Surface.ROTATION_0) { 4985 osf.bottom += outset; 4986 } else if (rotation == Surface.ROTATION_90) { 4987 osf.right += outset; 4988 } else if (rotation == Surface.ROTATION_180) { 4989 osf.top -= outset; 4990 } else if (rotation == Surface.ROTATION_270) { 4991 osf.left -= outset; 4992 } 4993 if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset 4994 + " with rotation " + rotation + ", result: " + osf); 4995 } 4996 } 4997 4998 if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle() 4999 + ": sim=#" + Integer.toHexString(sim) 5000 + " attach=" + attached + " type=" + attrs.type 5001 + String.format(" flags=0x%08x", fl) 5002 + " pf=" + pf.toShortString() + " df=" + df.toShortString() 5003 + " of=" + of.toShortString() 5004 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString() 5005 + " dcf=" + dcf.toShortString() 5006 + " sf=" + sf.toShortString() 5007 + " osf=" + (osf == null ? "null" : osf.toShortString())); 5008 5009 win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf); 5010 5011 // Dock windows carve out the bottom of the screen, so normal windows 5012 // can't appear underneath them. 5013 if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleOrBehindKeyguardLw() 5014 && win.isDisplayedLw() && !win.getGivenInsetsPendingLw()) { 5015 setLastInputMethodWindowLw(null, null); 5016 offsetInputMethodWindowLw(win); 5017 } 5018 if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleOrBehindKeyguardLw() 5019 && !win.getGivenInsetsPendingLw()) { 5020 offsetVoiceInputWindowLw(win); 5021 } 5022 } 5023 5024 private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) { 5025 5026 // The wallpaper also has Real Ultimate Power, but we want to tell 5027 // it about the overscan area. 5028 pf.left = df.left = mOverscanScreenLeft; 5029 pf.top = df.top = mOverscanScreenTop; 5030 pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth; 5031 pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight; 5032 of.left = cf.left = mUnrestrictedScreenLeft; 5033 of.top = cf.top = mUnrestrictedScreenTop; 5034 of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 5035 of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 5036 } 5037 5038 private void offsetInputMethodWindowLw(WindowState win) { 5039 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top); 5040 top += win.getGivenContentInsetsLw().top; 5041 if (mContentBottom > top) { 5042 mContentBottom = top; 5043 } 5044 if (mVoiceContentBottom > top) { 5045 mVoiceContentBottom = top; 5046 } 5047 top = win.getVisibleFrameLw().top; 5048 top += win.getGivenVisibleInsetsLw().top; 5049 if (mCurBottom > top) { 5050 mCurBottom = top; 5051 } 5052 if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom=" 5053 + mDockBottom + " mContentBottom=" 5054 + mContentBottom + " mCurBottom=" + mCurBottom); 5055 } 5056 5057 private void offsetVoiceInputWindowLw(WindowState win) { 5058 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top); 5059 top += win.getGivenContentInsetsLw().top; 5060 if (mVoiceContentBottom > top) { 5061 mVoiceContentBottom = top; 5062 } 5063 } 5064 5065 /** {@inheritDoc} */ 5066 @Override 5067 public void finishLayoutLw() { 5068 return; 5069 } 5070 5071 /** {@inheritDoc} */ 5072 @Override 5073 public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) { 5074 mTopFullscreenOpaqueWindowState = null; 5075 mTopFullscreenOpaqueOrDimmingWindowState = null; 5076 mTopDockedOpaqueWindowState = null; 5077 mTopDockedOpaqueOrDimmingWindowState = null; 5078 mAppsToBeHidden.clear(); 5079 mAppsThatDismissKeyguard.clear(); 5080 mForceStatusBar = false; 5081 mForceStatusBarFromKeyguard = false; 5082 mForceStatusBarTransparent = false; 5083 mForcingShowNavBar = false; 5084 mForcingShowNavBarLayer = -1; 5085 5086 mHideLockScreen = false; 5087 mAllowLockscreenWhenOn = false; 5088 mDismissKeyguard = DISMISS_KEYGUARD_NONE; 5089 mShowingLockscreen = false; 5090 mShowingDream = false; 5091 mWinShowWhenLocked = null; 5092 mKeyguardSecure = isKeyguardSecure(mCurrentUserId); 5093 mKeyguardSecureIncludingHidden = mKeyguardSecure 5094 && (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()); 5095 } 5096 5097 /** {@inheritDoc} */ 5098 @Override 5099 public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs, 5100 WindowState attached) { 5101 if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw=" 5102 + win.isVisibleOrBehindKeyguardLw()); 5103 final int fl = PolicyControl.getWindowFlags(win, attrs); 5104 if (mTopFullscreenOpaqueWindowState == null 5105 && win.isVisibleLw() && attrs.type == TYPE_INPUT_METHOD) { 5106 mForcingShowNavBar = true; 5107 mForcingShowNavBarLayer = win.getSurfaceLayer(); 5108 } 5109 if (attrs.type == TYPE_STATUS_BAR) { 5110 if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 5111 mForceStatusBarFromKeyguard = true; 5112 mShowingLockscreen = true; 5113 } 5114 if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) { 5115 mForceStatusBarTransparent = true; 5116 } 5117 } 5118 5119 boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW 5120 && attrs.type < FIRST_SYSTEM_WINDOW; 5121 final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0; 5122 final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0; 5123 final int stackId = win.getStackId(); 5124 if (mTopFullscreenOpaqueWindowState == null && 5125 win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) { 5126 if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) { 5127 if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 5128 mForceStatusBarFromKeyguard = true; 5129 } else { 5130 mForceStatusBar = true; 5131 } 5132 } 5133 if (attrs.type == TYPE_DREAM) { 5134 // If the lockscreen was showing when the dream started then wait 5135 // for the dream to draw before hiding the lockscreen. 5136 if (!mDreamingLockscreen 5137 || (win.isVisibleLw() && win.hasDrawnLw())) { 5138 mShowingDream = true; 5139 appWindow = true; 5140 } 5141 } 5142 5143 final IApplicationToken appToken = win.getAppToken(); 5144 5145 // For app windows that are not attached, we decide if all windows in the app they 5146 // represent should be hidden or if we should hide the lockscreen. For attached app 5147 // windows we defer the decision to the window it is attached to. 5148 if (appWindow && attached == null) { 5149 if (showWhenLocked) { 5150 // Remove any previous windows with the same appToken. 5151 mAppsToBeHidden.remove(appToken); 5152 mAppsThatDismissKeyguard.remove(appToken); 5153 if (mAppsToBeHidden.isEmpty()) { 5154 if (dismissKeyguard && !mKeyguardSecure) { 5155 mAppsThatDismissKeyguard.add(appToken); 5156 } else if (win.isDrawnLw() || win.hasAppShownWindows()) { 5157 mWinShowWhenLocked = win; 5158 mHideLockScreen = true; 5159 mForceStatusBarFromKeyguard = false; 5160 } 5161 } 5162 } else if (dismissKeyguard) { 5163 if (mKeyguardSecure) { 5164 mAppsToBeHidden.add(appToken); 5165 } else { 5166 mAppsToBeHidden.remove(appToken); 5167 } 5168 mAppsThatDismissKeyguard.add(appToken); 5169 } else { 5170 mAppsToBeHidden.add(appToken); 5171 } 5172 if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) { 5173 if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win); 5174 mTopFullscreenOpaqueWindowState = win; 5175 if (mTopFullscreenOpaqueOrDimmingWindowState == null) { 5176 mTopFullscreenOpaqueOrDimmingWindowState = win; 5177 } 5178 if (!mAppsThatDismissKeyguard.isEmpty() && 5179 mDismissKeyguard == DISMISS_KEYGUARD_NONE) { 5180 if (DEBUG_LAYOUT) Slog.v(TAG, 5181 "Setting mDismissKeyguard true by win " + win); 5182 mDismissKeyguard = (mWinDismissingKeyguard == win 5183 && mSecureDismissingKeyguard == mKeyguardSecure) 5184 ? DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START; 5185 mWinDismissingKeyguard = win; 5186 mSecureDismissingKeyguard = mKeyguardSecure; 5187 mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure; 5188 } else if (mAppsToBeHidden.isEmpty() && showWhenLocked 5189 && (win.isDrawnLw() || win.hasAppShownWindows())) { 5190 if (DEBUG_LAYOUT) Slog.v(TAG, 5191 "Setting mHideLockScreen to true by win " + win); 5192 mHideLockScreen = true; 5193 mForceStatusBarFromKeyguard = false; 5194 } 5195 if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) { 5196 mAllowLockscreenWhenOn = true; 5197 } 5198 } 5199 5200 if (!mKeyguardHidden && mWinShowWhenLocked != null && 5201 mWinShowWhenLocked.getAppToken() != win.getAppToken() && 5202 (attrs.flags & FLAG_SHOW_WHEN_LOCKED) == 0) { 5203 win.hideLw(false); 5204 } 5205 } 5206 } else if (mTopFullscreenOpaqueWindowState == null && mWinShowWhenLocked == null) { 5207 // No TopFullscreenOpaqueWindow is showing, but we found a SHOW_WHEN_LOCKED window 5208 // that is being hidden in an animation - keep the 5209 // keyguard hidden until the new window shows up and 5210 // we know whether to show the keyguard or not. 5211 if (win.isAnimatingLw() && appWindow && showWhenLocked && mKeyguardHidden) { 5212 mHideLockScreen = true; 5213 mWinShowWhenLocked = win; 5214 } 5215 } 5216 5217 final boolean reallyVisible = win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw(); 5218 5219 // Voice interaction overrides both top fullscreen and top docked. 5220 if (reallyVisible && win.getAttrs().type == TYPE_VOICE_INTERACTION) { 5221 if (mTopFullscreenOpaqueWindowState == null) { 5222 mTopFullscreenOpaqueWindowState = win; 5223 if (mTopFullscreenOpaqueOrDimmingWindowState == null) { 5224 mTopFullscreenOpaqueOrDimmingWindowState = win; 5225 } 5226 } 5227 if (mTopDockedOpaqueWindowState == null) { 5228 mTopDockedOpaqueWindowState = win; 5229 if (mTopDockedOpaqueOrDimmingWindowState == null) { 5230 mTopDockedOpaqueOrDimmingWindowState = win; 5231 } 5232 } 5233 } 5234 5235 // Keep track of the window if it's dimming but not necessarily fullscreen. 5236 if (mTopFullscreenOpaqueOrDimmingWindowState == null && reallyVisible 5237 && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) { 5238 mTopFullscreenOpaqueOrDimmingWindowState = win; 5239 } 5240 5241 // We need to keep track of the top "fullscreen" opaque window for the docked stack 5242 // separately, because both the "real fullscreen" opaque window and the one for the docked 5243 // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR. 5244 if (mTopDockedOpaqueWindowState == null && reallyVisible && appWindow && attached == null 5245 && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) { 5246 mTopDockedOpaqueWindowState = win; 5247 if (mTopDockedOpaqueOrDimmingWindowState == null) { 5248 mTopDockedOpaqueOrDimmingWindowState = win; 5249 } 5250 } 5251 5252 // Also keep track of any windows that are dimming but not necessarily fullscreen in the 5253 // docked stack. 5254 if (mTopDockedOpaqueOrDimmingWindowState == null && reallyVisible && win.isDimming() 5255 && stackId == DOCKED_STACK_ID) { 5256 mTopDockedOpaqueOrDimmingWindowState = win; 5257 } 5258 } 5259 5260 private boolean isFullscreen(WindowManager.LayoutParams attrs) { 5261 return attrs.x == 0 && attrs.y == 0 5262 && attrs.width == WindowManager.LayoutParams.MATCH_PARENT 5263 && attrs.height == WindowManager.LayoutParams.MATCH_PARENT; 5264 } 5265 5266 /** {@inheritDoc} */ 5267 @Override 5268 public int finishPostLayoutPolicyLw() { 5269 if (mWinShowWhenLocked != null && mTopFullscreenOpaqueWindowState != null && 5270 mWinShowWhenLocked.getAppToken() != mTopFullscreenOpaqueWindowState.getAppToken() 5271 && isKeyguardLocked()) { 5272 // A dialog is dismissing the keyguard. Put the wallpaper behind it and hide the 5273 // fullscreen window. 5274 // TODO: Make sure FLAG_SHOW_WALLPAPER is restored when dialog is dismissed. Or not. 5275 mWinShowWhenLocked.getAttrs().flags |= FLAG_SHOW_WALLPAPER; 5276 mTopFullscreenOpaqueWindowState.hideLw(false); 5277 mTopFullscreenOpaqueWindowState = mWinShowWhenLocked; 5278 } 5279 5280 int changes = 0; 5281 boolean topIsFullscreen = false; 5282 5283 final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null) 5284 ? mTopFullscreenOpaqueWindowState.getAttrs() 5285 : null; 5286 5287 // If we are not currently showing a dream then remember the current 5288 // lockscreen state. We will use this to determine whether the dream 5289 // started while the lockscreen was showing and remember this state 5290 // while the dream is showing. 5291 if (!mShowingDream) { 5292 mDreamingLockscreen = mShowingLockscreen; 5293 if (mDreamingSleepTokenNeeded) { 5294 mDreamingSleepTokenNeeded = false; 5295 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget(); 5296 } 5297 } else { 5298 if (!mDreamingSleepTokenNeeded) { 5299 mDreamingSleepTokenNeeded = true; 5300 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget(); 5301 } 5302 } 5303 5304 if (mStatusBar != null) { 5305 if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar 5306 + " forcefkg=" + mForceStatusBarFromKeyguard 5307 + " top=" + mTopFullscreenOpaqueWindowState); 5308 boolean shouldBeTransparent = mForceStatusBarTransparent 5309 && !mForceStatusBar 5310 && !mForceStatusBarFromKeyguard; 5311 if (!shouldBeTransparent) { 5312 mStatusBarController.setShowTransparent(false /* transparent */); 5313 } else if (!mStatusBar.isVisibleLw()) { 5314 mStatusBarController.setShowTransparent(true /* transparent */); 5315 } 5316 5317 WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs(); 5318 boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT 5319 && statusBarAttrs.width == MATCH_PARENT; 5320 if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent 5321 || statusBarExpanded) { 5322 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced"); 5323 if (mStatusBarController.setBarShowingLw(true)) { 5324 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5325 } 5326 // Maintain fullscreen layout until incoming animation is complete. 5327 topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw(); 5328 // Transient status bar on the lockscreen is not allowed 5329 if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) { 5330 mStatusBarController.updateVisibilityLw(false /*transientAllowed*/, 5331 mLastSystemUiFlags, mLastSystemUiFlags); 5332 } 5333 if (statusBarExpanded && mNavigationBar != null) { 5334 if (mNavigationBarController.setBarShowingLw(true)) { 5335 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5336 } 5337 } 5338 } else if (mTopFullscreenOpaqueWindowState != null) { 5339 final int fl = PolicyControl.getWindowFlags(null, lp); 5340 if (localLOGV) { 5341 Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() 5342 + " shown position: " 5343 + mTopFullscreenOpaqueWindowState.getShownPositionLw()); 5344 Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs() 5345 + " lp.flags=0x" + Integer.toHexString(fl)); 5346 } 5347 topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0 5348 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 5349 // The subtle difference between the window for mTopFullscreenOpaqueWindowState 5350 // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window 5351 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the 5352 // case though. 5353 if (mStatusBarController.isTransientShowing()) { 5354 if (mStatusBarController.setBarShowingLw(true)) { 5355 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5356 } 5357 } else if (topIsFullscreen 5358 && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID) 5359 && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) { 5360 if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar"); 5361 if (mStatusBarController.setBarShowingLw(false)) { 5362 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5363 } else { 5364 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding"); 5365 } 5366 } else { 5367 if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen"); 5368 if (mStatusBarController.setBarShowingLw(true)) { 5369 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5370 } 5371 } 5372 } 5373 } 5374 5375 if (mTopIsFullscreen != topIsFullscreen) { 5376 if (!topIsFullscreen) { 5377 // Force another layout when status bar becomes fully shown. 5378 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5379 } 5380 mTopIsFullscreen = topIsFullscreen; 5381 } 5382 5383 // Hide the key guard if a visible window explicitly specifies that it wants to be 5384 // displayed when the screen is locked. 5385 if (mKeyguardDelegate != null && mStatusBar != null) { 5386 if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard=" 5387 + mHideLockScreen); 5388 if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardSecure) { 5389 mKeyguardHidden = true; 5390 if (setKeyguardOccludedLw(true)) { 5391 changes |= FINISH_LAYOUT_REDO_LAYOUT 5392 | FINISH_LAYOUT_REDO_CONFIG 5393 | FINISH_LAYOUT_REDO_WALLPAPER; 5394 } 5395 if (mKeyguardDelegate.isShowing()) { 5396 mHandler.post(new Runnable() { 5397 @Override 5398 public void run() { 5399 mKeyguardDelegate.keyguardDone(false, false); 5400 } 5401 }); 5402 } 5403 } else if (mHideLockScreen) { 5404 mKeyguardHidden = true; 5405 mWinDismissingKeyguard = null; 5406 if (setKeyguardOccludedLw(true)) { 5407 changes |= FINISH_LAYOUT_REDO_LAYOUT 5408 | FINISH_LAYOUT_REDO_CONFIG 5409 | FINISH_LAYOUT_REDO_WALLPAPER; 5410 } 5411 } else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) { 5412 mKeyguardHidden = false; 5413 boolean willDismiss = false; 5414 if (mDismissKeyguard == DISMISS_KEYGUARD_START) { 5415 final boolean trusted = mKeyguardDelegate.isTrusted(); 5416 willDismiss = trusted && mKeyguardOccluded && mKeyguardDelegate != null 5417 && mKeyguardDelegate.isShowing(); 5418 if (willDismiss) { 5419 mCurrentlyDismissingKeyguard = true; 5420 } 5421 5422 // Only launch the next keyguard unlock window once per window. 5423 mHandler.post(() -> mKeyguardDelegate.dismiss( 5424 trusted /* allowWhileOccluded */)); 5425 } 5426 5427 // If we are currently dismissing Keyguard, there is no need to unocclude it. 5428 if (!mCurrentlyDismissingKeyguard) { 5429 if (setKeyguardOccludedLw(false)) { 5430 changes |= FINISH_LAYOUT_REDO_LAYOUT 5431 | FINISH_LAYOUT_REDO_CONFIG 5432 | FINISH_LAYOUT_REDO_WALLPAPER; 5433 } 5434 } 5435 } else { 5436 mWinDismissingKeyguard = null; 5437 mSecureDismissingKeyguard = false; 5438 mKeyguardHidden = false; 5439 if (setKeyguardOccludedLw(false)) { 5440 changes |= FINISH_LAYOUT_REDO_LAYOUT 5441 | FINISH_LAYOUT_REDO_CONFIG 5442 | FINISH_LAYOUT_REDO_WALLPAPER; 5443 } 5444 } 5445 } 5446 5447 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5448 // If the navigation bar has been hidden or shown, we need to do another 5449 // layout pass to update that window. 5450 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5451 } 5452 5453 // update since mAllowLockscreenWhenOn might have changed 5454 updateLockScreenTimeout(); 5455 return changes; 5456 } 5457 5458 /** 5459 * Updates the occluded state of the Keyguard. 5460 * 5461 * @return Whether the flags have changed and we have to redo the layout. 5462 */ 5463 private boolean setKeyguardOccludedLw(boolean isOccluded) { 5464 boolean wasOccluded = mKeyguardOccluded; 5465 boolean showing = mKeyguardDelegate.isShowing(); 5466 if (wasOccluded && !isOccluded && showing) { 5467 mKeyguardOccluded = false; 5468 mKeyguardDelegate.setOccluded(false, true /* animate */); 5469 mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD; 5470 if (!mKeyguardDelegate.hasLockscreenWallpaper()) { 5471 mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER; 5472 } 5473 Animation anim = AnimationUtils.loadAnimation(mContext, 5474 com.android.internal.R.anim.wallpaper_open_exit); 5475 mWindowManagerFuncs.overridePlayingAppAnimationsLw(anim); 5476 return true; 5477 } else if (!wasOccluded && isOccluded && showing) { 5478 mKeyguardOccluded = true; 5479 mKeyguardDelegate.setOccluded(true, false /* animate */); 5480 mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD; 5481 mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER; 5482 return true; 5483 } else { 5484 return false; 5485 } 5486 } 5487 5488 private void onKeyguardShowingStateChanged(boolean showing) { 5489 if (!showing) { 5490 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 5491 mCurrentlyDismissingKeyguard = false; 5492 } 5493 } 5494 } 5495 5496 private boolean isStatusBarKeyguard() { 5497 return mStatusBar != null 5498 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0; 5499 } 5500 5501 @Override 5502 public boolean allowAppAnimationsLw() { 5503 if (isStatusBarKeyguard() || mShowingDream) { 5504 // If keyguard or dreams is currently visible, no reason to animate behind it. 5505 return false; 5506 } 5507 return true; 5508 } 5509 5510 @Override 5511 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) { 5512 mFocusedWindow = newFocus; 5513 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5514 // If the navigation bar has been hidden or shown, we need to do another 5515 // layout pass to update that window. 5516 return FINISH_LAYOUT_REDO_LAYOUT; 5517 } 5518 return 0; 5519 } 5520 5521 /** {@inheritDoc} */ 5522 @Override 5523 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { 5524 // lid changed state 5525 final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED; 5526 if (newLidState == mLidState) { 5527 return; 5528 } 5529 5530 mLidState = newLidState; 5531 applyLidSwitchState(); 5532 updateRotation(true); 5533 5534 if (lidOpen) { 5535 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch, 5536 "android.policy:LID"); 5537 } else if (!mLidControlsSleep) { 5538 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 5539 } 5540 } 5541 5542 @Override 5543 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) { 5544 int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED; 5545 if (mCameraLensCoverState == lensCoverState) { 5546 return; 5547 } 5548 if (mCameraLensCoverState == CAMERA_LENS_COVERED && 5549 lensCoverState == CAMERA_LENS_UNCOVERED) { 5550 Intent intent; 5551 final boolean keyguardActive = mKeyguardDelegate == null ? false : 5552 mKeyguardDelegate.isShowing(); 5553 if (keyguardActive) { 5554 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE); 5555 } else { 5556 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); 5557 } 5558 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens, 5559 "android.policy:CAMERA_COVER"); 5560 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); 5561 } 5562 mCameraLensCoverState = lensCoverState; 5563 } 5564 5565 void setHdmiPlugged(boolean plugged) { 5566 if (mHdmiPlugged != plugged) { 5567 mHdmiPlugged = plugged; 5568 updateRotation(true, true); 5569 Intent intent = new Intent(ACTION_HDMI_PLUGGED); 5570 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5571 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged); 5572 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 5573 } 5574 } 5575 5576 void initializeHdmiState() { 5577 boolean plugged = false; 5578 // watch for HDMI plug messages if the hdmi switch exists 5579 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) { 5580 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi"); 5581 5582 final String filename = "/sys/class/switch/hdmi/state"; 5583 FileReader reader = null; 5584 try { 5585 reader = new FileReader(filename); 5586 char[] buf = new char[15]; 5587 int n = reader.read(buf); 5588 if (n > 1) { 5589 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1)); 5590 } 5591 } catch (IOException ex) { 5592 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5593 } catch (NumberFormatException ex) { 5594 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5595 } finally { 5596 if (reader != null) { 5597 try { 5598 reader.close(); 5599 } catch (IOException ex) { 5600 } 5601 } 5602 } 5603 } 5604 // This dance forces the code in setHdmiPlugged to run. 5605 // Always do this so the sticky intent is stuck (to false) if there is no hdmi. 5606 mHdmiPlugged = !plugged; 5607 setHdmiPlugged(!mHdmiPlugged); 5608 } 5609 5610 final Object mScreenshotLock = new Object(); 5611 ServiceConnection mScreenshotConnection = null; 5612 5613 final Runnable mScreenshotTimeout = new Runnable() { 5614 @Override public void run() { 5615 synchronized (mScreenshotLock) { 5616 if (mScreenshotConnection != null) { 5617 mContext.unbindService(mScreenshotConnection); 5618 mScreenshotConnection = null; 5619 notifyScreenshotError(); 5620 } 5621 } 5622 } 5623 }; 5624 5625 // Assume this is called from the Handler thread. 5626 private void takeScreenshot(final int screenshotType) { 5627 synchronized (mScreenshotLock) { 5628 if (mScreenshotConnection != null) { 5629 return; 5630 } 5631 final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE, 5632 SYSUI_SCREENSHOT_SERVICE); 5633 final Intent serviceIntent = new Intent(); 5634 serviceIntent.setComponent(serviceComponent); 5635 ServiceConnection conn = new ServiceConnection() { 5636 @Override 5637 public void onServiceConnected(ComponentName name, IBinder service) { 5638 synchronized (mScreenshotLock) { 5639 if (mScreenshotConnection != this) { 5640 return; 5641 } 5642 Messenger messenger = new Messenger(service); 5643 Message msg = Message.obtain(null, screenshotType); 5644 final ServiceConnection myConn = this; 5645 Handler h = new Handler(mHandler.getLooper()) { 5646 @Override 5647 public void handleMessage(Message msg) { 5648 synchronized (mScreenshotLock) { 5649 if (mScreenshotConnection == myConn) { 5650 mContext.unbindService(mScreenshotConnection); 5651 mScreenshotConnection = null; 5652 mHandler.removeCallbacks(mScreenshotTimeout); 5653 } 5654 } 5655 } 5656 }; 5657 msg.replyTo = new Messenger(h); 5658 msg.arg1 = msg.arg2 = 0; 5659 if (mStatusBar != null && mStatusBar.isVisibleLw()) 5660 msg.arg1 = 1; 5661 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) 5662 msg.arg2 = 1; 5663 try { 5664 messenger.send(msg); 5665 } catch (RemoteException e) { 5666 } 5667 } 5668 } 5669 5670 @Override 5671 public void onServiceDisconnected(ComponentName name) { 5672 synchronized (mScreenshotLock) { 5673 if (mScreenshotConnection != null) { 5674 mContext.unbindService(mScreenshotConnection); 5675 mScreenshotConnection = null; 5676 mHandler.removeCallbacks(mScreenshotTimeout); 5677 notifyScreenshotError(); 5678 } 5679 } 5680 } 5681 }; 5682 if (mContext.bindServiceAsUser(serviceIntent, conn, 5683 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, 5684 UserHandle.CURRENT)) { 5685 mScreenshotConnection = conn; 5686 mHandler.postDelayed(mScreenshotTimeout, 10000); 5687 } 5688 } 5689 } 5690 5691 /** 5692 * Notifies the screenshot service to show an error. 5693 */ 5694 private void notifyScreenshotError() { 5695 // If the service process is killed, then ask it to clean up after itself 5696 final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE, 5697 SYSUI_SCREENSHOT_ERROR_RECEIVER); 5698 Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT); 5699 errorIntent.setComponent(errorComponent); 5700 errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | 5701 Intent.FLAG_RECEIVER_FOREGROUND); 5702 mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT); 5703 } 5704 5705 /** {@inheritDoc} */ 5706 @Override 5707 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { 5708 if (!mSystemBooted) { 5709 // If we have not yet booted, don't let key events do anything. 5710 return 0; 5711 } 5712 5713 final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0; 5714 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; 5715 final boolean canceled = event.isCanceled(); 5716 final int keyCode = event.getKeyCode(); 5717 5718 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; 5719 5720 // If screen is off then we treat the case where the keyguard is open but hidden 5721 // the same as if it were open and in front. 5722 // This will prevent any keys other than the power button from waking the screen 5723 // when the keyguard is hidden by another activity. 5724 final boolean keyguardActive = (mKeyguardDelegate == null ? false : 5725 (interactive ? 5726 isKeyguardShowingAndNotOccluded() : 5727 mKeyguardDelegate.isShowing())); 5728 5729 if (DEBUG_INPUT) { 5730 Log.d(TAG, "interceptKeyTq keycode=" + keyCode 5731 + " interactive=" + interactive + " keyguardActive=" + keyguardActive 5732 + " policyFlags=" + Integer.toHexString(policyFlags)); 5733 } 5734 5735 // Basic policy based on interactive state. 5736 int result; 5737 boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0 5738 || event.isWakeKey(); 5739 if (interactive || (isInjected && !isWakeKey)) { 5740 // When the device is interactive or the key is injected pass the 5741 // key to the application. 5742 result = ACTION_PASS_TO_USER; 5743 isWakeKey = false; 5744 5745 if (interactive) { 5746 // If the screen is awake, but the button pressed was the one that woke the device 5747 // then don't pass it to the application 5748 if (keyCode == mPendingWakeKey && !down) { 5749 result = 0; 5750 } 5751 // Reset the pending key 5752 mPendingWakeKey = PENDING_KEY_NULL; 5753 } 5754 } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) { 5755 // If we're currently dozing with the screen on and the keyguard showing, pass the key 5756 // to the application but preserve its wake key status to make sure we still move 5757 // from dozing to fully interactive if we would normally go from off to fully 5758 // interactive. 5759 result = ACTION_PASS_TO_USER; 5760 // Since we're dispatching the input, reset the pending key 5761 mPendingWakeKey = PENDING_KEY_NULL; 5762 } else { 5763 // When the screen is off and the key is not injected, determine whether 5764 // to wake the device but don't pass the key to the application. 5765 result = 0; 5766 if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) { 5767 isWakeKey = false; 5768 } 5769 // Cache the wake key on down event so we can also avoid sending the up event to the app 5770 if (isWakeKey && down) { 5771 mPendingWakeKey = keyCode; 5772 } 5773 } 5774 5775 // If the key would be handled globally, just return the result, don't worry about special 5776 // key processing. 5777 if (isValidGlobalKey(keyCode) 5778 && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) { 5779 if (isWakeKey) { 5780 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 5781 } 5782 return result; 5783 } 5784 5785 boolean useHapticFeedback = down 5786 && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0 5787 && event.getRepeatCount() == 0; 5788 5789 // Handle special keys. 5790 switch (keyCode) { 5791 case KeyEvent.KEYCODE_BACK: { 5792 if (down) { 5793 interceptBackKeyDown(); 5794 } else { 5795 boolean handled = interceptBackKeyUp(event); 5796 5797 // Don't pass back press to app if we've already handled it via long press 5798 if (handled) { 5799 result &= ~ACTION_PASS_TO_USER; 5800 } 5801 } 5802 break; 5803 } 5804 5805 case KeyEvent.KEYCODE_VOLUME_DOWN: 5806 case KeyEvent.KEYCODE_VOLUME_UP: 5807 case KeyEvent.KEYCODE_VOLUME_MUTE: { 5808 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { 5809 if (down) { 5810 if (interactive && !mScreenshotChordVolumeDownKeyTriggered 5811 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5812 mScreenshotChordVolumeDownKeyTriggered = true; 5813 mScreenshotChordVolumeDownKeyTime = event.getDownTime(); 5814 mScreenshotChordVolumeDownKeyConsumed = false; 5815 cancelPendingPowerKeyAction(); 5816 interceptScreenshotChord(); 5817 } 5818 } else { 5819 mScreenshotChordVolumeDownKeyTriggered = false; 5820 cancelPendingScreenshotChordAction(); 5821 } 5822 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 5823 if (down) { 5824 if (interactive && !mScreenshotChordVolumeUpKeyTriggered 5825 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5826 mScreenshotChordVolumeUpKeyTriggered = true; 5827 cancelPendingPowerKeyAction(); 5828 cancelPendingScreenshotChordAction(); 5829 } 5830 } else { 5831 mScreenshotChordVolumeUpKeyTriggered = false; 5832 cancelPendingScreenshotChordAction(); 5833 } 5834 } 5835 if (down) { 5836 TelecomManager telecomManager = getTelecommService(); 5837 if (telecomManager != null) { 5838 if (telecomManager.isRinging()) { 5839 // If an incoming call is ringing, either VOLUME key means 5840 // "silence ringer". We handle these keys here, rather than 5841 // in the InCallScreen, to make sure we'll respond to them 5842 // even if the InCallScreen hasn't come to the foreground yet. 5843 // Look for the DOWN event here, to agree with the "fallback" 5844 // behavior in the InCallScreen. 5845 Log.i(TAG, "interceptKeyBeforeQueueing:" 5846 + " VOLUME key-down while ringing: Silence ringer!"); 5847 5848 // Silence the ringer. (It's safe to call this 5849 // even if the ringer has already been silenced.) 5850 telecomManager.silenceRinger(); 5851 5852 // And *don't* pass this key thru to the current activity 5853 // (which is probably the InCallScreen.) 5854 result &= ~ACTION_PASS_TO_USER; 5855 break; 5856 } 5857 if (telecomManager.isInCall() 5858 && (result & ACTION_PASS_TO_USER) == 0) { 5859 // If we are in call but we decided not to pass the key to 5860 // the application, just pass it to the session service. 5861 5862 MediaSessionLegacyHelper.getHelper(mContext) 5863 .sendVolumeKeyEvent(event, false); 5864 break; 5865 } 5866 } 5867 } 5868 if (mUseTvRouting) { 5869 // On TVs, defer special key handlings to 5870 // {@link interceptKeyBeforeDispatching()}. 5871 result |= ACTION_PASS_TO_USER; 5872 } else if ((result & ACTION_PASS_TO_USER) == 0) { 5873 // If we aren't passing to the user and no one else 5874 // handled it send it to the session manager to 5875 // figure out. 5876 MediaSessionLegacyHelper.getHelper(mContext) 5877 .sendVolumeKeyEvent(event, true); 5878 } 5879 break; 5880 } 5881 5882 case KeyEvent.KEYCODE_ENDCALL: { 5883 result &= ~ACTION_PASS_TO_USER; 5884 if (down) { 5885 TelecomManager telecomManager = getTelecommService(); 5886 boolean hungUp = false; 5887 if (telecomManager != null) { 5888 hungUp = telecomManager.endCall(); 5889 } 5890 if (interactive && !hungUp) { 5891 mEndCallKeyHandled = false; 5892 mHandler.postDelayed(mEndCallLongPress, 5893 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 5894 } else { 5895 mEndCallKeyHandled = true; 5896 } 5897 } else { 5898 if (!mEndCallKeyHandled) { 5899 mHandler.removeCallbacks(mEndCallLongPress); 5900 if (!canceled) { 5901 if ((mEndcallBehavior 5902 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) { 5903 if (goHome()) { 5904 break; 5905 } 5906 } 5907 if ((mEndcallBehavior 5908 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) { 5909 mPowerManager.goToSleep(event.getEventTime(), 5910 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); 5911 isWakeKey = false; 5912 } 5913 } 5914 } 5915 } 5916 break; 5917 } 5918 5919 case KeyEvent.KEYCODE_POWER: { 5920 result &= ~ACTION_PASS_TO_USER; 5921 isWakeKey = false; // wake-up will be handled separately 5922 if (down) { 5923 interceptPowerKeyDown(event, interactive); 5924 } else { 5925 interceptPowerKeyUp(event, interactive, canceled); 5926 } 5927 break; 5928 } 5929 5930 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN: 5931 // fall through 5932 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP: 5933 // fall through 5934 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT: 5935 // fall through 5936 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: { 5937 result &= ~ACTION_PASS_TO_USER; 5938 interceptSystemNavigationKey(event); 5939 break; 5940 } 5941 5942 case KeyEvent.KEYCODE_SLEEP: { 5943 result &= ~ACTION_PASS_TO_USER; 5944 isWakeKey = false; 5945 if (!mPowerManager.isInteractive()) { 5946 useHapticFeedback = false; // suppress feedback if already non-interactive 5947 } 5948 if (down) { 5949 sleepPress(event.getEventTime()); 5950 } else { 5951 sleepRelease(event.getEventTime()); 5952 } 5953 break; 5954 } 5955 5956 case KeyEvent.KEYCODE_SOFT_SLEEP: { 5957 result &= ~ACTION_PASS_TO_USER; 5958 isWakeKey = false; 5959 if (!down) { 5960 mPowerManagerInternal.setUserInactiveOverrideFromWindowManager(); 5961 } 5962 break; 5963 } 5964 5965 case KeyEvent.KEYCODE_WAKEUP: { 5966 result &= ~ACTION_PASS_TO_USER; 5967 isWakeKey = true; 5968 break; 5969 } 5970 5971 case KeyEvent.KEYCODE_MEDIA_PLAY: 5972 case KeyEvent.KEYCODE_MEDIA_PAUSE: 5973 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 5974 case KeyEvent.KEYCODE_HEADSETHOOK: 5975 case KeyEvent.KEYCODE_MUTE: 5976 case KeyEvent.KEYCODE_MEDIA_STOP: 5977 case KeyEvent.KEYCODE_MEDIA_NEXT: 5978 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 5979 case KeyEvent.KEYCODE_MEDIA_REWIND: 5980 case KeyEvent.KEYCODE_MEDIA_RECORD: 5981 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 5982 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { 5983 if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) { 5984 // If the global session is active pass all media keys to it 5985 // instead of the active window. 5986 result &= ~ACTION_PASS_TO_USER; 5987 } 5988 if ((result & ACTION_PASS_TO_USER) == 0) { 5989 // Only do this if we would otherwise not pass it to the user. In that 5990 // case, the PhoneWindow class will do the same thing, except it will 5991 // only do it if the showing app doesn't process the key on its own. 5992 // Note that we need to make a copy of the key event here because the 5993 // original key event will be recycled when we return. 5994 mBroadcastWakeLock.acquire(); 5995 Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK, 5996 new KeyEvent(event)); 5997 msg.setAsynchronous(true); 5998 msg.sendToTarget(); 5999 } 6000 break; 6001 } 6002 6003 case KeyEvent.KEYCODE_CALL: { 6004 if (down) { 6005 TelecomManager telecomManager = getTelecommService(); 6006 if (telecomManager != null) { 6007 if (telecomManager.isRinging()) { 6008 Log.i(TAG, "interceptKeyBeforeQueueing:" 6009 + " CALL key-down while ringing: Answer the call!"); 6010 telecomManager.acceptRingingCall(); 6011 6012 // And *don't* pass this key thru to the current activity 6013 // (which is presumably the InCallScreen.) 6014 result &= ~ACTION_PASS_TO_USER; 6015 } 6016 } 6017 } 6018 break; 6019 } 6020 case KeyEvent.KEYCODE_VOICE_ASSIST: { 6021 // Only do this if we would otherwise not pass it to the user. In that case, 6022 // interceptKeyBeforeDispatching would apply a similar but different policy in 6023 // order to invoke voice assist actions. Note that we need to make a copy of the 6024 // key event here because the original key event will be recycled when we return. 6025 if ((result & ACTION_PASS_TO_USER) == 0 && !down) { 6026 mBroadcastWakeLock.acquire(); 6027 Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK, 6028 keyguardActive ? 1 : 0, 0); 6029 msg.setAsynchronous(true); 6030 msg.sendToTarget(); 6031 } 6032 break; 6033 } 6034 case KeyEvent.KEYCODE_WINDOW: { 6035 if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) { 6036 if (mTvPictureInPictureVisible) { 6037 // Consumes the key only if picture-in-picture is visible 6038 // to show picture-in-picture control menu. 6039 // This gives a chance to the foreground activity 6040 // to customize PIP key behavior. 6041 if (!down) { 6042 showTvPictureInPictureMenu(event); 6043 } 6044 result &= ~ACTION_PASS_TO_USER; 6045 } 6046 } 6047 break; 6048 } 6049 } 6050 6051 if (useHapticFeedback) { 6052 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); 6053 } 6054 6055 if (isWakeKey) { 6056 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 6057 } 6058 6059 return result; 6060 } 6061 6062 /** 6063 * Handle statusbar expansion events. 6064 * @param event 6065 */ 6066 private void interceptSystemNavigationKey(KeyEvent event) { 6067 if (event.getAction() == KeyEvent.ACTION_UP && areSystemNavigationKeysEnabled()) { 6068 IStatusBarService sbar = getStatusBarService(); 6069 if (sbar != null) { 6070 try { 6071 sbar.handleSystemNavigationKey(event.getKeyCode()); 6072 } catch (RemoteException e1) { 6073 // oops, no statusbar. Ignore event. 6074 } 6075 } 6076 } 6077 } 6078 6079 /** 6080 * Returns true if the key can have global actions attached to it. 6081 * We reserve all power management keys for the system since they require 6082 * very careful handling. 6083 */ 6084 private static boolean isValidGlobalKey(int keyCode) { 6085 switch (keyCode) { 6086 case KeyEvent.KEYCODE_POWER: 6087 case KeyEvent.KEYCODE_WAKEUP: 6088 case KeyEvent.KEYCODE_SLEEP: 6089 return false; 6090 default: 6091 return true; 6092 } 6093 } 6094 6095 /** 6096 * When the screen is off we ignore some keys that might otherwise typically 6097 * be considered wake keys. We filter them out here. 6098 * 6099 * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it 6100 * is always considered a wake key. 6101 */ 6102 private boolean isWakeKeyWhenScreenOff(int keyCode) { 6103 switch (keyCode) { 6104 // ignore volume keys unless docked 6105 case KeyEvent.KEYCODE_VOLUME_UP: 6106 case KeyEvent.KEYCODE_VOLUME_DOWN: 6107 case KeyEvent.KEYCODE_VOLUME_MUTE: 6108 return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED; 6109 6110 // ignore media and camera keys 6111 case KeyEvent.KEYCODE_MUTE: 6112 case KeyEvent.KEYCODE_HEADSETHOOK: 6113 case KeyEvent.KEYCODE_MEDIA_PLAY: 6114 case KeyEvent.KEYCODE_MEDIA_PAUSE: 6115 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 6116 case KeyEvent.KEYCODE_MEDIA_STOP: 6117 case KeyEvent.KEYCODE_MEDIA_NEXT: 6118 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 6119 case KeyEvent.KEYCODE_MEDIA_REWIND: 6120 case KeyEvent.KEYCODE_MEDIA_RECORD: 6121 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 6122 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: 6123 case KeyEvent.KEYCODE_CAMERA: 6124 return false; 6125 } 6126 return true; 6127 } 6128 6129 6130 /** {@inheritDoc} */ 6131 @Override 6132 public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) { 6133 if ((policyFlags & FLAG_WAKE) != 0) { 6134 if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion, 6135 "android.policy:MOTION")) { 6136 return 0; 6137 } 6138 } 6139 6140 if (shouldDispatchInputWhenNonInteractive(null)) { 6141 return ACTION_PASS_TO_USER; 6142 } 6143 6144 // If we have not passed the action up and we are in theater mode without dreaming, 6145 // there will be no dream to intercept the touch and wake into ambient. The device should 6146 // wake up in this case. 6147 if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) { 6148 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming, 6149 "android.policy:MOTION"); 6150 } 6151 6152 return 0; 6153 } 6154 6155 private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) { 6156 final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF); 6157 6158 if (displayOff && !mHasFeatureWatch) { 6159 return false; 6160 } 6161 6162 // Send events to keyguard while the screen is on and it's showing. 6163 if (isKeyguardShowingAndNotOccluded() && !displayOff) { 6164 return true; 6165 } 6166 6167 // Watches handle BACK specially 6168 if (mHasFeatureWatch 6169 && event != null 6170 && (event.getKeyCode() == KeyEvent.KEYCODE_BACK 6171 || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) { 6172 return false; 6173 } 6174 6175 // Send events to a dozing dream even if the screen is off since the dream 6176 // is in control of the state of the screen. 6177 IDreamManager dreamManager = getDreamManager(); 6178 6179 try { 6180 if (dreamManager != null && dreamManager.isDreaming()) { 6181 return true; 6182 } 6183 } catch (RemoteException e) { 6184 Slog.e(TAG, "RemoteException when checking if dreaming", e); 6185 } 6186 6187 // Otherwise, consume events since the user can't see what is being 6188 // interacted with. 6189 return false; 6190 } 6191 6192 private void dispatchDirectAudioEvent(KeyEvent event) { 6193 if (event.getAction() != KeyEvent.ACTION_DOWN) { 6194 return; 6195 } 6196 int keyCode = event.getKeyCode(); 6197 int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND 6198 | AudioManager.FLAG_FROM_KEY; 6199 String pkgName = mContext.getOpPackageName(); 6200 switch (keyCode) { 6201 case KeyEvent.KEYCODE_VOLUME_UP: 6202 try { 6203 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE, 6204 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6205 } catch (RemoteException e) { 6206 Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e); 6207 } 6208 break; 6209 case KeyEvent.KEYCODE_VOLUME_DOWN: 6210 try { 6211 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER, 6212 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6213 } catch (RemoteException e) { 6214 Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e); 6215 } 6216 break; 6217 case KeyEvent.KEYCODE_VOLUME_MUTE: 6218 try { 6219 if (event.getRepeatCount() == 0) { 6220 getAudioService().adjustSuggestedStreamVolume( 6221 AudioManager.ADJUST_TOGGLE_MUTE, 6222 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6223 } 6224 } catch (RemoteException e) { 6225 Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e); 6226 } 6227 break; 6228 } 6229 } 6230 6231 void dispatchMediaKeyWithWakeLock(KeyEvent event) { 6232 if (DEBUG_INPUT) { 6233 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event); 6234 } 6235 6236 if (mHavePendingMediaKeyRepeatWithWakeLock) { 6237 if (DEBUG_INPUT) { 6238 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat"); 6239 } 6240 6241 mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK); 6242 mHavePendingMediaKeyRepeatWithWakeLock = false; 6243 mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock 6244 } 6245 6246 dispatchMediaKeyWithWakeLockToAudioService(event); 6247 6248 if (event.getAction() == KeyEvent.ACTION_DOWN 6249 && event.getRepeatCount() == 0) { 6250 mHavePendingMediaKeyRepeatWithWakeLock = true; 6251 6252 Message msg = mHandler.obtainMessage( 6253 MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event); 6254 msg.setAsynchronous(true); 6255 mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout()); 6256 } else { 6257 mBroadcastWakeLock.release(); 6258 } 6259 } 6260 6261 void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) { 6262 mHavePendingMediaKeyRepeatWithWakeLock = false; 6263 6264 KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event, 6265 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS); 6266 if (DEBUG_INPUT) { 6267 Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent); 6268 } 6269 6270 dispatchMediaKeyWithWakeLockToAudioService(repeatEvent); 6271 mBroadcastWakeLock.release(); 6272 } 6273 6274 void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) { 6275 if (ActivityManagerNative.isSystemReady()) { 6276 MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true); 6277 } 6278 } 6279 6280 void launchVoiceAssistWithWakeLock(boolean keyguardActive) { 6281 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface( 6282 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); 6283 if (dic != null) { 6284 try { 6285 dic.exitIdle("voice-search"); 6286 } catch (RemoteException e) { 6287 } 6288 } 6289 Intent voiceIntent = 6290 new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); 6291 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive); 6292 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF); 6293 mBroadcastWakeLock.release(); 6294 } 6295 6296 BroadcastReceiver mDockReceiver = new BroadcastReceiver() { 6297 @Override 6298 public void onReceive(Context context, Intent intent) { 6299 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) { 6300 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 6301 Intent.EXTRA_DOCK_STATE_UNDOCKED); 6302 } else { 6303 try { 6304 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface( 6305 ServiceManager.getService(Context.UI_MODE_SERVICE)); 6306 mUiMode = uiModeService.getCurrentModeType(); 6307 } catch (RemoteException e) { 6308 } 6309 } 6310 updateRotation(true); 6311 synchronized (mLock) { 6312 updateOrientationListenerLp(); 6313 } 6314 } 6315 }; 6316 6317 BroadcastReceiver mDreamReceiver = new BroadcastReceiver() { 6318 @Override 6319 public void onReceive(Context context, Intent intent) { 6320 if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) { 6321 if (mKeyguardDelegate != null) { 6322 mKeyguardDelegate.onDreamingStarted(); 6323 } 6324 } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) { 6325 if (mKeyguardDelegate != null) { 6326 mKeyguardDelegate.onDreamingStopped(); 6327 } 6328 } 6329 } 6330 }; 6331 6332 BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() { 6333 @Override 6334 public void onReceive(Context context, Intent intent) { 6335 if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) { 6336 // tickle the settings observer: this first ensures that we're 6337 // observing the relevant settings for the newly-active user, 6338 // and then updates our own bookkeeping based on the now- 6339 // current user. 6340 mSettingsObserver.onChange(false); 6341 6342 // force a re-application of focused window sysui visibility. 6343 // the window may never have been shown for this user 6344 // e.g. the keyguard when going through the new-user setup flow 6345 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6346 mLastSystemUiFlags = 0; 6347 updateSystemUiVisibilityLw(); 6348 } 6349 } 6350 } 6351 }; 6352 6353 private final Runnable mHiddenNavPanic = new Runnable() { 6354 @Override 6355 public void run() { 6356 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6357 if (!isUserSetupComplete()) { 6358 // Swipe-up for navigation bar is disabled during setup 6359 return; 6360 } 6361 mPendingPanicGestureUptime = SystemClock.uptimeMillis(); 6362 if (!isNavBarEmpty(mLastSystemUiFlags)) { 6363 mNavigationBarController.showTransient(); 6364 } 6365 } 6366 } 6367 }; 6368 6369 private void requestTransientBars(WindowState swipeTarget) { 6370 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6371 if (!isUserSetupComplete()) { 6372 // Swipe-up for navigation bar is disabled during setup 6373 return; 6374 } 6375 boolean sb = mStatusBarController.checkShowTransientBarLw(); 6376 boolean nb = mNavigationBarController.checkShowTransientBarLw() 6377 && !isNavBarEmpty(mLastSystemUiFlags); 6378 if (sb || nb) { 6379 // Don't show status bar when swiping on already visible navigation bar 6380 if (!nb && swipeTarget == mNavigationBar) { 6381 if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target"); 6382 return; 6383 } 6384 if (sb) mStatusBarController.showTransient(); 6385 if (nb) mNavigationBarController.showTransient(); 6386 mImmersiveModeConfirmation.confirmCurrentPrompt(); 6387 updateSystemUiVisibilityLw(); 6388 } 6389 } 6390 } 6391 6392 // Called on the PowerManager's Notifier thread. 6393 @Override 6394 public void startedGoingToSleep(int why) { 6395 if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")"); 6396 mCameraGestureTriggeredDuringGoingToSleep = false; 6397 mGoingToSleep = true; 6398 if (mKeyguardDelegate != null) { 6399 mKeyguardDelegate.onStartedGoingToSleep(why); 6400 } 6401 } 6402 6403 // Called on the PowerManager's Notifier thread. 6404 @Override 6405 public void finishedGoingToSleep(int why) { 6406 EventLog.writeEvent(70000, 0); 6407 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")"); 6408 MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000); 6409 6410 mGoingToSleep = false; 6411 6412 // We must get this work done here because the power manager will drop 6413 // the wake lock and let the system suspend once this function returns. 6414 synchronized (mLock) { 6415 mAwake = false; 6416 updateWakeGestureListenerLp(); 6417 updateOrientationListenerLp(); 6418 updateLockScreenTimeout(); 6419 } 6420 if (mKeyguardDelegate != null) { 6421 mKeyguardDelegate.onFinishedGoingToSleep(why, 6422 mCameraGestureTriggeredDuringGoingToSleep); 6423 } 6424 mCameraGestureTriggeredDuringGoingToSleep = false; 6425 } 6426 6427 // Called on the PowerManager's Notifier thread. 6428 @Override 6429 public void startedWakingUp() { 6430 EventLog.writeEvent(70000, 1); 6431 if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up..."); 6432 6433 // Since goToSleep performs these functions synchronously, we must 6434 // do the same here. We cannot post this work to a handler because 6435 // that might cause it to become reordered with respect to what 6436 // may happen in a future call to goToSleep. 6437 synchronized (mLock) { 6438 mAwake = true; 6439 6440 updateWakeGestureListenerLp(); 6441 updateOrientationListenerLp(); 6442 updateLockScreenTimeout(); 6443 } 6444 6445 if (mKeyguardDelegate != null) { 6446 mKeyguardDelegate.onStartedWakingUp(); 6447 } 6448 } 6449 6450 // Called on the PowerManager's Notifier thread. 6451 @Override 6452 public void finishedWakingUp() { 6453 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up..."); 6454 } 6455 6456 private void wakeUpFromPowerKey(long eventTime) { 6457 wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER"); 6458 } 6459 6460 private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) { 6461 final boolean theaterModeEnabled = isTheaterModeEnabled(); 6462 if (!wakeInTheaterMode && theaterModeEnabled) { 6463 return false; 6464 } 6465 6466 if (theaterModeEnabled) { 6467 Settings.Global.putInt(mContext.getContentResolver(), 6468 Settings.Global.THEATER_MODE_ON, 0); 6469 } 6470 6471 mPowerManager.wakeUp(wakeTime, reason); 6472 return true; 6473 } 6474 6475 private void finishKeyguardDrawn() { 6476 synchronized (mLock) { 6477 if (!mScreenOnEarly || mKeyguardDrawComplete) { 6478 return; // We are not awake yet or we have already informed of this event. 6479 } 6480 6481 mKeyguardDrawComplete = true; 6482 if (mKeyguardDelegate != null) { 6483 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6484 } 6485 mWindowManagerDrawComplete = false; 6486 } 6487 6488 // ... eventually calls finishWindowsDrawn which will finalize our screen turn on 6489 // as well as enabling the orientation change logic/sensor. 6490 mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback, 6491 WAITING_FOR_DRAWN_TIMEOUT); 6492 } 6493 6494 // Called on the DisplayManager's DisplayPowerController thread. 6495 @Override 6496 public void screenTurnedOff() { 6497 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off..."); 6498 6499 updateScreenOffSleepToken(true); 6500 synchronized (mLock) { 6501 mScreenOnEarly = false; 6502 mScreenOnFully = false; 6503 mKeyguardDrawComplete = false; 6504 mWindowManagerDrawComplete = false; 6505 mScreenOnListener = null; 6506 updateOrientationListenerLp(); 6507 6508 if (mKeyguardDelegate != null) { 6509 mKeyguardDelegate.onScreenTurnedOff(); 6510 } 6511 } 6512 } 6513 6514 // Called on the DisplayManager's DisplayPowerController thread. 6515 @Override 6516 public void screenTurningOn(final ScreenOnListener screenOnListener) { 6517 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on..."); 6518 6519 updateScreenOffSleepToken(false); 6520 synchronized (mLock) { 6521 mScreenOnEarly = true; 6522 mScreenOnFully = false; 6523 mKeyguardDrawComplete = false; 6524 mWindowManagerDrawComplete = false; 6525 mScreenOnListener = screenOnListener; 6526 6527 if (mKeyguardDelegate != null) { 6528 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6529 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000); 6530 mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback); 6531 } else { 6532 if (DEBUG_WAKEUP) Slog.d(TAG, 6533 "null mKeyguardDelegate: setting mKeyguardDrawComplete."); 6534 finishKeyguardDrawn(); 6535 } 6536 } 6537 } 6538 6539 // Called on the DisplayManager's DisplayPowerController thread. 6540 @Override 6541 public void screenTurnedOn() { 6542 synchronized (mLock) { 6543 if (mKeyguardDelegate != null) { 6544 mKeyguardDelegate.onScreenTurnedOn(); 6545 } 6546 } 6547 } 6548 6549 private void finishWindowsDrawn() { 6550 synchronized (mLock) { 6551 if (!mScreenOnEarly || mWindowManagerDrawComplete) { 6552 return; // Screen is not turned on or we did already handle this case earlier. 6553 } 6554 6555 mWindowManagerDrawComplete = true; 6556 } 6557 6558 finishScreenTurningOn(); 6559 } 6560 6561 private void finishScreenTurningOn() { 6562 synchronized (mLock) { 6563 // We have just finished drawing screen content. Since the orientation listener 6564 // gets only installed when all windows are drawn, we try to install it again. 6565 updateOrientationListenerLp(); 6566 } 6567 final ScreenOnListener listener; 6568 final boolean enableScreen; 6569 synchronized (mLock) { 6570 if (DEBUG_WAKEUP) Slog.d(TAG, 6571 "finishScreenTurningOn: mAwake=" + mAwake 6572 + ", mScreenOnEarly=" + mScreenOnEarly 6573 + ", mScreenOnFully=" + mScreenOnFully 6574 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete 6575 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete); 6576 6577 if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete 6578 || (mAwake && !mKeyguardDrawComplete)) { 6579 return; // spurious or not ready yet 6580 } 6581 6582 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on..."); 6583 listener = mScreenOnListener; 6584 mScreenOnListener = null; 6585 mScreenOnFully = true; 6586 6587 // Remember the first time we draw the keyguard so we know when we're done with 6588 // the main part of booting and can enable the screen and hide boot messages. 6589 if (!mKeyguardDrawnOnce && mAwake) { 6590 mKeyguardDrawnOnce = true; 6591 enableScreen = true; 6592 if (mBootMessageNeedsHiding) { 6593 mBootMessageNeedsHiding = false; 6594 hideBootMessages(); 6595 } 6596 } else { 6597 enableScreen = false; 6598 } 6599 } 6600 6601 if (listener != null) { 6602 listener.onScreenOn(); 6603 } 6604 6605 if (enableScreen) { 6606 try { 6607 mWindowManager.enableScreenIfNeeded(); 6608 } catch (RemoteException unhandled) { 6609 } 6610 } 6611 } 6612 6613 private void handleHideBootMessage() { 6614 synchronized (mLock) { 6615 if (!mKeyguardDrawnOnce) { 6616 mBootMessageNeedsHiding = true; 6617 return; // keyguard hasn't drawn the first time yet, not done booting 6618 } 6619 } 6620 6621 if (mBootMsgDialog != null) { 6622 if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing"); 6623 mBootMsgDialog.dismiss(); 6624 mBootMsgDialog = null; 6625 } 6626 } 6627 6628 @Override 6629 public boolean isScreenOn() { 6630 return mScreenOnFully; 6631 } 6632 6633 /** {@inheritDoc} */ 6634 @Override 6635 public void enableKeyguard(boolean enabled) { 6636 if (mKeyguardDelegate != null) { 6637 mKeyguardDelegate.setKeyguardEnabled(enabled); 6638 } 6639 } 6640 6641 /** {@inheritDoc} */ 6642 @Override 6643 public void exitKeyguardSecurely(OnKeyguardExitResult callback) { 6644 if (mKeyguardDelegate != null) { 6645 mKeyguardDelegate.verifyUnlock(callback); 6646 } 6647 } 6648 6649 private boolean isKeyguardShowingAndNotOccluded() { 6650 if (mKeyguardDelegate == null) return false; 6651 return mKeyguardDelegate.isShowing() && !mKeyguardOccluded; 6652 } 6653 6654 /** {@inheritDoc} */ 6655 @Override 6656 public boolean isKeyguardLocked() { 6657 return keyguardOn(); 6658 } 6659 6660 /** {@inheritDoc} */ 6661 @Override 6662 public boolean isKeyguardSecure(int userId) { 6663 if (mKeyguardDelegate == null) return false; 6664 return mKeyguardDelegate.isSecure(userId); 6665 } 6666 6667 /** {@inheritDoc} */ 6668 @Override 6669 public boolean isKeyguardShowingOrOccluded() { 6670 return mKeyguardDelegate == null ? false : mKeyguardDelegate.isShowing(); 6671 } 6672 6673 /** {@inheritDoc} */ 6674 @Override 6675 public boolean inKeyguardRestrictedKeyInputMode() { 6676 if (mKeyguardDelegate == null) return false; 6677 return mKeyguardDelegate.isInputRestricted(); 6678 } 6679 6680 @Override 6681 public void dismissKeyguardLw() { 6682 if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) { 6683 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw"); 6684 mHandler.post(new Runnable() { 6685 @Override 6686 public void run() { 6687 // ask the keyguard to prompt the user to authenticate if necessary 6688 mKeyguardDelegate.dismiss(false /* allowWhileOccluded */); 6689 } 6690 }); 6691 } 6692 } 6693 6694 @Override 6695 public void notifyActivityDrawnForKeyguardLw() { 6696 if (mKeyguardDelegate != null) { 6697 mHandler.post(new Runnable() { 6698 @Override 6699 public void run() { 6700 mKeyguardDelegate.onActivityDrawn(); 6701 } 6702 }); 6703 } 6704 } 6705 6706 @Override 6707 public boolean isKeyguardDrawnLw() { 6708 synchronized (mLock) { 6709 return mKeyguardDrawnOnce; 6710 } 6711 } 6712 6713 @Override 6714 public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) { 6715 if (mKeyguardDelegate != null) { 6716 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation"); 6717 mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration); 6718 } 6719 } 6720 6721 @Override 6722 public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6723 Rect outInsets) { 6724 outInsets.setEmpty(); 6725 6726 // Navigation bar and status bar. 6727 getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets); 6728 if (mStatusBar != null) { 6729 outInsets.top = mStatusBarHeight; 6730 } 6731 } 6732 6733 @Override 6734 public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6735 Rect outInsets) { 6736 outInsets.setEmpty(); 6737 6738 // Only navigation bar 6739 if (mNavigationBar != null) { 6740 int position = navigationBarPosition(displayWidth, displayHeight, displayRotation); 6741 if (position == NAV_BAR_BOTTOM) { 6742 outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode); 6743 } else if (position == NAV_BAR_RIGHT) { 6744 outInsets.right = getNavigationBarWidth(displayRotation, mUiMode); 6745 } else if (position == NAV_BAR_LEFT) { 6746 outInsets.left = getNavigationBarWidth(displayRotation, mUiMode); 6747 } 6748 } 6749 } 6750 6751 @Override 6752 public boolean isNavBarForcedShownLw(WindowState windowState) { 6753 return mForceShowSystemBars; 6754 } 6755 6756 @Override 6757 public boolean isDockSideAllowed(int dockSide) { 6758 6759 // We do not allow all dock sides at which the navigation bar touches the docked stack. 6760 if (!mNavigationBarCanMove) { 6761 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT; 6762 } else { 6763 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT; 6764 } 6765 } 6766 6767 void sendCloseSystemWindows() { 6768 PhoneWindow.sendCloseSystemWindows(mContext, null); 6769 } 6770 6771 void sendCloseSystemWindows(String reason) { 6772 PhoneWindow.sendCloseSystemWindows(mContext, reason); 6773 } 6774 6775 @Override 6776 public int rotationForOrientationLw(int orientation, int lastRotation) { 6777 if (false) { 6778 Slog.v(TAG, "rotationForOrientationLw(orient=" 6779 + orientation + ", last=" + lastRotation 6780 + "); user=" + mUserRotation + " " 6781 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) 6782 ? "USER_ROTATION_LOCKED" : "") 6783 ); 6784 } 6785 6786 if (mForceDefaultOrientation) { 6787 return Surface.ROTATION_0; 6788 } 6789 6790 synchronized (mLock) { 6791 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1 6792 if (sensorRotation < 0) { 6793 sensorRotation = lastRotation; 6794 } 6795 6796 final int preferredRotation; 6797 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) { 6798 // Ignore sensor when lid switch is open and rotation is forced. 6799 preferredRotation = mLidOpenRotation; 6800 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR 6801 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) { 6802 // Ignore sensor when in car dock unless explicitly enabled. 6803 // This case can override the behavior of NOSENSOR, and can also 6804 // enable 180 degree rotation while docked. 6805 preferredRotation = mCarDockEnablesAccelerometer 6806 ? sensorRotation : mCarDockRotation; 6807 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK 6808 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK 6809 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK) 6810 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) { 6811 // Ignore sensor when in desk dock unless explicitly enabled. 6812 // This case can override the behavior of NOSENSOR, and can also 6813 // enable 180 degree rotation while docked. 6814 preferredRotation = mDeskDockEnablesAccelerometer 6815 ? sensorRotation : mDeskDockRotation; 6816 } else if (mHdmiPlugged && mDemoHdmiRotationLock) { 6817 // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled. 6818 // Note that the dock orientation overrides the HDMI orientation. 6819 preferredRotation = mDemoHdmiRotation; 6820 } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED 6821 && mUndockedHdmiRotation >= 0) { 6822 // Ignore sensor when plugged into HDMI and an undocked orientation has 6823 // been specified in the configuration (only for legacy devices without 6824 // full multi-display support). 6825 // Note that the dock orientation overrides the HDMI orientation. 6826 preferredRotation = mUndockedHdmiRotation; 6827 } else if (mDemoRotationLock) { 6828 // Ignore sensor when demo rotation lock is enabled. 6829 // Note that the dock orientation and HDMI rotation lock override this. 6830 preferredRotation = mDemoRotation; 6831 } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) { 6832 // Application just wants to remain locked in the last rotation. 6833 preferredRotation = lastRotation; 6834 } else if (!mSupportAutoRotation) { 6835 // If we don't support auto-rotation then bail out here and ignore 6836 // the sensor and any rotation lock settings. 6837 preferredRotation = -1; 6838 } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE 6839 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER 6840 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 6841 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE 6842 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT 6843 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER)) 6844 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR 6845 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6846 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE 6847 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) { 6848 // Otherwise, use sensor only if requested by the application or enabled 6849 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR. 6850 if (mAllowAllRotations < 0) { 6851 // Can't read this during init() because the context doesn't 6852 // have display metrics at that time so we cannot determine 6853 // tablet vs. phone then. 6854 mAllowAllRotations = mContext.getResources().getBoolean( 6855 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0; 6856 } 6857 if (sensorRotation != Surface.ROTATION_180 6858 || mAllowAllRotations == 1 6859 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6860 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) { 6861 preferredRotation = sensorRotation; 6862 } else { 6863 preferredRotation = lastRotation; 6864 } 6865 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED 6866 && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) { 6867 // Apply rotation lock. Does not apply to NOSENSOR. 6868 // The idea is that the user rotation expresses a weak preference for the direction 6869 // of gravity and as NOSENSOR is never affected by gravity, then neither should 6870 // NOSENSOR be affected by rotation lock (although it will be affected by docks). 6871 preferredRotation = mUserRotation; 6872 } else { 6873 // No overriding preference. 6874 // We will do exactly what the application asked us to do. 6875 preferredRotation = -1; 6876 } 6877 6878 switch (orientation) { 6879 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 6880 // Return portrait unless overridden. 6881 if (isAnyPortrait(preferredRotation)) { 6882 return preferredRotation; 6883 } 6884 return mPortraitRotation; 6885 6886 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 6887 // Return landscape unless overridden. 6888 if (isLandscapeOrSeascape(preferredRotation)) { 6889 return preferredRotation; 6890 } 6891 return mLandscapeRotation; 6892 6893 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 6894 // Return reverse portrait unless overridden. 6895 if (isAnyPortrait(preferredRotation)) { 6896 return preferredRotation; 6897 } 6898 return mUpsideDownRotation; 6899 6900 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 6901 // Return seascape unless overridden. 6902 if (isLandscapeOrSeascape(preferredRotation)) { 6903 return preferredRotation; 6904 } 6905 return mSeascapeRotation; 6906 6907 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 6908 case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE: 6909 // Return either landscape rotation. 6910 if (isLandscapeOrSeascape(preferredRotation)) { 6911 return preferredRotation; 6912 } 6913 if (isLandscapeOrSeascape(lastRotation)) { 6914 return lastRotation; 6915 } 6916 return mLandscapeRotation; 6917 6918 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 6919 case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT: 6920 // Return either portrait rotation. 6921 if (isAnyPortrait(preferredRotation)) { 6922 return preferredRotation; 6923 } 6924 if (isAnyPortrait(lastRotation)) { 6925 return lastRotation; 6926 } 6927 return mPortraitRotation; 6928 6929 default: 6930 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR, 6931 // just return the preferred orientation we already calculated. 6932 if (preferredRotation >= 0) { 6933 return preferredRotation; 6934 } 6935 return Surface.ROTATION_0; 6936 } 6937 } 6938 } 6939 6940 @Override 6941 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) { 6942 switch (orientation) { 6943 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 6944 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 6945 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 6946 return isAnyPortrait(rotation); 6947 6948 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 6949 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 6950 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 6951 return isLandscapeOrSeascape(rotation); 6952 6953 default: 6954 return true; 6955 } 6956 } 6957 6958 @Override 6959 public void setRotationLw(int rotation) { 6960 mOrientationListener.setCurrentRotation(rotation); 6961 } 6962 6963 private boolean isLandscapeOrSeascape(int rotation) { 6964 return rotation == mLandscapeRotation || rotation == mSeascapeRotation; 6965 } 6966 6967 private boolean isAnyPortrait(int rotation) { 6968 return rotation == mPortraitRotation || rotation == mUpsideDownRotation; 6969 } 6970 6971 @Override 6972 public int getUserRotationMode() { 6973 return Settings.System.getIntForUser(mContext.getContentResolver(), 6974 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ? 6975 WindowManagerPolicy.USER_ROTATION_FREE : 6976 WindowManagerPolicy.USER_ROTATION_LOCKED; 6977 } 6978 6979 // User rotation: to be used when all else fails in assigning an orientation to the device 6980 @Override 6981 public void setUserRotationMode(int mode, int rot) { 6982 ContentResolver res = mContext.getContentResolver(); 6983 6984 // mUserRotationMode and mUserRotation will be assigned by the content observer 6985 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) { 6986 Settings.System.putIntForUser(res, 6987 Settings.System.USER_ROTATION, 6988 rot, 6989 UserHandle.USER_CURRENT); 6990 Settings.System.putIntForUser(res, 6991 Settings.System.ACCELEROMETER_ROTATION, 6992 0, 6993 UserHandle.USER_CURRENT); 6994 } else { 6995 Settings.System.putIntForUser(res, 6996 Settings.System.ACCELEROMETER_ROTATION, 6997 1, 6998 UserHandle.USER_CURRENT); 6999 } 7000 } 7001 7002 @Override 7003 public void setSafeMode(boolean safeMode) { 7004 mSafeMode = safeMode; 7005 performHapticFeedbackLw(null, safeMode 7006 ? HapticFeedbackConstants.SAFE_MODE_ENABLED 7007 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true); 7008 } 7009 7010 static long[] getLongIntArray(Resources r, int resid) { 7011 int[] ar = r.getIntArray(resid); 7012 if (ar == null) { 7013 return null; 7014 } 7015 long[] out = new long[ar.length]; 7016 for (int i=0; i<ar.length; i++) { 7017 out[i] = ar[i]; 7018 } 7019 return out; 7020 } 7021 7022 /** {@inheritDoc} */ 7023 @Override 7024 public void systemReady() { 7025 mKeyguardDelegate = new KeyguardServiceDelegate(mContext, 7026 this::onKeyguardShowingStateChanged); 7027 mKeyguardDelegate.onSystemReady(); 7028 7029 readCameraLensCoverState(); 7030 updateUiMode(); 7031 boolean bindKeyguardNow; 7032 synchronized (mLock) { 7033 updateOrientationListenerLp(); 7034 mSystemReady = true; 7035 mHandler.post(new Runnable() { 7036 @Override 7037 public void run() { 7038 updateSettings(); 7039 } 7040 }); 7041 7042 bindKeyguardNow = mDeferBindKeyguard; 7043 if (bindKeyguardNow) { 7044 // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now. 7045 mDeferBindKeyguard = false; 7046 } 7047 } 7048 7049 if (bindKeyguardNow) { 7050 mKeyguardDelegate.bindService(mContext); 7051 mKeyguardDelegate.onBootCompleted(); 7052 } 7053 mSystemGestures.systemReady(); 7054 mImmersiveModeConfirmation.systemReady(); 7055 } 7056 7057 /** {@inheritDoc} */ 7058 @Override 7059 public void systemBooted() { 7060 boolean bindKeyguardNow = false; 7061 synchronized (mLock) { 7062 // Time to bind Keyguard; take care to only bind it once, either here if ready or 7063 // in systemReady if not. 7064 if (mKeyguardDelegate != null) { 7065 bindKeyguardNow = true; 7066 } else { 7067 // Because mKeyguardDelegate is null, we know that the synchronized block in 7068 // systemReady didn't run yet and setting this will actually have an effect. 7069 mDeferBindKeyguard = true; 7070 } 7071 } 7072 if (bindKeyguardNow) { 7073 mKeyguardDelegate.bindService(mContext); 7074 mKeyguardDelegate.onBootCompleted(); 7075 } 7076 synchronized (mLock) { 7077 mSystemBooted = true; 7078 } 7079 startedWakingUp(); 7080 screenTurningOn(null); 7081 screenTurnedOn(); 7082 } 7083 7084 ProgressDialog mBootMsgDialog = null; 7085 7086 /** {@inheritDoc} */ 7087 @Override 7088 public void showBootMessage(final CharSequence msg, final boolean always) { 7089 mHandler.post(new Runnable() { 7090 @Override public void run() { 7091 if (mBootMsgDialog == null) { 7092 int theme; 7093 if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) { 7094 theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert; 7095 } else { 7096 theme = 0; 7097 } 7098 7099 mBootMsgDialog = new ProgressDialog(mContext, theme) { 7100 // This dialog will consume all events coming in to 7101 // it, to avoid it trying to do things too early in boot. 7102 @Override public boolean dispatchKeyEvent(KeyEvent event) { 7103 return true; 7104 } 7105 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { 7106 return true; 7107 } 7108 @Override public boolean dispatchTouchEvent(MotionEvent ev) { 7109 return true; 7110 } 7111 @Override public boolean dispatchTrackballEvent(MotionEvent ev) { 7112 return true; 7113 } 7114 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) { 7115 return true; 7116 } 7117 @Override public boolean dispatchPopulateAccessibilityEvent( 7118 AccessibilityEvent event) { 7119 return true; 7120 } 7121 }; 7122 if (mContext.getPackageManager().isUpgrade()) { 7123 mBootMsgDialog.setTitle(R.string.android_upgrading_title); 7124 } else { 7125 mBootMsgDialog.setTitle(R.string.android_start_title); 7126 } 7127 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 7128 mBootMsgDialog.setIndeterminate(true); 7129 mBootMsgDialog.getWindow().setType( 7130 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS); 7131 mBootMsgDialog.getWindow().addFlags( 7132 WindowManager.LayoutParams.FLAG_DIM_BEHIND 7133 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); 7134 mBootMsgDialog.getWindow().setDimAmount(1); 7135 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes(); 7136 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 7137 mBootMsgDialog.getWindow().setAttributes(lp); 7138 mBootMsgDialog.setCancelable(false); 7139 mBootMsgDialog.show(); 7140 } 7141 mBootMsgDialog.setMessage(msg); 7142 } 7143 }); 7144 } 7145 7146 /** {@inheritDoc} */ 7147 @Override 7148 public void hideBootMessages() { 7149 mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE); 7150 } 7151 7152 /** {@inheritDoc} */ 7153 @Override 7154 public void userActivity() { 7155 // *************************************** 7156 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE 7157 // *************************************** 7158 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER 7159 // WITH ITS LOCKS HELD. 7160 // 7161 // This code must be VERY careful about the locks 7162 // it acquires. 7163 // In fact, the current code acquires way too many, 7164 // and probably has lurking deadlocks. 7165 7166 synchronized (mScreenLockTimeout) { 7167 if (mLockScreenTimerActive) { 7168 // reset the timer 7169 mHandler.removeCallbacks(mScreenLockTimeout); 7170 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7171 } 7172 } 7173 } 7174 7175 class ScreenLockTimeout implements Runnable { 7176 Bundle options; 7177 7178 @Override 7179 public void run() { 7180 synchronized (this) { 7181 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard"); 7182 if (mKeyguardDelegate != null) { 7183 mKeyguardDelegate.doKeyguardTimeout(options); 7184 } 7185 mLockScreenTimerActive = false; 7186 options = null; 7187 } 7188 } 7189 7190 public void setLockOptions(Bundle options) { 7191 this.options = options; 7192 } 7193 } 7194 7195 ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout(); 7196 7197 @Override 7198 public void lockNow(Bundle options) { 7199 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 7200 mHandler.removeCallbacks(mScreenLockTimeout); 7201 if (options != null) { 7202 // In case multiple calls are made to lockNow, we don't wipe out the options 7203 // until the runnable actually executes. 7204 mScreenLockTimeout.setLockOptions(options); 7205 } 7206 mHandler.post(mScreenLockTimeout); 7207 } 7208 7209 private void updateLockScreenTimeout() { 7210 synchronized (mScreenLockTimeout) { 7211 boolean enable = (mAllowLockscreenWhenOn && mAwake && 7212 mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId)); 7213 if (mLockScreenTimerActive != enable) { 7214 if (enable) { 7215 if (localLOGV) Log.v(TAG, "setting lockscreen timer"); 7216 mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests 7217 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7218 } else { 7219 if (localLOGV) Log.v(TAG, "clearing lockscreen timer"); 7220 mHandler.removeCallbacks(mScreenLockTimeout); 7221 } 7222 mLockScreenTimerActive = enable; 7223 } 7224 } 7225 } 7226 7227 private void updateDreamingSleepToken(boolean acquire) { 7228 if (acquire) { 7229 if (mDreamingSleepToken == null) { 7230 mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream"); 7231 } 7232 } else { 7233 if (mDreamingSleepToken != null) { 7234 mDreamingSleepToken.release(); 7235 mDreamingSleepToken = null; 7236 } 7237 } 7238 } 7239 7240 private void updateScreenOffSleepToken(boolean acquire) { 7241 if (acquire) { 7242 if (mScreenOffSleepToken == null) { 7243 mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff"); 7244 } 7245 } else { 7246 if (mScreenOffSleepToken != null) { 7247 mScreenOffSleepToken.release(); 7248 mScreenOffSleepToken = null; 7249 } 7250 } 7251 } 7252 7253 /** {@inheritDoc} */ 7254 @Override 7255 public void enableScreenAfterBoot() { 7256 readLidState(); 7257 applyLidSwitchState(); 7258 updateRotation(true); 7259 } 7260 7261 private void applyLidSwitchState() { 7262 if (mLidState == LID_CLOSED && mLidControlsSleep) { 7263 mPowerManager.goToSleep(SystemClock.uptimeMillis(), 7264 PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH, 7265 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); 7266 } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) { 7267 mWindowManagerFuncs.lockDeviceNow(); 7268 } 7269 7270 synchronized (mLock) { 7271 updateWakeGestureListenerLp(); 7272 } 7273 } 7274 7275 void updateUiMode() { 7276 if (mUiModeManager == null) { 7277 mUiModeManager = IUiModeManager.Stub.asInterface( 7278 ServiceManager.getService(Context.UI_MODE_SERVICE)); 7279 } 7280 try { 7281 mUiMode = mUiModeManager.getCurrentModeType(); 7282 } catch (RemoteException e) { 7283 } 7284 } 7285 7286 void updateRotation(boolean alwaysSendConfiguration) { 7287 try { 7288 //set orientation on WindowManager 7289 mWindowManager.updateRotation(alwaysSendConfiguration, false); 7290 } catch (RemoteException e) { 7291 // Ignore 7292 } 7293 } 7294 7295 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 7296 try { 7297 //set orientation on WindowManager 7298 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout); 7299 } catch (RemoteException e) { 7300 // Ignore 7301 } 7302 } 7303 7304 /** 7305 * Return an Intent to launch the currently active dock app as home. Returns 7306 * null if the standard home should be launched, which is the case if any of the following is 7307 * true: 7308 * <ul> 7309 * <li>The device is not in either car mode or desk mode 7310 * <li>The device is in car mode but mEnableCarDockHomeCapture is false 7311 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false 7312 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME 7313 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME 7314 * </ul> 7315 * @return A dock intent. 7316 */ 7317 Intent createHomeDockIntent() { 7318 Intent intent = null; 7319 7320 // What home does is based on the mode, not the dock state. That 7321 // is, when in car mode you should be taken to car home regardless 7322 // of whether we are actually in a car dock. 7323 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) { 7324 if (mEnableCarDockHomeCapture) { 7325 intent = mCarDockIntent; 7326 } 7327 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) { 7328 if (ENABLE_DESK_DOCK_HOME_CAPTURE) { 7329 intent = mDeskDockIntent; 7330 } 7331 } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH 7332 && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK 7333 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK 7334 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) { 7335 // Always launch dock home from home when watch is docked, if it exists. 7336 intent = mDeskDockIntent; 7337 } 7338 7339 if (intent == null) { 7340 return null; 7341 } 7342 7343 ActivityInfo ai = null; 7344 ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser( 7345 intent, 7346 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA, 7347 mCurrentUserId); 7348 if (info != null) { 7349 ai = info.activityInfo; 7350 } 7351 if (ai != null 7352 && ai.metaData != null 7353 && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) { 7354 intent = new Intent(intent); 7355 intent.setClassName(ai.packageName, ai.name); 7356 return intent; 7357 } 7358 7359 return null; 7360 } 7361 7362 void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) { 7363 if (awakenFromDreams) { 7364 awakenDreams(); 7365 } 7366 7367 Intent dock = createHomeDockIntent(); 7368 if (dock != null) { 7369 try { 7370 if (fromHomeKey) { 7371 dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7372 } 7373 startActivityAsUser(dock, UserHandle.CURRENT); 7374 return; 7375 } catch (ActivityNotFoundException e) { 7376 } 7377 } 7378 7379 Intent intent; 7380 7381 if (fromHomeKey) { 7382 intent = new Intent(mHomeIntent); 7383 intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7384 } else { 7385 intent = mHomeIntent; 7386 } 7387 7388 startActivityAsUser(intent, UserHandle.CURRENT); 7389 } 7390 7391 /** 7392 * goes to the home screen 7393 * @return whether it did anything 7394 */ 7395 boolean goHome() { 7396 if (!isUserSetupComplete()) { 7397 Slog.i(TAG, "Not going home because user setup is in progress."); 7398 return false; 7399 } 7400 if (false) { 7401 // This code always brings home to the front. 7402 try { 7403 ActivityManagerNative.getDefault().stopAppSwitches(); 7404 } catch (RemoteException e) { 7405 } 7406 sendCloseSystemWindows(); 7407 startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */); 7408 } else { 7409 // This code brings home to the front or, if it is already 7410 // at the front, puts the device to sleep. 7411 try { 7412 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) { 7413 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry. 7414 Log.d(TAG, "UTS-TEST-MODE"); 7415 } else { 7416 ActivityManagerNative.getDefault().stopAppSwitches(); 7417 sendCloseSystemWindows(); 7418 Intent dock = createHomeDockIntent(); 7419 if (dock != null) { 7420 int result = ActivityManagerNative.getDefault() 7421 .startActivityAsUser(null, null, dock, 7422 dock.resolveTypeIfNeeded(mContext.getContentResolver()), 7423 null, null, 0, 7424 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7425 null, null, UserHandle.USER_CURRENT); 7426 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7427 return false; 7428 } 7429 } 7430 } 7431 int result = ActivityManagerNative.getDefault() 7432 .startActivityAsUser(null, null, mHomeIntent, 7433 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()), 7434 null, null, 0, 7435 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7436 null, null, UserHandle.USER_CURRENT); 7437 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7438 return false; 7439 } 7440 } catch (RemoteException ex) { 7441 // bummer, the activity manager, which is in this process, is dead 7442 } 7443 } 7444 return true; 7445 } 7446 7447 @Override 7448 public void setCurrentOrientationLw(int newOrientation) { 7449 synchronized (mLock) { 7450 if (newOrientation != mCurrentAppOrientation) { 7451 mCurrentAppOrientation = newOrientation; 7452 updateOrientationListenerLp(); 7453 } 7454 } 7455 } 7456 7457 private void performAuditoryFeedbackForAccessibilityIfNeed() { 7458 if (!isGlobalAccessibilityGestureEnabled()) { 7459 return; 7460 } 7461 AudioManager audioManager = (AudioManager) mContext.getSystemService( 7462 Context.AUDIO_SERVICE); 7463 if (audioManager.isSilentMode()) { 7464 return; 7465 } 7466 Ringtone ringTone = RingtoneManager.getRingtone(mContext, 7467 Settings.System.DEFAULT_NOTIFICATION_URI); 7468 ringTone.setStreamType(AudioManager.STREAM_MUSIC); 7469 ringTone.play(); 7470 } 7471 7472 private boolean isTheaterModeEnabled() { 7473 return Settings.Global.getInt(mContext.getContentResolver(), 7474 Settings.Global.THEATER_MODE_ON, 0) == 1; 7475 } 7476 7477 private boolean isGlobalAccessibilityGestureEnabled() { 7478 return Settings.Global.getInt(mContext.getContentResolver(), 7479 Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1; 7480 } 7481 7482 private boolean areSystemNavigationKeysEnabled() { 7483 return Settings.Secure.getIntForUser(mContext.getContentResolver(), 7484 Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1; 7485 } 7486 7487 @Override 7488 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) { 7489 if (!mVibrator.hasVibrator()) { 7490 return false; 7491 } 7492 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(), 7493 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0; 7494 if (hapticsDisabled && !always) { 7495 return false; 7496 } 7497 long[] pattern = null; 7498 switch (effectId) { 7499 case HapticFeedbackConstants.LONG_PRESS: 7500 pattern = mLongPressVibePattern; 7501 break; 7502 case HapticFeedbackConstants.VIRTUAL_KEY: 7503 pattern = mVirtualKeyVibePattern; 7504 break; 7505 case HapticFeedbackConstants.KEYBOARD_TAP: 7506 pattern = mKeyboardTapVibePattern; 7507 break; 7508 case HapticFeedbackConstants.CLOCK_TICK: 7509 pattern = mClockTickVibePattern; 7510 break; 7511 case HapticFeedbackConstants.CALENDAR_DATE: 7512 pattern = mCalendarDateVibePattern; 7513 break; 7514 case HapticFeedbackConstants.SAFE_MODE_DISABLED: 7515 pattern = mSafeModeDisabledVibePattern; 7516 break; 7517 case HapticFeedbackConstants.SAFE_MODE_ENABLED: 7518 pattern = mSafeModeEnabledVibePattern; 7519 break; 7520 case HapticFeedbackConstants.CONTEXT_CLICK: 7521 pattern = mContextClickVibePattern; 7522 break; 7523 default: 7524 return false; 7525 } 7526 int owningUid; 7527 String owningPackage; 7528 if (win != null) { 7529 owningUid = win.getOwningUid(); 7530 owningPackage = win.getOwningPackage(); 7531 } else { 7532 owningUid = android.os.Process.myUid(); 7533 owningPackage = mContext.getOpPackageName(); 7534 } 7535 if (pattern.length == 1) { 7536 // One-shot vibration 7537 mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES); 7538 } else { 7539 // Pattern vibration 7540 mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES); 7541 } 7542 return true; 7543 } 7544 7545 @Override 7546 public void keepScreenOnStartedLw() { 7547 } 7548 7549 @Override 7550 public void keepScreenOnStoppedLw() { 7551 if (isKeyguardShowingAndNotOccluded()) { 7552 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 7553 } 7554 } 7555 7556 private int updateSystemUiVisibilityLw() { 7557 // If there is no window focused, there will be nobody to handle the events 7558 // anyway, so just hang on in whatever state we're in until things settle down. 7559 WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow 7560 : mTopFullscreenOpaqueWindowState; 7561 if (winCandidate == null) { 7562 return 0; 7563 } 7564 if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) { 7565 // The immersive mode confirmation should never affect the system bar visibility, 7566 // otherwise it will unhide the navigation bar and hide itself. 7567 winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState; 7568 if (winCandidate == null) { 7569 return 0; 7570 } 7571 } 7572 final WindowState win = winCandidate; 7573 if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) { 7574 // We are updating at a point where the keyguard has gotten 7575 // focus, but we were last in a state where the top window is 7576 // hiding it. This is probably because the keyguard as been 7577 // shown while the top window was displayed, so we want to ignore 7578 // it here because this is just a very transient change and it 7579 // will quickly lose focus once it correctly gets hidden. 7580 return 0; 7581 } 7582 7583 int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null) 7584 & ~mResettingSystemUiFlags 7585 & ~mForceClearedSystemUiFlags; 7586 if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) { 7587 tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS); 7588 } 7589 7590 final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */, 7591 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState); 7592 final int dockedVisibility = updateLightStatusBarLw(0 /* vis */, 7593 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState); 7594 mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds); 7595 mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds); 7596 final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility); 7597 final int diff = visibility ^ mLastSystemUiFlags; 7598 final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags; 7599 final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags; 7600 final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState); 7601 if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu 7602 && mFocusedApp == win.getAppToken() 7603 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds) 7604 && mLastDockedStackBounds.equals(mDockedStackBounds)) { 7605 return 0; 7606 } 7607 mLastSystemUiFlags = visibility; 7608 mLastFullscreenStackSysUiFlags = fullscreenVisibility; 7609 mLastDockedStackSysUiFlags = dockedVisibility; 7610 mLastFocusNeedsMenu = needsMenu; 7611 mFocusedApp = win.getAppToken(); 7612 final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds); 7613 final Rect dockedStackBounds = new Rect(mDockedStackBounds); 7614 mHandler.post(new Runnable() { 7615 @Override 7616 public void run() { 7617 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 7618 if (statusbar != null) { 7619 statusbar.setSystemUiVisibility(visibility, fullscreenVisibility, 7620 dockedVisibility, 0xffffffff, fullscreenStackBounds, 7621 dockedStackBounds, win.toString()); 7622 statusbar.topAppWindowChanged(needsMenu); 7623 } 7624 } 7625 }); 7626 return diff; 7627 } 7628 7629 private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) { 7630 WindowState statusColorWin = isStatusBarKeyguard() && !mHideLockScreen 7631 ? mStatusBar 7632 : opaqueOrDimming; 7633 7634 if (statusColorWin != null) { 7635 if (statusColorWin == opaque) { 7636 // If the top fullscreen-or-dimming window is also the top fullscreen, respect 7637 // its light flag. 7638 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7639 vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null) 7640 & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7641 } else if (statusColorWin != null && statusColorWin.isDimming()) { 7642 // Otherwise if it's dimming, clear the light flag. 7643 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7644 } 7645 } 7646 return vis; 7647 } 7648 7649 private boolean drawsSystemBarBackground(WindowState win) { 7650 return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0; 7651 } 7652 7653 private boolean forcesDrawStatusBarBackground(WindowState win) { 7654 return win == null || (win.getAttrs().privateFlags 7655 & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0; 7656 } 7657 7658 private int updateSystemBarsLw(WindowState win, int oldVis, int vis) { 7659 final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID); 7660 final boolean freeformStackVisible = 7661 mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID); 7662 final boolean resizing = mWindowManagerInternal.isDockedDividerResizing(); 7663 7664 // We need to force system bars when the docked stack is visible, when the freeform stack 7665 // is visible but also when we are resizing for the transitions when docked stack 7666 // visibility changes. 7667 mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing; 7668 final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard; 7669 7670 // apply translucent bar vis flags 7671 WindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen 7672 ? mStatusBar 7673 : mTopFullscreenOpaqueWindowState; 7674 vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7675 vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7676 final int dockedVis = mStatusBarController.applyTranslucentFlagLw( 7677 mTopDockedOpaqueWindowState, 0, 0); 7678 7679 final boolean fullscreenDrawsStatusBarBackground = 7680 (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState) 7681 && (vis & View.STATUS_BAR_TRANSLUCENT) == 0) 7682 || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState); 7683 final boolean dockedDrawsStatusBarBackground = 7684 (drawsSystemBarBackground(mTopDockedOpaqueWindowState) 7685 && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0) 7686 || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState); 7687 7688 // prevent status bar interaction from clearing certain flags 7689 int type = win.getAttrs().type; 7690 boolean statusBarHasFocus = type == TYPE_STATUS_BAR; 7691 if (statusBarHasFocus && !isStatusBarKeyguard()) { 7692 int flags = View.SYSTEM_UI_FLAG_FULLSCREEN 7693 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 7694 | View.SYSTEM_UI_FLAG_IMMERSIVE 7695 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 7696 | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7697 if (mHideLockScreen) { 7698 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT; 7699 } 7700 vis = (vis & ~flags) | (oldVis & flags); 7701 } 7702 7703 if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) { 7704 vis |= View.STATUS_BAR_TRANSPARENT; 7705 vis &= ~View.STATUS_BAR_TRANSLUCENT; 7706 } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar) 7707 || forceOpaqueStatusBar) { 7708 vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT); 7709 } 7710 7711 vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing); 7712 7713 // update status bar 7714 boolean immersiveSticky = 7715 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7716 final boolean hideStatusBarWM = 7717 mTopFullscreenOpaqueWindowState != null 7718 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null) 7719 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; 7720 final boolean hideStatusBarSysui = 7721 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 7722 final boolean hideNavBarSysui = 7723 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0; 7724 7725 final boolean transientStatusBarAllowed = mStatusBar != null 7726 && (statusBarHasFocus || (!mForceShowSystemBars 7727 && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky)))); 7728 7729 final boolean transientNavBarAllowed = mNavigationBar != null 7730 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky; 7731 7732 final long now = SystemClock.uptimeMillis(); 7733 final boolean pendingPanic = mPendingPanicGestureUptime != 0 7734 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION; 7735 if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) { 7736 // The user performed the panic gesture recently, we're about to hide the bars, 7737 // we're no longer on the Keyguard and the screen is ready. We can now request the bars. 7738 mPendingPanicGestureUptime = 0; 7739 mStatusBarController.showTransient(); 7740 if (!isNavBarEmpty(vis)) { 7741 mNavigationBarController.showTransient(); 7742 } 7743 } 7744 7745 final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested() 7746 && !transientStatusBarAllowed && hideStatusBarSysui; 7747 final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested() 7748 && !transientNavBarAllowed; 7749 if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) { 7750 // clear the clearable flags instead 7751 clearClearableFlagsLw(); 7752 vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS; 7753 } 7754 7755 final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; 7756 immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7757 final boolean navAllowedHidden = immersive || immersiveSticky; 7758 7759 if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType()) 7760 > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) { 7761 // We can't hide the navbar from this window otherwise the input consumer would not get 7762 // the input events. 7763 vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); 7764 } 7765 7766 vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis); 7767 7768 // update navigation bar 7769 boolean oldImmersiveMode = isImmersiveMode(oldVis); 7770 boolean newImmersiveMode = isImmersiveMode(vis); 7771 if (win != null && oldImmersiveMode != newImmersiveMode) { 7772 final String pkg = win.getOwningPackage(); 7773 mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode, 7774 isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility())); 7775 } 7776 7777 vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis); 7778 7779 return vis; 7780 } 7781 7782 /** 7783 * @return the current visibility flags with the nav-bar opacity related flags toggled based 7784 * on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}. 7785 */ 7786 private int configureNavBarOpacity(int visibility, boolean dockedStackVisible, 7787 boolean freeformStackVisible, boolean isDockedDividerResizing) { 7788 if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) { 7789 if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) { 7790 visibility = setNavBarOpaqueFlag(visibility); 7791 } 7792 } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) { 7793 if (isDockedDividerResizing) { 7794 visibility = setNavBarOpaqueFlag(visibility); 7795 } else if (freeformStackVisible) { 7796 visibility = setNavBarTranslucentFlag(visibility); 7797 } else { 7798 visibility = setNavBarOpaqueFlag(visibility); 7799 } 7800 } 7801 7802 if (!areTranslucentBarsAllowed()) { 7803 visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT; 7804 } 7805 return visibility; 7806 } 7807 7808 private int setNavBarOpaqueFlag(int visibility) { 7809 return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT); 7810 } 7811 7812 private int setNavBarTranslucentFlag(int visibility) { 7813 visibility &= ~View.NAVIGATION_BAR_TRANSPARENT; 7814 return visibility |= View.NAVIGATION_BAR_TRANSLUCENT; 7815 } 7816 7817 private void clearClearableFlagsLw() { 7818 int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS; 7819 if (newVal != mResettingSystemUiFlags) { 7820 mResettingSystemUiFlags = newVal; 7821 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 7822 } 7823 } 7824 7825 private boolean isImmersiveMode(int vis) { 7826 final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; 7827 return mNavigationBar != null 7828 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0 7829 && (vis & flags) != 0 7830 && canHideNavigationBar(); 7831 } 7832 7833 private static boolean isNavBarEmpty(int systemUiFlags) { 7834 final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME 7835 | View.STATUS_BAR_DISABLE_BACK 7836 | View.STATUS_BAR_DISABLE_RECENT); 7837 7838 return (systemUiFlags & disableNavigationBar) == disableNavigationBar; 7839 } 7840 7841 /** 7842 * @return whether the navigation or status bar can be made translucent 7843 * 7844 * This should return true unless touch exploration is not enabled or 7845 * R.boolean.config_enableTranslucentDecor is false. 7846 */ 7847 private boolean areTranslucentBarsAllowed() { 7848 return mTranslucentDecorEnabled; 7849 } 7850 7851 // Use this instead of checking config_showNavigationBar so that it can be consistently 7852 // overridden by qemu.hw.mainkeys in the emulator. 7853 @Override 7854 public boolean hasNavigationBar() { 7855 return mHasNavigationBar; 7856 } 7857 7858 @Override 7859 public void setLastInputMethodWindowLw(WindowState ime, WindowState target) { 7860 mLastInputMethodWindow = ime; 7861 mLastInputMethodTargetWindow = target; 7862 } 7863 7864 @Override 7865 public int getInputMethodWindowVisibleHeightLw() { 7866 return mDockBottom - mCurBottom; 7867 } 7868 7869 @Override 7870 public void setCurrentUserLw(int newUserId) { 7871 mCurrentUserId = newUserId; 7872 if (mKeyguardDelegate != null) { 7873 mKeyguardDelegate.setCurrentUser(newUserId); 7874 } 7875 StatusBarManagerInternal statusBar = getStatusBarManagerInternal(); 7876 if (statusBar != null) { 7877 statusBar.setCurrentUser(newUserId); 7878 } 7879 setLastInputMethodWindowLw(null, null); 7880 } 7881 7882 @Override 7883 public boolean canMagnifyWindow(int windowType) { 7884 switch (windowType) { 7885 case WindowManager.LayoutParams.TYPE_INPUT_METHOD: 7886 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: 7887 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR: 7888 case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: { 7889 return false; 7890 } 7891 } 7892 return true; 7893 } 7894 7895 @Override 7896 public boolean isTopLevelWindow(int windowType) { 7897 if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW 7898 && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 7899 return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG); 7900 } 7901 return true; 7902 } 7903 7904 @Override 7905 public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) { 7906 // For the upside down rotation we don't rotate seamlessly as the navigation 7907 // bar moves position. 7908 // Note most apps (using orientation:sensor or user as opposed to fullSensor) 7909 // will not enter the reverse portrait orientation, so actually the 7910 // orientation won't change at all. 7911 if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) { 7912 return false; 7913 } 7914 int delta = newRotation - oldRotation; 7915 if (delta < 0) delta += 4; 7916 // Likewise we don't rotate seamlessly for 180 degree rotations 7917 // in this case the surfaces never resize, and our logic to 7918 // revert the transformations on size change will fail. We could 7919 // fix this in the future with the "tagged" frames idea. 7920 if (delta == Surface.ROTATION_180) { 7921 return false; 7922 } 7923 7924 final WindowState w = mTopFullscreenOpaqueWindowState; 7925 if (w != mFocusedWindow) { 7926 return false; 7927 } 7928 7929 // We only enable seamless rotation if the top window has requested 7930 // it and is in the fullscreen opaque state. Seamless rotation 7931 // requires freezing various Surface states and won't work well 7932 // with animations, so we disable it in the animation case for now. 7933 if (w != null && !w.isAnimatingLw() && 7934 ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) || 7935 (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) { 7936 return true; 7937 } 7938 return false; 7939 } 7940 7941 @Override 7942 public void dump(String prefix, PrintWriter pw, String[] args) { 7943 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode); 7944 pw.print(" mSystemReady="); pw.print(mSystemReady); 7945 pw.print(" mSystemBooted="); pw.println(mSystemBooted); 7946 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState); 7947 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation); 7948 pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState); 7949 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged); 7950 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0 7951 || mForceClearedSystemUiFlags != 0) { 7952 pw.print(prefix); pw.print("mLastSystemUiFlags=0x"); 7953 pw.print(Integer.toHexString(mLastSystemUiFlags)); 7954 pw.print(" mResettingSystemUiFlags=0x"); 7955 pw.print(Integer.toHexString(mResettingSystemUiFlags)); 7956 pw.print(" mForceClearedSystemUiFlags=0x"); 7957 pw.println(Integer.toHexString(mForceClearedSystemUiFlags)); 7958 } 7959 if (mLastFocusNeedsMenu) { 7960 pw.print(prefix); pw.print("mLastFocusNeedsMenu="); 7961 pw.println(mLastFocusNeedsMenu); 7962 } 7963 pw.print(prefix); pw.print("mWakeGestureEnabledSetting="); 7964 pw.println(mWakeGestureEnabledSetting); 7965 7966 pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation); 7967 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode); 7968 pw.print(" mDockMode="); pw.print(mDockMode); 7969 pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture); 7970 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation); 7971 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation); 7972 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode); 7973 pw.print(" mUserRotation="); pw.print(mUserRotation); 7974 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations); 7975 pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation); 7976 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer="); 7977 pw.print(mCarDockEnablesAccelerometer); 7978 pw.print(" mDeskDockEnablesAccelerometer="); 7979 pw.println(mDeskDockEnablesAccelerometer); 7980 pw.print(prefix); pw.print("mLidKeyboardAccessibility="); 7981 pw.print(mLidKeyboardAccessibility); 7982 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility); 7983 pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock); 7984 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep); 7985 pw.print(prefix); 7986 pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior); 7987 pw.print(prefix); 7988 pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior); 7989 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior); 7990 pw.print(prefix); 7991 pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior); 7992 pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior); 7993 pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput); 7994 pw.print(prefix); pw.print("mAwake="); pw.println(mAwake); 7995 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly); 7996 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully); 7997 pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete); 7998 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete); 7999 pw.print(prefix); pw.print("mOrientationSensorEnabled="); 8000 pw.println(mOrientationSensorEnabled); 8001 pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft); 8002 pw.print(","); pw.print(mOverscanScreenTop); 8003 pw.print(") "); pw.print(mOverscanScreenWidth); 8004 pw.print("x"); pw.println(mOverscanScreenHeight); 8005 if (mOverscanLeft != 0 || mOverscanTop != 0 8006 || mOverscanRight != 0 || mOverscanBottom != 0) { 8007 pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft); 8008 pw.print(" top="); pw.print(mOverscanTop); 8009 pw.print(" right="); pw.print(mOverscanRight); 8010 pw.print(" bottom="); pw.println(mOverscanBottom); 8011 } 8012 pw.print(prefix); pw.print("mRestrictedOverscanScreen=("); 8013 pw.print(mRestrictedOverscanScreenLeft); 8014 pw.print(","); pw.print(mRestrictedOverscanScreenTop); 8015 pw.print(") "); pw.print(mRestrictedOverscanScreenWidth); 8016 pw.print("x"); pw.println(mRestrictedOverscanScreenHeight); 8017 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft); 8018 pw.print(","); pw.print(mUnrestrictedScreenTop); 8019 pw.print(") "); pw.print(mUnrestrictedScreenWidth); 8020 pw.print("x"); pw.println(mUnrestrictedScreenHeight); 8021 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft); 8022 pw.print(","); pw.print(mRestrictedScreenTop); 8023 pw.print(") "); pw.print(mRestrictedScreenWidth); 8024 pw.print("x"); pw.println(mRestrictedScreenHeight); 8025 pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft); 8026 pw.print(","); pw.print(mStableFullscreenTop); 8027 pw.print(")-("); pw.print(mStableFullscreenRight); 8028 pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")"); 8029 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft); 8030 pw.print(","); pw.print(mStableTop); 8031 pw.print(")-("); pw.print(mStableRight); 8032 pw.print(","); pw.print(mStableBottom); pw.println(")"); 8033 pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft); 8034 pw.print(","); pw.print(mSystemTop); 8035 pw.print(")-("); pw.print(mSystemRight); 8036 pw.print(","); pw.print(mSystemBottom); pw.println(")"); 8037 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft); 8038 pw.print(","); pw.print(mCurTop); 8039 pw.print(")-("); pw.print(mCurRight); 8040 pw.print(","); pw.print(mCurBottom); pw.println(")"); 8041 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft); 8042 pw.print(","); pw.print(mContentTop); 8043 pw.print(")-("); pw.print(mContentRight); 8044 pw.print(","); pw.print(mContentBottom); pw.println(")"); 8045 pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft); 8046 pw.print(","); pw.print(mVoiceContentTop); 8047 pw.print(")-("); pw.print(mVoiceContentRight); 8048 pw.print(","); pw.print(mVoiceContentBottom); pw.println(")"); 8049 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft); 8050 pw.print(","); pw.print(mDockTop); 8051 pw.print(")-("); pw.print(mDockRight); 8052 pw.print(","); pw.print(mDockBottom); pw.println(")"); 8053 pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer); 8054 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer); 8055 pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen); 8056 pw.print(" mShowingDream="); pw.print(mShowingDream); 8057 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen); 8058 pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken); 8059 if (mLastInputMethodWindow != null) { 8060 pw.print(prefix); pw.print("mLastInputMethodWindow="); 8061 pw.println(mLastInputMethodWindow); 8062 } 8063 if (mLastInputMethodTargetWindow != null) { 8064 pw.print(prefix); pw.print("mLastInputMethodTargetWindow="); 8065 pw.println(mLastInputMethodTargetWindow); 8066 } 8067 if (mStatusBar != null) { 8068 pw.print(prefix); pw.print("mStatusBar="); 8069 pw.print(mStatusBar); pw.print(" isStatusBarKeyguard="); 8070 pw.println(isStatusBarKeyguard()); 8071 } 8072 if (mNavigationBar != null) { 8073 pw.print(prefix); pw.print("mNavigationBar="); 8074 pw.println(mNavigationBar); 8075 } 8076 if (mFocusedWindow != null) { 8077 pw.print(prefix); pw.print("mFocusedWindow="); 8078 pw.println(mFocusedWindow); 8079 } 8080 if (mFocusedApp != null) { 8081 pw.print(prefix); pw.print("mFocusedApp="); 8082 pw.println(mFocusedApp); 8083 } 8084 if (mWinDismissingKeyguard != null) { 8085 pw.print(prefix); pw.print("mWinDismissingKeyguard="); 8086 pw.println(mWinDismissingKeyguard); 8087 } 8088 if (mTopFullscreenOpaqueWindowState != null) { 8089 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState="); 8090 pw.println(mTopFullscreenOpaqueWindowState); 8091 } 8092 if (mTopFullscreenOpaqueOrDimmingWindowState != null) { 8093 pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState="); 8094 pw.println(mTopFullscreenOpaqueOrDimmingWindowState); 8095 } 8096 if (mForcingShowNavBar) { 8097 pw.print(prefix); pw.print("mForcingShowNavBar="); 8098 pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer="); 8099 pw.println(mForcingShowNavBarLayer); 8100 } 8101 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen); 8102 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen); 8103 pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar); 8104 pw.print(" mForceStatusBarFromKeyguard="); 8105 pw.println(mForceStatusBarFromKeyguard); 8106 pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard); 8107 pw.print(" mCurrentlyDismissingKeyguard="); pw.println(mCurrentlyDismissingKeyguard); 8108 pw.print(" mWinDismissingKeyguard="); pw.print(mWinDismissingKeyguard); 8109 pw.print(" mHomePressed="); pw.println(mHomePressed); 8110 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn); 8111 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout); 8112 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive); 8113 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior); 8114 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior); 8115 pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior); 8116 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior); 8117 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation); 8118 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation); 8119 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation); 8120 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation); 8121 pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation); 8122 pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock); 8123 pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation); 8124 8125 mGlobalKeyManager.dump(prefix, pw); 8126 mStatusBarController.dump(pw, prefix); 8127 mNavigationBarController.dump(pw, prefix); 8128 PolicyControl.dump(prefix, pw); 8129 8130 if (mWakeGestureListener != null) { 8131 mWakeGestureListener.dump(pw, prefix); 8132 } 8133 if (mOrientationListener != null) { 8134 mOrientationListener.dump(pw, prefix); 8135 } 8136 if (mBurnInProtectionHelper != null) { 8137 mBurnInProtectionHelper.dump(prefix, pw); 8138 } 8139 if (mKeyguardDelegate != null) { 8140 mKeyguardDelegate.dump(prefix, pw); 8141 } 8142 } 8143} 8144