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