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