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