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