PhoneWindowManager.java revision a8a9bc5860c5d6139366f01b2f66e3f592da92e1
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.equals(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 if (wasOccluded != isOccluded) { 5488 mKeyguardOccluded = isOccluded; 5489 mKeyguardDelegate.setOccluded(isOccluded, false /* animate */); 5490 return false; 5491 } else { 5492 return false; 5493 } 5494 } 5495 5496 private void onKeyguardShowingStateChanged(boolean showing) { 5497 if (!showing) { 5498 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 5499 mCurrentlyDismissingKeyguard = false; 5500 } 5501 } 5502 } 5503 5504 private boolean isStatusBarKeyguard() { 5505 return mStatusBar != null 5506 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0; 5507 } 5508 5509 @Override 5510 public boolean allowAppAnimationsLw() { 5511 if (isStatusBarKeyguard() || mShowingDream) { 5512 // If keyguard or dreams is currently visible, no reason to animate behind it. 5513 return false; 5514 } 5515 return true; 5516 } 5517 5518 @Override 5519 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) { 5520 mFocusedWindow = newFocus; 5521 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5522 // If the navigation bar has been hidden or shown, we need to do another 5523 // layout pass to update that window. 5524 return FINISH_LAYOUT_REDO_LAYOUT; 5525 } 5526 return 0; 5527 } 5528 5529 /** {@inheritDoc} */ 5530 @Override 5531 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { 5532 // lid changed state 5533 final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED; 5534 if (newLidState == mLidState) { 5535 return; 5536 } 5537 5538 mLidState = newLidState; 5539 applyLidSwitchState(); 5540 updateRotation(true); 5541 5542 if (lidOpen) { 5543 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch, 5544 "android.policy:LID"); 5545 } else if (!mLidControlsSleep) { 5546 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 5547 } 5548 } 5549 5550 @Override 5551 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) { 5552 int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED; 5553 if (mCameraLensCoverState == lensCoverState) { 5554 return; 5555 } 5556 if (mCameraLensCoverState == CAMERA_LENS_COVERED && 5557 lensCoverState == CAMERA_LENS_UNCOVERED) { 5558 Intent intent; 5559 final boolean keyguardActive = mKeyguardDelegate == null ? false : 5560 mKeyguardDelegate.isShowing(); 5561 if (keyguardActive) { 5562 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE); 5563 } else { 5564 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); 5565 } 5566 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens, 5567 "android.policy:CAMERA_COVER"); 5568 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); 5569 } 5570 mCameraLensCoverState = lensCoverState; 5571 } 5572 5573 void setHdmiPlugged(boolean plugged) { 5574 if (mHdmiPlugged != plugged) { 5575 mHdmiPlugged = plugged; 5576 updateRotation(true, true); 5577 Intent intent = new Intent(ACTION_HDMI_PLUGGED); 5578 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5579 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged); 5580 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 5581 } 5582 } 5583 5584 void initializeHdmiState() { 5585 boolean plugged = false; 5586 // watch for HDMI plug messages if the hdmi switch exists 5587 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) { 5588 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi"); 5589 5590 final String filename = "/sys/class/switch/hdmi/state"; 5591 FileReader reader = null; 5592 try { 5593 reader = new FileReader(filename); 5594 char[] buf = new char[15]; 5595 int n = reader.read(buf); 5596 if (n > 1) { 5597 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1)); 5598 } 5599 } catch (IOException ex) { 5600 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5601 } catch (NumberFormatException ex) { 5602 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5603 } finally { 5604 if (reader != null) { 5605 try { 5606 reader.close(); 5607 } catch (IOException ex) { 5608 } 5609 } 5610 } 5611 } 5612 // This dance forces the code in setHdmiPlugged to run. 5613 // Always do this so the sticky intent is stuck (to false) if there is no hdmi. 5614 mHdmiPlugged = !plugged; 5615 setHdmiPlugged(!mHdmiPlugged); 5616 } 5617 5618 final Object mScreenshotLock = new Object(); 5619 ServiceConnection mScreenshotConnection = null; 5620 5621 final Runnable mScreenshotTimeout = new Runnable() { 5622 @Override public void run() { 5623 synchronized (mScreenshotLock) { 5624 if (mScreenshotConnection != null) { 5625 mContext.unbindService(mScreenshotConnection); 5626 mScreenshotConnection = null; 5627 notifyScreenshotError(); 5628 } 5629 } 5630 } 5631 }; 5632 5633 // Assume this is called from the Handler thread. 5634 private void takeScreenshot(final int screenshotType) { 5635 synchronized (mScreenshotLock) { 5636 if (mScreenshotConnection != null) { 5637 return; 5638 } 5639 final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE, 5640 SYSUI_SCREENSHOT_SERVICE); 5641 final Intent serviceIntent = new Intent(); 5642 serviceIntent.setComponent(serviceComponent); 5643 ServiceConnection conn = new ServiceConnection() { 5644 @Override 5645 public void onServiceConnected(ComponentName name, IBinder service) { 5646 synchronized (mScreenshotLock) { 5647 if (mScreenshotConnection != this) { 5648 return; 5649 } 5650 Messenger messenger = new Messenger(service); 5651 Message msg = Message.obtain(null, screenshotType); 5652 final ServiceConnection myConn = this; 5653 Handler h = new Handler(mHandler.getLooper()) { 5654 @Override 5655 public void handleMessage(Message msg) { 5656 synchronized (mScreenshotLock) { 5657 if (mScreenshotConnection == myConn) { 5658 mContext.unbindService(mScreenshotConnection); 5659 mScreenshotConnection = null; 5660 mHandler.removeCallbacks(mScreenshotTimeout); 5661 } 5662 } 5663 } 5664 }; 5665 msg.replyTo = new Messenger(h); 5666 msg.arg1 = msg.arg2 = 0; 5667 if (mStatusBar != null && mStatusBar.isVisibleLw()) 5668 msg.arg1 = 1; 5669 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) 5670 msg.arg2 = 1; 5671 try { 5672 messenger.send(msg); 5673 } catch (RemoteException e) { 5674 } 5675 } 5676 } 5677 5678 @Override 5679 public void onServiceDisconnected(ComponentName name) { 5680 synchronized (mScreenshotLock) { 5681 if (mScreenshotConnection != null) { 5682 mContext.unbindService(mScreenshotConnection); 5683 mScreenshotConnection = null; 5684 mHandler.removeCallbacks(mScreenshotTimeout); 5685 notifyScreenshotError(); 5686 } 5687 } 5688 } 5689 }; 5690 if (mContext.bindServiceAsUser(serviceIntent, conn, 5691 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, 5692 UserHandle.CURRENT)) { 5693 mScreenshotConnection = conn; 5694 mHandler.postDelayed(mScreenshotTimeout, 10000); 5695 } 5696 } 5697 } 5698 5699 /** 5700 * Notifies the screenshot service to show an error. 5701 */ 5702 private void notifyScreenshotError() { 5703 // If the service process is killed, then ask it to clean up after itself 5704 final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE, 5705 SYSUI_SCREENSHOT_ERROR_RECEIVER); 5706 Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT); 5707 errorIntent.setComponent(errorComponent); 5708 errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | 5709 Intent.FLAG_RECEIVER_FOREGROUND); 5710 mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT); 5711 } 5712 5713 /** {@inheritDoc} */ 5714 @Override 5715 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { 5716 if (!mSystemBooted) { 5717 // If we have not yet booted, don't let key events do anything. 5718 return 0; 5719 } 5720 5721 final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0; 5722 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; 5723 final boolean canceled = event.isCanceled(); 5724 final int keyCode = event.getKeyCode(); 5725 5726 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; 5727 5728 // If screen is off then we treat the case where the keyguard is open but hidden 5729 // the same as if it were open and in front. 5730 // This will prevent any keys other than the power button from waking the screen 5731 // when the keyguard is hidden by another activity. 5732 final boolean keyguardActive = (mKeyguardDelegate == null ? false : 5733 (interactive ? 5734 isKeyguardShowingAndNotOccluded() : 5735 mKeyguardDelegate.isShowing())); 5736 5737 if (DEBUG_INPUT) { 5738 Log.d(TAG, "interceptKeyTq keycode=" + keyCode 5739 + " interactive=" + interactive + " keyguardActive=" + keyguardActive 5740 + " policyFlags=" + Integer.toHexString(policyFlags)); 5741 } 5742 5743 // Basic policy based on interactive state. 5744 int result; 5745 boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0 5746 || event.isWakeKey(); 5747 if (interactive || (isInjected && !isWakeKey)) { 5748 // When the device is interactive or the key is injected pass the 5749 // key to the application. 5750 result = ACTION_PASS_TO_USER; 5751 isWakeKey = false; 5752 5753 if (interactive) { 5754 // If the screen is awake, but the button pressed was the one that woke the device 5755 // then don't pass it to the application 5756 if (keyCode == mPendingWakeKey && !down) { 5757 result = 0; 5758 } 5759 // Reset the pending key 5760 mPendingWakeKey = PENDING_KEY_NULL; 5761 } 5762 } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) { 5763 // If we're currently dozing with the screen on and the keyguard showing, pass the key 5764 // to the application but preserve its wake key status to make sure we still move 5765 // from dozing to fully interactive if we would normally go from off to fully 5766 // interactive. 5767 result = ACTION_PASS_TO_USER; 5768 // Since we're dispatching the input, reset the pending key 5769 mPendingWakeKey = PENDING_KEY_NULL; 5770 } else { 5771 // When the screen is off and the key is not injected, determine whether 5772 // to wake the device but don't pass the key to the application. 5773 result = 0; 5774 if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) { 5775 isWakeKey = false; 5776 } 5777 // Cache the wake key on down event so we can also avoid sending the up event to the app 5778 if (isWakeKey && down) { 5779 mPendingWakeKey = keyCode; 5780 } 5781 } 5782 5783 // If the key would be handled globally, just return the result, don't worry about special 5784 // key processing. 5785 if (isValidGlobalKey(keyCode) 5786 && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) { 5787 if (isWakeKey) { 5788 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 5789 } 5790 return result; 5791 } 5792 5793 boolean useHapticFeedback = down 5794 && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0 5795 && event.getRepeatCount() == 0; 5796 5797 // Handle special keys. 5798 switch (keyCode) { 5799 case KeyEvent.KEYCODE_BACK: { 5800 if (down) { 5801 interceptBackKeyDown(); 5802 } else { 5803 boolean handled = interceptBackKeyUp(event); 5804 5805 // Don't pass back press to app if we've already handled it via long press 5806 if (handled) { 5807 result &= ~ACTION_PASS_TO_USER; 5808 } 5809 } 5810 break; 5811 } 5812 5813 case KeyEvent.KEYCODE_VOLUME_DOWN: 5814 case KeyEvent.KEYCODE_VOLUME_UP: 5815 case KeyEvent.KEYCODE_VOLUME_MUTE: { 5816 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { 5817 if (down) { 5818 if (interactive && !mScreenshotChordVolumeDownKeyTriggered 5819 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5820 mScreenshotChordVolumeDownKeyTriggered = true; 5821 mScreenshotChordVolumeDownKeyTime = event.getDownTime(); 5822 mScreenshotChordVolumeDownKeyConsumed = false; 5823 cancelPendingPowerKeyAction(); 5824 interceptScreenshotChord(); 5825 } 5826 } else { 5827 mScreenshotChordVolumeDownKeyTriggered = false; 5828 cancelPendingScreenshotChordAction(); 5829 } 5830 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 5831 if (down) { 5832 if (interactive && !mScreenshotChordVolumeUpKeyTriggered 5833 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5834 mScreenshotChordVolumeUpKeyTriggered = true; 5835 cancelPendingPowerKeyAction(); 5836 cancelPendingScreenshotChordAction(); 5837 } 5838 } else { 5839 mScreenshotChordVolumeUpKeyTriggered = false; 5840 cancelPendingScreenshotChordAction(); 5841 } 5842 } 5843 if (down) { 5844 TelecomManager telecomManager = getTelecommService(); 5845 if (telecomManager != null) { 5846 if (telecomManager.isRinging()) { 5847 // If an incoming call is ringing, either VOLUME key means 5848 // "silence ringer". We handle these keys here, rather than 5849 // in the InCallScreen, to make sure we'll respond to them 5850 // even if the InCallScreen hasn't come to the foreground yet. 5851 // Look for the DOWN event here, to agree with the "fallback" 5852 // behavior in the InCallScreen. 5853 Log.i(TAG, "interceptKeyBeforeQueueing:" 5854 + " VOLUME key-down while ringing: Silence ringer!"); 5855 5856 // Silence the ringer. (It's safe to call this 5857 // even if the ringer has already been silenced.) 5858 telecomManager.silenceRinger(); 5859 5860 // And *don't* pass this key thru to the current activity 5861 // (which is probably the InCallScreen.) 5862 result &= ~ACTION_PASS_TO_USER; 5863 break; 5864 } 5865 if (telecomManager.isInCall() 5866 && (result & ACTION_PASS_TO_USER) == 0) { 5867 // If we are in call but we decided not to pass the key to 5868 // the application, just pass it to the session service. 5869 5870 MediaSessionLegacyHelper.getHelper(mContext) 5871 .sendVolumeKeyEvent(event, false); 5872 break; 5873 } 5874 } 5875 } 5876 if (mUseTvRouting) { 5877 // On TVs, defer special key handlings to 5878 // {@link interceptKeyBeforeDispatching()}. 5879 result |= ACTION_PASS_TO_USER; 5880 } else if ((result & ACTION_PASS_TO_USER) == 0) { 5881 // If we aren't passing to the user and no one else 5882 // handled it send it to the session manager to 5883 // figure out. 5884 MediaSessionLegacyHelper.getHelper(mContext) 5885 .sendVolumeKeyEvent(event, true); 5886 } 5887 break; 5888 } 5889 5890 case KeyEvent.KEYCODE_ENDCALL: { 5891 result &= ~ACTION_PASS_TO_USER; 5892 if (down) { 5893 TelecomManager telecomManager = getTelecommService(); 5894 boolean hungUp = false; 5895 if (telecomManager != null) { 5896 hungUp = telecomManager.endCall(); 5897 } 5898 if (interactive && !hungUp) { 5899 mEndCallKeyHandled = false; 5900 mHandler.postDelayed(mEndCallLongPress, 5901 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 5902 } else { 5903 mEndCallKeyHandled = true; 5904 } 5905 } else { 5906 if (!mEndCallKeyHandled) { 5907 mHandler.removeCallbacks(mEndCallLongPress); 5908 if (!canceled) { 5909 if ((mEndcallBehavior 5910 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) { 5911 if (goHome()) { 5912 break; 5913 } 5914 } 5915 if ((mEndcallBehavior 5916 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) { 5917 mPowerManager.goToSleep(event.getEventTime(), 5918 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); 5919 isWakeKey = false; 5920 } 5921 } 5922 } 5923 } 5924 break; 5925 } 5926 5927 case KeyEvent.KEYCODE_POWER: { 5928 result &= ~ACTION_PASS_TO_USER; 5929 isWakeKey = false; // wake-up will be handled separately 5930 if (down) { 5931 interceptPowerKeyDown(event, interactive); 5932 } else { 5933 interceptPowerKeyUp(event, interactive, canceled); 5934 } 5935 break; 5936 } 5937 5938 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN: 5939 // fall through 5940 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP: 5941 // fall through 5942 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT: 5943 // fall through 5944 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: { 5945 result &= ~ACTION_PASS_TO_USER; 5946 interceptSystemNavigationKey(event); 5947 break; 5948 } 5949 5950 case KeyEvent.KEYCODE_SLEEP: { 5951 result &= ~ACTION_PASS_TO_USER; 5952 isWakeKey = false; 5953 if (!mPowerManager.isInteractive()) { 5954 useHapticFeedback = false; // suppress feedback if already non-interactive 5955 } 5956 if (down) { 5957 sleepPress(event.getEventTime()); 5958 } else { 5959 sleepRelease(event.getEventTime()); 5960 } 5961 break; 5962 } 5963 5964 case KeyEvent.KEYCODE_SOFT_SLEEP: { 5965 result &= ~ACTION_PASS_TO_USER; 5966 isWakeKey = false; 5967 if (!down) { 5968 mPowerManagerInternal.setUserInactiveOverrideFromWindowManager(); 5969 } 5970 break; 5971 } 5972 5973 case KeyEvent.KEYCODE_WAKEUP: { 5974 result &= ~ACTION_PASS_TO_USER; 5975 isWakeKey = true; 5976 break; 5977 } 5978 5979 case KeyEvent.KEYCODE_MEDIA_PLAY: 5980 case KeyEvent.KEYCODE_MEDIA_PAUSE: 5981 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 5982 case KeyEvent.KEYCODE_HEADSETHOOK: 5983 case KeyEvent.KEYCODE_MUTE: 5984 case KeyEvent.KEYCODE_MEDIA_STOP: 5985 case KeyEvent.KEYCODE_MEDIA_NEXT: 5986 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 5987 case KeyEvent.KEYCODE_MEDIA_REWIND: 5988 case KeyEvent.KEYCODE_MEDIA_RECORD: 5989 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 5990 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { 5991 if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) { 5992 // If the global session is active pass all media keys to it 5993 // instead of the active window. 5994 result &= ~ACTION_PASS_TO_USER; 5995 } 5996 if ((result & ACTION_PASS_TO_USER) == 0) { 5997 // Only do this if we would otherwise not pass it to the user. In that 5998 // case, the PhoneWindow class will do the same thing, except it will 5999 // only do it if the showing app doesn't process the key on its own. 6000 // Note that we need to make a copy of the key event here because the 6001 // original key event will be recycled when we return. 6002 mBroadcastWakeLock.acquire(); 6003 Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK, 6004 new KeyEvent(event)); 6005 msg.setAsynchronous(true); 6006 msg.sendToTarget(); 6007 } 6008 break; 6009 } 6010 6011 case KeyEvent.KEYCODE_CALL: { 6012 if (down) { 6013 TelecomManager telecomManager = getTelecommService(); 6014 if (telecomManager != null) { 6015 if (telecomManager.isRinging()) { 6016 Log.i(TAG, "interceptKeyBeforeQueueing:" 6017 + " CALL key-down while ringing: Answer the call!"); 6018 telecomManager.acceptRingingCall(); 6019 6020 // And *don't* pass this key thru to the current activity 6021 // (which is presumably the InCallScreen.) 6022 result &= ~ACTION_PASS_TO_USER; 6023 } 6024 } 6025 } 6026 break; 6027 } 6028 case KeyEvent.KEYCODE_VOICE_ASSIST: { 6029 // Only do this if we would otherwise not pass it to the user. In that case, 6030 // interceptKeyBeforeDispatching would apply a similar but different policy in 6031 // order to invoke voice assist actions. Note that we need to make a copy of the 6032 // key event here because the original key event will be recycled when we return. 6033 if ((result & ACTION_PASS_TO_USER) == 0 && !down) { 6034 mBroadcastWakeLock.acquire(); 6035 Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK, 6036 keyguardActive ? 1 : 0, 0); 6037 msg.setAsynchronous(true); 6038 msg.sendToTarget(); 6039 } 6040 break; 6041 } 6042 case KeyEvent.KEYCODE_WINDOW: { 6043 if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) { 6044 if (mTvPictureInPictureVisible) { 6045 // Consumes the key only if picture-in-picture is visible 6046 // to show picture-in-picture control menu. 6047 // This gives a chance to the foreground activity 6048 // to customize PIP key behavior. 6049 if (!down) { 6050 showTvPictureInPictureMenu(event); 6051 } 6052 result &= ~ACTION_PASS_TO_USER; 6053 } 6054 } 6055 break; 6056 } 6057 } 6058 6059 if (useHapticFeedback) { 6060 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); 6061 } 6062 6063 if (isWakeKey) { 6064 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 6065 } 6066 6067 return result; 6068 } 6069 6070 /** 6071 * Handle statusbar expansion events. 6072 * @param event 6073 */ 6074 private void interceptSystemNavigationKey(KeyEvent event) { 6075 if (event.getAction() == KeyEvent.ACTION_UP && areSystemNavigationKeysEnabled()) { 6076 IStatusBarService sbar = getStatusBarService(); 6077 if (sbar != null) { 6078 try { 6079 sbar.handleSystemNavigationKey(event.getKeyCode()); 6080 } catch (RemoteException e1) { 6081 // oops, no statusbar. Ignore event. 6082 } 6083 } 6084 } 6085 } 6086 6087 /** 6088 * Returns true if the key can have global actions attached to it. 6089 * We reserve all power management keys for the system since they require 6090 * very careful handling. 6091 */ 6092 private static boolean isValidGlobalKey(int keyCode) { 6093 switch (keyCode) { 6094 case KeyEvent.KEYCODE_POWER: 6095 case KeyEvent.KEYCODE_WAKEUP: 6096 case KeyEvent.KEYCODE_SLEEP: 6097 return false; 6098 default: 6099 return true; 6100 } 6101 } 6102 6103 /** 6104 * When the screen is off we ignore some keys that might otherwise typically 6105 * be considered wake keys. We filter them out here. 6106 * 6107 * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it 6108 * is always considered a wake key. 6109 */ 6110 private boolean isWakeKeyWhenScreenOff(int keyCode) { 6111 switch (keyCode) { 6112 // ignore volume keys unless docked 6113 case KeyEvent.KEYCODE_VOLUME_UP: 6114 case KeyEvent.KEYCODE_VOLUME_DOWN: 6115 case KeyEvent.KEYCODE_VOLUME_MUTE: 6116 return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED; 6117 6118 // ignore media and camera keys 6119 case KeyEvent.KEYCODE_MUTE: 6120 case KeyEvent.KEYCODE_HEADSETHOOK: 6121 case KeyEvent.KEYCODE_MEDIA_PLAY: 6122 case KeyEvent.KEYCODE_MEDIA_PAUSE: 6123 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 6124 case KeyEvent.KEYCODE_MEDIA_STOP: 6125 case KeyEvent.KEYCODE_MEDIA_NEXT: 6126 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 6127 case KeyEvent.KEYCODE_MEDIA_REWIND: 6128 case KeyEvent.KEYCODE_MEDIA_RECORD: 6129 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 6130 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: 6131 case KeyEvent.KEYCODE_CAMERA: 6132 return false; 6133 } 6134 return true; 6135 } 6136 6137 6138 /** {@inheritDoc} */ 6139 @Override 6140 public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) { 6141 if ((policyFlags & FLAG_WAKE) != 0) { 6142 if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion, 6143 "android.policy:MOTION")) { 6144 return 0; 6145 } 6146 } 6147 6148 if (shouldDispatchInputWhenNonInteractive(null)) { 6149 return ACTION_PASS_TO_USER; 6150 } 6151 6152 // If we have not passed the action up and we are in theater mode without dreaming, 6153 // there will be no dream to intercept the touch and wake into ambient. The device should 6154 // wake up in this case. 6155 if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) { 6156 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming, 6157 "android.policy:MOTION"); 6158 } 6159 6160 return 0; 6161 } 6162 6163 private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) { 6164 final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF); 6165 6166 if (displayOff && !mHasFeatureWatch) { 6167 return false; 6168 } 6169 6170 // Send events to keyguard while the screen is on and it's showing. 6171 if (isKeyguardShowingAndNotOccluded() && !displayOff) { 6172 return true; 6173 } 6174 6175 // Watches handle BACK specially 6176 if (mHasFeatureWatch 6177 && event != null 6178 && (event.getKeyCode() == KeyEvent.KEYCODE_BACK 6179 || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) { 6180 return false; 6181 } 6182 6183 // Send events to a dozing dream even if the screen is off since the dream 6184 // is in control of the state of the screen. 6185 IDreamManager dreamManager = getDreamManager(); 6186 6187 try { 6188 if (dreamManager != null && dreamManager.isDreaming()) { 6189 return true; 6190 } 6191 } catch (RemoteException e) { 6192 Slog.e(TAG, "RemoteException when checking if dreaming", e); 6193 } 6194 6195 // Otherwise, consume events since the user can't see what is being 6196 // interacted with. 6197 return false; 6198 } 6199 6200 private void dispatchDirectAudioEvent(KeyEvent event) { 6201 if (event.getAction() != KeyEvent.ACTION_DOWN) { 6202 return; 6203 } 6204 int keyCode = event.getKeyCode(); 6205 int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND 6206 | AudioManager.FLAG_FROM_KEY; 6207 String pkgName = mContext.getOpPackageName(); 6208 switch (keyCode) { 6209 case KeyEvent.KEYCODE_VOLUME_UP: 6210 try { 6211 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE, 6212 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6213 } catch (RemoteException e) { 6214 Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e); 6215 } 6216 break; 6217 case KeyEvent.KEYCODE_VOLUME_DOWN: 6218 try { 6219 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER, 6220 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6221 } catch (RemoteException e) { 6222 Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e); 6223 } 6224 break; 6225 case KeyEvent.KEYCODE_VOLUME_MUTE: 6226 try { 6227 if (event.getRepeatCount() == 0) { 6228 getAudioService().adjustSuggestedStreamVolume( 6229 AudioManager.ADJUST_TOGGLE_MUTE, 6230 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6231 } 6232 } catch (RemoteException e) { 6233 Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e); 6234 } 6235 break; 6236 } 6237 } 6238 6239 void dispatchMediaKeyWithWakeLock(KeyEvent event) { 6240 if (DEBUG_INPUT) { 6241 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event); 6242 } 6243 6244 if (mHavePendingMediaKeyRepeatWithWakeLock) { 6245 if (DEBUG_INPUT) { 6246 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat"); 6247 } 6248 6249 mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK); 6250 mHavePendingMediaKeyRepeatWithWakeLock = false; 6251 mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock 6252 } 6253 6254 dispatchMediaKeyWithWakeLockToAudioService(event); 6255 6256 if (event.getAction() == KeyEvent.ACTION_DOWN 6257 && event.getRepeatCount() == 0) { 6258 mHavePendingMediaKeyRepeatWithWakeLock = true; 6259 6260 Message msg = mHandler.obtainMessage( 6261 MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event); 6262 msg.setAsynchronous(true); 6263 mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout()); 6264 } else { 6265 mBroadcastWakeLock.release(); 6266 } 6267 } 6268 6269 void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) { 6270 mHavePendingMediaKeyRepeatWithWakeLock = false; 6271 6272 KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event, 6273 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS); 6274 if (DEBUG_INPUT) { 6275 Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent); 6276 } 6277 6278 dispatchMediaKeyWithWakeLockToAudioService(repeatEvent); 6279 mBroadcastWakeLock.release(); 6280 } 6281 6282 void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) { 6283 if (ActivityManagerNative.isSystemReady()) { 6284 MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true); 6285 } 6286 } 6287 6288 void launchVoiceAssistWithWakeLock(boolean keyguardActive) { 6289 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface( 6290 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); 6291 if (dic != null) { 6292 try { 6293 dic.exitIdle("voice-search"); 6294 } catch (RemoteException e) { 6295 } 6296 } 6297 Intent voiceIntent = 6298 new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); 6299 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive); 6300 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF); 6301 mBroadcastWakeLock.release(); 6302 } 6303 6304 BroadcastReceiver mDockReceiver = new BroadcastReceiver() { 6305 @Override 6306 public void onReceive(Context context, Intent intent) { 6307 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) { 6308 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 6309 Intent.EXTRA_DOCK_STATE_UNDOCKED); 6310 } else { 6311 try { 6312 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface( 6313 ServiceManager.getService(Context.UI_MODE_SERVICE)); 6314 mUiMode = uiModeService.getCurrentModeType(); 6315 } catch (RemoteException e) { 6316 } 6317 } 6318 updateRotation(true); 6319 synchronized (mLock) { 6320 updateOrientationListenerLp(); 6321 } 6322 } 6323 }; 6324 6325 BroadcastReceiver mDreamReceiver = new BroadcastReceiver() { 6326 @Override 6327 public void onReceive(Context context, Intent intent) { 6328 if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) { 6329 if (mKeyguardDelegate != null) { 6330 mKeyguardDelegate.onDreamingStarted(); 6331 } 6332 } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) { 6333 if (mKeyguardDelegate != null) { 6334 mKeyguardDelegate.onDreamingStopped(); 6335 } 6336 } 6337 } 6338 }; 6339 6340 BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() { 6341 @Override 6342 public void onReceive(Context context, Intent intent) { 6343 if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) { 6344 // tickle the settings observer: this first ensures that we're 6345 // observing the relevant settings for the newly-active user, 6346 // and then updates our own bookkeeping based on the now- 6347 // current user. 6348 mSettingsObserver.onChange(false); 6349 6350 // force a re-application of focused window sysui visibility. 6351 // the window may never have been shown for this user 6352 // e.g. the keyguard when going through the new-user setup flow 6353 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6354 mLastSystemUiFlags = 0; 6355 updateSystemUiVisibilityLw(); 6356 } 6357 } 6358 } 6359 }; 6360 6361 private final Runnable mHiddenNavPanic = new Runnable() { 6362 @Override 6363 public void run() { 6364 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6365 if (!isUserSetupComplete()) { 6366 // Swipe-up for navigation bar is disabled during setup 6367 return; 6368 } 6369 mPendingPanicGestureUptime = SystemClock.uptimeMillis(); 6370 if (!isNavBarEmpty(mLastSystemUiFlags)) { 6371 mNavigationBarController.showTransient(); 6372 } 6373 } 6374 } 6375 }; 6376 6377 private void requestTransientBars(WindowState swipeTarget) { 6378 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6379 if (!isUserSetupComplete()) { 6380 // Swipe-up for navigation bar is disabled during setup 6381 return; 6382 } 6383 boolean sb = mStatusBarController.checkShowTransientBarLw(); 6384 boolean nb = mNavigationBarController.checkShowTransientBarLw() 6385 && !isNavBarEmpty(mLastSystemUiFlags); 6386 if (sb || nb) { 6387 // Don't show status bar when swiping on already visible navigation bar 6388 if (!nb && swipeTarget == mNavigationBar) { 6389 if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target"); 6390 return; 6391 } 6392 if (sb) mStatusBarController.showTransient(); 6393 if (nb) mNavigationBarController.showTransient(); 6394 mImmersiveModeConfirmation.confirmCurrentPrompt(); 6395 updateSystemUiVisibilityLw(); 6396 } 6397 } 6398 } 6399 6400 // Called on the PowerManager's Notifier thread. 6401 @Override 6402 public void startedGoingToSleep(int why) { 6403 if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")"); 6404 mCameraGestureTriggeredDuringGoingToSleep = false; 6405 mGoingToSleep = true; 6406 if (mKeyguardDelegate != null) { 6407 mKeyguardDelegate.onStartedGoingToSleep(why); 6408 } 6409 } 6410 6411 // Called on the PowerManager's Notifier thread. 6412 @Override 6413 public void finishedGoingToSleep(int why) { 6414 EventLog.writeEvent(70000, 0); 6415 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")"); 6416 MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000); 6417 6418 mGoingToSleep = false; 6419 6420 // We must get this work done here because the power manager will drop 6421 // the wake lock and let the system suspend once this function returns. 6422 synchronized (mLock) { 6423 mAwake = false; 6424 updateWakeGestureListenerLp(); 6425 updateOrientationListenerLp(); 6426 updateLockScreenTimeout(); 6427 } 6428 if (mKeyguardDelegate != null) { 6429 mKeyguardDelegate.onFinishedGoingToSleep(why, 6430 mCameraGestureTriggeredDuringGoingToSleep); 6431 } 6432 mCameraGestureTriggeredDuringGoingToSleep = false; 6433 } 6434 6435 // Called on the PowerManager's Notifier thread. 6436 @Override 6437 public void startedWakingUp() { 6438 EventLog.writeEvent(70000, 1); 6439 if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up..."); 6440 6441 // Since goToSleep performs these functions synchronously, we must 6442 // do the same here. We cannot post this work to a handler because 6443 // that might cause it to become reordered with respect to what 6444 // may happen in a future call to goToSleep. 6445 synchronized (mLock) { 6446 mAwake = true; 6447 6448 updateWakeGestureListenerLp(); 6449 updateOrientationListenerLp(); 6450 updateLockScreenTimeout(); 6451 } 6452 6453 if (mKeyguardDelegate != null) { 6454 mKeyguardDelegate.onStartedWakingUp(); 6455 } 6456 } 6457 6458 // Called on the PowerManager's Notifier thread. 6459 @Override 6460 public void finishedWakingUp() { 6461 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up..."); 6462 } 6463 6464 private void wakeUpFromPowerKey(long eventTime) { 6465 wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER"); 6466 } 6467 6468 private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) { 6469 final boolean theaterModeEnabled = isTheaterModeEnabled(); 6470 if (!wakeInTheaterMode && theaterModeEnabled) { 6471 return false; 6472 } 6473 6474 if (theaterModeEnabled) { 6475 Settings.Global.putInt(mContext.getContentResolver(), 6476 Settings.Global.THEATER_MODE_ON, 0); 6477 } 6478 6479 mPowerManager.wakeUp(wakeTime, reason); 6480 return true; 6481 } 6482 6483 private void finishKeyguardDrawn() { 6484 synchronized (mLock) { 6485 if (!mScreenOnEarly || mKeyguardDrawComplete) { 6486 return; // We are not awake yet or we have already informed of this event. 6487 } 6488 6489 mKeyguardDrawComplete = true; 6490 if (mKeyguardDelegate != null) { 6491 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6492 } 6493 mWindowManagerDrawComplete = false; 6494 } 6495 6496 // ... eventually calls finishWindowsDrawn which will finalize our screen turn on 6497 // as well as enabling the orientation change logic/sensor. 6498 mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback, 6499 WAITING_FOR_DRAWN_TIMEOUT); 6500 } 6501 6502 // Called on the DisplayManager's DisplayPowerController thread. 6503 @Override 6504 public void screenTurnedOff() { 6505 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off..."); 6506 6507 updateScreenOffSleepToken(true); 6508 synchronized (mLock) { 6509 mScreenOnEarly = false; 6510 mScreenOnFully = false; 6511 mKeyguardDrawComplete = false; 6512 mWindowManagerDrawComplete = false; 6513 mScreenOnListener = null; 6514 updateOrientationListenerLp(); 6515 6516 if (mKeyguardDelegate != null) { 6517 mKeyguardDelegate.onScreenTurnedOff(); 6518 } 6519 } 6520 } 6521 6522 // Called on the DisplayManager's DisplayPowerController thread. 6523 @Override 6524 public void screenTurningOn(final ScreenOnListener screenOnListener) { 6525 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on..."); 6526 6527 updateScreenOffSleepToken(false); 6528 synchronized (mLock) { 6529 mScreenOnEarly = true; 6530 mScreenOnFully = false; 6531 mKeyguardDrawComplete = false; 6532 mWindowManagerDrawComplete = false; 6533 mScreenOnListener = screenOnListener; 6534 6535 if (mKeyguardDelegate != null) { 6536 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6537 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000); 6538 mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback); 6539 } else { 6540 if (DEBUG_WAKEUP) Slog.d(TAG, 6541 "null mKeyguardDelegate: setting mKeyguardDrawComplete."); 6542 finishKeyguardDrawn(); 6543 } 6544 } 6545 } 6546 6547 // Called on the DisplayManager's DisplayPowerController thread. 6548 @Override 6549 public void screenTurnedOn() { 6550 synchronized (mLock) { 6551 if (mKeyguardDelegate != null) { 6552 mKeyguardDelegate.onScreenTurnedOn(); 6553 } 6554 } 6555 } 6556 6557 private void finishWindowsDrawn() { 6558 synchronized (mLock) { 6559 if (!mScreenOnEarly || mWindowManagerDrawComplete) { 6560 return; // Screen is not turned on or we did already handle this case earlier. 6561 } 6562 6563 mWindowManagerDrawComplete = true; 6564 } 6565 6566 finishScreenTurningOn(); 6567 } 6568 6569 private void finishScreenTurningOn() { 6570 synchronized (mLock) { 6571 // We have just finished drawing screen content. Since the orientation listener 6572 // gets only installed when all windows are drawn, we try to install it again. 6573 updateOrientationListenerLp(); 6574 } 6575 final ScreenOnListener listener; 6576 final boolean enableScreen; 6577 synchronized (mLock) { 6578 if (DEBUG_WAKEUP) Slog.d(TAG, 6579 "finishScreenTurningOn: mAwake=" + mAwake 6580 + ", mScreenOnEarly=" + mScreenOnEarly 6581 + ", mScreenOnFully=" + mScreenOnFully 6582 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete 6583 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete); 6584 6585 if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete 6586 || (mAwake && !mKeyguardDrawComplete)) { 6587 return; // spurious or not ready yet 6588 } 6589 6590 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on..."); 6591 listener = mScreenOnListener; 6592 mScreenOnListener = null; 6593 mScreenOnFully = true; 6594 6595 // Remember the first time we draw the keyguard so we know when we're done with 6596 // the main part of booting and can enable the screen and hide boot messages. 6597 if (!mKeyguardDrawnOnce && mAwake) { 6598 mKeyguardDrawnOnce = true; 6599 enableScreen = true; 6600 if (mBootMessageNeedsHiding) { 6601 mBootMessageNeedsHiding = false; 6602 hideBootMessages(); 6603 } 6604 } else { 6605 enableScreen = false; 6606 } 6607 } 6608 6609 if (listener != null) { 6610 listener.onScreenOn(); 6611 } 6612 6613 if (enableScreen) { 6614 try { 6615 mWindowManager.enableScreenIfNeeded(); 6616 } catch (RemoteException unhandled) { 6617 } 6618 } 6619 } 6620 6621 private void handleHideBootMessage() { 6622 synchronized (mLock) { 6623 if (!mKeyguardDrawnOnce) { 6624 mBootMessageNeedsHiding = true; 6625 return; // keyguard hasn't drawn the first time yet, not done booting 6626 } 6627 } 6628 6629 if (mBootMsgDialog != null) { 6630 if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing"); 6631 mBootMsgDialog.dismiss(); 6632 mBootMsgDialog = null; 6633 } 6634 } 6635 6636 @Override 6637 public boolean isScreenOn() { 6638 return mScreenOnFully; 6639 } 6640 6641 /** {@inheritDoc} */ 6642 @Override 6643 public void enableKeyguard(boolean enabled) { 6644 if (mKeyguardDelegate != null) { 6645 mKeyguardDelegate.setKeyguardEnabled(enabled); 6646 } 6647 } 6648 6649 /** {@inheritDoc} */ 6650 @Override 6651 public void exitKeyguardSecurely(OnKeyguardExitResult callback) { 6652 if (mKeyguardDelegate != null) { 6653 mKeyguardDelegate.verifyUnlock(callback); 6654 } 6655 } 6656 6657 @Override 6658 public boolean isKeyguardShowingAndNotOccluded() { 6659 if (mKeyguardDelegate == null) return false; 6660 return mKeyguardDelegate.isShowing() && !mKeyguardOccluded; 6661 } 6662 6663 /** {@inheritDoc} */ 6664 @Override 6665 public boolean isKeyguardLocked() { 6666 return keyguardOn(); 6667 } 6668 6669 /** {@inheritDoc} */ 6670 @Override 6671 public boolean isKeyguardSecure(int userId) { 6672 if (mKeyguardDelegate == null) return false; 6673 return mKeyguardDelegate.isSecure(userId); 6674 } 6675 6676 /** {@inheritDoc} */ 6677 @Override 6678 public boolean isKeyguardShowingOrOccluded() { 6679 return mKeyguardDelegate == null ? false : mKeyguardDelegate.isShowing(); 6680 } 6681 6682 /** {@inheritDoc} */ 6683 @Override 6684 public boolean inKeyguardRestrictedKeyInputMode() { 6685 if (mKeyguardDelegate == null) return false; 6686 return mKeyguardDelegate.isInputRestricted(); 6687 } 6688 6689 @Override 6690 public void dismissKeyguardLw() { 6691 if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) { 6692 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw"); 6693 mHandler.post(new Runnable() { 6694 @Override 6695 public void run() { 6696 // ask the keyguard to prompt the user to authenticate if necessary 6697 mKeyguardDelegate.dismiss(false /* allowWhileOccluded */); 6698 } 6699 }); 6700 } 6701 } 6702 6703 @Override 6704 public void notifyActivityDrawnForKeyguardLw() { 6705 if (mKeyguardDelegate != null) { 6706 mHandler.post(new Runnable() { 6707 @Override 6708 public void run() { 6709 mKeyguardDelegate.onActivityDrawn(); 6710 } 6711 }); 6712 } 6713 } 6714 6715 @Override 6716 public boolean isKeyguardDrawnLw() { 6717 synchronized (mLock) { 6718 return mKeyguardDrawnOnce; 6719 } 6720 } 6721 6722 @Override 6723 public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) { 6724 if (mKeyguardDelegate != null) { 6725 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation"); 6726 mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration); 6727 } 6728 } 6729 6730 @Override 6731 public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6732 Rect outInsets) { 6733 outInsets.setEmpty(); 6734 6735 // Navigation bar and status bar. 6736 getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets); 6737 if (mStatusBar != null) { 6738 outInsets.top = mStatusBarHeight; 6739 } 6740 } 6741 6742 @Override 6743 public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6744 Rect outInsets) { 6745 outInsets.setEmpty(); 6746 6747 // Only navigation bar 6748 if (mNavigationBar != null) { 6749 int position = navigationBarPosition(displayWidth, displayHeight, displayRotation); 6750 if (position == NAV_BAR_BOTTOM) { 6751 outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode); 6752 } else if (position == NAV_BAR_RIGHT) { 6753 outInsets.right = getNavigationBarWidth(displayRotation, mUiMode); 6754 } else if (position == NAV_BAR_LEFT) { 6755 outInsets.left = getNavigationBarWidth(displayRotation, mUiMode); 6756 } 6757 } 6758 } 6759 6760 @Override 6761 public boolean isNavBarForcedShownLw(WindowState windowState) { 6762 return mForceShowSystemBars; 6763 } 6764 6765 @Override 6766 public boolean isDockSideAllowed(int dockSide) { 6767 6768 // We do not allow all dock sides at which the navigation bar touches the docked stack. 6769 if (!mNavigationBarCanMove) { 6770 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT; 6771 } else { 6772 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT; 6773 } 6774 } 6775 6776 void sendCloseSystemWindows() { 6777 PhoneWindow.sendCloseSystemWindows(mContext, null); 6778 } 6779 6780 void sendCloseSystemWindows(String reason) { 6781 PhoneWindow.sendCloseSystemWindows(mContext, reason); 6782 } 6783 6784 @Override 6785 public int rotationForOrientationLw(int orientation, int lastRotation) { 6786 if (false) { 6787 Slog.v(TAG, "rotationForOrientationLw(orient=" 6788 + orientation + ", last=" + lastRotation 6789 + "); user=" + mUserRotation + " " 6790 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) 6791 ? "USER_ROTATION_LOCKED" : "") 6792 ); 6793 } 6794 6795 if (mForceDefaultOrientation) { 6796 return Surface.ROTATION_0; 6797 } 6798 6799 synchronized (mLock) { 6800 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1 6801 if (sensorRotation < 0) { 6802 sensorRotation = lastRotation; 6803 } 6804 6805 final int preferredRotation; 6806 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) { 6807 // Ignore sensor when lid switch is open and rotation is forced. 6808 preferredRotation = mLidOpenRotation; 6809 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR 6810 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) { 6811 // Ignore sensor when in car dock unless explicitly enabled. 6812 // This case can override the behavior of NOSENSOR, and can also 6813 // enable 180 degree rotation while docked. 6814 preferredRotation = mCarDockEnablesAccelerometer 6815 ? sensorRotation : mCarDockRotation; 6816 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK 6817 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK 6818 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK) 6819 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) { 6820 // Ignore sensor when in desk dock unless explicitly enabled. 6821 // This case can override the behavior of NOSENSOR, and can also 6822 // enable 180 degree rotation while docked. 6823 preferredRotation = mDeskDockEnablesAccelerometer 6824 ? sensorRotation : mDeskDockRotation; 6825 } else if (mHdmiPlugged && mDemoHdmiRotationLock) { 6826 // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled. 6827 // Note that the dock orientation overrides the HDMI orientation. 6828 preferredRotation = mDemoHdmiRotation; 6829 } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED 6830 && mUndockedHdmiRotation >= 0) { 6831 // Ignore sensor when plugged into HDMI and an undocked orientation has 6832 // been specified in the configuration (only for legacy devices without 6833 // full multi-display support). 6834 // Note that the dock orientation overrides the HDMI orientation. 6835 preferredRotation = mUndockedHdmiRotation; 6836 } else if (mDemoRotationLock) { 6837 // Ignore sensor when demo rotation lock is enabled. 6838 // Note that the dock orientation and HDMI rotation lock override this. 6839 preferredRotation = mDemoRotation; 6840 } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) { 6841 // Application just wants to remain locked in the last rotation. 6842 preferredRotation = lastRotation; 6843 } else if (!mSupportAutoRotation) { 6844 // If we don't support auto-rotation then bail out here and ignore 6845 // the sensor and any rotation lock settings. 6846 preferredRotation = -1; 6847 } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE 6848 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER 6849 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 6850 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE 6851 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT 6852 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER)) 6853 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR 6854 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6855 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE 6856 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) { 6857 // Otherwise, use sensor only if requested by the application or enabled 6858 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR. 6859 if (mAllowAllRotations < 0) { 6860 // Can't read this during init() because the context doesn't 6861 // have display metrics at that time so we cannot determine 6862 // tablet vs. phone then. 6863 mAllowAllRotations = mContext.getResources().getBoolean( 6864 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0; 6865 } 6866 if (sensorRotation != Surface.ROTATION_180 6867 || mAllowAllRotations == 1 6868 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6869 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) { 6870 preferredRotation = sensorRotation; 6871 } else { 6872 preferredRotation = lastRotation; 6873 } 6874 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED 6875 && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) { 6876 // Apply rotation lock. Does not apply to NOSENSOR. 6877 // The idea is that the user rotation expresses a weak preference for the direction 6878 // of gravity and as NOSENSOR is never affected by gravity, then neither should 6879 // NOSENSOR be affected by rotation lock (although it will be affected by docks). 6880 preferredRotation = mUserRotation; 6881 } else { 6882 // No overriding preference. 6883 // We will do exactly what the application asked us to do. 6884 preferredRotation = -1; 6885 } 6886 6887 switch (orientation) { 6888 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 6889 // Return portrait unless overridden. 6890 if (isAnyPortrait(preferredRotation)) { 6891 return preferredRotation; 6892 } 6893 return mPortraitRotation; 6894 6895 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 6896 // Return landscape unless overridden. 6897 if (isLandscapeOrSeascape(preferredRotation)) { 6898 return preferredRotation; 6899 } 6900 return mLandscapeRotation; 6901 6902 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 6903 // Return reverse portrait unless overridden. 6904 if (isAnyPortrait(preferredRotation)) { 6905 return preferredRotation; 6906 } 6907 return mUpsideDownRotation; 6908 6909 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 6910 // Return seascape unless overridden. 6911 if (isLandscapeOrSeascape(preferredRotation)) { 6912 return preferredRotation; 6913 } 6914 return mSeascapeRotation; 6915 6916 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 6917 case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE: 6918 // Return either landscape rotation. 6919 if (isLandscapeOrSeascape(preferredRotation)) { 6920 return preferredRotation; 6921 } 6922 if (isLandscapeOrSeascape(lastRotation)) { 6923 return lastRotation; 6924 } 6925 return mLandscapeRotation; 6926 6927 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 6928 case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT: 6929 // Return either portrait rotation. 6930 if (isAnyPortrait(preferredRotation)) { 6931 return preferredRotation; 6932 } 6933 if (isAnyPortrait(lastRotation)) { 6934 return lastRotation; 6935 } 6936 return mPortraitRotation; 6937 6938 default: 6939 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR, 6940 // just return the preferred orientation we already calculated. 6941 if (preferredRotation >= 0) { 6942 return preferredRotation; 6943 } 6944 return Surface.ROTATION_0; 6945 } 6946 } 6947 } 6948 6949 @Override 6950 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) { 6951 switch (orientation) { 6952 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 6953 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 6954 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 6955 return isAnyPortrait(rotation); 6956 6957 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 6958 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 6959 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 6960 return isLandscapeOrSeascape(rotation); 6961 6962 default: 6963 return true; 6964 } 6965 } 6966 6967 @Override 6968 public void setRotationLw(int rotation) { 6969 mOrientationListener.setCurrentRotation(rotation); 6970 } 6971 6972 private boolean isLandscapeOrSeascape(int rotation) { 6973 return rotation == mLandscapeRotation || rotation == mSeascapeRotation; 6974 } 6975 6976 private boolean isAnyPortrait(int rotation) { 6977 return rotation == mPortraitRotation || rotation == mUpsideDownRotation; 6978 } 6979 6980 @Override 6981 public int getUserRotationMode() { 6982 return Settings.System.getIntForUser(mContext.getContentResolver(), 6983 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ? 6984 WindowManagerPolicy.USER_ROTATION_FREE : 6985 WindowManagerPolicy.USER_ROTATION_LOCKED; 6986 } 6987 6988 // User rotation: to be used when all else fails in assigning an orientation to the device 6989 @Override 6990 public void setUserRotationMode(int mode, int rot) { 6991 ContentResolver res = mContext.getContentResolver(); 6992 6993 // mUserRotationMode and mUserRotation will be assigned by the content observer 6994 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) { 6995 Settings.System.putIntForUser(res, 6996 Settings.System.USER_ROTATION, 6997 rot, 6998 UserHandle.USER_CURRENT); 6999 Settings.System.putIntForUser(res, 7000 Settings.System.ACCELEROMETER_ROTATION, 7001 0, 7002 UserHandle.USER_CURRENT); 7003 } else { 7004 Settings.System.putIntForUser(res, 7005 Settings.System.ACCELEROMETER_ROTATION, 7006 1, 7007 UserHandle.USER_CURRENT); 7008 } 7009 } 7010 7011 @Override 7012 public void setSafeMode(boolean safeMode) { 7013 mSafeMode = safeMode; 7014 performHapticFeedbackLw(null, safeMode 7015 ? HapticFeedbackConstants.SAFE_MODE_ENABLED 7016 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true); 7017 } 7018 7019 static long[] getLongIntArray(Resources r, int resid) { 7020 int[] ar = r.getIntArray(resid); 7021 if (ar == null) { 7022 return null; 7023 } 7024 long[] out = new long[ar.length]; 7025 for (int i=0; i<ar.length; i++) { 7026 out[i] = ar[i]; 7027 } 7028 return out; 7029 } 7030 7031 /** {@inheritDoc} */ 7032 @Override 7033 public void systemReady() { 7034 mKeyguardDelegate = new KeyguardServiceDelegate(mContext, 7035 this::onKeyguardShowingStateChanged); 7036 mKeyguardDelegate.onSystemReady(); 7037 7038 readCameraLensCoverState(); 7039 updateUiMode(); 7040 boolean bindKeyguardNow; 7041 synchronized (mLock) { 7042 updateOrientationListenerLp(); 7043 mSystemReady = true; 7044 mHandler.post(new Runnable() { 7045 @Override 7046 public void run() { 7047 updateSettings(); 7048 } 7049 }); 7050 7051 bindKeyguardNow = mDeferBindKeyguard; 7052 if (bindKeyguardNow) { 7053 // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now. 7054 mDeferBindKeyguard = false; 7055 } 7056 } 7057 7058 if (bindKeyguardNow) { 7059 mKeyguardDelegate.bindService(mContext); 7060 mKeyguardDelegate.onBootCompleted(); 7061 } 7062 mSystemGestures.systemReady(); 7063 mImmersiveModeConfirmation.systemReady(); 7064 } 7065 7066 /** {@inheritDoc} */ 7067 @Override 7068 public void systemBooted() { 7069 boolean bindKeyguardNow = false; 7070 synchronized (mLock) { 7071 // Time to bind Keyguard; take care to only bind it once, either here if ready or 7072 // in systemReady if not. 7073 if (mKeyguardDelegate != null) { 7074 bindKeyguardNow = true; 7075 } else { 7076 // Because mKeyguardDelegate is null, we know that the synchronized block in 7077 // systemReady didn't run yet and setting this will actually have an effect. 7078 mDeferBindKeyguard = true; 7079 } 7080 } 7081 if (bindKeyguardNow) { 7082 mKeyguardDelegate.bindService(mContext); 7083 mKeyguardDelegate.onBootCompleted(); 7084 } 7085 synchronized (mLock) { 7086 mSystemBooted = true; 7087 } 7088 startedWakingUp(); 7089 screenTurningOn(null); 7090 screenTurnedOn(); 7091 } 7092 7093 ProgressDialog mBootMsgDialog = null; 7094 7095 /** {@inheritDoc} */ 7096 @Override 7097 public void showBootMessage(final CharSequence msg, final boolean always) { 7098 mHandler.post(new Runnable() { 7099 @Override public void run() { 7100 if (mBootMsgDialog == null) { 7101 int theme; 7102 if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) { 7103 theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert; 7104 } else { 7105 theme = 0; 7106 } 7107 7108 mBootMsgDialog = new ProgressDialog(mContext, theme) { 7109 // This dialog will consume all events coming in to 7110 // it, to avoid it trying to do things too early in boot. 7111 @Override public boolean dispatchKeyEvent(KeyEvent event) { 7112 return true; 7113 } 7114 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { 7115 return true; 7116 } 7117 @Override public boolean dispatchTouchEvent(MotionEvent ev) { 7118 return true; 7119 } 7120 @Override public boolean dispatchTrackballEvent(MotionEvent ev) { 7121 return true; 7122 } 7123 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) { 7124 return true; 7125 } 7126 @Override public boolean dispatchPopulateAccessibilityEvent( 7127 AccessibilityEvent event) { 7128 return true; 7129 } 7130 }; 7131 if (mContext.getPackageManager().isUpgrade()) { 7132 mBootMsgDialog.setTitle(R.string.android_upgrading_title); 7133 } else { 7134 mBootMsgDialog.setTitle(R.string.android_start_title); 7135 } 7136 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 7137 mBootMsgDialog.setIndeterminate(true); 7138 mBootMsgDialog.getWindow().setType( 7139 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS); 7140 mBootMsgDialog.getWindow().addFlags( 7141 WindowManager.LayoutParams.FLAG_DIM_BEHIND 7142 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); 7143 mBootMsgDialog.getWindow().setDimAmount(1); 7144 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes(); 7145 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 7146 mBootMsgDialog.getWindow().setAttributes(lp); 7147 mBootMsgDialog.setCancelable(false); 7148 mBootMsgDialog.show(); 7149 } 7150 mBootMsgDialog.setMessage(msg); 7151 } 7152 }); 7153 } 7154 7155 /** {@inheritDoc} */ 7156 @Override 7157 public void hideBootMessages() { 7158 mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE); 7159 } 7160 7161 /** {@inheritDoc} */ 7162 @Override 7163 public void userActivity() { 7164 // *************************************** 7165 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE 7166 // *************************************** 7167 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER 7168 // WITH ITS LOCKS HELD. 7169 // 7170 // This code must be VERY careful about the locks 7171 // it acquires. 7172 // In fact, the current code acquires way too many, 7173 // and probably has lurking deadlocks. 7174 7175 synchronized (mScreenLockTimeout) { 7176 if (mLockScreenTimerActive) { 7177 // reset the timer 7178 mHandler.removeCallbacks(mScreenLockTimeout); 7179 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7180 } 7181 } 7182 } 7183 7184 class ScreenLockTimeout implements Runnable { 7185 Bundle options; 7186 7187 @Override 7188 public void run() { 7189 synchronized (this) { 7190 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard"); 7191 if (mKeyguardDelegate != null) { 7192 mKeyguardDelegate.doKeyguardTimeout(options); 7193 } 7194 mLockScreenTimerActive = false; 7195 options = null; 7196 } 7197 } 7198 7199 public void setLockOptions(Bundle options) { 7200 this.options = options; 7201 } 7202 } 7203 7204 ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout(); 7205 7206 @Override 7207 public void lockNow(Bundle options) { 7208 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 7209 mHandler.removeCallbacks(mScreenLockTimeout); 7210 if (options != null) { 7211 // In case multiple calls are made to lockNow, we don't wipe out the options 7212 // until the runnable actually executes. 7213 mScreenLockTimeout.setLockOptions(options); 7214 } 7215 mHandler.post(mScreenLockTimeout); 7216 } 7217 7218 private void updateLockScreenTimeout() { 7219 synchronized (mScreenLockTimeout) { 7220 boolean enable = (mAllowLockscreenWhenOn && mAwake && 7221 mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId)); 7222 if (mLockScreenTimerActive != enable) { 7223 if (enable) { 7224 if (localLOGV) Log.v(TAG, "setting lockscreen timer"); 7225 mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests 7226 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7227 } else { 7228 if (localLOGV) Log.v(TAG, "clearing lockscreen timer"); 7229 mHandler.removeCallbacks(mScreenLockTimeout); 7230 } 7231 mLockScreenTimerActive = enable; 7232 } 7233 } 7234 } 7235 7236 private void updateDreamingSleepToken(boolean acquire) { 7237 if (acquire) { 7238 if (mDreamingSleepToken == null) { 7239 mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream"); 7240 } 7241 } else { 7242 if (mDreamingSleepToken != null) { 7243 mDreamingSleepToken.release(); 7244 mDreamingSleepToken = null; 7245 } 7246 } 7247 } 7248 7249 private void updateScreenOffSleepToken(boolean acquire) { 7250 if (acquire) { 7251 if (mScreenOffSleepToken == null) { 7252 mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff"); 7253 } 7254 } else { 7255 if (mScreenOffSleepToken != null) { 7256 mScreenOffSleepToken.release(); 7257 mScreenOffSleepToken = null; 7258 } 7259 } 7260 } 7261 7262 /** {@inheritDoc} */ 7263 @Override 7264 public void enableScreenAfterBoot() { 7265 readLidState(); 7266 applyLidSwitchState(); 7267 updateRotation(true); 7268 } 7269 7270 private void applyLidSwitchState() { 7271 if (mLidState == LID_CLOSED && mLidControlsSleep) { 7272 mPowerManager.goToSleep(SystemClock.uptimeMillis(), 7273 PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH, 7274 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); 7275 } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) { 7276 mWindowManagerFuncs.lockDeviceNow(); 7277 } 7278 7279 synchronized (mLock) { 7280 updateWakeGestureListenerLp(); 7281 } 7282 } 7283 7284 void updateUiMode() { 7285 if (mUiModeManager == null) { 7286 mUiModeManager = IUiModeManager.Stub.asInterface( 7287 ServiceManager.getService(Context.UI_MODE_SERVICE)); 7288 } 7289 try { 7290 mUiMode = mUiModeManager.getCurrentModeType(); 7291 } catch (RemoteException e) { 7292 } 7293 } 7294 7295 void updateRotation(boolean alwaysSendConfiguration) { 7296 try { 7297 //set orientation on WindowManager 7298 mWindowManager.updateRotation(alwaysSendConfiguration, false); 7299 } catch (RemoteException e) { 7300 // Ignore 7301 } 7302 } 7303 7304 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 7305 try { 7306 //set orientation on WindowManager 7307 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout); 7308 } catch (RemoteException e) { 7309 // Ignore 7310 } 7311 } 7312 7313 /** 7314 * Return an Intent to launch the currently active dock app as home. Returns 7315 * null if the standard home should be launched, which is the case if any of the following is 7316 * true: 7317 * <ul> 7318 * <li>The device is not in either car mode or desk mode 7319 * <li>The device is in car mode but mEnableCarDockHomeCapture is false 7320 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false 7321 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME 7322 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME 7323 * </ul> 7324 * @return A dock intent. 7325 */ 7326 Intent createHomeDockIntent() { 7327 Intent intent = null; 7328 7329 // What home does is based on the mode, not the dock state. That 7330 // is, when in car mode you should be taken to car home regardless 7331 // of whether we are actually in a car dock. 7332 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) { 7333 if (mEnableCarDockHomeCapture) { 7334 intent = mCarDockIntent; 7335 } 7336 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) { 7337 if (ENABLE_DESK_DOCK_HOME_CAPTURE) { 7338 intent = mDeskDockIntent; 7339 } 7340 } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH 7341 && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK 7342 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK 7343 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) { 7344 // Always launch dock home from home when watch is docked, if it exists. 7345 intent = mDeskDockIntent; 7346 } 7347 7348 if (intent == null) { 7349 return null; 7350 } 7351 7352 ActivityInfo ai = null; 7353 ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser( 7354 intent, 7355 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA, 7356 mCurrentUserId); 7357 if (info != null) { 7358 ai = info.activityInfo; 7359 } 7360 if (ai != null 7361 && ai.metaData != null 7362 && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) { 7363 intent = new Intent(intent); 7364 intent.setClassName(ai.packageName, ai.name); 7365 return intent; 7366 } 7367 7368 return null; 7369 } 7370 7371 void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) { 7372 if (awakenFromDreams) { 7373 awakenDreams(); 7374 } 7375 7376 Intent dock = createHomeDockIntent(); 7377 if (dock != null) { 7378 try { 7379 if (fromHomeKey) { 7380 dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7381 } 7382 startActivityAsUser(dock, UserHandle.CURRENT); 7383 return; 7384 } catch (ActivityNotFoundException e) { 7385 } 7386 } 7387 7388 Intent intent; 7389 7390 if (fromHomeKey) { 7391 intent = new Intent(mHomeIntent); 7392 intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7393 } else { 7394 intent = mHomeIntent; 7395 } 7396 7397 startActivityAsUser(intent, UserHandle.CURRENT); 7398 } 7399 7400 /** 7401 * goes to the home screen 7402 * @return whether it did anything 7403 */ 7404 boolean goHome() { 7405 if (!isUserSetupComplete()) { 7406 Slog.i(TAG, "Not going home because user setup is in progress."); 7407 return false; 7408 } 7409 if (false) { 7410 // This code always brings home to the front. 7411 try { 7412 ActivityManagerNative.getDefault().stopAppSwitches(); 7413 } catch (RemoteException e) { 7414 } 7415 sendCloseSystemWindows(); 7416 startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */); 7417 } else { 7418 // This code brings home to the front or, if it is already 7419 // at the front, puts the device to sleep. 7420 try { 7421 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) { 7422 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry. 7423 Log.d(TAG, "UTS-TEST-MODE"); 7424 } else { 7425 ActivityManagerNative.getDefault().stopAppSwitches(); 7426 sendCloseSystemWindows(); 7427 Intent dock = createHomeDockIntent(); 7428 if (dock != null) { 7429 int result = ActivityManagerNative.getDefault() 7430 .startActivityAsUser(null, null, dock, 7431 dock.resolveTypeIfNeeded(mContext.getContentResolver()), 7432 null, null, 0, 7433 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7434 null, null, UserHandle.USER_CURRENT); 7435 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7436 return false; 7437 } 7438 } 7439 } 7440 int result = ActivityManagerNative.getDefault() 7441 .startActivityAsUser(null, null, mHomeIntent, 7442 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()), 7443 null, null, 0, 7444 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7445 null, null, UserHandle.USER_CURRENT); 7446 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7447 return false; 7448 } 7449 } catch (RemoteException ex) { 7450 // bummer, the activity manager, which is in this process, is dead 7451 } 7452 } 7453 return true; 7454 } 7455 7456 @Override 7457 public void setCurrentOrientationLw(int newOrientation) { 7458 synchronized (mLock) { 7459 if (newOrientation != mCurrentAppOrientation) { 7460 mCurrentAppOrientation = newOrientation; 7461 updateOrientationListenerLp(); 7462 } 7463 } 7464 } 7465 7466 private void performAuditoryFeedbackForAccessibilityIfNeed() { 7467 if (!isGlobalAccessibilityGestureEnabled()) { 7468 return; 7469 } 7470 AudioManager audioManager = (AudioManager) mContext.getSystemService( 7471 Context.AUDIO_SERVICE); 7472 if (audioManager.isSilentMode()) { 7473 return; 7474 } 7475 Ringtone ringTone = RingtoneManager.getRingtone(mContext, 7476 Settings.System.DEFAULT_NOTIFICATION_URI); 7477 ringTone.setStreamType(AudioManager.STREAM_MUSIC); 7478 ringTone.play(); 7479 } 7480 7481 private boolean isTheaterModeEnabled() { 7482 return Settings.Global.getInt(mContext.getContentResolver(), 7483 Settings.Global.THEATER_MODE_ON, 0) == 1; 7484 } 7485 7486 private boolean isGlobalAccessibilityGestureEnabled() { 7487 return Settings.Global.getInt(mContext.getContentResolver(), 7488 Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1; 7489 } 7490 7491 private boolean areSystemNavigationKeysEnabled() { 7492 return Settings.Secure.getIntForUser(mContext.getContentResolver(), 7493 Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1; 7494 } 7495 7496 @Override 7497 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) { 7498 if (!mVibrator.hasVibrator()) { 7499 return false; 7500 } 7501 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(), 7502 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0; 7503 if (hapticsDisabled && !always) { 7504 return false; 7505 } 7506 long[] pattern = null; 7507 switch (effectId) { 7508 case HapticFeedbackConstants.LONG_PRESS: 7509 pattern = mLongPressVibePattern; 7510 break; 7511 case HapticFeedbackConstants.VIRTUAL_KEY: 7512 pattern = mVirtualKeyVibePattern; 7513 break; 7514 case HapticFeedbackConstants.KEYBOARD_TAP: 7515 pattern = mKeyboardTapVibePattern; 7516 break; 7517 case HapticFeedbackConstants.CLOCK_TICK: 7518 pattern = mClockTickVibePattern; 7519 break; 7520 case HapticFeedbackConstants.CALENDAR_DATE: 7521 pattern = mCalendarDateVibePattern; 7522 break; 7523 case HapticFeedbackConstants.SAFE_MODE_DISABLED: 7524 pattern = mSafeModeDisabledVibePattern; 7525 break; 7526 case HapticFeedbackConstants.SAFE_MODE_ENABLED: 7527 pattern = mSafeModeEnabledVibePattern; 7528 break; 7529 case HapticFeedbackConstants.CONTEXT_CLICK: 7530 pattern = mContextClickVibePattern; 7531 break; 7532 default: 7533 return false; 7534 } 7535 int owningUid; 7536 String owningPackage; 7537 if (win != null) { 7538 owningUid = win.getOwningUid(); 7539 owningPackage = win.getOwningPackage(); 7540 } else { 7541 owningUid = android.os.Process.myUid(); 7542 owningPackage = mContext.getOpPackageName(); 7543 } 7544 if (pattern.length == 1) { 7545 // One-shot vibration 7546 mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES); 7547 } else { 7548 // Pattern vibration 7549 mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES); 7550 } 7551 return true; 7552 } 7553 7554 @Override 7555 public void keepScreenOnStartedLw() { 7556 } 7557 7558 @Override 7559 public void keepScreenOnStoppedLw() { 7560 if (isKeyguardShowingAndNotOccluded()) { 7561 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 7562 } 7563 } 7564 7565 private int updateSystemUiVisibilityLw() { 7566 // If there is no window focused, there will be nobody to handle the events 7567 // anyway, so just hang on in whatever state we're in until things settle down. 7568 WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow 7569 : mTopFullscreenOpaqueWindowState; 7570 if (winCandidate == null) { 7571 return 0; 7572 } 7573 if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) { 7574 // The immersive mode confirmation should never affect the system bar visibility, 7575 // otherwise it will unhide the navigation bar and hide itself. 7576 winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState; 7577 if (winCandidate == null) { 7578 return 0; 7579 } 7580 } 7581 final WindowState win = winCandidate; 7582 if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) { 7583 // We are updating at a point where the keyguard has gotten 7584 // focus, but we were last in a state where the top window is 7585 // hiding it. This is probably because the keyguard as been 7586 // shown while the top window was displayed, so we want to ignore 7587 // it here because this is just a very transient change and it 7588 // will quickly lose focus once it correctly gets hidden. 7589 return 0; 7590 } 7591 7592 int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null) 7593 & ~mResettingSystemUiFlags 7594 & ~mForceClearedSystemUiFlags; 7595 if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) { 7596 tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS); 7597 } 7598 7599 final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */, 7600 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState); 7601 final int dockedVisibility = updateLightStatusBarLw(0 /* vis */, 7602 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState); 7603 mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds); 7604 mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds); 7605 final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility); 7606 final int diff = visibility ^ mLastSystemUiFlags; 7607 final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags; 7608 final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags; 7609 final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState); 7610 if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu 7611 && mFocusedApp == win.getAppToken() 7612 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds) 7613 && mLastDockedStackBounds.equals(mDockedStackBounds)) { 7614 return 0; 7615 } 7616 mLastSystemUiFlags = visibility; 7617 mLastFullscreenStackSysUiFlags = fullscreenVisibility; 7618 mLastDockedStackSysUiFlags = dockedVisibility; 7619 mLastFocusNeedsMenu = needsMenu; 7620 mFocusedApp = win.getAppToken(); 7621 final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds); 7622 final Rect dockedStackBounds = new Rect(mDockedStackBounds); 7623 mHandler.post(new Runnable() { 7624 @Override 7625 public void run() { 7626 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 7627 if (statusbar != null) { 7628 statusbar.setSystemUiVisibility(visibility, fullscreenVisibility, 7629 dockedVisibility, 0xffffffff, fullscreenStackBounds, 7630 dockedStackBounds, win.toString()); 7631 statusbar.topAppWindowChanged(needsMenu); 7632 } 7633 } 7634 }); 7635 return diff; 7636 } 7637 7638 private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) { 7639 WindowState statusColorWin = isStatusBarKeyguard() && !mHideLockScreen 7640 ? mStatusBar 7641 : opaqueOrDimming; 7642 7643 if (statusColorWin != null) { 7644 if (statusColorWin == opaque) { 7645 // If the top fullscreen-or-dimming window is also the top fullscreen, respect 7646 // its light flag. 7647 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7648 vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null) 7649 & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7650 } else if (statusColorWin != null && statusColorWin.isDimming()) { 7651 // Otherwise if it's dimming, clear the light flag. 7652 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7653 } 7654 } 7655 return vis; 7656 } 7657 7658 private boolean drawsSystemBarBackground(WindowState win) { 7659 return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0; 7660 } 7661 7662 private boolean forcesDrawStatusBarBackground(WindowState win) { 7663 return win == null || (win.getAttrs().privateFlags 7664 & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0; 7665 } 7666 7667 private int updateSystemBarsLw(WindowState win, int oldVis, int vis) { 7668 final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID); 7669 final boolean freeformStackVisible = 7670 mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID); 7671 final boolean resizing = mWindowManagerInternal.isDockedDividerResizing(); 7672 7673 // We need to force system bars when the docked stack is visible, when the freeform stack 7674 // is visible but also when we are resizing for the transitions when docked stack 7675 // visibility changes. 7676 mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing; 7677 final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard; 7678 7679 // apply translucent bar vis flags 7680 WindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen 7681 ? mStatusBar 7682 : mTopFullscreenOpaqueWindowState; 7683 vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7684 vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7685 final int dockedVis = mStatusBarController.applyTranslucentFlagLw( 7686 mTopDockedOpaqueWindowState, 0, 0); 7687 7688 final boolean fullscreenDrawsStatusBarBackground = 7689 (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState) 7690 && (vis & View.STATUS_BAR_TRANSLUCENT) == 0) 7691 || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState); 7692 final boolean dockedDrawsStatusBarBackground = 7693 (drawsSystemBarBackground(mTopDockedOpaqueWindowState) 7694 && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0) 7695 || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState); 7696 7697 // prevent status bar interaction from clearing certain flags 7698 int type = win.getAttrs().type; 7699 boolean statusBarHasFocus = type == TYPE_STATUS_BAR; 7700 if (statusBarHasFocus && !isStatusBarKeyguard()) { 7701 int flags = View.SYSTEM_UI_FLAG_FULLSCREEN 7702 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 7703 | View.SYSTEM_UI_FLAG_IMMERSIVE 7704 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 7705 | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7706 if (mHideLockScreen) { 7707 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT; 7708 } 7709 vis = (vis & ~flags) | (oldVis & flags); 7710 } 7711 7712 if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) { 7713 vis |= View.STATUS_BAR_TRANSPARENT; 7714 vis &= ~View.STATUS_BAR_TRANSLUCENT; 7715 } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar) 7716 || forceOpaqueStatusBar) { 7717 vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT); 7718 } 7719 7720 vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing); 7721 7722 // update status bar 7723 boolean immersiveSticky = 7724 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7725 final boolean hideStatusBarWM = 7726 mTopFullscreenOpaqueWindowState != null 7727 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null) 7728 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; 7729 final boolean hideStatusBarSysui = 7730 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 7731 final boolean hideNavBarSysui = 7732 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0; 7733 7734 final boolean transientStatusBarAllowed = mStatusBar != null 7735 && (statusBarHasFocus || (!mForceShowSystemBars 7736 && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky)))); 7737 7738 final boolean transientNavBarAllowed = mNavigationBar != null 7739 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky; 7740 7741 final long now = SystemClock.uptimeMillis(); 7742 final boolean pendingPanic = mPendingPanicGestureUptime != 0 7743 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION; 7744 if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) { 7745 // The user performed the panic gesture recently, we're about to hide the bars, 7746 // we're no longer on the Keyguard and the screen is ready. We can now request the bars. 7747 mPendingPanicGestureUptime = 0; 7748 mStatusBarController.showTransient(); 7749 if (!isNavBarEmpty(vis)) { 7750 mNavigationBarController.showTransient(); 7751 } 7752 } 7753 7754 final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested() 7755 && !transientStatusBarAllowed && hideStatusBarSysui; 7756 final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested() 7757 && !transientNavBarAllowed; 7758 if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) { 7759 // clear the clearable flags instead 7760 clearClearableFlagsLw(); 7761 vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS; 7762 } 7763 7764 final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; 7765 immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7766 final boolean navAllowedHidden = immersive || immersiveSticky; 7767 7768 if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType()) 7769 > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) { 7770 // We can't hide the navbar from this window otherwise the input consumer would not get 7771 // the input events. 7772 vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); 7773 } 7774 7775 vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis); 7776 7777 // update navigation bar 7778 boolean oldImmersiveMode = isImmersiveMode(oldVis); 7779 boolean newImmersiveMode = isImmersiveMode(vis); 7780 if (win != null && oldImmersiveMode != newImmersiveMode) { 7781 final String pkg = win.getOwningPackage(); 7782 mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode, 7783 isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility())); 7784 } 7785 7786 vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis); 7787 7788 return vis; 7789 } 7790 7791 /** 7792 * @return the current visibility flags with the nav-bar opacity related flags toggled based 7793 * on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}. 7794 */ 7795 private int configureNavBarOpacity(int visibility, boolean dockedStackVisible, 7796 boolean freeformStackVisible, boolean isDockedDividerResizing) { 7797 if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) { 7798 if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) { 7799 visibility = setNavBarOpaqueFlag(visibility); 7800 } 7801 } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) { 7802 if (isDockedDividerResizing) { 7803 visibility = setNavBarOpaqueFlag(visibility); 7804 } else if (freeformStackVisible) { 7805 visibility = setNavBarTranslucentFlag(visibility); 7806 } else { 7807 visibility = setNavBarOpaqueFlag(visibility); 7808 } 7809 } 7810 7811 if (!areTranslucentBarsAllowed()) { 7812 visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT; 7813 } 7814 return visibility; 7815 } 7816 7817 private int setNavBarOpaqueFlag(int visibility) { 7818 return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT); 7819 } 7820 7821 private int setNavBarTranslucentFlag(int visibility) { 7822 visibility &= ~View.NAVIGATION_BAR_TRANSPARENT; 7823 return visibility |= View.NAVIGATION_BAR_TRANSLUCENT; 7824 } 7825 7826 private void clearClearableFlagsLw() { 7827 int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS; 7828 if (newVal != mResettingSystemUiFlags) { 7829 mResettingSystemUiFlags = newVal; 7830 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 7831 } 7832 } 7833 7834 private boolean isImmersiveMode(int vis) { 7835 final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; 7836 return mNavigationBar != null 7837 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0 7838 && (vis & flags) != 0 7839 && canHideNavigationBar(); 7840 } 7841 7842 private static boolean isNavBarEmpty(int systemUiFlags) { 7843 final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME 7844 | View.STATUS_BAR_DISABLE_BACK 7845 | View.STATUS_BAR_DISABLE_RECENT); 7846 7847 return (systemUiFlags & disableNavigationBar) == disableNavigationBar; 7848 } 7849 7850 /** 7851 * @return whether the navigation or status bar can be made translucent 7852 * 7853 * This should return true unless touch exploration is not enabled or 7854 * R.boolean.config_enableTranslucentDecor is false. 7855 */ 7856 private boolean areTranslucentBarsAllowed() { 7857 return mTranslucentDecorEnabled; 7858 } 7859 7860 // Use this instead of checking config_showNavigationBar so that it can be consistently 7861 // overridden by qemu.hw.mainkeys in the emulator. 7862 @Override 7863 public boolean hasNavigationBar() { 7864 return mHasNavigationBar; 7865 } 7866 7867 @Override 7868 public void setLastInputMethodWindowLw(WindowState ime, WindowState target) { 7869 mLastInputMethodWindow = ime; 7870 mLastInputMethodTargetWindow = target; 7871 } 7872 7873 @Override 7874 public int getInputMethodWindowVisibleHeightLw() { 7875 return mDockBottom - mCurBottom; 7876 } 7877 7878 @Override 7879 public void setCurrentUserLw(int newUserId) { 7880 mCurrentUserId = newUserId; 7881 if (mKeyguardDelegate != null) { 7882 mKeyguardDelegate.setCurrentUser(newUserId); 7883 } 7884 StatusBarManagerInternal statusBar = getStatusBarManagerInternal(); 7885 if (statusBar != null) { 7886 statusBar.setCurrentUser(newUserId); 7887 } 7888 setLastInputMethodWindowLw(null, null); 7889 } 7890 7891 @Override 7892 public void setSwitchingUser(boolean switching) { 7893 mKeyguardDelegate.setSwitchingUser(switching); 7894 } 7895 7896 @Override 7897 public boolean canMagnifyWindow(int windowType) { 7898 switch (windowType) { 7899 case WindowManager.LayoutParams.TYPE_INPUT_METHOD: 7900 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: 7901 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR: 7902 case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: { 7903 return false; 7904 } 7905 } 7906 return true; 7907 } 7908 7909 @Override 7910 public boolean isTopLevelWindow(int windowType) { 7911 if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW 7912 && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 7913 return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG); 7914 } 7915 return true; 7916 } 7917 7918 @Override 7919 public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) { 7920 // For the upside down rotation we don't rotate seamlessly as the navigation 7921 // bar moves position. 7922 // Note most apps (using orientation:sensor or user as opposed to fullSensor) 7923 // will not enter the reverse portrait orientation, so actually the 7924 // orientation won't change at all. 7925 if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) { 7926 return false; 7927 } 7928 int delta = newRotation - oldRotation; 7929 if (delta < 0) delta += 4; 7930 // Likewise we don't rotate seamlessly for 180 degree rotations 7931 // in this case the surfaces never resize, and our logic to 7932 // revert the transformations on size change will fail. We could 7933 // fix this in the future with the "tagged" frames idea. 7934 if (delta == Surface.ROTATION_180) { 7935 return false; 7936 } 7937 7938 final WindowState w = mTopFullscreenOpaqueWindowState; 7939 if (w != mFocusedWindow) { 7940 return false; 7941 } 7942 7943 // We only enable seamless rotation if the top window has requested 7944 // it and is in the fullscreen opaque state. Seamless rotation 7945 // requires freezing various Surface states and won't work well 7946 // with animations, so we disable it in the animation case for now. 7947 if (w != null && !w.isAnimatingLw() && 7948 ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) || 7949 (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) { 7950 return true; 7951 } 7952 return false; 7953 } 7954 7955 @Override 7956 public void dump(String prefix, PrintWriter pw, String[] args) { 7957 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode); 7958 pw.print(" mSystemReady="); pw.print(mSystemReady); 7959 pw.print(" mSystemBooted="); pw.println(mSystemBooted); 7960 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState); 7961 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation); 7962 pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState); 7963 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged); 7964 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0 7965 || mForceClearedSystemUiFlags != 0) { 7966 pw.print(prefix); pw.print("mLastSystemUiFlags=0x"); 7967 pw.print(Integer.toHexString(mLastSystemUiFlags)); 7968 pw.print(" mResettingSystemUiFlags=0x"); 7969 pw.print(Integer.toHexString(mResettingSystemUiFlags)); 7970 pw.print(" mForceClearedSystemUiFlags=0x"); 7971 pw.println(Integer.toHexString(mForceClearedSystemUiFlags)); 7972 } 7973 if (mLastFocusNeedsMenu) { 7974 pw.print(prefix); pw.print("mLastFocusNeedsMenu="); 7975 pw.println(mLastFocusNeedsMenu); 7976 } 7977 pw.print(prefix); pw.print("mWakeGestureEnabledSetting="); 7978 pw.println(mWakeGestureEnabledSetting); 7979 7980 pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation); 7981 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode); 7982 pw.print(" mDockMode="); pw.print(mDockMode); 7983 pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture); 7984 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation); 7985 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation); 7986 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode); 7987 pw.print(" mUserRotation="); pw.print(mUserRotation); 7988 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations); 7989 pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation); 7990 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer="); 7991 pw.print(mCarDockEnablesAccelerometer); 7992 pw.print(" mDeskDockEnablesAccelerometer="); 7993 pw.println(mDeskDockEnablesAccelerometer); 7994 pw.print(prefix); pw.print("mLidKeyboardAccessibility="); 7995 pw.print(mLidKeyboardAccessibility); 7996 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility); 7997 pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock); 7998 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep); 7999 pw.print(prefix); 8000 pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior); 8001 pw.print(prefix); 8002 pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior); 8003 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior); 8004 pw.print(prefix); 8005 pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior); 8006 pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior); 8007 pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput); 8008 pw.print(prefix); pw.print("mAwake="); pw.println(mAwake); 8009 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly); 8010 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully); 8011 pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete); 8012 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete); 8013 pw.print(prefix); pw.print("mOrientationSensorEnabled="); 8014 pw.println(mOrientationSensorEnabled); 8015 pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft); 8016 pw.print(","); pw.print(mOverscanScreenTop); 8017 pw.print(") "); pw.print(mOverscanScreenWidth); 8018 pw.print("x"); pw.println(mOverscanScreenHeight); 8019 if (mOverscanLeft != 0 || mOverscanTop != 0 8020 || mOverscanRight != 0 || mOverscanBottom != 0) { 8021 pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft); 8022 pw.print(" top="); pw.print(mOverscanTop); 8023 pw.print(" right="); pw.print(mOverscanRight); 8024 pw.print(" bottom="); pw.println(mOverscanBottom); 8025 } 8026 pw.print(prefix); pw.print("mRestrictedOverscanScreen=("); 8027 pw.print(mRestrictedOverscanScreenLeft); 8028 pw.print(","); pw.print(mRestrictedOverscanScreenTop); 8029 pw.print(") "); pw.print(mRestrictedOverscanScreenWidth); 8030 pw.print("x"); pw.println(mRestrictedOverscanScreenHeight); 8031 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft); 8032 pw.print(","); pw.print(mUnrestrictedScreenTop); 8033 pw.print(") "); pw.print(mUnrestrictedScreenWidth); 8034 pw.print("x"); pw.println(mUnrestrictedScreenHeight); 8035 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft); 8036 pw.print(","); pw.print(mRestrictedScreenTop); 8037 pw.print(") "); pw.print(mRestrictedScreenWidth); 8038 pw.print("x"); pw.println(mRestrictedScreenHeight); 8039 pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft); 8040 pw.print(","); pw.print(mStableFullscreenTop); 8041 pw.print(")-("); pw.print(mStableFullscreenRight); 8042 pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")"); 8043 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft); 8044 pw.print(","); pw.print(mStableTop); 8045 pw.print(")-("); pw.print(mStableRight); 8046 pw.print(","); pw.print(mStableBottom); pw.println(")"); 8047 pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft); 8048 pw.print(","); pw.print(mSystemTop); 8049 pw.print(")-("); pw.print(mSystemRight); 8050 pw.print(","); pw.print(mSystemBottom); pw.println(")"); 8051 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft); 8052 pw.print(","); pw.print(mCurTop); 8053 pw.print(")-("); pw.print(mCurRight); 8054 pw.print(","); pw.print(mCurBottom); pw.println(")"); 8055 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft); 8056 pw.print(","); pw.print(mContentTop); 8057 pw.print(")-("); pw.print(mContentRight); 8058 pw.print(","); pw.print(mContentBottom); pw.println(")"); 8059 pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft); 8060 pw.print(","); pw.print(mVoiceContentTop); 8061 pw.print(")-("); pw.print(mVoiceContentRight); 8062 pw.print(","); pw.print(mVoiceContentBottom); pw.println(")"); 8063 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft); 8064 pw.print(","); pw.print(mDockTop); 8065 pw.print(")-("); pw.print(mDockRight); 8066 pw.print(","); pw.print(mDockBottom); pw.println(")"); 8067 pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer); 8068 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer); 8069 pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen); 8070 pw.print(" mShowingDream="); pw.print(mShowingDream); 8071 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen); 8072 pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken); 8073 if (mLastInputMethodWindow != null) { 8074 pw.print(prefix); pw.print("mLastInputMethodWindow="); 8075 pw.println(mLastInputMethodWindow); 8076 } 8077 if (mLastInputMethodTargetWindow != null) { 8078 pw.print(prefix); pw.print("mLastInputMethodTargetWindow="); 8079 pw.println(mLastInputMethodTargetWindow); 8080 } 8081 if (mStatusBar != null) { 8082 pw.print(prefix); pw.print("mStatusBar="); 8083 pw.print(mStatusBar); pw.print(" isStatusBarKeyguard="); 8084 pw.println(isStatusBarKeyguard()); 8085 } 8086 if (mNavigationBar != null) { 8087 pw.print(prefix); pw.print("mNavigationBar="); 8088 pw.println(mNavigationBar); 8089 } 8090 if (mFocusedWindow != null) { 8091 pw.print(prefix); pw.print("mFocusedWindow="); 8092 pw.println(mFocusedWindow); 8093 } 8094 if (mFocusedApp != null) { 8095 pw.print(prefix); pw.print("mFocusedApp="); 8096 pw.println(mFocusedApp); 8097 } 8098 if (mWinDismissingKeyguard != null) { 8099 pw.print(prefix); pw.print("mWinDismissingKeyguard="); 8100 pw.println(mWinDismissingKeyguard); 8101 } 8102 if (mTopFullscreenOpaqueWindowState != null) { 8103 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState="); 8104 pw.println(mTopFullscreenOpaqueWindowState); 8105 } 8106 if (mTopFullscreenOpaqueOrDimmingWindowState != null) { 8107 pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState="); 8108 pw.println(mTopFullscreenOpaqueOrDimmingWindowState); 8109 } 8110 if (mForcingShowNavBar) { 8111 pw.print(prefix); pw.print("mForcingShowNavBar="); 8112 pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer="); 8113 pw.println(mForcingShowNavBarLayer); 8114 } 8115 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen); 8116 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen); 8117 pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar); 8118 pw.print(" mForceStatusBarFromKeyguard="); 8119 pw.println(mForceStatusBarFromKeyguard); 8120 pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard); 8121 pw.print(" mCurrentlyDismissingKeyguard="); pw.println(mCurrentlyDismissingKeyguard); 8122 pw.print(" mWinDismissingKeyguard="); pw.print(mWinDismissingKeyguard); 8123 pw.print(" mHomePressed="); pw.println(mHomePressed); 8124 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn); 8125 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout); 8126 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive); 8127 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior); 8128 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior); 8129 pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior); 8130 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior); 8131 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation); 8132 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation); 8133 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation); 8134 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation); 8135 pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation); 8136 pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock); 8137 pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation); 8138 8139 mGlobalKeyManager.dump(prefix, pw); 8140 mStatusBarController.dump(pw, prefix); 8141 mNavigationBarController.dump(pw, prefix); 8142 PolicyControl.dump(prefix, pw); 8143 8144 if (mWakeGestureListener != null) { 8145 mWakeGestureListener.dump(pw, prefix); 8146 } 8147 if (mOrientationListener != null) { 8148 mOrientationListener.dump(pw, prefix); 8149 } 8150 if (mBurnInProtectionHelper != null) { 8151 mBurnInProtectionHelper.dump(prefix, pw); 8152 } 8153 if (mKeyguardDelegate != null) { 8154 mKeyguardDelegate.dump(prefix, pw); 8155 } 8156 } 8157} 8158