PhoneWindowManager.java revision 1b7c5631c4e572f911e996f1f928de5adebfd47a
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 if (panic) { 1029 mHandler.post(mHiddenNavPanic); 1030 } 1031 1032 // Latch power key state to detect screenshot chord. 1033 if (interactive && !mScreenshotChordPowerKeyTriggered 1034 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 1035 mScreenshotChordPowerKeyTriggered = true; 1036 mScreenshotChordPowerKeyTime = event.getDownTime(); 1037 interceptScreenshotChord(); 1038 } 1039 1040 // Stop ringing or end call if configured to do so when power is pressed. 1041 TelecomManager telecomManager = getTelecommService(); 1042 boolean hungUp = false; 1043 if (telecomManager != null) { 1044 if (telecomManager.isRinging()) { 1045 // Pressing Power while there's a ringing incoming 1046 // call should silence the ringer. 1047 telecomManager.silenceRinger(); 1048 } else if ((mIncallPowerBehavior 1049 & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0 1050 && telecomManager.isInCall() && interactive) { 1051 // Otherwise, if "Power button ends call" is enabled, 1052 // the Power button will hang up any current active call. 1053 hungUp = telecomManager.endCall(); 1054 } 1055 } 1056 1057 GestureLauncherService gestureService = LocalServices.getService( 1058 GestureLauncherService.class); 1059 boolean gesturedServiceIntercepted = false; 1060 if (gestureService != null) { 1061 gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive, 1062 mTmpBoolean); 1063 if (mTmpBoolean.value && mGoingToSleep) { 1064 mCameraGestureTriggeredDuringGoingToSleep = true; 1065 } 1066 } 1067 1068 // If the power key has still not yet been handled, then detect short 1069 // press, long press, or multi press and decide what to do. 1070 mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered 1071 || mScreenshotChordVolumeUpKeyTriggered || gesturedServiceIntercepted; 1072 if (!mPowerKeyHandled) { 1073 if (interactive) { 1074 // When interactive, we're already awake. 1075 // Wait for a long press or for the button to be released to decide what to do. 1076 if (hasLongPressOnPowerBehavior()) { 1077 Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS); 1078 msg.setAsynchronous(true); 1079 mHandler.sendMessageDelayed(msg, 1080 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 1081 } 1082 } else { 1083 wakeUpFromPowerKey(event.getDownTime()); 1084 1085 if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) { 1086 Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS); 1087 msg.setAsynchronous(true); 1088 mHandler.sendMessageDelayed(msg, 1089 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 1090 mBeganFromNonInteractive = true; 1091 } else { 1092 final int maxCount = getMaxMultiPressPowerCount(); 1093 1094 if (maxCount <= 1) { 1095 mPowerKeyHandled = true; 1096 } else { 1097 mBeganFromNonInteractive = true; 1098 } 1099 } 1100 } 1101 } 1102 } 1103 1104 private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) { 1105 final boolean handled = canceled || mPowerKeyHandled; 1106 mScreenshotChordPowerKeyTriggered = false; 1107 cancelPendingScreenshotChordAction(); 1108 cancelPendingPowerKeyAction(); 1109 1110 if (!handled) { 1111 // Figure out how to handle the key now that it has been released. 1112 mPowerKeyPressCounter += 1; 1113 1114 final int maxCount = getMaxMultiPressPowerCount(); 1115 final long eventTime = event.getDownTime(); 1116 if (mPowerKeyPressCounter < maxCount) { 1117 // This could be a multi-press. Wait a little bit longer to confirm. 1118 // Continue holding the wake lock. 1119 Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS, 1120 interactive ? 1 : 0, mPowerKeyPressCounter, eventTime); 1121 msg.setAsynchronous(true); 1122 mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout()); 1123 return; 1124 } 1125 1126 // No other actions. Handle it immediately. 1127 powerPress(eventTime, interactive, mPowerKeyPressCounter); 1128 } 1129 1130 // Done. Reset our state. 1131 finishPowerKeyPress(); 1132 } 1133 1134 private void finishPowerKeyPress() { 1135 mBeganFromNonInteractive = false; 1136 mPowerKeyPressCounter = 0; 1137 if (mPowerKeyWakeLock.isHeld()) { 1138 mPowerKeyWakeLock.release(); 1139 } 1140 } 1141 1142 private void cancelPendingPowerKeyAction() { 1143 if (!mPowerKeyHandled) { 1144 mPowerKeyHandled = true; 1145 mHandler.removeMessages(MSG_POWER_LONG_PRESS); 1146 } 1147 } 1148 1149 private void cancelPendingBackKeyAction() { 1150 if (!mBackKeyHandled) { 1151 mBackKeyHandled = true; 1152 mHandler.removeMessages(MSG_BACK_LONG_PRESS); 1153 } 1154 } 1155 1156 private void powerPress(long eventTime, boolean interactive, int count) { 1157 if (mScreenOnEarly && !mScreenOnFully) { 1158 Slog.i(TAG, "Suppressed redundant power key press while " 1159 + "already in the process of turning the screen on."); 1160 return; 1161 } 1162 1163 if (count == 2) { 1164 powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior); 1165 } else if (count == 3) { 1166 powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior); 1167 } else if (interactive && !mBeganFromNonInteractive) { 1168 switch (mShortPressOnPowerBehavior) { 1169 case SHORT_PRESS_POWER_NOTHING: 1170 break; 1171 case SHORT_PRESS_POWER_GO_TO_SLEEP: 1172 mPowerManager.goToSleep(eventTime, 1173 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); 1174 break; 1175 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP: 1176 mPowerManager.goToSleep(eventTime, 1177 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 1178 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); 1179 break; 1180 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME: 1181 mPowerManager.goToSleep(eventTime, 1182 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 1183 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); 1184 launchHomeFromHotKey(); 1185 break; 1186 case SHORT_PRESS_POWER_GO_HOME: 1187 launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/); 1188 break; 1189 } 1190 } 1191 } 1192 1193 private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) { 1194 switch (behavior) { 1195 case MULTI_PRESS_POWER_NOTHING: 1196 break; 1197 case MULTI_PRESS_POWER_THEATER_MODE: 1198 if (!isUserSetupComplete()) { 1199 Slog.i(TAG, "Ignoring toggling theater mode - device not setup."); 1200 break; 1201 } 1202 1203 if (isTheaterModeEnabled()) { 1204 Slog.i(TAG, "Toggling theater mode off."); 1205 Settings.Global.putInt(mContext.getContentResolver(), 1206 Settings.Global.THEATER_MODE_ON, 0); 1207 if (!interactive) { 1208 wakeUpFromPowerKey(eventTime); 1209 } 1210 } else { 1211 Slog.i(TAG, "Toggling theater mode on."); 1212 Settings.Global.putInt(mContext.getContentResolver(), 1213 Settings.Global.THEATER_MODE_ON, 1); 1214 1215 if (mGoToSleepOnButtonPressTheaterMode && interactive) { 1216 mPowerManager.goToSleep(eventTime, 1217 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); 1218 } 1219 } 1220 break; 1221 case MULTI_PRESS_POWER_BRIGHTNESS_BOOST: 1222 Slog.i(TAG, "Starting brightness boost."); 1223 if (!interactive) { 1224 wakeUpFromPowerKey(eventTime); 1225 } 1226 mPowerManager.boostScreenBrightness(eventTime); 1227 break; 1228 } 1229 } 1230 1231 private int getMaxMultiPressPowerCount() { 1232 if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) { 1233 return 3; 1234 } 1235 if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) { 1236 return 2; 1237 } 1238 return 1; 1239 } 1240 1241 private void powerLongPress() { 1242 final int behavior = getResolvedLongPressOnPowerBehavior(); 1243 switch (behavior) { 1244 case LONG_PRESS_POWER_NOTHING: 1245 break; 1246 case LONG_PRESS_POWER_GLOBAL_ACTIONS: 1247 mPowerKeyHandled = true; 1248 if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) { 1249 performAuditoryFeedbackForAccessibilityIfNeed(); 1250 } 1251 showGlobalActionsInternal(); 1252 break; 1253 case LONG_PRESS_POWER_SHUT_OFF: 1254 case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM: 1255 mPowerKeyHandled = true; 1256 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); 1257 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); 1258 mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF); 1259 break; 1260 } 1261 } 1262 1263 private void backLongPress() { 1264 mBackKeyHandled = true; 1265 1266 switch (mLongPressOnBackBehavior) { 1267 case LONG_PRESS_BACK_NOTHING: 1268 break; 1269 case LONG_PRESS_BACK_GO_TO_VOICE_ASSIST: 1270 Intent intent = new Intent(Intent.ACTION_VOICE_ASSIST); 1271 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); 1272 break; 1273 } 1274 } 1275 1276 private void disposeInputConsumer(InputConsumer inputConsumer) { 1277 if (inputConsumer != null) { 1278 inputConsumer.dismiss(); 1279 } 1280 } 1281 1282 private void sleepPress(long eventTime) { 1283 if (mShortPressOnSleepBehavior == SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME) { 1284 launchHomeFromHotKey(false /* awakenDreams */, true /*respectKeyguard*/); 1285 } 1286 } 1287 1288 private void sleepRelease(long eventTime) { 1289 switch (mShortPressOnSleepBehavior) { 1290 case SHORT_PRESS_SLEEP_GO_TO_SLEEP: 1291 case SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME: 1292 Slog.i(TAG, "sleepRelease() calling goToSleep(GO_TO_SLEEP_REASON_SLEEP_BUTTON)"); 1293 mPowerManager.goToSleep(eventTime, 1294 PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON, 0); 1295 break; 1296 } 1297 } 1298 1299 private int getResolvedLongPressOnPowerBehavior() { 1300 if (FactoryTest.isLongPressOnPowerOffEnabled()) { 1301 return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM; 1302 } 1303 return mLongPressOnPowerBehavior; 1304 } 1305 1306 private boolean hasLongPressOnPowerBehavior() { 1307 return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING; 1308 } 1309 1310 private boolean hasLongPressOnBackBehavior() { 1311 return mLongPressOnBackBehavior != LONG_PRESS_BACK_NOTHING; 1312 } 1313 1314 private void interceptScreenshotChord() { 1315 if (mScreenshotChordEnabled 1316 && mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered 1317 && !mScreenshotChordVolumeUpKeyTriggered) { 1318 final long now = SystemClock.uptimeMillis(); 1319 if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS 1320 && now <= mScreenshotChordPowerKeyTime 1321 + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) { 1322 mScreenshotChordVolumeDownKeyConsumed = true; 1323 cancelPendingPowerKeyAction(); 1324 mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN); 1325 mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay()); 1326 } 1327 } 1328 } 1329 1330 private long getScreenshotChordLongPressDelay() { 1331 if (mKeyguardDelegate.isShowing()) { 1332 // Double the time it takes to take a screenshot from the keyguard 1333 return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER * 1334 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 1335 } 1336 return ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout(); 1337 } 1338 1339 private void cancelPendingScreenshotChordAction() { 1340 mHandler.removeCallbacks(mScreenshotRunnable); 1341 } 1342 1343 private final Runnable mEndCallLongPress = new Runnable() { 1344 @Override 1345 public void run() { 1346 mEndCallKeyHandled = true; 1347 if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) { 1348 performAuditoryFeedbackForAccessibilityIfNeed(); 1349 } 1350 showGlobalActionsInternal(); 1351 } 1352 }; 1353 1354 private class ScreenshotRunnable implements Runnable { 1355 private int mScreenshotType = TAKE_SCREENSHOT_FULLSCREEN; 1356 1357 public void setScreenshotType(int screenshotType) { 1358 mScreenshotType = screenshotType; 1359 } 1360 1361 @Override 1362 public void run() { 1363 takeScreenshot(mScreenshotType); 1364 } 1365 } 1366 1367 private final ScreenshotRunnable mScreenshotRunnable = new ScreenshotRunnable(); 1368 1369 @Override 1370 public void showGlobalActions() { 1371 mHandler.removeMessages(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS); 1372 mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS); 1373 } 1374 1375 void showGlobalActionsInternal() { 1376 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); 1377 if (mGlobalActions == null) { 1378 mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs); 1379 } 1380 final boolean keyguardShowing = isKeyguardShowingAndNotOccluded(); 1381 mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned()); 1382 if (keyguardShowing) { 1383 // since it took two seconds of long press to bring this up, 1384 // poke the wake lock so they have some time to see the dialog. 1385 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 1386 } 1387 } 1388 1389 boolean isDeviceProvisioned() { 1390 return Settings.Global.getInt( 1391 mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0; 1392 } 1393 1394 boolean isUserSetupComplete() { 1395 return Settings.Secure.getIntForUser(mContext.getContentResolver(), 1396 Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0; 1397 } 1398 1399 private void handleShortPressOnHome() { 1400 // Turn on the connected TV and switch HDMI input if we're a HDMI playback device. 1401 getHdmiControl().turnOnTv(); 1402 1403 // If there's a dream running then use home to escape the dream 1404 // but don't actually go home. 1405 if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) { 1406 mDreamManagerInternal.stopDream(false /*immediate*/); 1407 return; 1408 } 1409 1410 // Go home! 1411 launchHomeFromHotKey(); 1412 } 1413 1414 /** 1415 * Creates an accessor to HDMI control service that performs the operation of 1416 * turning on TV (optional) and switching input to us. If HDMI control service 1417 * is not available or we're not a HDMI playback device, the operation is no-op. 1418 */ 1419 private HdmiControl getHdmiControl() { 1420 if (null == mHdmiControl) { 1421 HdmiControlManager manager = (HdmiControlManager) mContext.getSystemService( 1422 Context.HDMI_CONTROL_SERVICE); 1423 HdmiPlaybackClient client = null; 1424 if (manager != null) { 1425 client = manager.getPlaybackClient(); 1426 } 1427 mHdmiControl = new HdmiControl(client); 1428 } 1429 return mHdmiControl; 1430 } 1431 1432 private static class HdmiControl { 1433 private final HdmiPlaybackClient mClient; 1434 1435 private HdmiControl(HdmiPlaybackClient client) { 1436 mClient = client; 1437 } 1438 1439 public void turnOnTv() { 1440 if (mClient == null) { 1441 return; 1442 } 1443 mClient.oneTouchPlay(new OneTouchPlayCallback() { 1444 @Override 1445 public void onComplete(int result) { 1446 if (result != HdmiControlManager.RESULT_SUCCESS) { 1447 Log.w(TAG, "One touch play failed: " + result); 1448 } 1449 } 1450 }); 1451 } 1452 } 1453 1454 private void handleLongPressOnHome(int deviceId) { 1455 if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_NOTHING) { 1456 return; 1457 } 1458 mHomeConsumed = true; 1459 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); 1460 1461 switch (mLongPressOnHomeBehavior) { 1462 case LONG_PRESS_HOME_RECENT_SYSTEM_UI: 1463 toggleRecentApps(); 1464 break; 1465 case LONG_PRESS_HOME_ASSIST: 1466 launchAssistAction(null, deviceId); 1467 break; 1468 default: 1469 Log.w(TAG, "Undefined home long press behavior: " + mLongPressOnHomeBehavior); 1470 break; 1471 } 1472 } 1473 1474 private void handleDoubleTapOnHome() { 1475 if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) { 1476 mHomeConsumed = true; 1477 toggleRecentApps(); 1478 } 1479 } 1480 1481 private void showTvPictureInPictureMenu(KeyEvent event) { 1482 if (DEBUG_INPUT) Log.d(TAG, "showTvPictureInPictureMenu event=" + event); 1483 mHandler.removeMessages(MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU); 1484 Message msg = mHandler.obtainMessage(MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU); 1485 msg.setAsynchronous(true); 1486 msg.sendToTarget(); 1487 } 1488 1489 private void showTvPictureInPictureMenuInternal() { 1490 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 1491 if (statusbar != null) { 1492 statusbar.showTvPictureInPictureMenu(); 1493 } 1494 } 1495 1496 private final Runnable mHomeDoubleTapTimeoutRunnable = new Runnable() { 1497 @Override 1498 public void run() { 1499 if (mHomeDoubleTapPending) { 1500 mHomeDoubleTapPending = false; 1501 handleShortPressOnHome(); 1502 } 1503 } 1504 }; 1505 1506 private boolean isRoundWindow() { 1507 return mContext.getResources().getConfiguration().isScreenRound(); 1508 } 1509 1510 /** {@inheritDoc} */ 1511 @Override 1512 public void init(Context context, IWindowManager windowManager, 1513 WindowManagerFuncs windowManagerFuncs) { 1514 mContext = context; 1515 mWindowManager = windowManager; 1516 mWindowManagerFuncs = windowManagerFuncs; 1517 mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); 1518 mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); 1519 mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); 1520 mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class); 1521 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 1522 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 1523 mHasFeatureWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH); 1524 1525 // Init display burn-in protection 1526 boolean burnInProtectionEnabled = context.getResources().getBoolean( 1527 com.android.internal.R.bool.config_enableBurnInProtection); 1528 // Allow a system property to override this. Used by developer settings. 1529 boolean burnInProtectionDevMode = 1530 SystemProperties.getBoolean("persist.debug.force_burn_in", false); 1531 if (burnInProtectionEnabled || burnInProtectionDevMode) { 1532 final int minHorizontal; 1533 final int maxHorizontal; 1534 final int minVertical; 1535 final int maxVertical; 1536 final int maxRadius; 1537 if (burnInProtectionDevMode) { 1538 minHorizontal = -8; 1539 maxHorizontal = 8; 1540 minVertical = -8; 1541 maxVertical = -4; 1542 maxRadius = (isRoundWindow()) ? 6 : -1; 1543 } else { 1544 Resources resources = context.getResources(); 1545 minHorizontal = resources.getInteger( 1546 com.android.internal.R.integer.config_burnInProtectionMinHorizontalOffset); 1547 maxHorizontal = resources.getInteger( 1548 com.android.internal.R.integer.config_burnInProtectionMaxHorizontalOffset); 1549 minVertical = resources.getInteger( 1550 com.android.internal.R.integer.config_burnInProtectionMinVerticalOffset); 1551 maxVertical = resources.getInteger( 1552 com.android.internal.R.integer.config_burnInProtectionMaxVerticalOffset); 1553 maxRadius = resources.getInteger( 1554 com.android.internal.R.integer.config_burnInProtectionMaxRadius); 1555 } 1556 mBurnInProtectionHelper = new BurnInProtectionHelper( 1557 context, minHorizontal, maxHorizontal, minVertical, maxVertical, maxRadius); 1558 } 1559 1560 mHandler = new PolicyHandler(); 1561 mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler); 1562 mOrientationListener = new MyOrientationListener(mContext, mHandler); 1563 try { 1564 mOrientationListener.setCurrentRotation(windowManager.getRotation()); 1565 } catch (RemoteException ex) { } 1566 mSettingsObserver = new SettingsObserver(mHandler); 1567 mSettingsObserver.observe(); 1568 mShortcutManager = new ShortcutManager(context); 1569 mUiMode = context.getResources().getInteger( 1570 com.android.internal.R.integer.config_defaultUiModeType); 1571 mHomeIntent = new Intent(Intent.ACTION_MAIN, null); 1572 mHomeIntent.addCategory(Intent.CATEGORY_HOME); 1573 mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 1574 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 1575 mEnableCarDockHomeCapture = context.getResources().getBoolean( 1576 com.android.internal.R.bool.config_enableCarDockHomeLaunch); 1577 mCarDockIntent = new Intent(Intent.ACTION_MAIN, null); 1578 mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK); 1579 mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 1580 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 1581 mDeskDockIntent = new Intent(Intent.ACTION_MAIN, null); 1582 mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK); 1583 mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 1584 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 1585 1586 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 1587 mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 1588 "PhoneWindowManager.mBroadcastWakeLock"); 1589 mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 1590 "PhoneWindowManager.mPowerKeyWakeLock"); 1591 mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable")); 1592 mSupportAutoRotation = mContext.getResources().getBoolean( 1593 com.android.internal.R.bool.config_supportAutoRotation); 1594 mLidOpenRotation = readRotation( 1595 com.android.internal.R.integer.config_lidOpenRotation); 1596 mCarDockRotation = readRotation( 1597 com.android.internal.R.integer.config_carDockRotation); 1598 mDeskDockRotation = readRotation( 1599 com.android.internal.R.integer.config_deskDockRotation); 1600 mUndockedHdmiRotation = readRotation( 1601 com.android.internal.R.integer.config_undockedHdmiRotation); 1602 mCarDockEnablesAccelerometer = mContext.getResources().getBoolean( 1603 com.android.internal.R.bool.config_carDockEnablesAccelerometer); 1604 mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean( 1605 com.android.internal.R.bool.config_deskDockEnablesAccelerometer); 1606 mLidKeyboardAccessibility = mContext.getResources().getInteger( 1607 com.android.internal.R.integer.config_lidKeyboardAccessibility); 1608 mLidNavigationAccessibility = mContext.getResources().getInteger( 1609 com.android.internal.R.integer.config_lidNavigationAccessibility); 1610 mLidControlsScreenLock = mContext.getResources().getBoolean( 1611 com.android.internal.R.bool.config_lidControlsScreenLock); 1612 mLidControlsSleep = mContext.getResources().getBoolean( 1613 com.android.internal.R.bool.config_lidControlsSleep); 1614 mTranslucentDecorEnabled = mContext.getResources().getBoolean( 1615 com.android.internal.R.bool.config_enableTranslucentDecor); 1616 1617 mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean( 1618 com.android.internal.R.bool.config_allowTheaterModeWakeFromKey); 1619 mAllowTheaterModeWakeFromPowerKey = mAllowTheaterModeWakeFromKey 1620 || mContext.getResources().getBoolean( 1621 com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey); 1622 mAllowTheaterModeWakeFromMotion = mContext.getResources().getBoolean( 1623 com.android.internal.R.bool.config_allowTheaterModeWakeFromMotion); 1624 mAllowTheaterModeWakeFromMotionWhenNotDreaming = mContext.getResources().getBoolean( 1625 com.android.internal.R.bool.config_allowTheaterModeWakeFromMotionWhenNotDreaming); 1626 mAllowTheaterModeWakeFromCameraLens = mContext.getResources().getBoolean( 1627 com.android.internal.R.bool.config_allowTheaterModeWakeFromCameraLens); 1628 mAllowTheaterModeWakeFromLidSwitch = mContext.getResources().getBoolean( 1629 com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch); 1630 mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean( 1631 com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture); 1632 1633 mGoToSleepOnButtonPressTheaterMode = mContext.getResources().getBoolean( 1634 com.android.internal.R.bool.config_goToSleepOnButtonPressTheaterMode); 1635 1636 mSupportLongPressPowerWhenNonInteractive = mContext.getResources().getBoolean( 1637 com.android.internal.R.bool.config_supportLongPressPowerWhenNonInteractive); 1638 1639 mLongPressOnBackBehavior = mContext.getResources().getInteger( 1640 com.android.internal.R.integer.config_longPressOnBackBehavior); 1641 1642 mShortPressOnPowerBehavior = mContext.getResources().getInteger( 1643 com.android.internal.R.integer.config_shortPressOnPowerBehavior); 1644 mLongPressOnPowerBehavior = mContext.getResources().getInteger( 1645 com.android.internal.R.integer.config_longPressOnPowerBehavior); 1646 mDoublePressOnPowerBehavior = mContext.getResources().getInteger( 1647 com.android.internal.R.integer.config_doublePressOnPowerBehavior); 1648 mTriplePressOnPowerBehavior = mContext.getResources().getInteger( 1649 com.android.internal.R.integer.config_triplePressOnPowerBehavior); 1650 mShortPressOnSleepBehavior = mContext.getResources().getInteger( 1651 com.android.internal.R.integer.config_shortPressOnSleepBehavior); 1652 1653 mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION; 1654 1655 readConfigurationDependentBehaviors(); 1656 1657 mAccessibilityManager = (AccessibilityManager) context.getSystemService( 1658 Context.ACCESSIBILITY_SERVICE); 1659 1660 // register for dock events 1661 IntentFilter filter = new IntentFilter(); 1662 filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE); 1663 filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE); 1664 filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE); 1665 filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE); 1666 filter.addAction(Intent.ACTION_DOCK_EVENT); 1667 Intent intent = context.registerReceiver(mDockReceiver, filter); 1668 if (intent != null) { 1669 // Retrieve current sticky dock event broadcast. 1670 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 1671 Intent.EXTRA_DOCK_STATE_UNDOCKED); 1672 } 1673 1674 // register for dream-related broadcasts 1675 filter = new IntentFilter(); 1676 filter.addAction(Intent.ACTION_DREAMING_STARTED); 1677 filter.addAction(Intent.ACTION_DREAMING_STOPPED); 1678 context.registerReceiver(mDreamReceiver, filter); 1679 1680 // register for multiuser-relevant broadcasts 1681 filter = new IntentFilter(Intent.ACTION_USER_SWITCHED); 1682 context.registerReceiver(mMultiuserReceiver, filter); 1683 1684 // monitor for system gestures 1685 mSystemGestures = new SystemGesturesPointerEventListener(context, 1686 new SystemGesturesPointerEventListener.Callbacks() { 1687 @Override 1688 public void onSwipeFromTop() { 1689 if (mStatusBar != null) { 1690 requestTransientBars(mStatusBar); 1691 } 1692 } 1693 @Override 1694 public void onSwipeFromBottom() { 1695 if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_BOTTOM) { 1696 requestTransientBars(mNavigationBar); 1697 } 1698 } 1699 @Override 1700 public void onSwipeFromRight() { 1701 if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_RIGHT) { 1702 requestTransientBars(mNavigationBar); 1703 } 1704 } 1705 @Override 1706 public void onSwipeFromLeft() { 1707 if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_LEFT) { 1708 requestTransientBars(mNavigationBar); 1709 } 1710 } 1711 @Override 1712 public void onFling(int duration) { 1713 if (mPowerManagerInternal != null) { 1714 mPowerManagerInternal.powerHint( 1715 PowerManagerInternal.POWER_HINT_INTERACTION, duration); 1716 } 1717 } 1718 @Override 1719 public void onDebug() { 1720 // no-op 1721 } 1722 @Override 1723 public void onDown() { 1724 mOrientationListener.onTouchStart(); 1725 } 1726 @Override 1727 public void onUpOrCancel() { 1728 mOrientationListener.onTouchEnd(); 1729 } 1730 @Override 1731 public void onMouseHoverAtTop() { 1732 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS); 1733 Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS); 1734 msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS; 1735 mHandler.sendMessageDelayed(msg, 500); 1736 } 1737 @Override 1738 public void onMouseHoverAtBottom() { 1739 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS); 1740 Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS); 1741 msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION; 1742 mHandler.sendMessageDelayed(msg, 500); 1743 } 1744 @Override 1745 public void onMouseLeaveFromEdge() { 1746 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS); 1747 } 1748 }); 1749 mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext); 1750 mWindowManagerFuncs.registerPointerEventListener(mSystemGestures); 1751 1752 mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE); 1753 mLongPressVibePattern = getLongIntArray(mContext.getResources(), 1754 com.android.internal.R.array.config_longPressVibePattern); 1755 mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(), 1756 com.android.internal.R.array.config_virtualKeyVibePattern); 1757 mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(), 1758 com.android.internal.R.array.config_keyboardTapVibePattern); 1759 mClockTickVibePattern = getLongIntArray(mContext.getResources(), 1760 com.android.internal.R.array.config_clockTickVibePattern); 1761 mCalendarDateVibePattern = getLongIntArray(mContext.getResources(), 1762 com.android.internal.R.array.config_calendarDateVibePattern); 1763 mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(), 1764 com.android.internal.R.array.config_safeModeDisabledVibePattern); 1765 mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(), 1766 com.android.internal.R.array.config_safeModeEnabledVibePattern); 1767 mContextClickVibePattern = getLongIntArray(mContext.getResources(), 1768 com.android.internal.R.array.config_contextClickVibePattern); 1769 1770 mScreenshotChordEnabled = mContext.getResources().getBoolean( 1771 com.android.internal.R.bool.config_enableScreenshotChord); 1772 1773 mGlobalKeyManager = new GlobalKeyManager(mContext); 1774 1775 // Controls rotation and the like. 1776 initializeHdmiState(); 1777 1778 // Match current screen state. 1779 if (!mPowerManager.isInteractive()) { 1780 startedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER); 1781 finishedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER); 1782 } 1783 1784 mWindowManagerInternal.registerAppTransitionListener( 1785 mStatusBarController.getAppTransitionListener()); 1786 } 1787 1788 /** 1789 * Read values from config.xml that may be overridden depending on 1790 * the configuration of the device. 1791 * eg. Disable long press on home goes to recents on sw600dp. 1792 */ 1793 private void readConfigurationDependentBehaviors() { 1794 final Resources res = mContext.getResources(); 1795 1796 mLongPressOnHomeBehavior = res.getInteger( 1797 com.android.internal.R.integer.config_longPressOnHomeBehavior); 1798 if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING || 1799 mLongPressOnHomeBehavior > LAST_LONG_PRESS_HOME_BEHAVIOR) { 1800 mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING; 1801 } 1802 1803 mDoubleTapOnHomeBehavior = res.getInteger( 1804 com.android.internal.R.integer.config_doubleTapOnHomeBehavior); 1805 if (mDoubleTapOnHomeBehavior < DOUBLE_TAP_HOME_NOTHING || 1806 mDoubleTapOnHomeBehavior > DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) { 1807 mDoubleTapOnHomeBehavior = LONG_PRESS_HOME_NOTHING; 1808 } 1809 1810 mShortPressWindowBehavior = SHORT_PRESS_WINDOW_NOTHING; 1811 if (mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) { 1812 mShortPressWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE; 1813 } 1814 1815 mNavBarOpacityMode = res.getInteger( 1816 com.android.internal.R.integer.config_navBarOpacityMode); 1817 } 1818 1819 @Override 1820 public void setInitialDisplaySize(Display display, int width, int height, int density) { 1821 // This method might be called before the policy has been fully initialized 1822 // or for other displays we don't care about. 1823 if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) { 1824 return; 1825 } 1826 mDisplay = display; 1827 1828 final Resources res = mContext.getResources(); 1829 int shortSize, longSize; 1830 if (width > height) { 1831 shortSize = height; 1832 longSize = width; 1833 mLandscapeRotation = Surface.ROTATION_0; 1834 mSeascapeRotation = Surface.ROTATION_180; 1835 if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) { 1836 mPortraitRotation = Surface.ROTATION_90; 1837 mUpsideDownRotation = Surface.ROTATION_270; 1838 } else { 1839 mPortraitRotation = Surface.ROTATION_270; 1840 mUpsideDownRotation = Surface.ROTATION_90; 1841 } 1842 } else { 1843 shortSize = width; 1844 longSize = height; 1845 mPortraitRotation = Surface.ROTATION_0; 1846 mUpsideDownRotation = Surface.ROTATION_180; 1847 if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) { 1848 mLandscapeRotation = Surface.ROTATION_270; 1849 mSeascapeRotation = Surface.ROTATION_90; 1850 } else { 1851 mLandscapeRotation = Surface.ROTATION_90; 1852 mSeascapeRotation = Surface.ROTATION_270; 1853 } 1854 } 1855 1856 // SystemUI (status bar) layout policy 1857 int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density; 1858 int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density; 1859 1860 // Allow the navigation bar to move on non-square small devices (phones). 1861 mNavigationBarCanMove = width != height && shortSizeDp < 600; 1862 1863 mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar); 1864 1865 // Allow a system property to override this. Used by the emulator. 1866 // See also hasNavigationBar(). 1867 String navBarOverride = SystemProperties.get("qemu.hw.mainkeys"); 1868 if ("1".equals(navBarOverride)) { 1869 mHasNavigationBar = false; 1870 } else if ("0".equals(navBarOverride)) { 1871 mHasNavigationBar = true; 1872 } 1873 1874 // For demo purposes, allow the rotation of the HDMI display to be controlled. 1875 // By default, HDMI locks rotation to landscape. 1876 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) { 1877 mDemoHdmiRotation = mPortraitRotation; 1878 } else { 1879 mDemoHdmiRotation = mLandscapeRotation; 1880 } 1881 mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false); 1882 1883 // For demo purposes, allow the rotation of the remote display to be controlled. 1884 // By default, remote display locks rotation to landscape. 1885 if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) { 1886 mDemoRotation = mPortraitRotation; 1887 } else { 1888 mDemoRotation = mLandscapeRotation; 1889 } 1890 mDemoRotationLock = SystemProperties.getBoolean( 1891 "persist.demo.rotationlock", false); 1892 1893 // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per 1894 // http://developer.android.com/guide/practices/screens_support.html#range 1895 mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 && 1896 res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) && 1897 // For debug purposes the next line turns this feature off with: 1898 // $ adb shell setprop config.override_forced_orient true 1899 // $ adb shell wm size reset 1900 !"true".equals(SystemProperties.get("config.override_forced_orient")); 1901 } 1902 1903 /** 1904 * @return whether the navigation bar can be hidden, e.g. the device has a 1905 * navigation bar and touch exploration is not enabled 1906 */ 1907 private boolean canHideNavigationBar() { 1908 return mHasNavigationBar; 1909 } 1910 1911 @Override 1912 public boolean isDefaultOrientationForced() { 1913 return mForceDefaultOrientation; 1914 } 1915 1916 @Override 1917 public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) { 1918 if (display.getDisplayId() == Display.DEFAULT_DISPLAY) { 1919 mOverscanLeft = left; 1920 mOverscanTop = top; 1921 mOverscanRight = right; 1922 mOverscanBottom = bottom; 1923 } 1924 } 1925 1926 public void updateSettings() { 1927 ContentResolver resolver = mContext.getContentResolver(); 1928 boolean updateRotation = false; 1929 synchronized (mLock) { 1930 mEndcallBehavior = Settings.System.getIntForUser(resolver, 1931 Settings.System.END_BUTTON_BEHAVIOR, 1932 Settings.System.END_BUTTON_BEHAVIOR_DEFAULT, 1933 UserHandle.USER_CURRENT); 1934 mIncallPowerBehavior = Settings.Secure.getIntForUser(resolver, 1935 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR, 1936 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT, 1937 UserHandle.USER_CURRENT); 1938 1939 // Configure wake gesture. 1940 boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver, 1941 Settings.Secure.WAKE_GESTURE_ENABLED, 0, 1942 UserHandle.USER_CURRENT) != 0; 1943 if (mWakeGestureEnabledSetting != wakeGestureEnabledSetting) { 1944 mWakeGestureEnabledSetting = wakeGestureEnabledSetting; 1945 updateWakeGestureListenerLp(); 1946 } 1947 1948 // Configure rotation lock. 1949 int userRotation = Settings.System.getIntForUser(resolver, 1950 Settings.System.USER_ROTATION, Surface.ROTATION_0, 1951 UserHandle.USER_CURRENT); 1952 if (mUserRotation != userRotation) { 1953 mUserRotation = userRotation; 1954 updateRotation = true; 1955 } 1956 int userRotationMode = Settings.System.getIntForUser(resolver, 1957 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ? 1958 WindowManagerPolicy.USER_ROTATION_FREE : 1959 WindowManagerPolicy.USER_ROTATION_LOCKED; 1960 if (mUserRotationMode != userRotationMode) { 1961 mUserRotationMode = userRotationMode; 1962 updateRotation = true; 1963 updateOrientationListenerLp(); 1964 } 1965 1966 if (mSystemReady) { 1967 int pointerLocation = Settings.System.getIntForUser(resolver, 1968 Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT); 1969 if (mPointerLocationMode != pointerLocation) { 1970 mPointerLocationMode = pointerLocation; 1971 mHandler.sendEmptyMessage(pointerLocation != 0 ? 1972 MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION); 1973 } 1974 } 1975 // use screen off timeout setting as the timeout for the lockscreen 1976 mLockScreenTimeout = Settings.System.getIntForUser(resolver, 1977 Settings.System.SCREEN_OFF_TIMEOUT, 0, UserHandle.USER_CURRENT); 1978 String imId = Settings.Secure.getStringForUser(resolver, 1979 Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.USER_CURRENT); 1980 boolean hasSoftInput = imId != null && imId.length() > 0; 1981 if (mHasSoftInput != hasSoftInput) { 1982 mHasSoftInput = hasSoftInput; 1983 updateRotation = true; 1984 } 1985 if (mImmersiveModeConfirmation != null) { 1986 mImmersiveModeConfirmation.loadSetting(mCurrentUserId); 1987 } 1988 } 1989 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 1990 PolicyControl.reloadFromSetting(mContext); 1991 } 1992 if (updateRotation) { 1993 updateRotation(true); 1994 } 1995 } 1996 1997 private void updateWakeGestureListenerLp() { 1998 if (shouldEnableWakeGestureLp()) { 1999 mWakeGestureListener.requestWakeUpTrigger(); 2000 } else { 2001 mWakeGestureListener.cancelWakeUpTrigger(); 2002 } 2003 } 2004 2005 private boolean shouldEnableWakeGestureLp() { 2006 return mWakeGestureEnabledSetting && !mAwake 2007 && (!mLidControlsSleep || mLidState != LID_CLOSED) 2008 && mWakeGestureListener.isSupported(); 2009 } 2010 2011 private void enablePointerLocation() { 2012 if (mPointerLocationView == null) { 2013 mPointerLocationView = new PointerLocationView(mContext); 2014 mPointerLocationView.setPrintCoords(false); 2015 WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 2016 WindowManager.LayoutParams.MATCH_PARENT, 2017 WindowManager.LayoutParams.MATCH_PARENT); 2018 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY; 2019 lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN 2020 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE 2021 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 2022 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; 2023 if (ActivityManager.isHighEndGfx()) { 2024 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; 2025 lp.privateFlags |= 2026 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED; 2027 } 2028 lp.format = PixelFormat.TRANSLUCENT; 2029 lp.setTitle("PointerLocation"); 2030 WindowManager wm = (WindowManager) 2031 mContext.getSystemService(Context.WINDOW_SERVICE); 2032 lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; 2033 wm.addView(mPointerLocationView, lp); 2034 mWindowManagerFuncs.registerPointerEventListener(mPointerLocationView); 2035 } 2036 } 2037 2038 private void disablePointerLocation() { 2039 if (mPointerLocationView != null) { 2040 mWindowManagerFuncs.unregisterPointerEventListener(mPointerLocationView); 2041 WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); 2042 wm.removeView(mPointerLocationView); 2043 mPointerLocationView = null; 2044 } 2045 } 2046 2047 private int readRotation(int resID) { 2048 try { 2049 int rotation = mContext.getResources().getInteger(resID); 2050 switch (rotation) { 2051 case 0: 2052 return Surface.ROTATION_0; 2053 case 90: 2054 return Surface.ROTATION_90; 2055 case 180: 2056 return Surface.ROTATION_180; 2057 case 270: 2058 return Surface.ROTATION_270; 2059 } 2060 } catch (Resources.NotFoundException e) { 2061 // fall through 2062 } 2063 return -1; 2064 } 2065 2066 /** {@inheritDoc} */ 2067 @Override 2068 public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) { 2069 int type = attrs.type; 2070 2071 outAppOp[0] = AppOpsManager.OP_NONE; 2072 2073 if (!((type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) 2074 || (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) 2075 || (type >= FIRST_SYSTEM_WINDOW && type <= LAST_SYSTEM_WINDOW))) { 2076 return WindowManagerGlobal.ADD_INVALID_TYPE; 2077 } 2078 2079 if (type < FIRST_SYSTEM_WINDOW || type > LAST_SYSTEM_WINDOW) { 2080 // Window manager will make sure these are okay. 2081 return WindowManagerGlobal.ADD_OKAY; 2082 } 2083 String permission = null; 2084 switch (type) { 2085 case TYPE_TOAST: 2086 // XXX right now the app process has complete control over 2087 // this... should introduce a token to let the system 2088 // monitor/control what they are doing. 2089 outAppOp[0] = AppOpsManager.OP_TOAST_WINDOW; 2090 break; 2091 case TYPE_DREAM: 2092 case TYPE_INPUT_METHOD: 2093 case TYPE_WALLPAPER: 2094 case TYPE_PRIVATE_PRESENTATION: 2095 case TYPE_VOICE_INTERACTION: 2096 case TYPE_ACCESSIBILITY_OVERLAY: 2097 case TYPE_QS_DIALOG: 2098 // The window manager will check these. 2099 break; 2100 case TYPE_PHONE: 2101 case TYPE_PRIORITY_PHONE: 2102 case TYPE_SYSTEM_ALERT: 2103 case TYPE_SYSTEM_ERROR: 2104 case TYPE_SYSTEM_OVERLAY: 2105 permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW; 2106 outAppOp[0] = AppOpsManager.OP_SYSTEM_ALERT_WINDOW; 2107 break; 2108 default: 2109 permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; 2110 } 2111 if (permission != null) { 2112 if (android.Manifest.permission.SYSTEM_ALERT_WINDOW.equals(permission)) { 2113 final int callingUid = Binder.getCallingUid(); 2114 // system processes will be automatically allowed privilege to draw 2115 if (callingUid == Process.SYSTEM_UID) { 2116 return WindowManagerGlobal.ADD_OKAY; 2117 } 2118 2119 // check if user has enabled this operation. SecurityException will be thrown if 2120 // this app has not been allowed by the user 2121 final int mode = mAppOpsManager.checkOpNoThrow(outAppOp[0], callingUid, 2122 attrs.packageName); 2123 switch (mode) { 2124 case AppOpsManager.MODE_ALLOWED: 2125 case AppOpsManager.MODE_IGNORED: 2126 // although we return ADD_OKAY for MODE_IGNORED, the added window will 2127 // actually be hidden in WindowManagerService 2128 return WindowManagerGlobal.ADD_OKAY; 2129 case AppOpsManager.MODE_ERRORED: 2130 try { 2131 ApplicationInfo appInfo = mContext.getPackageManager() 2132 .getApplicationInfo(attrs.packageName, 2133 UserHandle.getUserId(callingUid)); 2134 // Don't crash legacy apps 2135 if (appInfo.targetSdkVersion < Build.VERSION_CODES.M) { 2136 return WindowManagerGlobal.ADD_OKAY; 2137 } 2138 } catch (PackageManager.NameNotFoundException e) { 2139 /* ignore */ 2140 } 2141 return WindowManagerGlobal.ADD_PERMISSION_DENIED; 2142 default: 2143 // in the default mode, we will make a decision here based on 2144 // checkCallingPermission() 2145 if (mContext.checkCallingPermission(permission) != 2146 PackageManager.PERMISSION_GRANTED) { 2147 return WindowManagerGlobal.ADD_PERMISSION_DENIED; 2148 } else { 2149 return WindowManagerGlobal.ADD_OKAY; 2150 } 2151 } 2152 } 2153 2154 if (mContext.checkCallingOrSelfPermission(permission) 2155 != PackageManager.PERMISSION_GRANTED) { 2156 return WindowManagerGlobal.ADD_PERMISSION_DENIED; 2157 } 2158 } 2159 return WindowManagerGlobal.ADD_OKAY; 2160 } 2161 2162 @Override 2163 public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) { 2164 2165 // If this switch statement is modified, modify the comment in the declarations of 2166 // the type in {@link WindowManager.LayoutParams} as well. 2167 switch (attrs.type) { 2168 default: 2169 // These are the windows that by default are shown only to the user that created 2170 // them. If this needs to be overridden, set 2171 // {@link WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS} in 2172 // {@link WindowManager.LayoutParams}. Note that permission 2173 // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well. 2174 if ((attrs.privateFlags & PRIVATE_FLAG_SHOW_FOR_ALL_USERS) == 0) { 2175 return true; 2176 } 2177 break; 2178 2179 // These are the windows that by default are shown to all users. However, to 2180 // protect against spoofing, check permissions below. 2181 case TYPE_APPLICATION_STARTING: 2182 case TYPE_BOOT_PROGRESS: 2183 case TYPE_DISPLAY_OVERLAY: 2184 case TYPE_INPUT_CONSUMER: 2185 case TYPE_KEYGUARD_SCRIM: 2186 case TYPE_KEYGUARD_DIALOG: 2187 case TYPE_MAGNIFICATION_OVERLAY: 2188 case TYPE_NAVIGATION_BAR: 2189 case TYPE_NAVIGATION_BAR_PANEL: 2190 case TYPE_PHONE: 2191 case TYPE_POINTER: 2192 case TYPE_PRIORITY_PHONE: 2193 case TYPE_SEARCH_BAR: 2194 case TYPE_STATUS_BAR: 2195 case TYPE_STATUS_BAR_PANEL: 2196 case TYPE_STATUS_BAR_SUB_PANEL: 2197 case TYPE_SYSTEM_DIALOG: 2198 case TYPE_VOLUME_OVERLAY: 2199 case TYPE_PRIVATE_PRESENTATION: 2200 case TYPE_DOCK_DIVIDER: 2201 break; 2202 } 2203 2204 // Check if third party app has set window to system window type. 2205 return mContext.checkCallingOrSelfPermission( 2206 android.Manifest.permission.INTERNAL_SYSTEM_WINDOW) 2207 != PackageManager.PERMISSION_GRANTED; 2208 } 2209 2210 @Override 2211 public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) { 2212 switch (attrs.type) { 2213 case TYPE_SYSTEM_OVERLAY: 2214 case TYPE_SECURE_SYSTEM_OVERLAY: 2215 // These types of windows can't receive input events. 2216 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 2217 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 2218 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; 2219 break; 2220 case TYPE_STATUS_BAR: 2221 2222 // If the Keyguard is in a hidden state (occluded by another window), we force to 2223 // remove the wallpaper and keyguard flag so that any change in-flight after setting 2224 // the keyguard as occluded wouldn't set these flags again. 2225 // See {@link #processKeyguardSetHiddenResultLw}. 2226 if (mKeyguardHidden) { 2227 attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 2228 attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 2229 } 2230 break; 2231 } 2232 2233 if (attrs.type != TYPE_STATUS_BAR) { 2234 // The status bar is the only window allowed to exhibit keyguard behavior. 2235 attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 2236 } 2237 2238 if (ActivityManager.isHighEndGfx()) { 2239 if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) { 2240 attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; 2241 } 2242 final boolean forceWindowDrawsStatusBarBackground = 2243 (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) 2244 != 0; 2245 if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 2246 || forceWindowDrawsStatusBarBackground 2247 && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) { 2248 attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 2249 } 2250 } 2251 } 2252 2253 void readLidState() { 2254 mLidState = mWindowManagerFuncs.getLidState(); 2255 } 2256 2257 private void readCameraLensCoverState() { 2258 mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState(); 2259 } 2260 2261 private boolean isHidden(int accessibilityMode) { 2262 switch (accessibilityMode) { 2263 case 1: 2264 return mLidState == LID_CLOSED; 2265 case 2: 2266 return mLidState == LID_OPEN; 2267 default: 2268 return false; 2269 } 2270 } 2271 2272 /** {@inheritDoc} */ 2273 @Override 2274 public void adjustConfigurationLw(Configuration config, int keyboardPresence, 2275 int navigationPresence) { 2276 mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0; 2277 2278 readConfigurationDependentBehaviors(); 2279 readLidState(); 2280 2281 if (config.keyboard == Configuration.KEYBOARD_NOKEYS 2282 || (keyboardPresence == PRESENCE_INTERNAL 2283 && isHidden(mLidKeyboardAccessibility))) { 2284 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES; 2285 if (!mHasSoftInput) { 2286 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES; 2287 } 2288 } 2289 2290 if (config.navigation == Configuration.NAVIGATION_NONAV 2291 || (navigationPresence == PRESENCE_INTERNAL 2292 && isHidden(mLidNavigationAccessibility))) { 2293 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES; 2294 } 2295 } 2296 2297 @Override 2298 public void onConfigurationChanged() { 2299 final Resources res = mContext.getResources(); 2300 2301 mStatusBarHeight = 2302 res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); 2303 2304 // Height of the navigation bar when presented horizontally at bottom 2305 mNavigationBarHeightForRotationDefault[mPortraitRotation] = 2306 mNavigationBarHeightForRotationDefault[mUpsideDownRotation] = 2307 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height); 2308 mNavigationBarHeightForRotationDefault[mLandscapeRotation] = 2309 mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize( 2310 com.android.internal.R.dimen.navigation_bar_height_landscape); 2311 2312 // Width of the navigation bar when presented vertically along one side 2313 mNavigationBarWidthForRotationDefault[mPortraitRotation] = 2314 mNavigationBarWidthForRotationDefault[mUpsideDownRotation] = 2315 mNavigationBarWidthForRotationDefault[mLandscapeRotation] = 2316 mNavigationBarWidthForRotationDefault[mSeascapeRotation] = 2317 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width); 2318 2319 // Height of the navigation bar when presented horizontally at bottom 2320 mNavigationBarHeightForRotationInCarMode[mPortraitRotation] = 2321 mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] = 2322 res.getDimensionPixelSize( 2323 com.android.internal.R.dimen.navigation_bar_height_car_mode); 2324 mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] = 2325 mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize( 2326 com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode); 2327 2328 // Width of the navigation bar when presented vertically along one side 2329 mNavigationBarWidthForRotationInCarMode[mPortraitRotation] = 2330 mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] = 2331 mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] = 2332 mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] = 2333 res.getDimensionPixelSize( 2334 com.android.internal.R.dimen.navigation_bar_width_car_mode); 2335 } 2336 2337 /** {@inheritDoc} */ 2338 @Override 2339 public int windowTypeToLayerLw(int type) { 2340 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 2341 return 2; 2342 } 2343 switch (type) { 2344 case TYPE_PRIVATE_PRESENTATION: 2345 return 2; 2346 case TYPE_WALLPAPER: 2347 // wallpaper is at the bottom, though the window manager may move it. 2348 return 2; 2349 case TYPE_DOCK_DIVIDER: 2350 return 2; 2351 case TYPE_QS_DIALOG: 2352 return 2; 2353 case TYPE_PHONE: 2354 return 3; 2355 case TYPE_SEARCH_BAR: 2356 case TYPE_VOICE_INTERACTION_STARTING: 2357 return 4; 2358 case TYPE_VOICE_INTERACTION: 2359 // voice interaction layer is almost immediately above apps. 2360 return 5; 2361 case TYPE_INPUT_CONSUMER: 2362 return 6; 2363 case TYPE_SYSTEM_DIALOG: 2364 return 7; 2365 case TYPE_TOAST: 2366 // toasts and the plugged-in battery thing 2367 return 8; 2368 case TYPE_PRIORITY_PHONE: 2369 // SIM errors and unlock. Not sure if this really should be in a high layer. 2370 return 9; 2371 case TYPE_DREAM: 2372 // used for Dreams (screensavers with TYPE_DREAM windows) 2373 return 10; 2374 case TYPE_SYSTEM_ALERT: 2375 // like the ANR / app crashed dialogs 2376 return 11; 2377 case TYPE_INPUT_METHOD: 2378 // on-screen keyboards and other such input method user interfaces go here. 2379 return 12; 2380 case TYPE_INPUT_METHOD_DIALOG: 2381 // on-screen keyboards and other such input method user interfaces go here. 2382 return 13; 2383 case TYPE_KEYGUARD_SCRIM: 2384 // the safety window that shows behind keyguard while keyguard is starting 2385 return 14; 2386 case TYPE_STATUS_BAR_SUB_PANEL: 2387 return 15; 2388 case TYPE_STATUS_BAR: 2389 return 16; 2390 case TYPE_STATUS_BAR_PANEL: 2391 return 17; 2392 case TYPE_KEYGUARD_DIALOG: 2393 return 18; 2394 case TYPE_VOLUME_OVERLAY: 2395 // the on-screen volume indicator and controller shown when the user 2396 // changes the device volume 2397 return 19; 2398 case TYPE_SYSTEM_OVERLAY: 2399 // the on-screen volume indicator and controller shown when the user 2400 // changes the device volume 2401 return 20; 2402 case TYPE_NAVIGATION_BAR: 2403 // the navigation bar, if available, shows atop most things 2404 return 21; 2405 case TYPE_NAVIGATION_BAR_PANEL: 2406 // some panels (e.g. search) need to show on top of the navigation bar 2407 return 22; 2408 case TYPE_SCREENSHOT: 2409 // screenshot selection layer shouldn't go above system error, but it should cover 2410 // navigation bars at the very least. 2411 return 23; 2412 case TYPE_SYSTEM_ERROR: 2413 // system-level error dialogs 2414 return 24; 2415 case TYPE_MAGNIFICATION_OVERLAY: 2416 // used to highlight the magnified portion of a display 2417 return 25; 2418 case TYPE_DISPLAY_OVERLAY: 2419 // used to simulate secondary display devices 2420 return 26; 2421 case TYPE_DRAG: 2422 // the drag layer: input for drag-and-drop is associated with this window, 2423 // which sits above all other focusable windows 2424 return 27; 2425 case TYPE_ACCESSIBILITY_OVERLAY: 2426 // overlay put by accessibility services to intercept user interaction 2427 return 28; 2428 case TYPE_SECURE_SYSTEM_OVERLAY: 2429 return 29; 2430 case TYPE_BOOT_PROGRESS: 2431 return 30; 2432 case TYPE_POINTER: 2433 // the (mouse) pointer layer 2434 return 31; 2435 } 2436 Log.e(TAG, "Unknown window type: " + type); 2437 return 2; 2438 } 2439 2440 /** {@inheritDoc} */ 2441 @Override 2442 public int subWindowTypeToLayerLw(int type) { 2443 switch (type) { 2444 case TYPE_APPLICATION_PANEL: 2445 case TYPE_APPLICATION_ATTACHED_DIALOG: 2446 return APPLICATION_PANEL_SUBLAYER; 2447 case TYPE_APPLICATION_MEDIA: 2448 return APPLICATION_MEDIA_SUBLAYER; 2449 case TYPE_APPLICATION_MEDIA_OVERLAY: 2450 return APPLICATION_MEDIA_OVERLAY_SUBLAYER; 2451 case TYPE_APPLICATION_SUB_PANEL: 2452 return APPLICATION_SUB_PANEL_SUBLAYER; 2453 case TYPE_APPLICATION_ABOVE_SUB_PANEL: 2454 return APPLICATION_ABOVE_SUB_PANEL_SUBLAYER; 2455 } 2456 Log.e(TAG, "Unknown sub-window type: " + type); 2457 return 0; 2458 } 2459 2460 @Override 2461 public int getMaxWallpaperLayer() { 2462 return windowTypeToLayerLw(TYPE_STATUS_BAR); 2463 } 2464 2465 private int getNavigationBarWidth(int rotation, int uiMode) { 2466 if ((uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) { 2467 return mNavigationBarWidthForRotationInCarMode[rotation]; 2468 } else { 2469 return mNavigationBarWidthForRotationDefault[rotation]; 2470 } 2471 } 2472 2473 @Override 2474 public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, 2475 int uiMode) { 2476 if (mHasNavigationBar) { 2477 // For a basic navigation bar, when we are in landscape mode we place 2478 // the navigation bar to the side. 2479 if (mNavigationBarCanMove && fullWidth > fullHeight) { 2480 return fullWidth - getNavigationBarWidth(rotation, uiMode); 2481 } 2482 } 2483 return fullWidth; 2484 } 2485 2486 private int getNavigationBarHeight(int rotation, int uiMode) { 2487 if ((uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) { 2488 return mNavigationBarHeightForRotationInCarMode[rotation]; 2489 } else { 2490 return mNavigationBarHeightForRotationDefault[rotation]; 2491 } 2492 } 2493 2494 @Override 2495 public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, 2496 int uiMode) { 2497 if (mHasNavigationBar) { 2498 // For a basic navigation bar, when we are in portrait mode we place 2499 // the navigation bar to the bottom. 2500 if (!mNavigationBarCanMove || fullWidth < fullHeight) { 2501 return fullHeight - getNavigationBarHeight(rotation, uiMode); 2502 } 2503 } 2504 return fullHeight; 2505 } 2506 2507 @Override 2508 public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode) { 2509 return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode); 2510 } 2511 2512 @Override 2513 public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode) { 2514 // There is a separate status bar at the top of the display. We don't count that as part 2515 // of the fixed decor, since it can hide; however, for purposes of configurations, 2516 // we do want to exclude it since applications can't generally use that part 2517 // of the screen. 2518 return getNonDecorDisplayHeight( 2519 fullWidth, fullHeight, rotation, uiMode) - mStatusBarHeight; 2520 } 2521 2522 @Override 2523 public boolean isForceHiding(WindowManager.LayoutParams attrs) { 2524 return (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 || 2525 (isKeyguardHostWindow(attrs) && 2526 (mKeyguardDelegate != null && mKeyguardDelegate.isShowing())) || 2527 (attrs.type == TYPE_KEYGUARD_SCRIM); 2528 } 2529 2530 @Override 2531 public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) { 2532 return attrs.type == TYPE_STATUS_BAR; 2533 } 2534 2535 @Override 2536 public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) { 2537 switch (attrs.type) { 2538 case TYPE_STATUS_BAR: 2539 case TYPE_NAVIGATION_BAR: 2540 case TYPE_WALLPAPER: 2541 case TYPE_DREAM: 2542 case TYPE_KEYGUARD_SCRIM: 2543 return false; 2544 default: 2545 // Hide only windows below the keyguard host window. 2546 return windowTypeToLayerLw(win.getBaseType()) 2547 < windowTypeToLayerLw(TYPE_STATUS_BAR); 2548 } 2549 } 2550 2551 @Override 2552 public WindowState getWinShowWhenLockedLw() { 2553 return mWinShowWhenLocked; 2554 } 2555 2556 /** {@inheritDoc} */ 2557 @Override 2558 public View addStartingWindow(IBinder appToken, String packageName, int theme, 2559 CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, 2560 int icon, int logo, int windowFlags, Configuration overrideConfig) { 2561 if (!SHOW_STARTING_ANIMATIONS) { 2562 return null; 2563 } 2564 if (packageName == null) { 2565 return null; 2566 } 2567 2568 WindowManager wm = null; 2569 View view = null; 2570 2571 try { 2572 Context context = mContext; 2573 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow " + packageName 2574 + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme=" 2575 + Integer.toHexString(theme)); 2576 if (theme != context.getThemeResId() || labelRes != 0) { 2577 try { 2578 context = context.createPackageContext(packageName, 0); 2579 context.setTheme(theme); 2580 } catch (PackageManager.NameNotFoundException e) { 2581 // Ignore 2582 } 2583 } 2584 2585 if (overrideConfig != null && overrideConfig != EMPTY) { 2586 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: creating context based" 2587 + " on overrideConfig" + overrideConfig + " for starting window"); 2588 final Context overrideContext = context.createConfigurationContext(overrideConfig); 2589 overrideContext.setTheme(theme); 2590 final TypedArray typedArray = overrideContext.obtainStyledAttributes( 2591 com.android.internal.R.styleable.Window); 2592 final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0); 2593 if (resId != 0 && overrideContext.getDrawable(resId) != null) { 2594 // We want to use the windowBackground for the override context if it is 2595 // available, otherwise we use the default one to make sure a themed starting 2596 // window is displayed for the app. 2597 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: apply overrideConfig" 2598 + overrideConfig + " to starting window resId=" + resId); 2599 context = overrideContext; 2600 } 2601 } 2602 2603 final PhoneWindow win = new PhoneWindow(context); 2604 win.setIsStartingWindow(true); 2605 2606 CharSequence label = context.getResources().getText(labelRes, null); 2607 // Only change the accessibility title if the label is localized 2608 if (label != null) { 2609 win.setTitle(label, true); 2610 } else { 2611 win.setTitle(nonLocalizedLabel, false); 2612 } 2613 2614 win.setType( 2615 WindowManager.LayoutParams.TYPE_APPLICATION_STARTING); 2616 2617 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 2618 // Assumes it's safe to show starting windows of launched apps while 2619 // the keyguard is being hidden. This is okay because starting windows never show 2620 // secret information. 2621 if (mKeyguardHidden) { 2622 windowFlags |= FLAG_SHOW_WHEN_LOCKED; 2623 } 2624 } 2625 2626 // Force the window flags: this is a fake window, so it is not really 2627 // touchable or focusable by the user. We also add in the ALT_FOCUSABLE_IM 2628 // flag because we do know that the next window will take input 2629 // focus, so we want to get the IME window up on top of us right away. 2630 win.setFlags( 2631 windowFlags| 2632 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE| 2633 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| 2634 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, 2635 windowFlags| 2636 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE| 2637 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| 2638 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 2639 2640 win.setDefaultIcon(icon); 2641 win.setDefaultLogo(logo); 2642 2643 win.setLayout(WindowManager.LayoutParams.MATCH_PARENT, 2644 WindowManager.LayoutParams.MATCH_PARENT); 2645 2646 final WindowManager.LayoutParams params = win.getAttributes(); 2647 params.token = appToken; 2648 params.packageName = packageName; 2649 params.windowAnimations = win.getWindowStyle().getResourceId( 2650 com.android.internal.R.styleable.Window_windowAnimationStyle, 0); 2651 params.privateFlags |= 2652 WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED; 2653 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; 2654 2655 if (!compatInfo.supportsScreen()) { 2656 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; 2657 } 2658 2659 params.setTitle("Starting " + packageName); 2660 2661 wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); 2662 view = win.getDecorView(); 2663 2664 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Adding starting window for " 2665 + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null)); 2666 2667 wm.addView(view, params); 2668 2669 // Only return the view if it was successfully added to the 2670 // window manager... which we can tell by it having a parent. 2671 return view.getParent() != null ? view : null; 2672 } catch (WindowManager.BadTokenException e) { 2673 // ignore 2674 Log.w(TAG, appToken + " already running, starting window not displayed. " + 2675 e.getMessage()); 2676 } catch (RuntimeException e) { 2677 // don't crash if something else bad happens, for example a 2678 // failure loading resources because we are loading from an app 2679 // on external storage that has been unmounted. 2680 Log.w(TAG, appToken + " failed creating starting window", e); 2681 } finally { 2682 if (view != null && view.getParent() == null) { 2683 Log.w(TAG, "view not successfully added to wm, removing view"); 2684 wm.removeViewImmediate(view); 2685 } 2686 } 2687 2688 return null; 2689 } 2690 2691 /** {@inheritDoc} */ 2692 @Override 2693 public void removeStartingWindow(IBinder appToken, View window) { 2694 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Removing starting window for " + appToken + ": " 2695 + window + " Callers=" + Debug.getCallers(4)); 2696 2697 if (window != null) { 2698 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); 2699 wm.removeView(window); 2700 } 2701 } 2702 2703 /** 2704 * Preflight adding a window to the system. 2705 * 2706 * Currently enforces that three window types are singletons: 2707 * <ul> 2708 * <li>STATUS_BAR_TYPE</li> 2709 * <li>KEYGUARD_TYPE</li> 2710 * </ul> 2711 * 2712 * @param win The window to be added 2713 * @param attrs Information about the window to be added 2714 * 2715 * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons, 2716 * WindowManagerImpl.ADD_MULTIPLE_SINGLETON 2717 */ 2718 @Override 2719 public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) { 2720 switch (attrs.type) { 2721 case TYPE_STATUS_BAR: 2722 mContext.enforceCallingOrSelfPermission( 2723 android.Manifest.permission.STATUS_BAR_SERVICE, 2724 "PhoneWindowManager"); 2725 if (mStatusBar != null) { 2726 if (mStatusBar.isAlive()) { 2727 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON; 2728 } 2729 } 2730 mStatusBar = win; 2731 mStatusBarController.setWindow(win); 2732 break; 2733 case TYPE_NAVIGATION_BAR: 2734 mContext.enforceCallingOrSelfPermission( 2735 android.Manifest.permission.STATUS_BAR_SERVICE, 2736 "PhoneWindowManager"); 2737 if (mNavigationBar != null) { 2738 if (mNavigationBar.isAlive()) { 2739 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON; 2740 } 2741 } 2742 mNavigationBar = win; 2743 mNavigationBarController.setWindow(win); 2744 if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar); 2745 break; 2746 case TYPE_NAVIGATION_BAR_PANEL: 2747 case TYPE_STATUS_BAR_PANEL: 2748 case TYPE_STATUS_BAR_SUB_PANEL: 2749 case TYPE_VOICE_INTERACTION_STARTING: 2750 mContext.enforceCallingOrSelfPermission( 2751 android.Manifest.permission.STATUS_BAR_SERVICE, 2752 "PhoneWindowManager"); 2753 break; 2754 case TYPE_KEYGUARD_SCRIM: 2755 if (mKeyguardScrim != null) { 2756 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON; 2757 } 2758 mKeyguardScrim = win; 2759 break; 2760 } 2761 return WindowManagerGlobal.ADD_OKAY; 2762 } 2763 2764 /** {@inheritDoc} */ 2765 @Override 2766 public void removeWindowLw(WindowState win) { 2767 if (mStatusBar == win) { 2768 mStatusBar = null; 2769 mStatusBarController.setWindow(null); 2770 mKeyguardDelegate.showScrim(); 2771 } else if (mKeyguardScrim == win) { 2772 Log.v(TAG, "Removing keyguard scrim"); 2773 mKeyguardScrim = null; 2774 } if (mNavigationBar == win) { 2775 mNavigationBar = null; 2776 mNavigationBarController.setWindow(null); 2777 } 2778 } 2779 2780 static final boolean PRINT_ANIM = false; 2781 2782 /** {@inheritDoc} */ 2783 @Override 2784 public int selectAnimationLw(WindowState win, int transit) { 2785 if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win 2786 + ": transit=" + transit); 2787 if (win == mStatusBar) { 2788 boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0; 2789 if (transit == TRANSIT_EXIT 2790 || transit == TRANSIT_HIDE) { 2791 return isKeyguard ? -1 : R.anim.dock_top_exit; 2792 } else if (transit == TRANSIT_ENTER 2793 || transit == TRANSIT_SHOW) { 2794 return isKeyguard ? -1 : R.anim.dock_top_enter; 2795 } 2796 } else if (win == mNavigationBar) { 2797 if (win.getAttrs().windowAnimations != 0) { 2798 return 0; 2799 } 2800 // This can be on either the bottom or the right or the left. 2801 if (mNavigationBarPosition == NAV_BAR_BOTTOM) { 2802 if (transit == TRANSIT_EXIT 2803 || transit == TRANSIT_HIDE) { 2804 return R.anim.dock_bottom_exit; 2805 } else if (transit == TRANSIT_ENTER 2806 || transit == TRANSIT_SHOW) { 2807 return R.anim.dock_bottom_enter; 2808 } 2809 } else if (mNavigationBarPosition == NAV_BAR_RIGHT) { 2810 if (transit == TRANSIT_EXIT 2811 || transit == TRANSIT_HIDE) { 2812 return R.anim.dock_right_exit; 2813 } else if (transit == TRANSIT_ENTER 2814 || transit == TRANSIT_SHOW) { 2815 return R.anim.dock_right_enter; 2816 } 2817 } else if (mNavigationBarPosition == NAV_BAR_LEFT) { 2818 if (transit == TRANSIT_EXIT 2819 || transit == TRANSIT_HIDE) { 2820 return R.anim.dock_left_exit; 2821 } else if (transit == TRANSIT_ENTER 2822 || transit == TRANSIT_SHOW) { 2823 return R.anim.dock_left_enter; 2824 } 2825 } 2826 } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) { 2827 return selectDockedDividerAnimationLw(win, transit); 2828 } 2829 2830 if (transit == TRANSIT_PREVIEW_DONE) { 2831 if (win.hasAppShownWindows()) { 2832 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT"); 2833 return com.android.internal.R.anim.app_starting_exit; 2834 } 2835 } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen 2836 && transit == TRANSIT_ENTER) { 2837 // Special case: we are animating in a dream, while the keyguard 2838 // is shown. We don't want an animation on the dream, because 2839 // we need it shown immediately with the keyguard animating away 2840 // to reveal it. 2841 return -1; 2842 } 2843 2844 return 0; 2845 } 2846 2847 private int selectDockedDividerAnimationLw(WindowState win, int transit) { 2848 int insets = mWindowManagerFuncs.getDockedDividerInsetsLw(); 2849 2850 // If the divider is behind the navigation bar, don't animate. 2851 final Rect frame = win.getFrameLw(); 2852 final boolean behindNavBar = mNavigationBar != null 2853 && ((mNavigationBarPosition == NAV_BAR_BOTTOM 2854 && frame.top + insets >= mNavigationBar.getFrameLw().top) 2855 || (mNavigationBarPosition == NAV_BAR_RIGHT 2856 && frame.left + insets >= mNavigationBar.getFrameLw().left) 2857 || (mNavigationBarPosition == NAV_BAR_LEFT 2858 && frame.right - insets <= mNavigationBar.getFrameLw().right)); 2859 final boolean landscape = frame.height() > frame.width(); 2860 final boolean offscreenLandscape = landscape && (frame.right - insets <= 0 2861 || frame.left + insets >= win.getDisplayFrameLw().right); 2862 final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0 2863 || frame.bottom + insets >= win.getDisplayFrameLw().bottom); 2864 final boolean offscreen = offscreenLandscape || offscreenPortrait; 2865 if (behindNavBar || offscreen) { 2866 return 0; 2867 } 2868 if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) { 2869 return R.anim.fade_in; 2870 } else if (transit == TRANSIT_EXIT) { 2871 return R.anim.fade_out; 2872 } else { 2873 return 0; 2874 } 2875 } 2876 2877 @Override 2878 public void selectRotationAnimationLw(int anim[]) { 2879 if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen=" 2880 + mTopFullscreenOpaqueWindowState + " rotationAnimation=" 2881 + (mTopFullscreenOpaqueWindowState == null ? 2882 "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation)); 2883 if (mTopFullscreenOpaqueWindowState != null) { 2884 int animationHint = mTopFullscreenOpaqueWindowState.getRotationAnimationHint(); 2885 if (animationHint < 0 && mTopIsFullscreen) { 2886 animationHint = mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation; 2887 } 2888 switch (animationHint) { 2889 case ROTATION_ANIMATION_CROSSFADE: 2890 anim[0] = R.anim.rotation_animation_xfade_exit; 2891 anim[1] = R.anim.rotation_animation_enter; 2892 break; 2893 case ROTATION_ANIMATION_JUMPCUT: 2894 anim[0] = R.anim.rotation_animation_jump_exit; 2895 anim[1] = R.anim.rotation_animation_enter; 2896 break; 2897 case ROTATION_ANIMATION_ROTATE: 2898 default: 2899 anim[0] = anim[1] = 0; 2900 break; 2901 } 2902 } else { 2903 anim[0] = anim[1] = 0; 2904 } 2905 } 2906 2907 @Override 2908 public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId, 2909 boolean forceDefault) { 2910 switch (exitAnimId) { 2911 case R.anim.rotation_animation_xfade_exit: 2912 case R.anim.rotation_animation_jump_exit: 2913 // These are the only cases that matter. 2914 if (forceDefault) { 2915 return false; 2916 } 2917 int anim[] = new int[2]; 2918 selectRotationAnimationLw(anim); 2919 return (exitAnimId == anim[0] && enterAnimId == anim[1]); 2920 default: 2921 return true; 2922 } 2923 } 2924 2925 @Override 2926 public Animation createForceHideEnterAnimation(boolean onWallpaper, 2927 boolean goingToNotificationShade) { 2928 if (goingToNotificationShade) { 2929 return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in); 2930 } 2931 2932 AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ? 2933 R.anim.lock_screen_behind_enter_wallpaper : 2934 R.anim.lock_screen_behind_enter); 2935 2936 // TODO: Use XML interpolators when we have log interpolators available in XML. 2937 final List<Animation> animations = set.getAnimations(); 2938 for (int i = animations.size() - 1; i >= 0; --i) { 2939 animations.get(i).setInterpolator(mLogDecelerateInterpolator); 2940 } 2941 2942 return set; 2943 } 2944 2945 2946 @Override 2947 public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade) { 2948 if (goingToNotificationShade) { 2949 return null; 2950 } else { 2951 return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit); 2952 } 2953 } 2954 2955 private static void awakenDreams() { 2956 IDreamManager dreamManager = getDreamManager(); 2957 if (dreamManager != null) { 2958 try { 2959 dreamManager.awaken(); 2960 } catch (RemoteException e) { 2961 // fine, stay asleep then 2962 } 2963 } 2964 } 2965 2966 static IDreamManager getDreamManager() { 2967 return IDreamManager.Stub.asInterface( 2968 ServiceManager.checkService(DreamService.DREAM_SERVICE)); 2969 } 2970 2971 TelecomManager getTelecommService() { 2972 return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); 2973 } 2974 2975 static IAudioService getAudioService() { 2976 IAudioService audioService = IAudioService.Stub.asInterface( 2977 ServiceManager.checkService(Context.AUDIO_SERVICE)); 2978 if (audioService == null) { 2979 Log.w(TAG, "Unable to find IAudioService interface."); 2980 } 2981 return audioService; 2982 } 2983 2984 boolean keyguardOn() { 2985 return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode(); 2986 } 2987 2988 private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = { 2989 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, 2990 WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, 2991 }; 2992 2993 /** {@inheritDoc} */ 2994 @Override 2995 public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) { 2996 final boolean keyguardOn = keyguardOn(); 2997 final int keyCode = event.getKeyCode(); 2998 final int repeatCount = event.getRepeatCount(); 2999 final int metaState = event.getMetaState(); 3000 final int flags = event.getFlags(); 3001 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; 3002 final boolean canceled = event.isCanceled(); 3003 3004 if (DEBUG_INPUT) { 3005 Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount=" 3006 + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed 3007 + " canceled=" + canceled); 3008 } 3009 3010 // If we think we might have a volume down & power key chord on the way 3011 // but we're not sure, then tell the dispatcher to wait a little while and 3012 // try again later before dispatching. 3013 if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) { 3014 if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) { 3015 final long now = SystemClock.uptimeMillis(); 3016 final long timeoutTime = mScreenshotChordVolumeDownKeyTime 3017 + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS; 3018 if (now < timeoutTime) { 3019 return timeoutTime - now; 3020 } 3021 } 3022 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN 3023 && mScreenshotChordVolumeDownKeyConsumed) { 3024 if (!down) { 3025 mScreenshotChordVolumeDownKeyConsumed = false; 3026 } 3027 return -1; 3028 } 3029 } 3030 3031 // Cancel any pending meta actions if we see any other keys being pressed between the down 3032 // of the meta key and its corresponding up. 3033 if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) { 3034 mPendingMetaAction = false; 3035 } 3036 // Any key that is not Alt or Meta cancels Caps Lock combo tracking. 3037 if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) { 3038 mPendingCapsLockToggle = false; 3039 } 3040 3041 // First we always handle the home key here, so applications 3042 // can never break it, although if keyguard is on, we do let 3043 // it handle it, because that gives us the correct 5 second 3044 // timeout. 3045 if (keyCode == KeyEvent.KEYCODE_HOME) { 3046 3047 // If we have released the home key, and didn't do anything else 3048 // while it was pressed, then it is time to go home! 3049 if (!down) { 3050 cancelPreloadRecentApps(); 3051 3052 mHomePressed = false; 3053 if (mHomeConsumed) { 3054 mHomeConsumed = false; 3055 return -1; 3056 } 3057 3058 if (canceled) { 3059 Log.i(TAG, "Ignoring HOME; event canceled."); 3060 return -1; 3061 } 3062 3063 // If an incoming call is ringing, HOME is totally disabled. 3064 // (The user is already on the InCallUI at this point, 3065 // and his ONLY options are to answer or reject the call.) 3066 TelecomManager telecomManager = getTelecommService(); 3067 if (telecomManager != null && telecomManager.isRinging()) { 3068 Log.i(TAG, "Ignoring HOME; there's a ringing incoming call."); 3069 return -1; 3070 } 3071 3072 // Delay handling home if a double-tap is possible. 3073 if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) { 3074 mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case 3075 mHomeDoubleTapPending = true; 3076 mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable, 3077 ViewConfiguration.getDoubleTapTimeout()); 3078 return -1; 3079 } 3080 3081 handleShortPressOnHome(); 3082 return -1; 3083 } 3084 3085 // If a system window has focus, then it doesn't make sense 3086 // right now to interact with applications. 3087 WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null; 3088 if (attrs != null) { 3089 final int type = attrs.type; 3090 if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM 3091 || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG 3092 || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 3093 // the "app" is keyguard, so give it the key 3094 return 0; 3095 } 3096 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length; 3097 for (int i=0; i<typeCount; i++) { 3098 if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) { 3099 // don't do anything, but also don't pass it to the app 3100 return -1; 3101 } 3102 } 3103 } 3104 3105 // Remember that home is pressed and handle special actions. 3106 if (repeatCount == 0) { 3107 mHomePressed = true; 3108 if (mHomeDoubleTapPending) { 3109 mHomeDoubleTapPending = false; 3110 mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); 3111 handleDoubleTapOnHome(); 3112 } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI 3113 || mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) { 3114 preloadRecentApps(); 3115 } 3116 } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { 3117 if (!keyguardOn) { 3118 handleLongPressOnHome(event.getDeviceId()); 3119 } 3120 } 3121 return -1; 3122 } else if (keyCode == KeyEvent.KEYCODE_MENU) { 3123 // Hijack modified menu keys for debugging features 3124 final int chordBug = KeyEvent.META_SHIFT_ON; 3125 3126 if (down && repeatCount == 0) { 3127 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) { 3128 Intent intent = new Intent(Intent.ACTION_BUG_REPORT); 3129 mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, 3130 null, null, null, 0, null, null); 3131 return -1; 3132 } else if (SHOW_PROCESSES_ON_ALT_MENU && 3133 (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) { 3134 Intent service = new Intent(); 3135 service.setClassName(mContext, "com.android.server.LoadAverageService"); 3136 ContentResolver res = mContext.getContentResolver(); 3137 boolean shown = Settings.Global.getInt( 3138 res, Settings.Global.SHOW_PROCESSES, 0) != 0; 3139 if (!shown) { 3140 mContext.startService(service); 3141 } else { 3142 mContext.stopService(service); 3143 } 3144 Settings.Global.putInt( 3145 res, Settings.Global.SHOW_PROCESSES, shown ? 0 : 1); 3146 return -1; 3147 } 3148 } 3149 } else if (keyCode == KeyEvent.KEYCODE_SEARCH) { 3150 if (down) { 3151 if (repeatCount == 0) { 3152 mSearchKeyShortcutPending = true; 3153 mConsumeSearchKeyUp = false; 3154 } 3155 } else { 3156 mSearchKeyShortcutPending = false; 3157 if (mConsumeSearchKeyUp) { 3158 mConsumeSearchKeyUp = false; 3159 return -1; 3160 } 3161 } 3162 return 0; 3163 } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) { 3164 if (!keyguardOn) { 3165 if (down && repeatCount == 0) { 3166 preloadRecentApps(); 3167 } else if (!down) { 3168 toggleRecentApps(); 3169 } 3170 } 3171 return -1; 3172 } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) { 3173 if (down) { 3174 IStatusBarService service = getStatusBarService(); 3175 if (service != null) { 3176 try { 3177 service.expandNotificationsPanel(); 3178 } catch (RemoteException e) { 3179 // do nothing. 3180 } 3181 } 3182 } 3183 } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed() 3184 && event.isCtrlPressed()) { 3185 if (down && repeatCount == 0) { 3186 int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION 3187 : TAKE_SCREENSHOT_FULLSCREEN; 3188 mScreenshotRunnable.setScreenshotType(type); 3189 mHandler.post(mScreenshotRunnable); 3190 return -1; 3191 } 3192 } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) { 3193 if (down && repeatCount == 0 && !isKeyguardLocked()) { 3194 toggleKeyboardShortcutsMenu(event.getDeviceId()); 3195 } 3196 } else if (keyCode == KeyEvent.KEYCODE_ASSIST) { 3197 if (down) { 3198 if (repeatCount == 0) { 3199 mAssistKeyLongPressed = false; 3200 } else if (repeatCount == 1) { 3201 mAssistKeyLongPressed = true; 3202 if (!keyguardOn) { 3203 launchAssistLongPressAction(); 3204 } 3205 } 3206 } else { 3207 if (mAssistKeyLongPressed) { 3208 mAssistKeyLongPressed = false; 3209 } else { 3210 if (!keyguardOn) { 3211 launchAssistAction(null, event.getDeviceId()); 3212 } 3213 } 3214 } 3215 return -1; 3216 } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) { 3217 if (!down) { 3218 Intent voiceIntent; 3219 if (!keyguardOn) { 3220 voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH); 3221 } else { 3222 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface( 3223 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); 3224 if (dic != null) { 3225 try { 3226 dic.exitIdle("voice-search"); 3227 } catch (RemoteException e) { 3228 } 3229 } 3230 voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); 3231 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true); 3232 } 3233 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF); 3234 } 3235 } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) { 3236 if (down && repeatCount == 0) { 3237 mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN); 3238 mHandler.post(mScreenshotRunnable); 3239 } 3240 return -1; 3241 } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP 3242 || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) { 3243 if (down) { 3244 int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1; 3245 3246 // Disable autobrightness if it's on 3247 int auto = Settings.System.getIntForUser( 3248 mContext.getContentResolver(), 3249 Settings.System.SCREEN_BRIGHTNESS_MODE, 3250 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, 3251 UserHandle.USER_CURRENT_OR_SELF); 3252 if (auto != 0) { 3253 Settings.System.putIntForUser(mContext.getContentResolver(), 3254 Settings.System.SCREEN_BRIGHTNESS_MODE, 3255 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, 3256 UserHandle.USER_CURRENT_OR_SELF); 3257 } 3258 3259 int min = mPowerManager.getMinimumScreenBrightnessSetting(); 3260 int max = mPowerManager.getMaximumScreenBrightnessSetting(); 3261 int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction; 3262 int brightness = Settings.System.getIntForUser(mContext.getContentResolver(), 3263 Settings.System.SCREEN_BRIGHTNESS, 3264 mPowerManager.getDefaultScreenBrightnessSetting(), 3265 UserHandle.USER_CURRENT_OR_SELF); 3266 brightness += step; 3267 // Make sure we don't go beyond the limits. 3268 brightness = Math.min(max, brightness); 3269 brightness = Math.max(min, brightness); 3270 3271 Settings.System.putIntForUser(mContext.getContentResolver(), 3272 Settings.System.SCREEN_BRIGHTNESS, brightness, 3273 UserHandle.USER_CURRENT_OR_SELF); 3274 startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG), 3275 UserHandle.CURRENT_OR_SELF); 3276 } 3277 return -1; 3278 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP 3279 || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN 3280 || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) { 3281 if (mUseTvRouting) { 3282 // On TVs volume keys never go to the foreground app. 3283 dispatchDirectAudioEvent(event); 3284 return -1; 3285 } 3286 } 3287 3288 // Toggle Caps Lock on META-ALT. 3289 boolean actionTriggered = false; 3290 if (KeyEvent.isModifierKey(keyCode)) { 3291 if (!mPendingCapsLockToggle) { 3292 // Start tracking meta state for combo. 3293 mInitialMetaState = mMetaState; 3294 mPendingCapsLockToggle = true; 3295 } else if (event.getAction() == KeyEvent.ACTION_UP) { 3296 int altOnMask = mMetaState & KeyEvent.META_ALT_MASK; 3297 int metaOnMask = mMetaState & KeyEvent.META_META_MASK; 3298 3299 // Check for Caps Lock toggle 3300 if ((metaOnMask != 0) && (altOnMask != 0)) { 3301 // Check if nothing else is pressed 3302 if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) { 3303 // Handle Caps Lock Toggle 3304 mInputManagerInternal.toggleCapsLock(event.getDeviceId()); 3305 actionTriggered = true; 3306 } 3307 } 3308 3309 // Always stop tracking when key goes up. 3310 mPendingCapsLockToggle = false; 3311 } 3312 } 3313 // Store current meta state to be able to evaluate it later. 3314 mMetaState = metaState; 3315 3316 if (actionTriggered) { 3317 return -1; 3318 } 3319 3320 if (KeyEvent.isMetaKey(keyCode)) { 3321 if (down) { 3322 mPendingMetaAction = true; 3323 } else if (mPendingMetaAction) { 3324 launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId()); 3325 } 3326 return -1; 3327 } 3328 3329 // Shortcuts are invoked through Search+key, so intercept those here 3330 // Any printing key that is chorded with Search should be consumed 3331 // even if no shortcut was invoked. This prevents text from being 3332 // inadvertently inserted when using a keyboard that has built-in macro 3333 // shortcut keys (that emit Search+x) and some of them are not registered. 3334 if (mSearchKeyShortcutPending) { 3335 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 3336 if (kcm.isPrintingKey(keyCode)) { 3337 mConsumeSearchKeyUp = true; 3338 mSearchKeyShortcutPending = false; 3339 if (down && repeatCount == 0 && !keyguardOn) { 3340 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState); 3341 if (shortcutIntent != null) { 3342 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3343 try { 3344 startActivityAsUser(shortcutIntent, UserHandle.CURRENT); 3345 dismissKeyboardShortcutsMenu(); 3346 } catch (ActivityNotFoundException ex) { 3347 Slog.w(TAG, "Dropping shortcut key combination because " 3348 + "the activity to which it is registered was not found: " 3349 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex); 3350 } 3351 } else { 3352 Slog.i(TAG, "Dropping unregistered shortcut key combination: " 3353 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode)); 3354 } 3355 } 3356 return -1; 3357 } 3358 } 3359 3360 // Invoke shortcuts using Meta. 3361 if (down && repeatCount == 0 && !keyguardOn 3362 && (metaState & KeyEvent.META_META_ON) != 0) { 3363 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 3364 if (kcm.isPrintingKey(keyCode)) { 3365 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, 3366 metaState & ~(KeyEvent.META_META_ON 3367 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON)); 3368 if (shortcutIntent != null) { 3369 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3370 try { 3371 startActivityAsUser(shortcutIntent, UserHandle.CURRENT); 3372 dismissKeyboardShortcutsMenu(); 3373 } catch (ActivityNotFoundException ex) { 3374 Slog.w(TAG, "Dropping shortcut key combination because " 3375 + "the activity to which it is registered was not found: " 3376 + "META+" + KeyEvent.keyCodeToString(keyCode), ex); 3377 } 3378 return -1; 3379 } 3380 } 3381 } 3382 3383 // Handle application launch keys. 3384 if (down && repeatCount == 0 && !keyguardOn) { 3385 String category = sApplicationLaunchKeyCategories.get(keyCode); 3386 if (category != null) { 3387 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category); 3388 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3389 try { 3390 startActivityAsUser(intent, UserHandle.CURRENT); 3391 dismissKeyboardShortcutsMenu(); 3392 } catch (ActivityNotFoundException ex) { 3393 Slog.w(TAG, "Dropping application launch key because " 3394 + "the activity to which it is registered was not found: " 3395 + "keyCode=" + keyCode + ", category=" + category, ex); 3396 } 3397 return -1; 3398 } 3399 } 3400 3401 // Display task switcher for ALT-TAB. 3402 if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) { 3403 if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) { 3404 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK; 3405 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) { 3406 mRecentAppsHeldModifiers = shiftlessModifiers; 3407 showRecentApps(true, false); 3408 return -1; 3409 } 3410 } 3411 } else if (!down && mRecentAppsHeldModifiers != 0 3412 && (metaState & mRecentAppsHeldModifiers) == 0) { 3413 mRecentAppsHeldModifiers = 0; 3414 hideRecentApps(true, false); 3415 } 3416 3417 // Handle input method switching. 3418 if (down && repeatCount == 0 3419 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH 3420 || (keyCode == KeyEvent.KEYCODE_SPACE 3421 && (metaState & KeyEvent.META_META_MASK) != 0))) { 3422 final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0; 3423 mWindowManagerFuncs.switchInputMethod(forwardDirection); 3424 return -1; 3425 } 3426 if (mLanguageSwitchKeyPressed && !down 3427 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH 3428 || keyCode == KeyEvent.KEYCODE_SPACE)) { 3429 mLanguageSwitchKeyPressed = false; 3430 return -1; 3431 } 3432 3433 if (isValidGlobalKey(keyCode) 3434 && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) { 3435 return -1; 3436 } 3437 3438 if (down) { 3439 long shortcutCode = keyCode; 3440 if (event.isCtrlPressed()) { 3441 shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE; 3442 } 3443 3444 if (event.isAltPressed()) { 3445 shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE; 3446 } 3447 3448 if (event.isShiftPressed()) { 3449 shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE; 3450 } 3451 3452 if (event.isMetaPressed()) { 3453 shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE; 3454 } 3455 3456 IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode); 3457 if (shortcutService != null) { 3458 try { 3459 if (isUserSetupComplete()) { 3460 shortcutService.notifyShortcutKeyPressed(shortcutCode); 3461 } 3462 } catch (RemoteException e) { 3463 mShortcutKeyServices.delete(shortcutCode); 3464 } 3465 return -1; 3466 } 3467 } 3468 3469 // Reserve all the META modifier combos for system behavior 3470 if ((metaState & KeyEvent.META_META_ON) != 0) { 3471 return -1; 3472 } 3473 3474 // Let the application handle the key. 3475 return 0; 3476 } 3477 3478 /** {@inheritDoc} */ 3479 @Override 3480 public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) { 3481 // Note: This method is only called if the initial down was unhandled. 3482 if (DEBUG_INPUT) { 3483 Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction() 3484 + ", flags=" + event.getFlags() 3485 + ", keyCode=" + event.getKeyCode() 3486 + ", scanCode=" + event.getScanCode() 3487 + ", metaState=" + event.getMetaState() 3488 + ", repeatCount=" + event.getRepeatCount() 3489 + ", policyFlags=" + policyFlags); 3490 } 3491 3492 KeyEvent fallbackEvent = null; 3493 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 3494 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 3495 final int keyCode = event.getKeyCode(); 3496 final int metaState = event.getMetaState(); 3497 final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN 3498 && event.getRepeatCount() == 0; 3499 3500 // Check for fallback actions specified by the key character map. 3501 final FallbackAction fallbackAction; 3502 if (initialDown) { 3503 fallbackAction = kcm.getFallbackAction(keyCode, metaState); 3504 } else { 3505 fallbackAction = mFallbackActions.get(keyCode); 3506 } 3507 3508 if (fallbackAction != null) { 3509 if (DEBUG_INPUT) { 3510 Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode 3511 + " metaState=" + Integer.toHexString(fallbackAction.metaState)); 3512 } 3513 3514 final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK; 3515 fallbackEvent = KeyEvent.obtain( 3516 event.getDownTime(), event.getEventTime(), 3517 event.getAction(), fallbackAction.keyCode, 3518 event.getRepeatCount(), fallbackAction.metaState, 3519 event.getDeviceId(), event.getScanCode(), 3520 flags, event.getSource(), null); 3521 3522 if (!interceptFallback(win, fallbackEvent, policyFlags)) { 3523 fallbackEvent.recycle(); 3524 fallbackEvent = null; 3525 } 3526 3527 if (initialDown) { 3528 mFallbackActions.put(keyCode, fallbackAction); 3529 } else if (event.getAction() == KeyEvent.ACTION_UP) { 3530 mFallbackActions.remove(keyCode); 3531 fallbackAction.recycle(); 3532 } 3533 } 3534 } 3535 3536 if (DEBUG_INPUT) { 3537 if (fallbackEvent == null) { 3538 Slog.d(TAG, "No fallback."); 3539 } else { 3540 Slog.d(TAG, "Performing fallback: " + fallbackEvent); 3541 } 3542 } 3543 return fallbackEvent; 3544 } 3545 3546 private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) { 3547 int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags); 3548 if ((actions & ACTION_PASS_TO_USER) != 0) { 3549 long delayMillis = interceptKeyBeforeDispatching( 3550 win, fallbackEvent, policyFlags); 3551 if (delayMillis == 0) { 3552 return true; 3553 } 3554 } 3555 return false; 3556 } 3557 3558 @Override 3559 public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService) 3560 throws RemoteException { 3561 synchronized (mLock) { 3562 IShortcutService service = mShortcutKeyServices.get(shortcutCode); 3563 if (service != null && service.asBinder().pingBinder()) { 3564 throw new RemoteException("Key already exists."); 3565 } 3566 3567 mShortcutKeyServices.put(shortcutCode, shortcutService); 3568 } 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 if (setKeyguardOccludedLw(false)) { 5268 changes |= FINISH_LAYOUT_REDO_LAYOUT 5269 | FINISH_LAYOUT_REDO_CONFIG 5270 | FINISH_LAYOUT_REDO_WALLPAPER; 5271 } 5272 if (mDismissKeyguard == DISMISS_KEYGUARD_START) { 5273 // Only launch the next keyguard unlock window once per window. 5274 mHandler.post(new Runnable() { 5275 @Override 5276 public void run() { 5277 mKeyguardDelegate.dismiss(); 5278 } 5279 }); 5280 } 5281 } else { 5282 mWinDismissingKeyguard = null; 5283 mSecureDismissingKeyguard = false; 5284 mKeyguardHidden = false; 5285 if (setKeyguardOccludedLw(false)) { 5286 changes |= FINISH_LAYOUT_REDO_LAYOUT 5287 | FINISH_LAYOUT_REDO_CONFIG 5288 | FINISH_LAYOUT_REDO_WALLPAPER; 5289 } 5290 } 5291 } 5292 5293 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5294 // If the navigation bar has been hidden or shown, we need to do another 5295 // layout pass to update that window. 5296 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5297 } 5298 5299 // update since mAllowLockscreenWhenOn might have changed 5300 updateLockScreenTimeout(); 5301 return changes; 5302 } 5303 5304 /** 5305 * Updates the occluded state of the Keyguard. 5306 * 5307 * @return Whether the flags have changed and we have to redo the layout. 5308 */ 5309 private boolean setKeyguardOccludedLw(boolean isOccluded) { 5310 boolean wasOccluded = mKeyguardOccluded; 5311 boolean showing = mKeyguardDelegate.isShowing(); 5312 if (wasOccluded && !isOccluded && showing) { 5313 mKeyguardOccluded = false; 5314 mKeyguardDelegate.setOccluded(false); 5315 mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD; 5316 return true; 5317 } else if (!wasOccluded && isOccluded && showing) { 5318 mKeyguardOccluded = true; 5319 mKeyguardDelegate.setOccluded(true); 5320 mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD; 5321 mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER; 5322 return true; 5323 } else { 5324 return false; 5325 } 5326 } 5327 5328 private boolean isStatusBarKeyguard() { 5329 return mStatusBar != null 5330 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0; 5331 } 5332 5333 @Override 5334 public boolean allowAppAnimationsLw() { 5335 if (isStatusBarKeyguard() || mShowingDream) { 5336 // If keyguard or dreams is currently visible, no reason to animate behind it. 5337 return false; 5338 } 5339 return true; 5340 } 5341 5342 @Override 5343 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) { 5344 mFocusedWindow = newFocus; 5345 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5346 // If the navigation bar has been hidden or shown, we need to do another 5347 // layout pass to update that window. 5348 return FINISH_LAYOUT_REDO_LAYOUT; 5349 } 5350 return 0; 5351 } 5352 5353 /** {@inheritDoc} */ 5354 @Override 5355 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { 5356 // lid changed state 5357 final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED; 5358 if (newLidState == mLidState) { 5359 return; 5360 } 5361 5362 mLidState = newLidState; 5363 applyLidSwitchState(); 5364 updateRotation(true); 5365 5366 if (lidOpen) { 5367 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch, 5368 "android.policy:LID"); 5369 } else if (!mLidControlsSleep) { 5370 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 5371 } 5372 } 5373 5374 @Override 5375 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) { 5376 int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED; 5377 if (mCameraLensCoverState == lensCoverState) { 5378 return; 5379 } 5380 if (mCameraLensCoverState == CAMERA_LENS_COVERED && 5381 lensCoverState == CAMERA_LENS_UNCOVERED) { 5382 Intent intent; 5383 final boolean keyguardActive = mKeyguardDelegate == null ? false : 5384 mKeyguardDelegate.isShowing(); 5385 if (keyguardActive) { 5386 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE); 5387 } else { 5388 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); 5389 } 5390 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens, 5391 "android.policy:CAMERA_COVER"); 5392 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); 5393 } 5394 mCameraLensCoverState = lensCoverState; 5395 } 5396 5397 void setHdmiPlugged(boolean plugged) { 5398 if (mHdmiPlugged != plugged) { 5399 mHdmiPlugged = plugged; 5400 updateRotation(true, true); 5401 Intent intent = new Intent(ACTION_HDMI_PLUGGED); 5402 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5403 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged); 5404 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 5405 } 5406 } 5407 5408 void initializeHdmiState() { 5409 boolean plugged = false; 5410 // watch for HDMI plug messages if the hdmi switch exists 5411 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) { 5412 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi"); 5413 5414 final String filename = "/sys/class/switch/hdmi/state"; 5415 FileReader reader = null; 5416 try { 5417 reader = new FileReader(filename); 5418 char[] buf = new char[15]; 5419 int n = reader.read(buf); 5420 if (n > 1) { 5421 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1)); 5422 } 5423 } catch (IOException ex) { 5424 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5425 } catch (NumberFormatException ex) { 5426 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5427 } finally { 5428 if (reader != null) { 5429 try { 5430 reader.close(); 5431 } catch (IOException ex) { 5432 } 5433 } 5434 } 5435 } 5436 // This dance forces the code in setHdmiPlugged to run. 5437 // Always do this so the sticky intent is stuck (to false) if there is no hdmi. 5438 mHdmiPlugged = !plugged; 5439 setHdmiPlugged(!mHdmiPlugged); 5440 } 5441 5442 final Object mScreenshotLock = new Object(); 5443 ServiceConnection mScreenshotConnection = null; 5444 5445 final Runnable mScreenshotTimeout = new Runnable() { 5446 @Override public void run() { 5447 synchronized (mScreenshotLock) { 5448 if (mScreenshotConnection != null) { 5449 mContext.unbindService(mScreenshotConnection); 5450 mScreenshotConnection = null; 5451 notifyScreenshotError(); 5452 } 5453 } 5454 } 5455 }; 5456 5457 // Assume this is called from the Handler thread. 5458 private void takeScreenshot(final int screenshotType) { 5459 synchronized (mScreenshotLock) { 5460 if (mScreenshotConnection != null) { 5461 return; 5462 } 5463 final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE, 5464 SYSUI_SCREENSHOT_SERVICE); 5465 final Intent serviceIntent = new Intent(); 5466 serviceIntent.setComponent(serviceComponent); 5467 ServiceConnection conn = new ServiceConnection() { 5468 @Override 5469 public void onServiceConnected(ComponentName name, IBinder service) { 5470 synchronized (mScreenshotLock) { 5471 if (mScreenshotConnection != this) { 5472 return; 5473 } 5474 Messenger messenger = new Messenger(service); 5475 Message msg = Message.obtain(null, screenshotType); 5476 final ServiceConnection myConn = this; 5477 Handler h = new Handler(mHandler.getLooper()) { 5478 @Override 5479 public void handleMessage(Message msg) { 5480 synchronized (mScreenshotLock) { 5481 if (mScreenshotConnection == myConn) { 5482 mContext.unbindService(mScreenshotConnection); 5483 mScreenshotConnection = null; 5484 mHandler.removeCallbacks(mScreenshotTimeout); 5485 } 5486 } 5487 } 5488 }; 5489 msg.replyTo = new Messenger(h); 5490 msg.arg1 = msg.arg2 = 0; 5491 if (mStatusBar != null && mStatusBar.isVisibleLw()) 5492 msg.arg1 = 1; 5493 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) 5494 msg.arg2 = 1; 5495 try { 5496 messenger.send(msg); 5497 } catch (RemoteException e) { 5498 } 5499 } 5500 } 5501 5502 @Override 5503 public void onServiceDisconnected(ComponentName name) { 5504 notifyScreenshotError(); 5505 } 5506 }; 5507 if (mContext.bindServiceAsUser(serviceIntent, conn, 5508 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, 5509 UserHandle.CURRENT)) { 5510 mScreenshotConnection = conn; 5511 mHandler.postDelayed(mScreenshotTimeout, 10000); 5512 } 5513 } 5514 } 5515 5516 /** 5517 * Notifies the screenshot service to show an error. 5518 */ 5519 private void notifyScreenshotError() { 5520 // If the service process is killed, then ask it to clean up after itself 5521 final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE, 5522 SYSUI_SCREENSHOT_ERROR_RECEIVER); 5523 Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT); 5524 errorIntent.setComponent(errorComponent); 5525 errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | 5526 Intent.FLAG_RECEIVER_FOREGROUND); 5527 mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT); 5528 } 5529 5530 /** {@inheritDoc} */ 5531 @Override 5532 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { 5533 if (!mSystemBooted) { 5534 // If we have not yet booted, don't let key events do anything. 5535 return 0; 5536 } 5537 5538 final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0; 5539 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; 5540 final boolean canceled = event.isCanceled(); 5541 final int keyCode = event.getKeyCode(); 5542 5543 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; 5544 5545 // If screen is off then we treat the case where the keyguard is open but hidden 5546 // the same as if it were open and in front. 5547 // This will prevent any keys other than the power button from waking the screen 5548 // when the keyguard is hidden by another activity. 5549 final boolean keyguardActive = (mKeyguardDelegate == null ? false : 5550 (interactive ? 5551 isKeyguardShowingAndNotOccluded() : 5552 mKeyguardDelegate.isShowing())); 5553 5554 if (DEBUG_INPUT) { 5555 Log.d(TAG, "interceptKeyTq keycode=" + keyCode 5556 + " interactive=" + interactive + " keyguardActive=" + keyguardActive 5557 + " policyFlags=" + Integer.toHexString(policyFlags)); 5558 } 5559 5560 // Basic policy based on interactive state. 5561 int result; 5562 boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0 5563 || event.isWakeKey(); 5564 if (interactive || (isInjected && !isWakeKey)) { 5565 // When the device is interactive or the key is injected pass the 5566 // key to the application. 5567 result = ACTION_PASS_TO_USER; 5568 isWakeKey = false; 5569 5570 if (interactive) { 5571 // If the screen is awake, but the button pressed was the one that woke the device 5572 // then don't pass it to the application 5573 if (keyCode == mPendingWakeKey && !down) { 5574 result = 0; 5575 } 5576 // Reset the pending key 5577 mPendingWakeKey = PENDING_KEY_NULL; 5578 } 5579 } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) { 5580 // If we're currently dozing with the screen on and the keyguard showing, pass the key 5581 // to the application but preserve its wake key status to make sure we still move 5582 // from dozing to fully interactive if we would normally go from off to fully 5583 // interactive. 5584 result = ACTION_PASS_TO_USER; 5585 // Since we're dispatching the input, reset the pending key 5586 mPendingWakeKey = PENDING_KEY_NULL; 5587 } else { 5588 // When the screen is off and the key is not injected, determine whether 5589 // to wake the device but don't pass the key to the application. 5590 result = 0; 5591 if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) { 5592 isWakeKey = false; 5593 } 5594 // Cache the wake key on down event so we can also avoid sending the up event to the app 5595 if (isWakeKey && down) { 5596 mPendingWakeKey = keyCode; 5597 } 5598 } 5599 5600 // If the key would be handled globally, just return the result, don't worry about special 5601 // key processing. 5602 if (isValidGlobalKey(keyCode) 5603 && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) { 5604 if (isWakeKey) { 5605 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 5606 } 5607 return result; 5608 } 5609 5610 boolean useHapticFeedback = down 5611 && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0 5612 && event.getRepeatCount() == 0; 5613 5614 // Handle special keys. 5615 switch (keyCode) { 5616 case KeyEvent.KEYCODE_BACK: { 5617 if (down) { 5618 mBackKeyHandled = false; 5619 if (hasLongPressOnBackBehavior()) { 5620 Message msg = mHandler.obtainMessage(MSG_BACK_LONG_PRESS); 5621 msg.setAsynchronous(true); 5622 mHandler.sendMessageDelayed(msg, 5623 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 5624 } 5625 } else { 5626 boolean handled = mBackKeyHandled; 5627 5628 // Reset back key state 5629 cancelPendingBackKeyAction(); 5630 5631 // Don't pass back press to app if we've already handled it 5632 if (handled) { 5633 result &= ~ACTION_PASS_TO_USER; 5634 } 5635 } 5636 break; 5637 } 5638 5639 case KeyEvent.KEYCODE_VOLUME_DOWN: 5640 case KeyEvent.KEYCODE_VOLUME_UP: 5641 case KeyEvent.KEYCODE_VOLUME_MUTE: { 5642 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { 5643 if (down) { 5644 if (interactive && !mScreenshotChordVolumeDownKeyTriggered 5645 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5646 mScreenshotChordVolumeDownKeyTriggered = true; 5647 mScreenshotChordVolumeDownKeyTime = event.getDownTime(); 5648 mScreenshotChordVolumeDownKeyConsumed = false; 5649 cancelPendingPowerKeyAction(); 5650 interceptScreenshotChord(); 5651 } 5652 } else { 5653 mScreenshotChordVolumeDownKeyTriggered = false; 5654 cancelPendingScreenshotChordAction(); 5655 } 5656 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 5657 if (down) { 5658 if (interactive && !mScreenshotChordVolumeUpKeyTriggered 5659 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5660 mScreenshotChordVolumeUpKeyTriggered = true; 5661 cancelPendingPowerKeyAction(); 5662 cancelPendingScreenshotChordAction(); 5663 } 5664 } else { 5665 mScreenshotChordVolumeUpKeyTriggered = false; 5666 cancelPendingScreenshotChordAction(); 5667 } 5668 } 5669 if (down) { 5670 TelecomManager telecomManager = getTelecommService(); 5671 if (telecomManager != null) { 5672 if (telecomManager.isRinging()) { 5673 // If an incoming call is ringing, either VOLUME key means 5674 // "silence ringer". We handle these keys here, rather than 5675 // in the InCallScreen, to make sure we'll respond to them 5676 // even if the InCallScreen hasn't come to the foreground yet. 5677 // Look for the DOWN event here, to agree with the "fallback" 5678 // behavior in the InCallScreen. 5679 Log.i(TAG, "interceptKeyBeforeQueueing:" 5680 + " VOLUME key-down while ringing: Silence ringer!"); 5681 5682 // Silence the ringer. (It's safe to call this 5683 // even if the ringer has already been silenced.) 5684 telecomManager.silenceRinger(); 5685 5686 // And *don't* pass this key thru to the current activity 5687 // (which is probably the InCallScreen.) 5688 result &= ~ACTION_PASS_TO_USER; 5689 break; 5690 } 5691 if (telecomManager.isInCall() 5692 && (result & ACTION_PASS_TO_USER) == 0) { 5693 // If we are in call but we decided not to pass the key to 5694 // the application, just pass it to the session service. 5695 5696 MediaSessionLegacyHelper.getHelper(mContext) 5697 .sendVolumeKeyEvent(event, false); 5698 break; 5699 } 5700 } 5701 } 5702 if (mUseTvRouting) { 5703 // On TVs, defer special key handlings to 5704 // {@link interceptKeyBeforeDispatching()}. 5705 result |= ACTION_PASS_TO_USER; 5706 } else if ((result & ACTION_PASS_TO_USER) == 0) { 5707 // If we aren't passing to the user and no one else 5708 // handled it send it to the session manager to 5709 // figure out. 5710 MediaSessionLegacyHelper.getHelper(mContext) 5711 .sendVolumeKeyEvent(event, true); 5712 } 5713 break; 5714 } 5715 5716 case KeyEvent.KEYCODE_ENDCALL: { 5717 result &= ~ACTION_PASS_TO_USER; 5718 if (down) { 5719 TelecomManager telecomManager = getTelecommService(); 5720 boolean hungUp = false; 5721 if (telecomManager != null) { 5722 hungUp = telecomManager.endCall(); 5723 } 5724 if (interactive && !hungUp) { 5725 mEndCallKeyHandled = false; 5726 mHandler.postDelayed(mEndCallLongPress, 5727 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 5728 } else { 5729 mEndCallKeyHandled = true; 5730 } 5731 } else { 5732 if (!mEndCallKeyHandled) { 5733 mHandler.removeCallbacks(mEndCallLongPress); 5734 if (!canceled) { 5735 if ((mEndcallBehavior 5736 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) { 5737 if (goHome()) { 5738 break; 5739 } 5740 } 5741 if ((mEndcallBehavior 5742 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) { 5743 mPowerManager.goToSleep(event.getEventTime(), 5744 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); 5745 isWakeKey = false; 5746 } 5747 } 5748 } 5749 } 5750 break; 5751 } 5752 5753 case KeyEvent.KEYCODE_POWER: { 5754 result &= ~ACTION_PASS_TO_USER; 5755 isWakeKey = false; // wake-up will be handled separately 5756 if (down) { 5757 interceptPowerKeyDown(event, interactive); 5758 } else { 5759 interceptPowerKeyUp(event, interactive, canceled); 5760 } 5761 break; 5762 } 5763 5764 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN: 5765 // fall through 5766 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP: 5767 // fall through 5768 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT: 5769 // fall through 5770 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: { 5771 result &= ~ACTION_PASS_TO_USER; 5772 interceptSystemNavigationKey(event); 5773 break; 5774 } 5775 5776 case KeyEvent.KEYCODE_SLEEP: { 5777 result &= ~ACTION_PASS_TO_USER; 5778 isWakeKey = false; 5779 if (!mPowerManager.isInteractive()) { 5780 useHapticFeedback = false; // suppress feedback if already non-interactive 5781 } 5782 if (down) { 5783 sleepPress(event.getEventTime()); 5784 } else { 5785 sleepRelease(event.getEventTime()); 5786 } 5787 break; 5788 } 5789 5790 case KeyEvent.KEYCODE_SOFT_SLEEP: { 5791 result &= ~ACTION_PASS_TO_USER; 5792 isWakeKey = false; 5793 if (!down) { 5794 mPowerManagerInternal.setUserInactiveOverrideFromWindowManager(); 5795 } 5796 break; 5797 } 5798 5799 case KeyEvent.KEYCODE_WAKEUP: { 5800 result &= ~ACTION_PASS_TO_USER; 5801 isWakeKey = true; 5802 break; 5803 } 5804 5805 case KeyEvent.KEYCODE_MEDIA_PLAY: 5806 case KeyEvent.KEYCODE_MEDIA_PAUSE: 5807 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 5808 case KeyEvent.KEYCODE_HEADSETHOOK: 5809 case KeyEvent.KEYCODE_MUTE: 5810 case KeyEvent.KEYCODE_MEDIA_STOP: 5811 case KeyEvent.KEYCODE_MEDIA_NEXT: 5812 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 5813 case KeyEvent.KEYCODE_MEDIA_REWIND: 5814 case KeyEvent.KEYCODE_MEDIA_RECORD: 5815 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 5816 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { 5817 if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) { 5818 // If the global session is active pass all media keys to it 5819 // instead of the active window. 5820 result &= ~ACTION_PASS_TO_USER; 5821 } 5822 if ((result & ACTION_PASS_TO_USER) == 0) { 5823 // Only do this if we would otherwise not pass it to the user. In that 5824 // case, the PhoneWindow class will do the same thing, except it will 5825 // only do it if the showing app doesn't process the key on its own. 5826 // Note that we need to make a copy of the key event here because the 5827 // original key event will be recycled when we return. 5828 mBroadcastWakeLock.acquire(); 5829 Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK, 5830 new KeyEvent(event)); 5831 msg.setAsynchronous(true); 5832 msg.sendToTarget(); 5833 } 5834 break; 5835 } 5836 5837 case KeyEvent.KEYCODE_CALL: { 5838 if (down) { 5839 TelecomManager telecomManager = getTelecommService(); 5840 if (telecomManager != null) { 5841 if (telecomManager.isRinging()) { 5842 Log.i(TAG, "interceptKeyBeforeQueueing:" 5843 + " CALL key-down while ringing: Answer the call!"); 5844 telecomManager.acceptRingingCall(); 5845 5846 // And *don't* pass this key thru to the current activity 5847 // (which is presumably the InCallScreen.) 5848 result &= ~ACTION_PASS_TO_USER; 5849 } 5850 } 5851 } 5852 break; 5853 } 5854 case KeyEvent.KEYCODE_VOICE_ASSIST: { 5855 // Only do this if we would otherwise not pass it to the user. In that case, 5856 // interceptKeyBeforeDispatching would apply a similar but different policy in 5857 // order to invoke voice assist actions. Note that we need to make a copy of the 5858 // key event here because the original key event will be recycled when we return. 5859 if ((result & ACTION_PASS_TO_USER) == 0 && !down) { 5860 mBroadcastWakeLock.acquire(); 5861 Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK, 5862 keyguardActive ? 1 : 0, 0); 5863 msg.setAsynchronous(true); 5864 msg.sendToTarget(); 5865 } 5866 break; 5867 } 5868 case KeyEvent.KEYCODE_WINDOW: { 5869 if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) { 5870 if (mTvPictureInPictureVisible) { 5871 // Consumes the key only if picture-in-picture is visible 5872 // to show picture-in-picture control menu. 5873 // This gives a chance to the foreground activity 5874 // to customize PIP key behavior. 5875 if (!down) { 5876 showTvPictureInPictureMenu(event); 5877 } 5878 result &= ~ACTION_PASS_TO_USER; 5879 } 5880 } 5881 break; 5882 } 5883 } 5884 5885 if (useHapticFeedback) { 5886 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); 5887 } 5888 5889 if (isWakeKey) { 5890 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 5891 } 5892 5893 return result; 5894 } 5895 5896 /** 5897 * Handle statusbar expansion events. 5898 * @param event 5899 */ 5900 private void interceptSystemNavigationKey(KeyEvent event) { 5901 if (event.getAction() == KeyEvent.ACTION_UP && areSystemNavigationKeysEnabled()) { 5902 IStatusBarService sbar = getStatusBarService(); 5903 if (sbar != null) { 5904 try { 5905 sbar.handleSystemNavigationKey(event.getKeyCode()); 5906 } catch (RemoteException e1) { 5907 // oops, no statusbar. Ignore event. 5908 } 5909 } 5910 } 5911 } 5912 5913 /** 5914 * Returns true if the key can have global actions attached to it. 5915 * We reserve all power management keys for the system since they require 5916 * very careful handling. 5917 */ 5918 private static boolean isValidGlobalKey(int keyCode) { 5919 switch (keyCode) { 5920 case KeyEvent.KEYCODE_POWER: 5921 case KeyEvent.KEYCODE_WAKEUP: 5922 case KeyEvent.KEYCODE_SLEEP: 5923 return false; 5924 default: 5925 return true; 5926 } 5927 } 5928 5929 /** 5930 * When the screen is off we ignore some keys that might otherwise typically 5931 * be considered wake keys. We filter them out here. 5932 * 5933 * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it 5934 * is always considered a wake key. 5935 */ 5936 private boolean isWakeKeyWhenScreenOff(int keyCode) { 5937 switch (keyCode) { 5938 // ignore volume keys unless docked 5939 case KeyEvent.KEYCODE_VOLUME_UP: 5940 case KeyEvent.KEYCODE_VOLUME_DOWN: 5941 case KeyEvent.KEYCODE_VOLUME_MUTE: 5942 return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED; 5943 5944 // ignore media and camera keys 5945 case KeyEvent.KEYCODE_MUTE: 5946 case KeyEvent.KEYCODE_HEADSETHOOK: 5947 case KeyEvent.KEYCODE_MEDIA_PLAY: 5948 case KeyEvent.KEYCODE_MEDIA_PAUSE: 5949 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 5950 case KeyEvent.KEYCODE_MEDIA_STOP: 5951 case KeyEvent.KEYCODE_MEDIA_NEXT: 5952 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 5953 case KeyEvent.KEYCODE_MEDIA_REWIND: 5954 case KeyEvent.KEYCODE_MEDIA_RECORD: 5955 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 5956 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: 5957 case KeyEvent.KEYCODE_CAMERA: 5958 return false; 5959 } 5960 return true; 5961 } 5962 5963 5964 /** {@inheritDoc} */ 5965 @Override 5966 public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) { 5967 if ((policyFlags & FLAG_WAKE) != 0) { 5968 if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion, 5969 "android.policy:MOTION")) { 5970 return 0; 5971 } 5972 } 5973 5974 if (shouldDispatchInputWhenNonInteractive(null)) { 5975 return ACTION_PASS_TO_USER; 5976 } 5977 5978 // If we have not passed the action up and we are in theater mode without dreaming, 5979 // there will be no dream to intercept the touch and wake into ambient. The device should 5980 // wake up in this case. 5981 if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) { 5982 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming, 5983 "android.policy:MOTION"); 5984 } 5985 5986 return 0; 5987 } 5988 5989 private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) { 5990 final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF); 5991 5992 if (displayOff && !mHasFeatureWatch) { 5993 return false; 5994 } 5995 5996 // Send events to keyguard while the screen is on and it's showing. 5997 if (isKeyguardShowingAndNotOccluded() && !displayOff) { 5998 return true; 5999 } 6000 6001 // Watches handle BACK specially 6002 if (mHasFeatureWatch 6003 && event != null 6004 && (event.getKeyCode() == KeyEvent.KEYCODE_BACK 6005 || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) { 6006 return false; 6007 } 6008 6009 // Send events to a dozing dream even if the screen is off since the dream 6010 // is in control of the state of the screen. 6011 IDreamManager dreamManager = getDreamManager(); 6012 6013 try { 6014 if (dreamManager != null && dreamManager.isDreaming()) { 6015 return true; 6016 } 6017 } catch (RemoteException e) { 6018 Slog.e(TAG, "RemoteException when checking if dreaming", e); 6019 } 6020 6021 // Otherwise, consume events since the user can't see what is being 6022 // interacted with. 6023 return false; 6024 } 6025 6026 private void dispatchDirectAudioEvent(KeyEvent event) { 6027 if (event.getAction() != KeyEvent.ACTION_DOWN) { 6028 return; 6029 } 6030 int keyCode = event.getKeyCode(); 6031 int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND 6032 | AudioManager.FLAG_FROM_KEY; 6033 String pkgName = mContext.getOpPackageName(); 6034 switch (keyCode) { 6035 case KeyEvent.KEYCODE_VOLUME_UP: 6036 try { 6037 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE, 6038 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6039 } catch (RemoteException e) { 6040 Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e); 6041 } 6042 break; 6043 case KeyEvent.KEYCODE_VOLUME_DOWN: 6044 try { 6045 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER, 6046 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6047 } catch (RemoteException e) { 6048 Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e); 6049 } 6050 break; 6051 case KeyEvent.KEYCODE_VOLUME_MUTE: 6052 try { 6053 if (event.getRepeatCount() == 0) { 6054 getAudioService().adjustSuggestedStreamVolume( 6055 AudioManager.ADJUST_TOGGLE_MUTE, 6056 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6057 } 6058 } catch (RemoteException e) { 6059 Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e); 6060 } 6061 break; 6062 } 6063 } 6064 6065 void dispatchMediaKeyWithWakeLock(KeyEvent event) { 6066 if (DEBUG_INPUT) { 6067 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event); 6068 } 6069 6070 if (mHavePendingMediaKeyRepeatWithWakeLock) { 6071 if (DEBUG_INPUT) { 6072 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat"); 6073 } 6074 6075 mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK); 6076 mHavePendingMediaKeyRepeatWithWakeLock = false; 6077 mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock 6078 } 6079 6080 dispatchMediaKeyWithWakeLockToAudioService(event); 6081 6082 if (event.getAction() == KeyEvent.ACTION_DOWN 6083 && event.getRepeatCount() == 0) { 6084 mHavePendingMediaKeyRepeatWithWakeLock = true; 6085 6086 Message msg = mHandler.obtainMessage( 6087 MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event); 6088 msg.setAsynchronous(true); 6089 mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout()); 6090 } else { 6091 mBroadcastWakeLock.release(); 6092 } 6093 } 6094 6095 void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) { 6096 mHavePendingMediaKeyRepeatWithWakeLock = false; 6097 6098 KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event, 6099 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS); 6100 if (DEBUG_INPUT) { 6101 Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent); 6102 } 6103 6104 dispatchMediaKeyWithWakeLockToAudioService(repeatEvent); 6105 mBroadcastWakeLock.release(); 6106 } 6107 6108 void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) { 6109 if (ActivityManagerNative.isSystemReady()) { 6110 MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true); 6111 } 6112 } 6113 6114 void launchVoiceAssistWithWakeLock(boolean keyguardActive) { 6115 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface( 6116 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); 6117 if (dic != null) { 6118 try { 6119 dic.exitIdle("voice-search"); 6120 } catch (RemoteException e) { 6121 } 6122 } 6123 Intent voiceIntent = 6124 new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); 6125 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive); 6126 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF); 6127 mBroadcastWakeLock.release(); 6128 } 6129 6130 BroadcastReceiver mDockReceiver = new BroadcastReceiver() { 6131 @Override 6132 public void onReceive(Context context, Intent intent) { 6133 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) { 6134 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 6135 Intent.EXTRA_DOCK_STATE_UNDOCKED); 6136 } else { 6137 try { 6138 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface( 6139 ServiceManager.getService(Context.UI_MODE_SERVICE)); 6140 mUiMode = uiModeService.getCurrentModeType(); 6141 } catch (RemoteException e) { 6142 } 6143 } 6144 updateRotation(true); 6145 synchronized (mLock) { 6146 updateOrientationListenerLp(); 6147 } 6148 } 6149 }; 6150 6151 BroadcastReceiver mDreamReceiver = new BroadcastReceiver() { 6152 @Override 6153 public void onReceive(Context context, Intent intent) { 6154 if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) { 6155 if (mKeyguardDelegate != null) { 6156 mKeyguardDelegate.onDreamingStarted(); 6157 } 6158 } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) { 6159 if (mKeyguardDelegate != null) { 6160 mKeyguardDelegate.onDreamingStopped(); 6161 } 6162 } 6163 } 6164 }; 6165 6166 BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() { 6167 @Override 6168 public void onReceive(Context context, Intent intent) { 6169 if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) { 6170 // tickle the settings observer: this first ensures that we're 6171 // observing the relevant settings for the newly-active user, 6172 // and then updates our own bookkeeping based on the now- 6173 // current user. 6174 mSettingsObserver.onChange(false); 6175 6176 // force a re-application of focused window sysui visibility. 6177 // the window may never have been shown for this user 6178 // e.g. the keyguard when going through the new-user setup flow 6179 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6180 mLastSystemUiFlags = 0; 6181 updateSystemUiVisibilityLw(); 6182 } 6183 } 6184 } 6185 }; 6186 6187 private final Runnable mHiddenNavPanic = new Runnable() { 6188 @Override 6189 public void run() { 6190 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6191 if (!isUserSetupComplete()) { 6192 // Swipe-up for navigation bar is disabled during setup 6193 return; 6194 } 6195 mPendingPanicGestureUptime = SystemClock.uptimeMillis(); 6196 mNavigationBarController.showTransient(); 6197 } 6198 } 6199 }; 6200 6201 private void requestTransientBars(WindowState swipeTarget) { 6202 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6203 if (!isUserSetupComplete()) { 6204 // Swipe-up for navigation bar is disabled during setup 6205 return; 6206 } 6207 boolean sb = mStatusBarController.checkShowTransientBarLw(); 6208 boolean nb = mNavigationBarController.checkShowTransientBarLw(); 6209 if (sb || nb) { 6210 // Don't show status bar when swiping on already visible navigation bar 6211 if (!nb && swipeTarget == mNavigationBar) { 6212 if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target"); 6213 return; 6214 } 6215 if (sb) mStatusBarController.showTransient(); 6216 if (nb) mNavigationBarController.showTransient(); 6217 mImmersiveModeConfirmation.confirmCurrentPrompt(); 6218 updateSystemUiVisibilityLw(); 6219 } 6220 } 6221 } 6222 6223 // Called on the PowerManager's Notifier thread. 6224 @Override 6225 public void startedGoingToSleep(int why) { 6226 if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")"); 6227 mCameraGestureTriggeredDuringGoingToSleep = false; 6228 mGoingToSleep = true; 6229 if (mKeyguardDelegate != null) { 6230 mKeyguardDelegate.onStartedGoingToSleep(why); 6231 } 6232 } 6233 6234 // Called on the PowerManager's Notifier thread. 6235 @Override 6236 public void finishedGoingToSleep(int why) { 6237 EventLog.writeEvent(70000, 0); 6238 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")"); 6239 MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000); 6240 6241 mGoingToSleep = false; 6242 6243 // We must get this work done here because the power manager will drop 6244 // the wake lock and let the system suspend once this function returns. 6245 synchronized (mLock) { 6246 mAwake = false; 6247 updateWakeGestureListenerLp(); 6248 updateOrientationListenerLp(); 6249 updateLockScreenTimeout(); 6250 } 6251 if (mKeyguardDelegate != null) { 6252 mKeyguardDelegate.onFinishedGoingToSleep(why, 6253 mCameraGestureTriggeredDuringGoingToSleep); 6254 } 6255 mCameraGestureTriggeredDuringGoingToSleep = false; 6256 } 6257 6258 // Called on the PowerManager's Notifier thread. 6259 @Override 6260 public void startedWakingUp() { 6261 EventLog.writeEvent(70000, 1); 6262 if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up..."); 6263 6264 // Since goToSleep performs these functions synchronously, we must 6265 // do the same here. We cannot post this work to a handler because 6266 // that might cause it to become reordered with respect to what 6267 // may happen in a future call to goToSleep. 6268 synchronized (mLock) { 6269 mAwake = true; 6270 6271 updateWakeGestureListenerLp(); 6272 updateOrientationListenerLp(); 6273 updateLockScreenTimeout(); 6274 } 6275 6276 if (mKeyguardDelegate != null) { 6277 mKeyguardDelegate.onStartedWakingUp(); 6278 } 6279 } 6280 6281 // Called on the PowerManager's Notifier thread. 6282 @Override 6283 public void finishedWakingUp() { 6284 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up..."); 6285 } 6286 6287 private void wakeUpFromPowerKey(long eventTime) { 6288 wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER"); 6289 } 6290 6291 private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) { 6292 final boolean theaterModeEnabled = isTheaterModeEnabled(); 6293 if (!wakeInTheaterMode && theaterModeEnabled) { 6294 return false; 6295 } 6296 6297 if (theaterModeEnabled) { 6298 Settings.Global.putInt(mContext.getContentResolver(), 6299 Settings.Global.THEATER_MODE_ON, 0); 6300 } 6301 6302 mPowerManager.wakeUp(wakeTime, reason); 6303 return true; 6304 } 6305 6306 private void finishKeyguardDrawn() { 6307 synchronized (mLock) { 6308 if (!mScreenOnEarly || mKeyguardDrawComplete) { 6309 return; // We are not awake yet or we have already informed of this event. 6310 } 6311 6312 mKeyguardDrawComplete = true; 6313 if (mKeyguardDelegate != null) { 6314 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6315 } 6316 mWindowManagerDrawComplete = false; 6317 } 6318 6319 // ... eventually calls finishWindowsDrawn which will finalize our screen turn on 6320 // as well as enabling the orientation change logic/sensor. 6321 mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback, 6322 WAITING_FOR_DRAWN_TIMEOUT); 6323 } 6324 6325 // Called on the DisplayManager's DisplayPowerController thread. 6326 @Override 6327 public void screenTurnedOff() { 6328 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off..."); 6329 6330 updateScreenOffSleepToken(true); 6331 synchronized (mLock) { 6332 mScreenOnEarly = false; 6333 mScreenOnFully = false; 6334 mKeyguardDrawComplete = false; 6335 mWindowManagerDrawComplete = false; 6336 mScreenOnListener = null; 6337 updateOrientationListenerLp(); 6338 6339 if (mKeyguardDelegate != null) { 6340 mKeyguardDelegate.onScreenTurnedOff(); 6341 } 6342 } 6343 } 6344 6345 // Called on the DisplayManager's DisplayPowerController thread. 6346 @Override 6347 public void screenTurningOn(final ScreenOnListener screenOnListener) { 6348 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on..."); 6349 6350 updateScreenOffSleepToken(false); 6351 synchronized (mLock) { 6352 mScreenOnEarly = true; 6353 mScreenOnFully = false; 6354 mKeyguardDrawComplete = false; 6355 mWindowManagerDrawComplete = false; 6356 mScreenOnListener = screenOnListener; 6357 6358 if (mKeyguardDelegate != null) { 6359 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6360 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000); 6361 mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback); 6362 } else { 6363 if (DEBUG_WAKEUP) Slog.d(TAG, 6364 "null mKeyguardDelegate: setting mKeyguardDrawComplete."); 6365 finishKeyguardDrawn(); 6366 } 6367 } 6368 } 6369 6370 // Called on the DisplayManager's DisplayPowerController thread. 6371 @Override 6372 public void screenTurnedOn() { 6373 synchronized (mLock) { 6374 if (mKeyguardDelegate != null) { 6375 mKeyguardDelegate.onScreenTurnedOn(); 6376 } 6377 } 6378 } 6379 6380 private void finishWindowsDrawn() { 6381 synchronized (mLock) { 6382 if (!mScreenOnEarly || mWindowManagerDrawComplete) { 6383 return; // Screen is not turned on or we did already handle this case earlier. 6384 } 6385 6386 mWindowManagerDrawComplete = true; 6387 } 6388 6389 finishScreenTurningOn(); 6390 } 6391 6392 private void finishScreenTurningOn() { 6393 synchronized (mLock) { 6394 // We have just finished drawing screen content. Since the orientation listener 6395 // gets only installed when all windows are drawn, we try to install it again. 6396 updateOrientationListenerLp(); 6397 } 6398 final ScreenOnListener listener; 6399 final boolean enableScreen; 6400 synchronized (mLock) { 6401 if (DEBUG_WAKEUP) Slog.d(TAG, 6402 "finishScreenTurningOn: mAwake=" + mAwake 6403 + ", mScreenOnEarly=" + mScreenOnEarly 6404 + ", mScreenOnFully=" + mScreenOnFully 6405 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete 6406 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete); 6407 6408 if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete 6409 || (mAwake && !mKeyguardDrawComplete)) { 6410 return; // spurious or not ready yet 6411 } 6412 6413 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on..."); 6414 listener = mScreenOnListener; 6415 mScreenOnListener = null; 6416 mScreenOnFully = true; 6417 6418 // Remember the first time we draw the keyguard so we know when we're done with 6419 // the main part of booting and can enable the screen and hide boot messages. 6420 if (!mKeyguardDrawnOnce && mAwake) { 6421 mKeyguardDrawnOnce = true; 6422 enableScreen = true; 6423 if (mBootMessageNeedsHiding) { 6424 mBootMessageNeedsHiding = false; 6425 hideBootMessages(); 6426 } 6427 } else { 6428 enableScreen = false; 6429 } 6430 } 6431 6432 if (listener != null) { 6433 listener.onScreenOn(); 6434 } 6435 6436 if (enableScreen) { 6437 try { 6438 mWindowManager.enableScreenIfNeeded(); 6439 } catch (RemoteException unhandled) { 6440 } 6441 } 6442 } 6443 6444 private void handleHideBootMessage() { 6445 synchronized (mLock) { 6446 if (!mKeyguardDrawnOnce) { 6447 mBootMessageNeedsHiding = true; 6448 return; // keyguard hasn't drawn the first time yet, not done booting 6449 } 6450 } 6451 6452 if (mBootMsgDialog != null) { 6453 if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing"); 6454 mBootMsgDialog.dismiss(); 6455 mBootMsgDialog = null; 6456 } 6457 } 6458 6459 @Override 6460 public boolean isScreenOn() { 6461 return mScreenOnFully; 6462 } 6463 6464 /** {@inheritDoc} */ 6465 @Override 6466 public void enableKeyguard(boolean enabled) { 6467 if (mKeyguardDelegate != null) { 6468 mKeyguardDelegate.setKeyguardEnabled(enabled); 6469 } 6470 } 6471 6472 /** {@inheritDoc} */ 6473 @Override 6474 public void exitKeyguardSecurely(OnKeyguardExitResult callback) { 6475 if (mKeyguardDelegate != null) { 6476 mKeyguardDelegate.verifyUnlock(callback); 6477 } 6478 } 6479 6480 private boolean isKeyguardShowingAndNotOccluded() { 6481 if (mKeyguardDelegate == null) return false; 6482 return mKeyguardDelegate.isShowing() && !mKeyguardOccluded; 6483 } 6484 6485 /** {@inheritDoc} */ 6486 @Override 6487 public boolean isKeyguardLocked() { 6488 return keyguardOn(); 6489 } 6490 6491 /** {@inheritDoc} */ 6492 @Override 6493 public boolean isKeyguardSecure(int userId) { 6494 if (mKeyguardDelegate == null) return false; 6495 return mKeyguardDelegate.isSecure(userId); 6496 } 6497 6498 /** {@inheritDoc} */ 6499 @Override 6500 public boolean isKeyguardShowingOrOccluded() { 6501 return mKeyguardDelegate == null ? false : mKeyguardDelegate.isShowing(); 6502 } 6503 6504 /** {@inheritDoc} */ 6505 @Override 6506 public boolean inKeyguardRestrictedKeyInputMode() { 6507 if (mKeyguardDelegate == null) return false; 6508 return mKeyguardDelegate.isInputRestricted(); 6509 } 6510 6511 @Override 6512 public void dismissKeyguardLw() { 6513 if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) { 6514 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw"); 6515 mHandler.post(new Runnable() { 6516 @Override 6517 public void run() { 6518 // ask the keyguard to prompt the user to authenticate if necessary 6519 mKeyguardDelegate.dismiss(); 6520 } 6521 }); 6522 } 6523 } 6524 6525 @Override 6526 public void notifyActivityDrawnForKeyguardLw() { 6527 if (mKeyguardDelegate != null) { 6528 mHandler.post(new Runnable() { 6529 @Override 6530 public void run() { 6531 mKeyguardDelegate.onActivityDrawn(); 6532 } 6533 }); 6534 } 6535 } 6536 6537 @Override 6538 public boolean isKeyguardDrawnLw() { 6539 synchronized (mLock) { 6540 return mKeyguardDrawnOnce; 6541 } 6542 } 6543 6544 @Override 6545 public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) { 6546 if (mKeyguardDelegate != null) { 6547 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation"); 6548 mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration); 6549 } 6550 } 6551 6552 @Override 6553 public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6554 Rect outInsets) { 6555 outInsets.setEmpty(); 6556 6557 // Navigation bar and status bar. 6558 getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets); 6559 if (mStatusBar != null) { 6560 outInsets.top = mStatusBarHeight; 6561 } 6562 } 6563 6564 @Override 6565 public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6566 Rect outInsets) { 6567 outInsets.setEmpty(); 6568 6569 // Only navigation bar 6570 if (mNavigationBar != null) { 6571 int position = navigationBarPosition(displayWidth, displayHeight, displayRotation); 6572 if (position == NAV_BAR_BOTTOM) { 6573 outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode); 6574 } else if (position == NAV_BAR_RIGHT) { 6575 outInsets.right = getNavigationBarWidth(displayRotation, mUiMode); 6576 } else if (position == NAV_BAR_LEFT) { 6577 outInsets.left = getNavigationBarWidth(displayRotation, mUiMode); 6578 } 6579 } 6580 } 6581 6582 @Override 6583 public boolean isNavBarForcedShownLw(WindowState windowState) { 6584 return mForceShowSystemBars; 6585 } 6586 6587 @Override 6588 public boolean isDockSideAllowed(int dockSide) { 6589 6590 // We do not allow all dock sides at which the navigation bar touches the docked stack. 6591 if (!mNavigationBarCanMove) { 6592 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT; 6593 } else { 6594 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT; 6595 } 6596 } 6597 6598 void sendCloseSystemWindows() { 6599 PhoneWindow.sendCloseSystemWindows(mContext, null); 6600 } 6601 6602 void sendCloseSystemWindows(String reason) { 6603 PhoneWindow.sendCloseSystemWindows(mContext, reason); 6604 } 6605 6606 @Override 6607 public int rotationForOrientationLw(int orientation, int lastRotation) { 6608 if (false) { 6609 Slog.v(TAG, "rotationForOrientationLw(orient=" 6610 + orientation + ", last=" + lastRotation 6611 + "); user=" + mUserRotation + " " 6612 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) 6613 ? "USER_ROTATION_LOCKED" : "") 6614 ); 6615 } 6616 6617 if (mForceDefaultOrientation) { 6618 return Surface.ROTATION_0; 6619 } 6620 6621 synchronized (mLock) { 6622 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1 6623 if (sensorRotation < 0) { 6624 sensorRotation = lastRotation; 6625 } 6626 6627 final int preferredRotation; 6628 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) { 6629 // Ignore sensor when lid switch is open and rotation is forced. 6630 preferredRotation = mLidOpenRotation; 6631 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR 6632 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) { 6633 // Ignore sensor when in car dock unless explicitly enabled. 6634 // This case can override the behavior of NOSENSOR, and can also 6635 // enable 180 degree rotation while docked. 6636 preferredRotation = mCarDockEnablesAccelerometer 6637 ? sensorRotation : mCarDockRotation; 6638 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK 6639 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK 6640 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK) 6641 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) { 6642 // Ignore sensor when in desk dock unless explicitly enabled. 6643 // This case can override the behavior of NOSENSOR, and can also 6644 // enable 180 degree rotation while docked. 6645 preferredRotation = mDeskDockEnablesAccelerometer 6646 ? sensorRotation : mDeskDockRotation; 6647 } else if (mHdmiPlugged && mDemoHdmiRotationLock) { 6648 // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled. 6649 // Note that the dock orientation overrides the HDMI orientation. 6650 preferredRotation = mDemoHdmiRotation; 6651 } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED 6652 && mUndockedHdmiRotation >= 0) { 6653 // Ignore sensor when plugged into HDMI and an undocked orientation has 6654 // been specified in the configuration (only for legacy devices without 6655 // full multi-display support). 6656 // Note that the dock orientation overrides the HDMI orientation. 6657 preferredRotation = mUndockedHdmiRotation; 6658 } else if (mDemoRotationLock) { 6659 // Ignore sensor when demo rotation lock is enabled. 6660 // Note that the dock orientation and HDMI rotation lock override this. 6661 preferredRotation = mDemoRotation; 6662 } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) { 6663 // Application just wants to remain locked in the last rotation. 6664 preferredRotation = lastRotation; 6665 } else if (!mSupportAutoRotation) { 6666 // If we don't support auto-rotation then bail out here and ignore 6667 // the sensor and any rotation lock settings. 6668 preferredRotation = -1; 6669 } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE 6670 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER 6671 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 6672 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE 6673 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT 6674 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER)) 6675 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR 6676 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6677 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE 6678 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) { 6679 // Otherwise, use sensor only if requested by the application or enabled 6680 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR. 6681 if (mAllowAllRotations < 0) { 6682 // Can't read this during init() because the context doesn't 6683 // have display metrics at that time so we cannot determine 6684 // tablet vs. phone then. 6685 mAllowAllRotations = mContext.getResources().getBoolean( 6686 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0; 6687 } 6688 if (sensorRotation != Surface.ROTATION_180 6689 || mAllowAllRotations == 1 6690 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6691 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) { 6692 preferredRotation = sensorRotation; 6693 } else { 6694 preferredRotation = lastRotation; 6695 } 6696 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED 6697 && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) { 6698 // Apply rotation lock. Does not apply to NOSENSOR. 6699 // The idea is that the user rotation expresses a weak preference for the direction 6700 // of gravity and as NOSENSOR is never affected by gravity, then neither should 6701 // NOSENSOR be affected by rotation lock (although it will be affected by docks). 6702 preferredRotation = mUserRotation; 6703 } else { 6704 // No overriding preference. 6705 // We will do exactly what the application asked us to do. 6706 preferredRotation = -1; 6707 } 6708 6709 switch (orientation) { 6710 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 6711 // Return portrait unless overridden. 6712 if (isAnyPortrait(preferredRotation)) { 6713 return preferredRotation; 6714 } 6715 return mPortraitRotation; 6716 6717 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 6718 // Return landscape unless overridden. 6719 if (isLandscapeOrSeascape(preferredRotation)) { 6720 return preferredRotation; 6721 } 6722 return mLandscapeRotation; 6723 6724 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 6725 // Return reverse portrait unless overridden. 6726 if (isAnyPortrait(preferredRotation)) { 6727 return preferredRotation; 6728 } 6729 return mUpsideDownRotation; 6730 6731 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 6732 // Return seascape unless overridden. 6733 if (isLandscapeOrSeascape(preferredRotation)) { 6734 return preferredRotation; 6735 } 6736 return mSeascapeRotation; 6737 6738 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 6739 case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE: 6740 // Return either landscape rotation. 6741 if (isLandscapeOrSeascape(preferredRotation)) { 6742 return preferredRotation; 6743 } 6744 if (isLandscapeOrSeascape(lastRotation)) { 6745 return lastRotation; 6746 } 6747 return mLandscapeRotation; 6748 6749 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 6750 case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT: 6751 // Return either portrait rotation. 6752 if (isAnyPortrait(preferredRotation)) { 6753 return preferredRotation; 6754 } 6755 if (isAnyPortrait(lastRotation)) { 6756 return lastRotation; 6757 } 6758 return mPortraitRotation; 6759 6760 default: 6761 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR, 6762 // just return the preferred orientation we already calculated. 6763 if (preferredRotation >= 0) { 6764 return preferredRotation; 6765 } 6766 return Surface.ROTATION_0; 6767 } 6768 } 6769 } 6770 6771 @Override 6772 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) { 6773 switch (orientation) { 6774 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 6775 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 6776 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 6777 return isAnyPortrait(rotation); 6778 6779 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 6780 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 6781 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 6782 return isLandscapeOrSeascape(rotation); 6783 6784 default: 6785 return true; 6786 } 6787 } 6788 6789 @Override 6790 public void setRotationLw(int rotation) { 6791 mOrientationListener.setCurrentRotation(rotation); 6792 } 6793 6794 private boolean isLandscapeOrSeascape(int rotation) { 6795 return rotation == mLandscapeRotation || rotation == mSeascapeRotation; 6796 } 6797 6798 private boolean isAnyPortrait(int rotation) { 6799 return rotation == mPortraitRotation || rotation == mUpsideDownRotation; 6800 } 6801 6802 @Override 6803 public int getUserRotationMode() { 6804 return Settings.System.getIntForUser(mContext.getContentResolver(), 6805 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ? 6806 WindowManagerPolicy.USER_ROTATION_FREE : 6807 WindowManagerPolicy.USER_ROTATION_LOCKED; 6808 } 6809 6810 // User rotation: to be used when all else fails in assigning an orientation to the device 6811 @Override 6812 public void setUserRotationMode(int mode, int rot) { 6813 ContentResolver res = mContext.getContentResolver(); 6814 6815 // mUserRotationMode and mUserRotation will be assigned by the content observer 6816 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) { 6817 Settings.System.putIntForUser(res, 6818 Settings.System.USER_ROTATION, 6819 rot, 6820 UserHandle.USER_CURRENT); 6821 Settings.System.putIntForUser(res, 6822 Settings.System.ACCELEROMETER_ROTATION, 6823 0, 6824 UserHandle.USER_CURRENT); 6825 } else { 6826 Settings.System.putIntForUser(res, 6827 Settings.System.ACCELEROMETER_ROTATION, 6828 1, 6829 UserHandle.USER_CURRENT); 6830 } 6831 } 6832 6833 @Override 6834 public void setSafeMode(boolean safeMode) { 6835 mSafeMode = safeMode; 6836 performHapticFeedbackLw(null, safeMode 6837 ? HapticFeedbackConstants.SAFE_MODE_ENABLED 6838 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true); 6839 } 6840 6841 static long[] getLongIntArray(Resources r, int resid) { 6842 int[] ar = r.getIntArray(resid); 6843 if (ar == null) { 6844 return null; 6845 } 6846 long[] out = new long[ar.length]; 6847 for (int i=0; i<ar.length; i++) { 6848 out[i] = ar[i]; 6849 } 6850 return out; 6851 } 6852 6853 /** {@inheritDoc} */ 6854 @Override 6855 public void systemReady() { 6856 mKeyguardDelegate = new KeyguardServiceDelegate(mContext); 6857 mKeyguardDelegate.onSystemReady(); 6858 6859 readCameraLensCoverState(); 6860 updateUiMode(); 6861 boolean bindKeyguardNow; 6862 synchronized (mLock) { 6863 updateOrientationListenerLp(); 6864 mSystemReady = true; 6865 mHandler.post(new Runnable() { 6866 @Override 6867 public void run() { 6868 updateSettings(); 6869 } 6870 }); 6871 6872 bindKeyguardNow = mDeferBindKeyguard; 6873 if (bindKeyguardNow) { 6874 // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now. 6875 mDeferBindKeyguard = false; 6876 } 6877 } 6878 6879 if (bindKeyguardNow) { 6880 mKeyguardDelegate.bindService(mContext); 6881 mKeyguardDelegate.onBootCompleted(); 6882 } 6883 mSystemGestures.systemReady(); 6884 mImmersiveModeConfirmation.systemReady(); 6885 } 6886 6887 /** {@inheritDoc} */ 6888 @Override 6889 public void systemBooted() { 6890 boolean bindKeyguardNow = false; 6891 synchronized (mLock) { 6892 // Time to bind Keyguard; take care to only bind it once, either here if ready or 6893 // in systemReady if not. 6894 if (mKeyguardDelegate != null) { 6895 bindKeyguardNow = true; 6896 } else { 6897 // Because mKeyguardDelegate is null, we know that the synchronized block in 6898 // systemReady didn't run yet and setting this will actually have an effect. 6899 mDeferBindKeyguard = true; 6900 } 6901 } 6902 if (bindKeyguardNow) { 6903 mKeyguardDelegate.bindService(mContext); 6904 mKeyguardDelegate.onBootCompleted(); 6905 } 6906 synchronized (mLock) { 6907 mSystemBooted = true; 6908 } 6909 startedWakingUp(); 6910 screenTurningOn(null); 6911 screenTurnedOn(); 6912 } 6913 6914 ProgressDialog mBootMsgDialog = null; 6915 6916 /** {@inheritDoc} */ 6917 @Override 6918 public void showBootMessage(final CharSequence msg, final boolean always) { 6919 mHandler.post(new Runnable() { 6920 @Override public void run() { 6921 if (mBootMsgDialog == null) { 6922 int theme; 6923 if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) { 6924 theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert; 6925 } else { 6926 theme = 0; 6927 } 6928 6929 mBootMsgDialog = new ProgressDialog(mContext, theme) { 6930 // This dialog will consume all events coming in to 6931 // it, to avoid it trying to do things too early in boot. 6932 @Override public boolean dispatchKeyEvent(KeyEvent event) { 6933 return true; 6934 } 6935 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { 6936 return true; 6937 } 6938 @Override public boolean dispatchTouchEvent(MotionEvent ev) { 6939 return true; 6940 } 6941 @Override public boolean dispatchTrackballEvent(MotionEvent ev) { 6942 return true; 6943 } 6944 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) { 6945 return true; 6946 } 6947 @Override public boolean dispatchPopulateAccessibilityEvent( 6948 AccessibilityEvent event) { 6949 return true; 6950 } 6951 }; 6952 if (mContext.getPackageManager().isUpgrade()) { 6953 mBootMsgDialog.setTitle(R.string.android_upgrading_title); 6954 } else { 6955 mBootMsgDialog.setTitle(R.string.android_start_title); 6956 } 6957 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 6958 mBootMsgDialog.setIndeterminate(true); 6959 mBootMsgDialog.getWindow().setType( 6960 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS); 6961 mBootMsgDialog.getWindow().addFlags( 6962 WindowManager.LayoutParams.FLAG_DIM_BEHIND 6963 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); 6964 mBootMsgDialog.getWindow().setDimAmount(1); 6965 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes(); 6966 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 6967 mBootMsgDialog.getWindow().setAttributes(lp); 6968 mBootMsgDialog.setCancelable(false); 6969 mBootMsgDialog.show(); 6970 } 6971 mBootMsgDialog.setMessage(msg); 6972 } 6973 }); 6974 } 6975 6976 /** {@inheritDoc} */ 6977 @Override 6978 public void hideBootMessages() { 6979 mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE); 6980 } 6981 6982 /** {@inheritDoc} */ 6983 @Override 6984 public void userActivity() { 6985 // *************************************** 6986 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE 6987 // *************************************** 6988 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER 6989 // WITH ITS LOCKS HELD. 6990 // 6991 // This code must be VERY careful about the locks 6992 // it acquires. 6993 // In fact, the current code acquires way too many, 6994 // and probably has lurking deadlocks. 6995 6996 synchronized (mScreenLockTimeout) { 6997 if (mLockScreenTimerActive) { 6998 // reset the timer 6999 mHandler.removeCallbacks(mScreenLockTimeout); 7000 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7001 } 7002 } 7003 } 7004 7005 class ScreenLockTimeout implements Runnable { 7006 Bundle options; 7007 7008 @Override 7009 public void run() { 7010 synchronized (this) { 7011 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard"); 7012 if (mKeyguardDelegate != null) { 7013 mKeyguardDelegate.doKeyguardTimeout(options); 7014 } 7015 mLockScreenTimerActive = false; 7016 options = null; 7017 } 7018 } 7019 7020 public void setLockOptions(Bundle options) { 7021 this.options = options; 7022 } 7023 } 7024 7025 ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout(); 7026 7027 @Override 7028 public void lockNow(Bundle options) { 7029 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 7030 mHandler.removeCallbacks(mScreenLockTimeout); 7031 if (options != null) { 7032 // In case multiple calls are made to lockNow, we don't wipe out the options 7033 // until the runnable actually executes. 7034 mScreenLockTimeout.setLockOptions(options); 7035 } 7036 mHandler.post(mScreenLockTimeout); 7037 } 7038 7039 private void updateLockScreenTimeout() { 7040 synchronized (mScreenLockTimeout) { 7041 boolean enable = (mAllowLockscreenWhenOn && mAwake && 7042 mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId)); 7043 if (mLockScreenTimerActive != enable) { 7044 if (enable) { 7045 if (localLOGV) Log.v(TAG, "setting lockscreen timer"); 7046 mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests 7047 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7048 } else { 7049 if (localLOGV) Log.v(TAG, "clearing lockscreen timer"); 7050 mHandler.removeCallbacks(mScreenLockTimeout); 7051 } 7052 mLockScreenTimerActive = enable; 7053 } 7054 } 7055 } 7056 7057 private void updateDreamingSleepToken(boolean acquire) { 7058 if (acquire) { 7059 if (mDreamingSleepToken == null) { 7060 mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream"); 7061 } 7062 } else { 7063 if (mDreamingSleepToken != null) { 7064 mDreamingSleepToken.release(); 7065 mDreamingSleepToken = null; 7066 } 7067 } 7068 } 7069 7070 private void updateScreenOffSleepToken(boolean acquire) { 7071 if (acquire) { 7072 if (mScreenOffSleepToken == null) { 7073 mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff"); 7074 } 7075 } else { 7076 if (mScreenOffSleepToken != null) { 7077 mScreenOffSleepToken.release(); 7078 mScreenOffSleepToken = null; 7079 } 7080 } 7081 } 7082 7083 /** {@inheritDoc} */ 7084 @Override 7085 public void enableScreenAfterBoot() { 7086 readLidState(); 7087 applyLidSwitchState(); 7088 updateRotation(true); 7089 } 7090 7091 private void applyLidSwitchState() { 7092 if (mLidState == LID_CLOSED && mLidControlsSleep) { 7093 mPowerManager.goToSleep(SystemClock.uptimeMillis(), 7094 PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH, 7095 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); 7096 } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) { 7097 mWindowManagerFuncs.lockDeviceNow(); 7098 } 7099 7100 synchronized (mLock) { 7101 updateWakeGestureListenerLp(); 7102 } 7103 } 7104 7105 void updateUiMode() { 7106 if (mUiModeManager == null) { 7107 mUiModeManager = IUiModeManager.Stub.asInterface( 7108 ServiceManager.getService(Context.UI_MODE_SERVICE)); 7109 } 7110 try { 7111 mUiMode = mUiModeManager.getCurrentModeType(); 7112 } catch (RemoteException e) { 7113 } 7114 } 7115 7116 void updateRotation(boolean alwaysSendConfiguration) { 7117 try { 7118 //set orientation on WindowManager 7119 mWindowManager.updateRotation(alwaysSendConfiguration, false); 7120 } catch (RemoteException e) { 7121 // Ignore 7122 } 7123 } 7124 7125 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 7126 try { 7127 //set orientation on WindowManager 7128 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout); 7129 } catch (RemoteException e) { 7130 // Ignore 7131 } 7132 } 7133 7134 /** 7135 * Return an Intent to launch the currently active dock app as home. Returns 7136 * null if the standard home should be launched, which is the case if any of the following is 7137 * true: 7138 * <ul> 7139 * <li>The device is not in either car mode or desk mode 7140 * <li>The device is in car mode but mEnableCarDockHomeCapture is false 7141 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false 7142 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME 7143 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME 7144 * </ul> 7145 * @return A dock intent. 7146 */ 7147 Intent createHomeDockIntent() { 7148 Intent intent = null; 7149 7150 // What home does is based on the mode, not the dock state. That 7151 // is, when in car mode you should be taken to car home regardless 7152 // of whether we are actually in a car dock. 7153 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) { 7154 if (mEnableCarDockHomeCapture) { 7155 intent = mCarDockIntent; 7156 } 7157 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) { 7158 if (ENABLE_DESK_DOCK_HOME_CAPTURE) { 7159 intent = mDeskDockIntent; 7160 } 7161 } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH 7162 && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK 7163 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK 7164 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) { 7165 // Always launch dock home from home when watch is docked, if it exists. 7166 intent = mDeskDockIntent; 7167 } 7168 7169 if (intent == null) { 7170 return null; 7171 } 7172 7173 ActivityInfo ai = null; 7174 ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser( 7175 intent, 7176 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA, 7177 mCurrentUserId); 7178 if (info != null) { 7179 ai = info.activityInfo; 7180 } 7181 if (ai != null 7182 && ai.metaData != null 7183 && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) { 7184 intent = new Intent(intent); 7185 intent.setClassName(ai.packageName, ai.name); 7186 return intent; 7187 } 7188 7189 return null; 7190 } 7191 7192 void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) { 7193 if (awakenFromDreams) { 7194 awakenDreams(); 7195 } 7196 7197 Intent dock = createHomeDockIntent(); 7198 if (dock != null) { 7199 try { 7200 if (fromHomeKey) { 7201 dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7202 } 7203 startActivityAsUser(dock, UserHandle.CURRENT); 7204 return; 7205 } catch (ActivityNotFoundException e) { 7206 } 7207 } 7208 7209 Intent intent; 7210 7211 if (fromHomeKey) { 7212 intent = new Intent(mHomeIntent); 7213 intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7214 } else { 7215 intent = mHomeIntent; 7216 } 7217 7218 startActivityAsUser(intent, UserHandle.CURRENT); 7219 } 7220 7221 /** 7222 * goes to the home screen 7223 * @return whether it did anything 7224 */ 7225 boolean goHome() { 7226 if (!isUserSetupComplete()) { 7227 Slog.i(TAG, "Not going home because user setup is in progress."); 7228 return false; 7229 } 7230 if (false) { 7231 // This code always brings home to the front. 7232 try { 7233 ActivityManagerNative.getDefault().stopAppSwitches(); 7234 } catch (RemoteException e) { 7235 } 7236 sendCloseSystemWindows(); 7237 startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */); 7238 } else { 7239 // This code brings home to the front or, if it is already 7240 // at the front, puts the device to sleep. 7241 try { 7242 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) { 7243 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry. 7244 Log.d(TAG, "UTS-TEST-MODE"); 7245 } else { 7246 ActivityManagerNative.getDefault().stopAppSwitches(); 7247 sendCloseSystemWindows(); 7248 Intent dock = createHomeDockIntent(); 7249 if (dock != null) { 7250 int result = ActivityManagerNative.getDefault() 7251 .startActivityAsUser(null, null, dock, 7252 dock.resolveTypeIfNeeded(mContext.getContentResolver()), 7253 null, null, 0, 7254 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7255 null, null, UserHandle.USER_CURRENT); 7256 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7257 return false; 7258 } 7259 } 7260 } 7261 int result = ActivityManagerNative.getDefault() 7262 .startActivityAsUser(null, null, mHomeIntent, 7263 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()), 7264 null, null, 0, 7265 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7266 null, null, UserHandle.USER_CURRENT); 7267 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7268 return false; 7269 } 7270 } catch (RemoteException ex) { 7271 // bummer, the activity manager, which is in this process, is dead 7272 } 7273 } 7274 return true; 7275 } 7276 7277 @Override 7278 public void setCurrentOrientationLw(int newOrientation) { 7279 synchronized (mLock) { 7280 if (newOrientation != mCurrentAppOrientation) { 7281 mCurrentAppOrientation = newOrientation; 7282 updateOrientationListenerLp(); 7283 } 7284 } 7285 } 7286 7287 private void performAuditoryFeedbackForAccessibilityIfNeed() { 7288 if (!isGlobalAccessibilityGestureEnabled()) { 7289 return; 7290 } 7291 AudioManager audioManager = (AudioManager) mContext.getSystemService( 7292 Context.AUDIO_SERVICE); 7293 if (audioManager.isSilentMode()) { 7294 return; 7295 } 7296 Ringtone ringTone = RingtoneManager.getRingtone(mContext, 7297 Settings.System.DEFAULT_NOTIFICATION_URI); 7298 ringTone.setStreamType(AudioManager.STREAM_MUSIC); 7299 ringTone.play(); 7300 } 7301 7302 private boolean isTheaterModeEnabled() { 7303 return Settings.Global.getInt(mContext.getContentResolver(), 7304 Settings.Global.THEATER_MODE_ON, 0) == 1; 7305 } 7306 7307 private boolean isGlobalAccessibilityGestureEnabled() { 7308 return Settings.Global.getInt(mContext.getContentResolver(), 7309 Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1; 7310 } 7311 7312 private boolean areSystemNavigationKeysEnabled() { 7313 return Settings.Secure.getInt(mContext.getContentResolver(), 7314 Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 1) == 1; 7315 } 7316 7317 @Override 7318 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) { 7319 if (!mVibrator.hasVibrator()) { 7320 return false; 7321 } 7322 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(), 7323 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0; 7324 if (hapticsDisabled && !always) { 7325 return false; 7326 } 7327 long[] pattern = null; 7328 switch (effectId) { 7329 case HapticFeedbackConstants.LONG_PRESS: 7330 pattern = mLongPressVibePattern; 7331 break; 7332 case HapticFeedbackConstants.VIRTUAL_KEY: 7333 pattern = mVirtualKeyVibePattern; 7334 break; 7335 case HapticFeedbackConstants.KEYBOARD_TAP: 7336 pattern = mKeyboardTapVibePattern; 7337 break; 7338 case HapticFeedbackConstants.CLOCK_TICK: 7339 pattern = mClockTickVibePattern; 7340 break; 7341 case HapticFeedbackConstants.CALENDAR_DATE: 7342 pattern = mCalendarDateVibePattern; 7343 break; 7344 case HapticFeedbackConstants.SAFE_MODE_DISABLED: 7345 pattern = mSafeModeDisabledVibePattern; 7346 break; 7347 case HapticFeedbackConstants.SAFE_MODE_ENABLED: 7348 pattern = mSafeModeEnabledVibePattern; 7349 break; 7350 case HapticFeedbackConstants.CONTEXT_CLICK: 7351 pattern = mContextClickVibePattern; 7352 break; 7353 default: 7354 return false; 7355 } 7356 int owningUid; 7357 String owningPackage; 7358 if (win != null) { 7359 owningUid = win.getOwningUid(); 7360 owningPackage = win.getOwningPackage(); 7361 } else { 7362 owningUid = android.os.Process.myUid(); 7363 owningPackage = mContext.getOpPackageName(); 7364 } 7365 if (pattern.length == 1) { 7366 // One-shot vibration 7367 mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES); 7368 } else { 7369 // Pattern vibration 7370 mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES); 7371 } 7372 return true; 7373 } 7374 7375 @Override 7376 public void keepScreenOnStartedLw() { 7377 } 7378 7379 @Override 7380 public void keepScreenOnStoppedLw() { 7381 if (isKeyguardShowingAndNotOccluded()) { 7382 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 7383 } 7384 } 7385 7386 private int updateSystemUiVisibilityLw() { 7387 // If there is no window focused, there will be nobody to handle the events 7388 // anyway, so just hang on in whatever state we're in until things settle down. 7389 final WindowState win = mFocusedWindow != null ? mFocusedWindow 7390 : mTopFullscreenOpaqueWindowState; 7391 if (win == null) { 7392 return 0; 7393 } 7394 if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) { 7395 // We are updating at a point where the keyguard has gotten 7396 // focus, but we were last in a state where the top window is 7397 // hiding it. This is probably because the keyguard as been 7398 // shown while the top window was displayed, so we want to ignore 7399 // it here because this is just a very transient change and it 7400 // will quickly lose focus once it correctly gets hidden. 7401 return 0; 7402 } 7403 7404 int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null) 7405 & ~mResettingSystemUiFlags 7406 & ~mForceClearedSystemUiFlags; 7407 if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) { 7408 tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS); 7409 } 7410 7411 final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */, 7412 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState); 7413 final int dockedVisibility = updateLightStatusBarLw(0 /* vis */, 7414 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState); 7415 mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds); 7416 mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds); 7417 final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility); 7418 final int diff = visibility ^ mLastSystemUiFlags; 7419 final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags; 7420 final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags; 7421 final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState); 7422 if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu 7423 && mFocusedApp == win.getAppToken() 7424 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds) 7425 && mLastDockedStackBounds.equals(mDockedStackBounds)) { 7426 return 0; 7427 } 7428 mLastSystemUiFlags = visibility; 7429 mLastFullscreenStackSysUiFlags = fullscreenVisibility; 7430 mLastDockedStackSysUiFlags = dockedVisibility; 7431 mLastFocusNeedsMenu = needsMenu; 7432 mFocusedApp = win.getAppToken(); 7433 final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds); 7434 final Rect dockedStackBounds = new Rect(mDockedStackBounds); 7435 mHandler.post(new Runnable() { 7436 @Override 7437 public void run() { 7438 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 7439 if (statusbar != null) { 7440 statusbar.setSystemUiVisibility(visibility, fullscreenVisibility, 7441 dockedVisibility, 0xffffffff, fullscreenStackBounds, 7442 dockedStackBounds, win.toString()); 7443 statusbar.topAppWindowChanged(needsMenu); 7444 } 7445 } 7446 }); 7447 return diff; 7448 } 7449 7450 private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) { 7451 WindowState statusColorWin = isStatusBarKeyguard() && !mHideLockScreen 7452 ? mStatusBar 7453 : opaqueOrDimming; 7454 7455 if (statusColorWin != null) { 7456 if (statusColorWin == opaque) { 7457 // If the top fullscreen-or-dimming window is also the top fullscreen, respect 7458 // its light flag. 7459 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7460 vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null) 7461 & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7462 } else if (statusColorWin != null && statusColorWin.isDimming()) { 7463 // Otherwise if it's dimming, clear the light flag. 7464 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7465 } 7466 } 7467 return vis; 7468 } 7469 7470 private boolean drawsSystemBarBackground(WindowState win) { 7471 return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0; 7472 } 7473 7474 private boolean forcesDrawStatusBarBackground(WindowState win) { 7475 return win == null || (win.getAttrs().privateFlags 7476 & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0; 7477 } 7478 7479 private int updateSystemBarsLw(WindowState win, int oldVis, int vis) { 7480 final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID); 7481 final boolean freeformStackVisible = 7482 mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID); 7483 final boolean resizing = mWindowManagerInternal.isDockedDividerResizing(); 7484 7485 // We need to force system bars when the docked stack is visible, when the freeform stack 7486 // is visible but also when we are resizing for the transitions when docked stack 7487 // visibility changes. 7488 mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing; 7489 final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard; 7490 7491 // apply translucent bar vis flags 7492 WindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen 7493 ? mStatusBar 7494 : mTopFullscreenOpaqueWindowState; 7495 vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7496 vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7497 final int dockedVis = mStatusBarController.applyTranslucentFlagLw( 7498 mTopDockedOpaqueWindowState, 0, 0); 7499 7500 final boolean fullscreenDrawsStatusBarBackground = 7501 (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState) 7502 && (vis & View.STATUS_BAR_TRANSLUCENT) == 0) 7503 || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState); 7504 final boolean dockedDrawsStatusBarBackground = 7505 (drawsSystemBarBackground(mTopDockedOpaqueWindowState) 7506 && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0) 7507 || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState); 7508 7509 // prevent status bar interaction from clearing certain flags 7510 int type = win.getAttrs().type; 7511 boolean statusBarHasFocus = type == TYPE_STATUS_BAR; 7512 if (statusBarHasFocus && !isStatusBarKeyguard()) { 7513 int flags = View.SYSTEM_UI_FLAG_FULLSCREEN 7514 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 7515 | View.SYSTEM_UI_FLAG_IMMERSIVE 7516 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 7517 | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7518 if (mHideLockScreen) { 7519 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT; 7520 } 7521 vis = (vis & ~flags) | (oldVis & flags); 7522 } 7523 7524 if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) { 7525 vis |= View.STATUS_BAR_TRANSPARENT; 7526 vis &= ~View.STATUS_BAR_TRANSLUCENT; 7527 } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar) 7528 || forceOpaqueStatusBar) { 7529 vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT); 7530 } 7531 7532 vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing); 7533 7534 // update status bar 7535 boolean immersiveSticky = 7536 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7537 final boolean hideStatusBarWM = 7538 mTopFullscreenOpaqueWindowState != null 7539 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null) 7540 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; 7541 final boolean hideStatusBarSysui = 7542 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 7543 final boolean hideNavBarSysui = 7544 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0; 7545 7546 final boolean transientStatusBarAllowed = mStatusBar != null 7547 && (statusBarHasFocus || (!mForceShowSystemBars 7548 && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky)))); 7549 7550 final boolean transientNavBarAllowed = mNavigationBar != null 7551 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky; 7552 7553 final long now = SystemClock.uptimeMillis(); 7554 final boolean pendingPanic = mPendingPanicGestureUptime != 0 7555 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION; 7556 if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) { 7557 // The user performed the panic gesture recently, we're about to hide the bars, 7558 // we're no longer on the Keyguard and the screen is ready. We can now request the bars. 7559 mPendingPanicGestureUptime = 0; 7560 mStatusBarController.showTransient(); 7561 mNavigationBarController.showTransient(); 7562 } 7563 7564 final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested() 7565 && !transientStatusBarAllowed && hideStatusBarSysui; 7566 final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested() 7567 && !transientNavBarAllowed; 7568 if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) { 7569 // clear the clearable flags instead 7570 clearClearableFlagsLw(); 7571 vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS; 7572 } 7573 7574 final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; 7575 immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7576 final boolean navAllowedHidden = immersive || immersiveSticky; 7577 7578 if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType()) 7579 > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) { 7580 // We can't hide the navbar from this window otherwise the input consumer would not get 7581 // the input events. 7582 vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); 7583 } 7584 7585 vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis); 7586 7587 // update navigation bar 7588 boolean oldImmersiveMode = isImmersiveMode(oldVis); 7589 boolean newImmersiveMode = isImmersiveMode(vis); 7590 if (win != null && oldImmersiveMode != newImmersiveMode) { 7591 final String pkg = win.getOwningPackage(); 7592 mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode, 7593 isUserSetupComplete()); 7594 } 7595 7596 vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis); 7597 7598 return vis; 7599 } 7600 7601 /** 7602 * @return the current visibility flags with the nav-bar opacity related flags toggled based 7603 * on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}. 7604 */ 7605 private int configureNavBarOpacity(int visibility, boolean dockedStackVisible, 7606 boolean freeformStackVisible, boolean isDockedDividerResizing) { 7607 if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) { 7608 if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) { 7609 visibility = setNavBarOpaqueFlag(visibility); 7610 } 7611 } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) { 7612 if (isDockedDividerResizing) { 7613 visibility = setNavBarOpaqueFlag(visibility); 7614 } else if (freeformStackVisible) { 7615 visibility = setNavBarTranslucentFlag(visibility); 7616 } else { 7617 visibility = setNavBarOpaqueFlag(visibility); 7618 } 7619 } 7620 7621 if (!areTranslucentBarsAllowed()) { 7622 visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT; 7623 } 7624 return visibility; 7625 } 7626 7627 private int setNavBarOpaqueFlag(int visibility) { 7628 return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT); 7629 } 7630 7631 private int setNavBarTranslucentFlag(int visibility) { 7632 visibility &= ~View.NAVIGATION_BAR_TRANSPARENT; 7633 return visibility |= View.NAVIGATION_BAR_TRANSLUCENT; 7634 } 7635 7636 private void clearClearableFlagsLw() { 7637 int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS; 7638 if (newVal != mResettingSystemUiFlags) { 7639 mResettingSystemUiFlags = newVal; 7640 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 7641 } 7642 } 7643 7644 private boolean isImmersiveMode(int vis) { 7645 final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; 7646 return mNavigationBar != null 7647 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0 7648 && (vis & flags) != 0 7649 && canHideNavigationBar(); 7650 } 7651 7652 /** 7653 * @return whether the navigation or status bar can be made translucent 7654 * 7655 * This should return true unless touch exploration is not enabled or 7656 * R.boolean.config_enableTranslucentDecor is false. 7657 */ 7658 private boolean areTranslucentBarsAllowed() { 7659 return mTranslucentDecorEnabled; 7660 } 7661 7662 // Use this instead of checking config_showNavigationBar so that it can be consistently 7663 // overridden by qemu.hw.mainkeys in the emulator. 7664 @Override 7665 public boolean hasNavigationBar() { 7666 return mHasNavigationBar; 7667 } 7668 7669 @Override 7670 public void setLastInputMethodWindowLw(WindowState ime, WindowState target) { 7671 mLastInputMethodWindow = ime; 7672 mLastInputMethodTargetWindow = target; 7673 } 7674 7675 @Override 7676 public int getInputMethodWindowVisibleHeightLw() { 7677 return mDockBottom - mCurBottom; 7678 } 7679 7680 @Override 7681 public void setCurrentUserLw(int newUserId) { 7682 mCurrentUserId = newUserId; 7683 if (mKeyguardDelegate != null) { 7684 mKeyguardDelegate.setCurrentUser(newUserId); 7685 } 7686 StatusBarManagerInternal statusBar = getStatusBarManagerInternal(); 7687 if (statusBar != null) { 7688 statusBar.setCurrentUser(newUserId); 7689 } 7690 setLastInputMethodWindowLw(null, null); 7691 } 7692 7693 @Override 7694 public boolean canMagnifyWindow(int windowType) { 7695 switch (windowType) { 7696 case WindowManager.LayoutParams.TYPE_INPUT_METHOD: 7697 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: 7698 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR: 7699 case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: { 7700 return false; 7701 } 7702 } 7703 return true; 7704 } 7705 7706 @Override 7707 public boolean isTopLevelWindow(int windowType) { 7708 if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW 7709 && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 7710 return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG); 7711 } 7712 return true; 7713 } 7714 7715 @Override 7716 public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) { 7717 // For the upside down rotation we don't rotate seamlessly as the navigation 7718 // bar moves position. 7719 // Note most apps (using orientation:sensor or user as opposed to fullSensor) 7720 // will not enter the reverse portrait orientation, so actually the 7721 // orientation won't change at all. 7722 if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) { 7723 return false; 7724 } 7725 int delta = newRotation - oldRotation; 7726 if (delta < 0) delta += 4; 7727 // Likewise we don't rotate seamlessly for 180 degree rotations 7728 // in this case the surfaces never resize, and our logic to 7729 // revert the transformations on size change will fail. We could 7730 // fix this in the future with the "tagged" frames idea. 7731 if (delta == Surface.ROTATION_180) { 7732 return false; 7733 } 7734 7735 // We only enable seamless rotation if the top window has requested 7736 // it and is in the fullscreen opaque state. Seamless rotation 7737 // requires freezing various Surface states and won't work well 7738 // with animations, so we disable it in the animation case for now. 7739 if (mTopFullscreenOpaqueWindowState != null && mTopIsFullscreen && 7740 !mTopFullscreenOpaqueWindowState.isAnimatingLw() && 7741 mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation == 7742 ROTATION_ANIMATION_JUMPCUT) { 7743 return true; 7744 } 7745 return false; 7746 } 7747 7748 @Override 7749 public void dump(String prefix, PrintWriter pw, String[] args) { 7750 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode); 7751 pw.print(" mSystemReady="); pw.print(mSystemReady); 7752 pw.print(" mSystemBooted="); pw.println(mSystemBooted); 7753 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState); 7754 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation); 7755 pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState); 7756 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged); 7757 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0 7758 || mForceClearedSystemUiFlags != 0) { 7759 pw.print(prefix); pw.print("mLastSystemUiFlags=0x"); 7760 pw.print(Integer.toHexString(mLastSystemUiFlags)); 7761 pw.print(" mResettingSystemUiFlags=0x"); 7762 pw.print(Integer.toHexString(mResettingSystemUiFlags)); 7763 pw.print(" mForceClearedSystemUiFlags=0x"); 7764 pw.println(Integer.toHexString(mForceClearedSystemUiFlags)); 7765 } 7766 if (mLastFocusNeedsMenu) { 7767 pw.print(prefix); pw.print("mLastFocusNeedsMenu="); 7768 pw.println(mLastFocusNeedsMenu); 7769 } 7770 pw.print(prefix); pw.print("mWakeGestureEnabledSetting="); 7771 pw.println(mWakeGestureEnabledSetting); 7772 7773 pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation); 7774 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode); 7775 pw.print(" mDockMode="); pw.print(mDockMode); 7776 pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture); 7777 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation); 7778 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation); 7779 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode); 7780 pw.print(" mUserRotation="); pw.print(mUserRotation); 7781 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations); 7782 pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation); 7783 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer="); 7784 pw.print(mCarDockEnablesAccelerometer); 7785 pw.print(" mDeskDockEnablesAccelerometer="); 7786 pw.println(mDeskDockEnablesAccelerometer); 7787 pw.print(prefix); pw.print("mLidKeyboardAccessibility="); 7788 pw.print(mLidKeyboardAccessibility); 7789 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility); 7790 pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock); 7791 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep); 7792 pw.print(prefix); 7793 pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior); 7794 pw.print(prefix); 7795 pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior); 7796 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior); 7797 pw.print(prefix); 7798 pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior); 7799 pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior); 7800 pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput); 7801 pw.print(prefix); pw.print("mAwake="); pw.println(mAwake); 7802 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly); 7803 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully); 7804 pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete); 7805 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete); 7806 pw.print(prefix); pw.print("mOrientationSensorEnabled="); 7807 pw.println(mOrientationSensorEnabled); 7808 pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft); 7809 pw.print(","); pw.print(mOverscanScreenTop); 7810 pw.print(") "); pw.print(mOverscanScreenWidth); 7811 pw.print("x"); pw.println(mOverscanScreenHeight); 7812 if (mOverscanLeft != 0 || mOverscanTop != 0 7813 || mOverscanRight != 0 || mOverscanBottom != 0) { 7814 pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft); 7815 pw.print(" top="); pw.print(mOverscanTop); 7816 pw.print(" right="); pw.print(mOverscanRight); 7817 pw.print(" bottom="); pw.println(mOverscanBottom); 7818 } 7819 pw.print(prefix); pw.print("mRestrictedOverscanScreen=("); 7820 pw.print(mRestrictedOverscanScreenLeft); 7821 pw.print(","); pw.print(mRestrictedOverscanScreenTop); 7822 pw.print(") "); pw.print(mRestrictedOverscanScreenWidth); 7823 pw.print("x"); pw.println(mRestrictedOverscanScreenHeight); 7824 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft); 7825 pw.print(","); pw.print(mUnrestrictedScreenTop); 7826 pw.print(") "); pw.print(mUnrestrictedScreenWidth); 7827 pw.print("x"); pw.println(mUnrestrictedScreenHeight); 7828 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft); 7829 pw.print(","); pw.print(mRestrictedScreenTop); 7830 pw.print(") "); pw.print(mRestrictedScreenWidth); 7831 pw.print("x"); pw.println(mRestrictedScreenHeight); 7832 pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft); 7833 pw.print(","); pw.print(mStableFullscreenTop); 7834 pw.print(")-("); pw.print(mStableFullscreenRight); 7835 pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")"); 7836 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft); 7837 pw.print(","); pw.print(mStableTop); 7838 pw.print(")-("); pw.print(mStableRight); 7839 pw.print(","); pw.print(mStableBottom); pw.println(")"); 7840 pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft); 7841 pw.print(","); pw.print(mSystemTop); 7842 pw.print(")-("); pw.print(mSystemRight); 7843 pw.print(","); pw.print(mSystemBottom); pw.println(")"); 7844 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft); 7845 pw.print(","); pw.print(mCurTop); 7846 pw.print(")-("); pw.print(mCurRight); 7847 pw.print(","); pw.print(mCurBottom); pw.println(")"); 7848 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft); 7849 pw.print(","); pw.print(mContentTop); 7850 pw.print(")-("); pw.print(mContentRight); 7851 pw.print(","); pw.print(mContentBottom); pw.println(")"); 7852 pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft); 7853 pw.print(","); pw.print(mVoiceContentTop); 7854 pw.print(")-("); pw.print(mVoiceContentRight); 7855 pw.print(","); pw.print(mVoiceContentBottom); pw.println(")"); 7856 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft); 7857 pw.print(","); pw.print(mDockTop); 7858 pw.print(")-("); pw.print(mDockRight); 7859 pw.print(","); pw.print(mDockBottom); pw.println(")"); 7860 pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer); 7861 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer); 7862 pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen); 7863 pw.print(" mShowingDream="); pw.print(mShowingDream); 7864 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen); 7865 pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken); 7866 if (mLastInputMethodWindow != null) { 7867 pw.print(prefix); pw.print("mLastInputMethodWindow="); 7868 pw.println(mLastInputMethodWindow); 7869 } 7870 if (mLastInputMethodTargetWindow != null) { 7871 pw.print(prefix); pw.print("mLastInputMethodTargetWindow="); 7872 pw.println(mLastInputMethodTargetWindow); 7873 } 7874 if (mStatusBar != null) { 7875 pw.print(prefix); pw.print("mStatusBar="); 7876 pw.print(mStatusBar); pw.print(" isStatusBarKeyguard="); 7877 pw.println(isStatusBarKeyguard()); 7878 } 7879 if (mNavigationBar != null) { 7880 pw.print(prefix); pw.print("mNavigationBar="); 7881 pw.println(mNavigationBar); 7882 } 7883 if (mFocusedWindow != null) { 7884 pw.print(prefix); pw.print("mFocusedWindow="); 7885 pw.println(mFocusedWindow); 7886 } 7887 if (mFocusedApp != null) { 7888 pw.print(prefix); pw.print("mFocusedApp="); 7889 pw.println(mFocusedApp); 7890 } 7891 if (mWinDismissingKeyguard != null) { 7892 pw.print(prefix); pw.print("mWinDismissingKeyguard="); 7893 pw.println(mWinDismissingKeyguard); 7894 } 7895 if (mTopFullscreenOpaqueWindowState != null) { 7896 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState="); 7897 pw.println(mTopFullscreenOpaqueWindowState); 7898 } 7899 if (mTopFullscreenOpaqueOrDimmingWindowState != null) { 7900 pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState="); 7901 pw.println(mTopFullscreenOpaqueOrDimmingWindowState); 7902 } 7903 if (mForcingShowNavBar) { 7904 pw.print(prefix); pw.print("mForcingShowNavBar="); 7905 pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer="); 7906 pw.println(mForcingShowNavBarLayer); 7907 } 7908 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen); 7909 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen); 7910 pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar); 7911 pw.print(" mForceStatusBarFromKeyguard="); 7912 pw.println(mForceStatusBarFromKeyguard); 7913 pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard); 7914 pw.print(" mWinDismissingKeyguard="); pw.print(mWinDismissingKeyguard); 7915 pw.print(" mHomePressed="); pw.println(mHomePressed); 7916 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn); 7917 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout); 7918 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive); 7919 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior); 7920 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior); 7921 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior); 7922 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation); 7923 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation); 7924 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation); 7925 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation); 7926 pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation); 7927 pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock); 7928 pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation); 7929 7930 mGlobalKeyManager.dump(prefix, pw); 7931 mStatusBarController.dump(pw, prefix); 7932 mNavigationBarController.dump(pw, prefix); 7933 PolicyControl.dump(prefix, pw); 7934 7935 if (mWakeGestureListener != null) { 7936 mWakeGestureListener.dump(pw, prefix); 7937 } 7938 if (mOrientationListener != null) { 7939 mOrientationListener.dump(pw, prefix); 7940 } 7941 if (mBurnInProtectionHelper != null) { 7942 mBurnInProtectionHelper.dump(prefix, pw); 7943 } 7944 if (mKeyguardDelegate != null) { 7945 mKeyguardDelegate.dump(prefix, pw); 7946 } 7947 } 7948} 7949