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