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