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