PhoneWindowManager.java revision 531eb4e9f6a12b7246acd0fe5a9b12f7908fade6
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 final boolean reallyVisible = win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw(); 5066 5067 // Voice interaction overrides both top fullscreen and top docked. 5068 if (reallyVisible && win.getAttrs().type == TYPE_VOICE_INTERACTION) { 5069 if (mTopFullscreenOpaqueWindowState == null) { 5070 mTopFullscreenOpaqueWindowState = win; 5071 if (mTopFullscreenOpaqueOrDimmingWindowState == null) { 5072 mTopFullscreenOpaqueOrDimmingWindowState = win; 5073 } 5074 } 5075 if (mTopDockedOpaqueWindowState == null) { 5076 mTopDockedOpaqueWindowState = win; 5077 if (mTopDockedOpaqueOrDimmingWindowState == null) { 5078 mTopDockedOpaqueOrDimmingWindowState = win; 5079 } 5080 } 5081 } 5082 5083 // Keep track of the window if it's dimming but not necessarily fullscreen. 5084 if (mTopFullscreenOpaqueOrDimmingWindowState == null && reallyVisible 5085 && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) { 5086 mTopFullscreenOpaqueOrDimmingWindowState = win; 5087 } 5088 5089 // We need to keep track of the top "fullscreen" opaque window for the docked stack 5090 // separately, because both the "real fullscreen" opaque window and the one for the docked 5091 // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR. 5092 if (mTopDockedOpaqueWindowState == null && reallyVisible && appWindow && attached == null 5093 && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) { 5094 mTopDockedOpaqueWindowState = win; 5095 if (mTopDockedOpaqueOrDimmingWindowState == null) { 5096 mTopDockedOpaqueOrDimmingWindowState = win; 5097 } 5098 } 5099 5100 // Also keep track of any windows that are dimming but not necessarily fullscreen in the 5101 // docked stack. 5102 if (mTopDockedOpaqueOrDimmingWindowState == null && reallyVisible && win.isDimming() 5103 && stackId == DOCKED_STACK_ID) { 5104 mTopDockedOpaqueOrDimmingWindowState = win; 5105 } 5106 } 5107 5108 private boolean isFullscreen(WindowManager.LayoutParams attrs) { 5109 return attrs.x == 0 && attrs.y == 0 5110 && attrs.width == WindowManager.LayoutParams.MATCH_PARENT 5111 && attrs.height == WindowManager.LayoutParams.MATCH_PARENT; 5112 } 5113 5114 /** {@inheritDoc} */ 5115 @Override 5116 public int finishPostLayoutPolicyLw() { 5117 if (mWinShowWhenLocked != null && mTopFullscreenOpaqueWindowState != null && 5118 mWinShowWhenLocked.getAppToken() != mTopFullscreenOpaqueWindowState.getAppToken() 5119 && isKeyguardLocked()) { 5120 // A dialog is dismissing the keyguard. Put the wallpaper behind it and hide the 5121 // fullscreen window. 5122 // TODO: Make sure FLAG_SHOW_WALLPAPER is restored when dialog is dismissed. Or not. 5123 mWinShowWhenLocked.getAttrs().flags |= FLAG_SHOW_WALLPAPER; 5124 mTopFullscreenOpaqueWindowState.hideLw(false); 5125 mTopFullscreenOpaqueWindowState = mWinShowWhenLocked; 5126 } 5127 5128 int changes = 0; 5129 boolean topIsFullscreen = false; 5130 5131 final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null) 5132 ? mTopFullscreenOpaqueWindowState.getAttrs() 5133 : null; 5134 5135 // If we are not currently showing a dream then remember the current 5136 // lockscreen state. We will use this to determine whether the dream 5137 // started while the lockscreen was showing and remember this state 5138 // while the dream is showing. 5139 if (!mShowingDream) { 5140 mDreamingLockscreen = mShowingLockscreen; 5141 if (mDreamingSleepTokenNeeded) { 5142 mDreamingSleepTokenNeeded = false; 5143 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget(); 5144 } 5145 } else { 5146 if (!mDreamingSleepTokenNeeded) { 5147 mDreamingSleepTokenNeeded = true; 5148 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget(); 5149 } 5150 } 5151 5152 if (mStatusBar != null) { 5153 if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar 5154 + " forcefkg=" + mForceStatusBarFromKeyguard 5155 + " top=" + mTopFullscreenOpaqueWindowState); 5156 boolean shouldBeTransparent = mForceStatusBarTransparent 5157 && !mForceStatusBar 5158 && !mForceStatusBarFromKeyguard; 5159 if (!shouldBeTransparent) { 5160 mStatusBarController.setShowTransparent(false /* transparent */); 5161 } else if (!mStatusBar.isVisibleLw()) { 5162 mStatusBarController.setShowTransparent(true /* transparent */); 5163 } 5164 5165 WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs(); 5166 boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT 5167 && statusBarAttrs.width == MATCH_PARENT; 5168 if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent 5169 || statusBarExpanded) { 5170 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced"); 5171 if (mStatusBarController.setBarShowingLw(true)) { 5172 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5173 } 5174 // Maintain fullscreen layout until incoming animation is complete. 5175 topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw(); 5176 // Transient status bar on the lockscreen is not allowed 5177 if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) { 5178 mStatusBarController.updateVisibilityLw(false /*transientAllowed*/, 5179 mLastSystemUiFlags, mLastSystemUiFlags); 5180 } 5181 if (statusBarExpanded && mNavigationBar != null) { 5182 if (mNavigationBarController.setBarShowingLw(true)) { 5183 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5184 } 5185 } 5186 } else if (mTopFullscreenOpaqueWindowState != null) { 5187 final int fl = PolicyControl.getWindowFlags(null, lp); 5188 if (localLOGV) { 5189 Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() 5190 + " shown position: " 5191 + mTopFullscreenOpaqueWindowState.getShownPositionLw()); 5192 Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs() 5193 + " lp.flags=0x" + Integer.toHexString(fl)); 5194 } 5195 topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0 5196 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 5197 // The subtle difference between the window for mTopFullscreenOpaqueWindowState 5198 // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window 5199 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the 5200 // case though. 5201 if (mStatusBarController.isTransientShowing()) { 5202 if (mStatusBarController.setBarShowingLw(true)) { 5203 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5204 } 5205 } else if (topIsFullscreen 5206 && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID) 5207 && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) { 5208 if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar"); 5209 if (mStatusBarController.setBarShowingLw(false)) { 5210 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5211 } else { 5212 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding"); 5213 } 5214 } else { 5215 if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen"); 5216 if (mStatusBarController.setBarShowingLw(true)) { 5217 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5218 } 5219 } 5220 } 5221 } 5222 5223 if (mTopIsFullscreen != topIsFullscreen) { 5224 if (!topIsFullscreen) { 5225 // Force another layout when status bar becomes fully shown. 5226 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5227 } 5228 mTopIsFullscreen = topIsFullscreen; 5229 } 5230 5231 // Hide the key guard if a visible window explicitly specifies that it wants to be 5232 // displayed when the screen is locked. 5233 if (mKeyguardDelegate != null && mStatusBar != null) { 5234 if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard=" 5235 + mHideLockScreen); 5236 if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardSecure) { 5237 mKeyguardHidden = true; 5238 if (setKeyguardOccludedLw(true)) { 5239 changes |= FINISH_LAYOUT_REDO_LAYOUT 5240 | FINISH_LAYOUT_REDO_CONFIG 5241 | FINISH_LAYOUT_REDO_WALLPAPER; 5242 } 5243 if (mKeyguardDelegate.isShowing()) { 5244 mHandler.post(new Runnable() { 5245 @Override 5246 public void run() { 5247 mKeyguardDelegate.keyguardDone(false, false); 5248 } 5249 }); 5250 } 5251 } else if (mHideLockScreen) { 5252 mKeyguardHidden = true; 5253 mWinDismissingKeyguard = null; 5254 if (setKeyguardOccludedLw(true)) { 5255 changes |= FINISH_LAYOUT_REDO_LAYOUT 5256 | FINISH_LAYOUT_REDO_CONFIG 5257 | FINISH_LAYOUT_REDO_WALLPAPER; 5258 } 5259 } else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) { 5260 mKeyguardHidden = false; 5261 if (setKeyguardOccludedLw(false)) { 5262 changes |= FINISH_LAYOUT_REDO_LAYOUT 5263 | FINISH_LAYOUT_REDO_CONFIG 5264 | FINISH_LAYOUT_REDO_WALLPAPER; 5265 } 5266 if (mDismissKeyguard == DISMISS_KEYGUARD_START) { 5267 // Only launch the next keyguard unlock window once per window. 5268 mHandler.post(new Runnable() { 5269 @Override 5270 public void run() { 5271 mKeyguardDelegate.dismiss(); 5272 } 5273 }); 5274 } 5275 } else { 5276 mWinDismissingKeyguard = null; 5277 mSecureDismissingKeyguard = false; 5278 mKeyguardHidden = false; 5279 if (setKeyguardOccludedLw(false)) { 5280 changes |= FINISH_LAYOUT_REDO_LAYOUT 5281 | FINISH_LAYOUT_REDO_CONFIG 5282 | FINISH_LAYOUT_REDO_WALLPAPER; 5283 } 5284 } 5285 } 5286 5287 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5288 // If the navigation bar has been hidden or shown, we need to do another 5289 // layout pass to update that window. 5290 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5291 } 5292 5293 // update since mAllowLockscreenWhenOn might have changed 5294 updateLockScreenTimeout(); 5295 return changes; 5296 } 5297 5298 /** 5299 * Updates the occluded state of the Keyguard. 5300 * 5301 * @return Whether the flags have changed and we have to redo the layout. 5302 */ 5303 private boolean setKeyguardOccludedLw(boolean isOccluded) { 5304 boolean wasOccluded = mKeyguardOccluded; 5305 boolean showing = mKeyguardDelegate.isShowing(); 5306 if (wasOccluded && !isOccluded && showing) { 5307 mKeyguardOccluded = false; 5308 mKeyguardDelegate.setOccluded(false); 5309 mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD; 5310 return true; 5311 } else if (!wasOccluded && isOccluded && showing) { 5312 mKeyguardOccluded = true; 5313 mKeyguardDelegate.setOccluded(true); 5314 mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD; 5315 mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER; 5316 return true; 5317 } else { 5318 return false; 5319 } 5320 } 5321 5322 private boolean isStatusBarKeyguard() { 5323 return mStatusBar != null 5324 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0; 5325 } 5326 5327 @Override 5328 public boolean allowAppAnimationsLw() { 5329 if (isStatusBarKeyguard() || mShowingDream) { 5330 // If keyguard or dreams is currently visible, no reason to animate behind it. 5331 return false; 5332 } 5333 return true; 5334 } 5335 5336 @Override 5337 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) { 5338 mFocusedWindow = newFocus; 5339 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5340 // If the navigation bar has been hidden or shown, we need to do another 5341 // layout pass to update that window. 5342 return FINISH_LAYOUT_REDO_LAYOUT; 5343 } 5344 return 0; 5345 } 5346 5347 /** {@inheritDoc} */ 5348 @Override 5349 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { 5350 // lid changed state 5351 final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED; 5352 if (newLidState == mLidState) { 5353 return; 5354 } 5355 5356 mLidState = newLidState; 5357 applyLidSwitchState(); 5358 updateRotation(true); 5359 5360 if (lidOpen) { 5361 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch, 5362 "android.policy:LID"); 5363 } else if (!mLidControlsSleep) { 5364 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 5365 } 5366 } 5367 5368 @Override 5369 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) { 5370 int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED; 5371 if (mCameraLensCoverState == lensCoverState) { 5372 return; 5373 } 5374 if (mCameraLensCoverState == CAMERA_LENS_COVERED && 5375 lensCoverState == CAMERA_LENS_UNCOVERED) { 5376 Intent intent; 5377 final boolean keyguardActive = mKeyguardDelegate == null ? false : 5378 mKeyguardDelegate.isShowing(); 5379 if (keyguardActive) { 5380 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE); 5381 } else { 5382 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); 5383 } 5384 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens, 5385 "android.policy:CAMERA_COVER"); 5386 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); 5387 } 5388 mCameraLensCoverState = lensCoverState; 5389 } 5390 5391 void setHdmiPlugged(boolean plugged) { 5392 if (mHdmiPlugged != plugged) { 5393 mHdmiPlugged = plugged; 5394 updateRotation(true, true); 5395 Intent intent = new Intent(ACTION_HDMI_PLUGGED); 5396 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5397 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged); 5398 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 5399 } 5400 } 5401 5402 void initializeHdmiState() { 5403 boolean plugged = false; 5404 // watch for HDMI plug messages if the hdmi switch exists 5405 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) { 5406 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi"); 5407 5408 final String filename = "/sys/class/switch/hdmi/state"; 5409 FileReader reader = null; 5410 try { 5411 reader = new FileReader(filename); 5412 char[] buf = new char[15]; 5413 int n = reader.read(buf); 5414 if (n > 1) { 5415 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1)); 5416 } 5417 } catch (IOException ex) { 5418 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5419 } catch (NumberFormatException ex) { 5420 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5421 } finally { 5422 if (reader != null) { 5423 try { 5424 reader.close(); 5425 } catch (IOException ex) { 5426 } 5427 } 5428 } 5429 } 5430 // This dance forces the code in setHdmiPlugged to run. 5431 // Always do this so the sticky intent is stuck (to false) if there is no hdmi. 5432 mHdmiPlugged = !plugged; 5433 setHdmiPlugged(!mHdmiPlugged); 5434 } 5435 5436 final Object mScreenshotLock = new Object(); 5437 ServiceConnection mScreenshotConnection = null; 5438 5439 final Runnable mScreenshotTimeout = new Runnable() { 5440 @Override public void run() { 5441 synchronized (mScreenshotLock) { 5442 if (mScreenshotConnection != null) { 5443 mContext.unbindService(mScreenshotConnection); 5444 mScreenshotConnection = null; 5445 notifyScreenshotError(); 5446 } 5447 } 5448 } 5449 }; 5450 5451 // Assume this is called from the Handler thread. 5452 private void takeScreenshot(final int screenshotType) { 5453 synchronized (mScreenshotLock) { 5454 if (mScreenshotConnection != null) { 5455 return; 5456 } 5457 final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE, 5458 SYSUI_SCREENSHOT_SERVICE); 5459 final Intent serviceIntent = new Intent(); 5460 serviceIntent.setComponent(serviceComponent); 5461 ServiceConnection conn = new ServiceConnection() { 5462 @Override 5463 public void onServiceConnected(ComponentName name, IBinder service) { 5464 synchronized (mScreenshotLock) { 5465 if (mScreenshotConnection != this) { 5466 return; 5467 } 5468 Messenger messenger = new Messenger(service); 5469 Message msg = Message.obtain(null, screenshotType); 5470 final ServiceConnection myConn = this; 5471 Handler h = new Handler(mHandler.getLooper()) { 5472 @Override 5473 public void handleMessage(Message msg) { 5474 synchronized (mScreenshotLock) { 5475 if (mScreenshotConnection == myConn) { 5476 mContext.unbindService(mScreenshotConnection); 5477 mScreenshotConnection = null; 5478 mHandler.removeCallbacks(mScreenshotTimeout); 5479 } 5480 } 5481 } 5482 }; 5483 msg.replyTo = new Messenger(h); 5484 msg.arg1 = msg.arg2 = 0; 5485 if (mStatusBar != null && mStatusBar.isVisibleLw()) 5486 msg.arg1 = 1; 5487 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) 5488 msg.arg2 = 1; 5489 try { 5490 messenger.send(msg); 5491 } catch (RemoteException e) { 5492 } 5493 } 5494 } 5495 5496 @Override 5497 public void onServiceDisconnected(ComponentName name) { 5498 notifyScreenshotError(); 5499 } 5500 }; 5501 if (mContext.bindServiceAsUser(serviceIntent, conn, 5502 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, 5503 UserHandle.CURRENT)) { 5504 mScreenshotConnection = conn; 5505 mHandler.postDelayed(mScreenshotTimeout, 10000); 5506 } 5507 } 5508 } 5509 5510 /** 5511 * Notifies the screenshot service to show an error. 5512 */ 5513 private void notifyScreenshotError() { 5514 // If the service process is killed, then ask it to clean up after itself 5515 final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE, 5516 SYSUI_SCREENSHOT_ERROR_RECEIVER); 5517 Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT); 5518 errorIntent.setComponent(errorComponent); 5519 errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | 5520 Intent.FLAG_RECEIVER_FOREGROUND); 5521 mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT); 5522 } 5523 5524 /** {@inheritDoc} */ 5525 @Override 5526 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { 5527 if (!mSystemBooted) { 5528 // If we have not yet booted, don't let key events do anything. 5529 return 0; 5530 } 5531 5532 final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0; 5533 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; 5534 final boolean canceled = event.isCanceled(); 5535 final int keyCode = event.getKeyCode(); 5536 5537 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; 5538 5539 // If screen is off then we treat the case where the keyguard is open but hidden 5540 // the same as if it were open and in front. 5541 // This will prevent any keys other than the power button from waking the screen 5542 // when the keyguard is hidden by another activity. 5543 final boolean keyguardActive = (mKeyguardDelegate == null ? false : 5544 (interactive ? 5545 isKeyguardShowingAndNotOccluded() : 5546 mKeyguardDelegate.isShowing())); 5547 5548 if (DEBUG_INPUT) { 5549 Log.d(TAG, "interceptKeyTq keycode=" + keyCode 5550 + " interactive=" + interactive + " keyguardActive=" + keyguardActive 5551 + " policyFlags=" + Integer.toHexString(policyFlags)); 5552 } 5553 5554 // Basic policy based on interactive state. 5555 int result; 5556 boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0 5557 || event.isWakeKey(); 5558 if (interactive || (isInjected && !isWakeKey)) { 5559 // When the device is interactive or the key is injected pass the 5560 // key to the application. 5561 result = ACTION_PASS_TO_USER; 5562 isWakeKey = false; 5563 } else if (!interactive && shouldDispatchInputWhenNonInteractive()) { 5564 // If we're currently dozing with the screen on and the keyguard showing, pass the key 5565 // to the application but preserve its wake key status to make sure we still move 5566 // from dozing to fully interactive if we would normally go from off to fully 5567 // interactive. 5568 result = ACTION_PASS_TO_USER; 5569 } else { 5570 // When the screen is off and the key is not injected, determine whether 5571 // to wake the device but don't pass the key to the application. 5572 result = 0; 5573 if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) { 5574 isWakeKey = false; 5575 } 5576 } 5577 5578 // If the key would be handled globally, just return the result, don't worry about special 5579 // key processing. 5580 if (isValidGlobalKey(keyCode) 5581 && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) { 5582 if (isWakeKey) { 5583 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 5584 } 5585 return result; 5586 } 5587 5588 boolean useHapticFeedback = down 5589 && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0 5590 && event.getRepeatCount() == 0; 5591 5592 // Handle special keys. 5593 switch (keyCode) { 5594 case KeyEvent.KEYCODE_BACK: { 5595 if (down) { 5596 mBackKeyHandled = false; 5597 if (hasLongPressOnBackBehavior()) { 5598 Message msg = mHandler.obtainMessage(MSG_BACK_LONG_PRESS); 5599 msg.setAsynchronous(true); 5600 mHandler.sendMessageDelayed(msg, 5601 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 5602 } 5603 } else { 5604 boolean handled = mBackKeyHandled; 5605 5606 // Reset back key state 5607 cancelPendingBackKeyAction(); 5608 5609 // Don't pass back press to app if we've already handled it 5610 if (handled) { 5611 result &= ~ACTION_PASS_TO_USER; 5612 } 5613 } 5614 break; 5615 } 5616 5617 case KeyEvent.KEYCODE_VOLUME_DOWN: 5618 case KeyEvent.KEYCODE_VOLUME_UP: 5619 case KeyEvent.KEYCODE_VOLUME_MUTE: { 5620 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { 5621 if (down) { 5622 if (interactive && !mScreenshotChordVolumeDownKeyTriggered 5623 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5624 mScreenshotChordVolumeDownKeyTriggered = true; 5625 mScreenshotChordVolumeDownKeyTime = event.getDownTime(); 5626 mScreenshotChordVolumeDownKeyConsumed = false; 5627 cancelPendingPowerKeyAction(); 5628 interceptScreenshotChord(); 5629 } 5630 } else { 5631 mScreenshotChordVolumeDownKeyTriggered = false; 5632 cancelPendingScreenshotChordAction(); 5633 } 5634 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 5635 if (down) { 5636 if (interactive && !mScreenshotChordVolumeUpKeyTriggered 5637 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5638 mScreenshotChordVolumeUpKeyTriggered = true; 5639 cancelPendingPowerKeyAction(); 5640 cancelPendingScreenshotChordAction(); 5641 } 5642 } else { 5643 mScreenshotChordVolumeUpKeyTriggered = false; 5644 cancelPendingScreenshotChordAction(); 5645 } 5646 } 5647 if (down) { 5648 TelecomManager telecomManager = getTelecommService(); 5649 if (telecomManager != null) { 5650 if (telecomManager.isRinging()) { 5651 // If an incoming call is ringing, either VOLUME key means 5652 // "silence ringer". We handle these keys here, rather than 5653 // in the InCallScreen, to make sure we'll respond to them 5654 // even if the InCallScreen hasn't come to the foreground yet. 5655 // Look for the DOWN event here, to agree with the "fallback" 5656 // behavior in the InCallScreen. 5657 Log.i(TAG, "interceptKeyBeforeQueueing:" 5658 + " VOLUME key-down while ringing: Silence ringer!"); 5659 5660 // Silence the ringer. (It's safe to call this 5661 // even if the ringer has already been silenced.) 5662 telecomManager.silenceRinger(); 5663 5664 // And *don't* pass this key thru to the current activity 5665 // (which is probably the InCallScreen.) 5666 result &= ~ACTION_PASS_TO_USER; 5667 break; 5668 } 5669 if (telecomManager.isInCall() 5670 && (result & ACTION_PASS_TO_USER) == 0) { 5671 // If we are in call but we decided not to pass the key to 5672 // the application, just pass it to the session service. 5673 5674 MediaSessionLegacyHelper.getHelper(mContext) 5675 .sendVolumeKeyEvent(event, false); 5676 break; 5677 } 5678 } 5679 } 5680 if (mUseTvRouting) { 5681 // On TVs, defer special key handlings to 5682 // {@link interceptKeyBeforeDispatching()}. 5683 result |= ACTION_PASS_TO_USER; 5684 } else if ((result & ACTION_PASS_TO_USER) == 0) { 5685 // If we aren't passing to the user and no one else 5686 // handled it send it to the session manager to 5687 // figure out. 5688 MediaSessionLegacyHelper.getHelper(mContext) 5689 .sendVolumeKeyEvent(event, true); 5690 } 5691 break; 5692 } 5693 5694 case KeyEvent.KEYCODE_ENDCALL: { 5695 result &= ~ACTION_PASS_TO_USER; 5696 if (down) { 5697 TelecomManager telecomManager = getTelecommService(); 5698 boolean hungUp = false; 5699 if (telecomManager != null) { 5700 hungUp = telecomManager.endCall(); 5701 } 5702 if (interactive && !hungUp) { 5703 mEndCallKeyHandled = false; 5704 mHandler.postDelayed(mEndCallLongPress, 5705 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 5706 } else { 5707 mEndCallKeyHandled = true; 5708 } 5709 } else { 5710 if (!mEndCallKeyHandled) { 5711 mHandler.removeCallbacks(mEndCallLongPress); 5712 if (!canceled) { 5713 if ((mEndcallBehavior 5714 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) { 5715 if (goHome()) { 5716 break; 5717 } 5718 } 5719 if ((mEndcallBehavior 5720 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) { 5721 mPowerManager.goToSleep(event.getEventTime(), 5722 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); 5723 isWakeKey = false; 5724 } 5725 } 5726 } 5727 } 5728 break; 5729 } 5730 5731 case KeyEvent.KEYCODE_POWER: { 5732 result &= ~ACTION_PASS_TO_USER; 5733 isWakeKey = false; // wake-up will be handled separately 5734 if (down) { 5735 interceptPowerKeyDown(event, interactive); 5736 } else { 5737 interceptPowerKeyUp(event, interactive, canceled); 5738 } 5739 break; 5740 } 5741 5742 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN: 5743 // fall through 5744 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP: 5745 // fall through 5746 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT: 5747 // fall through 5748 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: { 5749 result &= ~ACTION_PASS_TO_USER; 5750 interceptSystemNavigationKey(event); 5751 break; 5752 } 5753 5754 case KeyEvent.KEYCODE_SLEEP: { 5755 result &= ~ACTION_PASS_TO_USER; 5756 isWakeKey = false; 5757 if (!mPowerManager.isInteractive()) { 5758 useHapticFeedback = false; // suppress feedback if already non-interactive 5759 } 5760 if (down) { 5761 sleepPress(event.getEventTime()); 5762 } else { 5763 sleepRelease(event.getEventTime()); 5764 } 5765 break; 5766 } 5767 5768 case KeyEvent.KEYCODE_SOFT_SLEEP: { 5769 result &= ~ACTION_PASS_TO_USER; 5770 isWakeKey = false; 5771 if (!down) { 5772 mPowerManagerInternal.setUserInactiveOverrideFromWindowManager(); 5773 } 5774 break; 5775 } 5776 5777 case KeyEvent.KEYCODE_WAKEUP: { 5778 result &= ~ACTION_PASS_TO_USER; 5779 isWakeKey = true; 5780 break; 5781 } 5782 5783 case KeyEvent.KEYCODE_MEDIA_PLAY: 5784 case KeyEvent.KEYCODE_MEDIA_PAUSE: 5785 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 5786 case KeyEvent.KEYCODE_HEADSETHOOK: 5787 case KeyEvent.KEYCODE_MUTE: 5788 case KeyEvent.KEYCODE_MEDIA_STOP: 5789 case KeyEvent.KEYCODE_MEDIA_NEXT: 5790 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 5791 case KeyEvent.KEYCODE_MEDIA_REWIND: 5792 case KeyEvent.KEYCODE_MEDIA_RECORD: 5793 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 5794 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { 5795 if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) { 5796 // If the global session is active pass all media keys to it 5797 // instead of the active window. 5798 result &= ~ACTION_PASS_TO_USER; 5799 } 5800 if ((result & ACTION_PASS_TO_USER) == 0) { 5801 // Only do this if we would otherwise not pass it to the user. In that 5802 // case, the PhoneWindow class will do the same thing, except it will 5803 // only do it if the showing app doesn't process the key on its own. 5804 // Note that we need to make a copy of the key event here because the 5805 // original key event will be recycled when we return. 5806 mBroadcastWakeLock.acquire(); 5807 Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK, 5808 new KeyEvent(event)); 5809 msg.setAsynchronous(true); 5810 msg.sendToTarget(); 5811 } 5812 break; 5813 } 5814 5815 case KeyEvent.KEYCODE_CALL: { 5816 if (down) { 5817 TelecomManager telecomManager = getTelecommService(); 5818 if (telecomManager != null) { 5819 if (telecomManager.isRinging()) { 5820 Log.i(TAG, "interceptKeyBeforeQueueing:" 5821 + " CALL key-down while ringing: Answer the call!"); 5822 telecomManager.acceptRingingCall(); 5823 5824 // And *don't* pass this key thru to the current activity 5825 // (which is presumably the InCallScreen.) 5826 result &= ~ACTION_PASS_TO_USER; 5827 } 5828 } 5829 } 5830 break; 5831 } 5832 case KeyEvent.KEYCODE_VOICE_ASSIST: { 5833 // Only do this if we would otherwise not pass it to the user. In that case, 5834 // interceptKeyBeforeDispatching would apply a similar but different policy in 5835 // order to invoke voice assist actions. Note that we need to make a copy of the 5836 // key event here because the original key event will be recycled when we return. 5837 if ((result & ACTION_PASS_TO_USER) == 0 && !down) { 5838 mBroadcastWakeLock.acquire(); 5839 Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK, 5840 keyguardActive ? 1 : 0, 0); 5841 msg.setAsynchronous(true); 5842 msg.sendToTarget(); 5843 } 5844 break; 5845 } 5846 case KeyEvent.KEYCODE_WINDOW: { 5847 if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) { 5848 if (mTvPictureInPictureVisible) { 5849 // Consumes the key only if picture-in-picture is visible 5850 // to show picture-in-picture control menu. 5851 // This gives a chance to the foreground activity 5852 // to customize PIP key behavior. 5853 if (!down) { 5854 showTvPictureInPictureMenu(event); 5855 } 5856 result &= ~ACTION_PASS_TO_USER; 5857 } 5858 } 5859 break; 5860 } 5861 } 5862 5863 if (useHapticFeedback) { 5864 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); 5865 } 5866 5867 if (isWakeKey) { 5868 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 5869 } 5870 5871 return result; 5872 } 5873 5874 /** 5875 * Handle statusbar expansion events. 5876 * @param event 5877 */ 5878 private void interceptSystemNavigationKey(KeyEvent event) { 5879 if (event.getAction() == KeyEvent.ACTION_UP && areSystemNavigationKeysEnabled()) { 5880 IStatusBarService sbar = getStatusBarService(); 5881 if (sbar != null) { 5882 try { 5883 sbar.handleSystemNavigationKey(event.getKeyCode()); 5884 } catch (RemoteException e1) { 5885 // oops, no statusbar. Ignore event. 5886 } 5887 } 5888 } 5889 } 5890 5891 /** 5892 * Returns true if the key can have global actions attached to it. 5893 * We reserve all power management keys for the system since they require 5894 * very careful handling. 5895 */ 5896 private static boolean isValidGlobalKey(int keyCode) { 5897 switch (keyCode) { 5898 case KeyEvent.KEYCODE_POWER: 5899 case KeyEvent.KEYCODE_WAKEUP: 5900 case KeyEvent.KEYCODE_SLEEP: 5901 return false; 5902 default: 5903 return true; 5904 } 5905 } 5906 5907 /** 5908 * When the screen is off we ignore some keys that might otherwise typically 5909 * be considered wake keys. We filter them out here. 5910 * 5911 * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it 5912 * is always considered a wake key. 5913 */ 5914 private boolean isWakeKeyWhenScreenOff(int keyCode) { 5915 switch (keyCode) { 5916 // ignore volume keys unless docked 5917 case KeyEvent.KEYCODE_VOLUME_UP: 5918 case KeyEvent.KEYCODE_VOLUME_DOWN: 5919 case KeyEvent.KEYCODE_VOLUME_MUTE: 5920 return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED; 5921 5922 // ignore media and camera keys 5923 case KeyEvent.KEYCODE_MUTE: 5924 case KeyEvent.KEYCODE_HEADSETHOOK: 5925 case KeyEvent.KEYCODE_MEDIA_PLAY: 5926 case KeyEvent.KEYCODE_MEDIA_PAUSE: 5927 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 5928 case KeyEvent.KEYCODE_MEDIA_STOP: 5929 case KeyEvent.KEYCODE_MEDIA_NEXT: 5930 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 5931 case KeyEvent.KEYCODE_MEDIA_REWIND: 5932 case KeyEvent.KEYCODE_MEDIA_RECORD: 5933 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 5934 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: 5935 case KeyEvent.KEYCODE_CAMERA: 5936 return false; 5937 } 5938 return true; 5939 } 5940 5941 5942 /** {@inheritDoc} */ 5943 @Override 5944 public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) { 5945 if ((policyFlags & FLAG_WAKE) != 0) { 5946 if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion, 5947 "android.policy:MOTION")) { 5948 return 0; 5949 } 5950 } 5951 5952 if (shouldDispatchInputWhenNonInteractive()) { 5953 return ACTION_PASS_TO_USER; 5954 } 5955 5956 // If we have not passed the action up and we are in theater mode without dreaming, 5957 // there will be no dream to intercept the touch and wake into ambient. The device should 5958 // wake up in this case. 5959 if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) { 5960 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming, 5961 "android.policy:MOTION"); 5962 } 5963 5964 return 0; 5965 } 5966 5967 private boolean shouldDispatchInputWhenNonInteractive() { 5968 final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF); 5969 5970 if (displayOff && !mHasFeatureWatch) { 5971 return false; 5972 } 5973 5974 // Send events to keyguard while the screen is on and it's showing. 5975 if (isKeyguardShowingAndNotOccluded() && !displayOff) { 5976 return true; 5977 } 5978 5979 // Send events to a dozing dream even if the screen is off since the dream 5980 // is in control of the state of the screen. 5981 IDreamManager dreamManager = getDreamManager(); 5982 5983 try { 5984 if (dreamManager != null && dreamManager.isDreaming()) { 5985 return true; 5986 } 5987 } catch (RemoteException e) { 5988 Slog.e(TAG, "RemoteException when checking if dreaming", e); 5989 } 5990 5991 // Otherwise, consume events since the user can't see what is being 5992 // interacted with. 5993 return false; 5994 } 5995 5996 private void dispatchDirectAudioEvent(KeyEvent event) { 5997 if (event.getAction() != KeyEvent.ACTION_DOWN) { 5998 return; 5999 } 6000 int keyCode = event.getKeyCode(); 6001 int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND 6002 | AudioManager.FLAG_FROM_KEY; 6003 String pkgName = mContext.getOpPackageName(); 6004 switch (keyCode) { 6005 case KeyEvent.KEYCODE_VOLUME_UP: 6006 try { 6007 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE, 6008 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6009 } catch (RemoteException e) { 6010 Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e); 6011 } 6012 break; 6013 case KeyEvent.KEYCODE_VOLUME_DOWN: 6014 try { 6015 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER, 6016 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6017 } catch (RemoteException e) { 6018 Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e); 6019 } 6020 break; 6021 case KeyEvent.KEYCODE_VOLUME_MUTE: 6022 try { 6023 if (event.getRepeatCount() == 0) { 6024 getAudioService().adjustSuggestedStreamVolume( 6025 AudioManager.ADJUST_TOGGLE_MUTE, 6026 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6027 } 6028 } catch (RemoteException e) { 6029 Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e); 6030 } 6031 break; 6032 } 6033 } 6034 6035 void dispatchMediaKeyWithWakeLock(KeyEvent event) { 6036 if (DEBUG_INPUT) { 6037 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event); 6038 } 6039 6040 if (mHavePendingMediaKeyRepeatWithWakeLock) { 6041 if (DEBUG_INPUT) { 6042 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat"); 6043 } 6044 6045 mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK); 6046 mHavePendingMediaKeyRepeatWithWakeLock = false; 6047 mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock 6048 } 6049 6050 dispatchMediaKeyWithWakeLockToAudioService(event); 6051 6052 if (event.getAction() == KeyEvent.ACTION_DOWN 6053 && event.getRepeatCount() == 0) { 6054 mHavePendingMediaKeyRepeatWithWakeLock = true; 6055 6056 Message msg = mHandler.obtainMessage( 6057 MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event); 6058 msg.setAsynchronous(true); 6059 mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout()); 6060 } else { 6061 mBroadcastWakeLock.release(); 6062 } 6063 } 6064 6065 void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) { 6066 mHavePendingMediaKeyRepeatWithWakeLock = false; 6067 6068 KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event, 6069 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS); 6070 if (DEBUG_INPUT) { 6071 Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent); 6072 } 6073 6074 dispatchMediaKeyWithWakeLockToAudioService(repeatEvent); 6075 mBroadcastWakeLock.release(); 6076 } 6077 6078 void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) { 6079 if (ActivityManagerNative.isSystemReady()) { 6080 MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true); 6081 } 6082 } 6083 6084 void launchVoiceAssistWithWakeLock(boolean keyguardActive) { 6085 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface( 6086 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); 6087 if (dic != null) { 6088 try { 6089 dic.exitIdle("voice-search"); 6090 } catch (RemoteException e) { 6091 } 6092 } 6093 Intent voiceIntent = 6094 new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); 6095 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive); 6096 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF); 6097 mBroadcastWakeLock.release(); 6098 } 6099 6100 BroadcastReceiver mDockReceiver = new BroadcastReceiver() { 6101 @Override 6102 public void onReceive(Context context, Intent intent) { 6103 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) { 6104 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 6105 Intent.EXTRA_DOCK_STATE_UNDOCKED); 6106 } else { 6107 try { 6108 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface( 6109 ServiceManager.getService(Context.UI_MODE_SERVICE)); 6110 mUiMode = uiModeService.getCurrentModeType(); 6111 } catch (RemoteException e) { 6112 } 6113 } 6114 updateRotation(true); 6115 synchronized (mLock) { 6116 updateOrientationListenerLp(); 6117 } 6118 } 6119 }; 6120 6121 BroadcastReceiver mDreamReceiver = new BroadcastReceiver() { 6122 @Override 6123 public void onReceive(Context context, Intent intent) { 6124 if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) { 6125 if (mKeyguardDelegate != null) { 6126 mKeyguardDelegate.onDreamingStarted(); 6127 } 6128 } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) { 6129 if (mKeyguardDelegate != null) { 6130 mKeyguardDelegate.onDreamingStopped(); 6131 } 6132 } 6133 } 6134 }; 6135 6136 BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() { 6137 @Override 6138 public void onReceive(Context context, Intent intent) { 6139 if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) { 6140 // tickle the settings observer: this first ensures that we're 6141 // observing the relevant settings for the newly-active user, 6142 // and then updates our own bookkeeping based on the now- 6143 // current user. 6144 mSettingsObserver.onChange(false); 6145 6146 // force a re-application of focused window sysui visibility. 6147 // the window may never have been shown for this user 6148 // e.g. the keyguard when going through the new-user setup flow 6149 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6150 mLastSystemUiFlags = 0; 6151 updateSystemUiVisibilityLw(); 6152 } 6153 } 6154 } 6155 }; 6156 6157 private final Runnable mHiddenNavPanic = new Runnable() { 6158 @Override 6159 public void run() { 6160 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6161 if (!isUserSetupComplete()) { 6162 // Swipe-up for navigation bar is disabled during setup 6163 return; 6164 } 6165 mPendingPanicGestureUptime = SystemClock.uptimeMillis(); 6166 mNavigationBarController.showTransient(); 6167 } 6168 } 6169 }; 6170 6171 private void requestTransientBars(WindowState swipeTarget) { 6172 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6173 if (!isUserSetupComplete()) { 6174 // Swipe-up for navigation bar is disabled during setup 6175 return; 6176 } 6177 boolean sb = mStatusBarController.checkShowTransientBarLw(); 6178 boolean nb = mNavigationBarController.checkShowTransientBarLw(); 6179 if (sb || nb) { 6180 // Don't show status bar when swiping on already visible navigation bar 6181 if (!nb && swipeTarget == mNavigationBar) { 6182 if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target"); 6183 return; 6184 } 6185 if (sb) mStatusBarController.showTransient(); 6186 if (nb) mNavigationBarController.showTransient(); 6187 mImmersiveModeConfirmation.confirmCurrentPrompt(); 6188 updateSystemUiVisibilityLw(); 6189 } 6190 } 6191 } 6192 6193 // Called on the PowerManager's Notifier thread. 6194 @Override 6195 public void startedGoingToSleep(int why) { 6196 if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")"); 6197 mCameraGestureTriggeredDuringGoingToSleep = false; 6198 mGoingToSleep = true; 6199 if (mKeyguardDelegate != null) { 6200 mKeyguardDelegate.onStartedGoingToSleep(why); 6201 } 6202 } 6203 6204 // Called on the PowerManager's Notifier thread. 6205 @Override 6206 public void finishedGoingToSleep(int why) { 6207 EventLog.writeEvent(70000, 0); 6208 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")"); 6209 MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000); 6210 6211 mGoingToSleep = false; 6212 6213 // We must get this work done here because the power manager will drop 6214 // the wake lock and let the system suspend once this function returns. 6215 synchronized (mLock) { 6216 mAwake = false; 6217 updateWakeGestureListenerLp(); 6218 updateOrientationListenerLp(); 6219 updateLockScreenTimeout(); 6220 } 6221 if (mKeyguardDelegate != null) { 6222 mKeyguardDelegate.onFinishedGoingToSleep(why, 6223 mCameraGestureTriggeredDuringGoingToSleep); 6224 } 6225 mCameraGestureTriggeredDuringGoingToSleep = false; 6226 } 6227 6228 // Called on the PowerManager's Notifier thread. 6229 @Override 6230 public void startedWakingUp() { 6231 EventLog.writeEvent(70000, 1); 6232 if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up..."); 6233 6234 // Since goToSleep performs these functions synchronously, we must 6235 // do the same here. We cannot post this work to a handler because 6236 // that might cause it to become reordered with respect to what 6237 // may happen in a future call to goToSleep. 6238 synchronized (mLock) { 6239 mAwake = true; 6240 6241 updateWakeGestureListenerLp(); 6242 updateOrientationListenerLp(); 6243 updateLockScreenTimeout(); 6244 } 6245 6246 if (mKeyguardDelegate != null) { 6247 mKeyguardDelegate.onStartedWakingUp(); 6248 } 6249 } 6250 6251 // Called on the PowerManager's Notifier thread. 6252 @Override 6253 public void finishedWakingUp() { 6254 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up..."); 6255 } 6256 6257 private void wakeUpFromPowerKey(long eventTime) { 6258 wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER"); 6259 } 6260 6261 private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) { 6262 final boolean theaterModeEnabled = isTheaterModeEnabled(); 6263 if (!wakeInTheaterMode && theaterModeEnabled) { 6264 return false; 6265 } 6266 6267 if (theaterModeEnabled) { 6268 Settings.Global.putInt(mContext.getContentResolver(), 6269 Settings.Global.THEATER_MODE_ON, 0); 6270 } 6271 6272 mPowerManager.wakeUp(wakeTime, reason); 6273 return true; 6274 } 6275 6276 private void finishKeyguardDrawn() { 6277 synchronized (mLock) { 6278 if (!mScreenOnEarly || mKeyguardDrawComplete) { 6279 return; // We are not awake yet or we have already informed of this event. 6280 } 6281 6282 mKeyguardDrawComplete = true; 6283 if (mKeyguardDelegate != null) { 6284 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6285 } 6286 mWindowManagerDrawComplete = false; 6287 } 6288 6289 // ... eventually calls finishWindowsDrawn which will finalize our screen turn on 6290 // as well as enabling the orientation change logic/sensor. 6291 mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback, 6292 WAITING_FOR_DRAWN_TIMEOUT); 6293 } 6294 6295 // Called on the DisplayManager's DisplayPowerController thread. 6296 @Override 6297 public void screenTurnedOff() { 6298 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off..."); 6299 6300 updateScreenOffSleepToken(true); 6301 synchronized (mLock) { 6302 mScreenOnEarly = false; 6303 mScreenOnFully = false; 6304 mKeyguardDrawComplete = false; 6305 mWindowManagerDrawComplete = false; 6306 mScreenOnListener = null; 6307 updateOrientationListenerLp(); 6308 6309 if (mKeyguardDelegate != null) { 6310 mKeyguardDelegate.onScreenTurnedOff(); 6311 } 6312 } 6313 } 6314 6315 // Called on the DisplayManager's DisplayPowerController thread. 6316 @Override 6317 public void screenTurningOn(final ScreenOnListener screenOnListener) { 6318 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on..."); 6319 6320 updateScreenOffSleepToken(false); 6321 synchronized (mLock) { 6322 mScreenOnEarly = true; 6323 mScreenOnFully = false; 6324 mKeyguardDrawComplete = false; 6325 mWindowManagerDrawComplete = false; 6326 mScreenOnListener = screenOnListener; 6327 6328 if (mKeyguardDelegate != null) { 6329 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6330 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000); 6331 mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback); 6332 } else { 6333 if (DEBUG_WAKEUP) Slog.d(TAG, 6334 "null mKeyguardDelegate: setting mKeyguardDrawComplete."); 6335 finishKeyguardDrawn(); 6336 } 6337 } 6338 } 6339 6340 // Called on the DisplayManager's DisplayPowerController thread. 6341 @Override 6342 public void screenTurnedOn() { 6343 synchronized (mLock) { 6344 if (mKeyguardDelegate != null) { 6345 mKeyguardDelegate.onScreenTurnedOn(); 6346 } 6347 } 6348 } 6349 6350 private void finishWindowsDrawn() { 6351 synchronized (mLock) { 6352 if (!mScreenOnEarly || mWindowManagerDrawComplete) { 6353 return; // Screen is not turned on or we did already handle this case earlier. 6354 } 6355 6356 mWindowManagerDrawComplete = true; 6357 } 6358 6359 finishScreenTurningOn(); 6360 } 6361 6362 private void finishScreenTurningOn() { 6363 synchronized (mLock) { 6364 // We have just finished drawing screen content. Since the orientation listener 6365 // gets only installed when all windows are drawn, we try to install it again. 6366 updateOrientationListenerLp(); 6367 } 6368 final ScreenOnListener listener; 6369 final boolean enableScreen; 6370 synchronized (mLock) { 6371 if (DEBUG_WAKEUP) Slog.d(TAG, 6372 "finishScreenTurningOn: mAwake=" + mAwake 6373 + ", mScreenOnEarly=" + mScreenOnEarly 6374 + ", mScreenOnFully=" + mScreenOnFully 6375 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete 6376 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete); 6377 6378 if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete 6379 || (mAwake && !mKeyguardDrawComplete)) { 6380 return; // spurious or not ready yet 6381 } 6382 6383 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on..."); 6384 listener = mScreenOnListener; 6385 mScreenOnListener = null; 6386 mScreenOnFully = true; 6387 6388 // Remember the first time we draw the keyguard so we know when we're done with 6389 // the main part of booting and can enable the screen and hide boot messages. 6390 if (!mKeyguardDrawnOnce && mAwake) { 6391 mKeyguardDrawnOnce = true; 6392 enableScreen = true; 6393 if (mBootMessageNeedsHiding) { 6394 mBootMessageNeedsHiding = false; 6395 hideBootMessages(); 6396 } 6397 } else { 6398 enableScreen = false; 6399 } 6400 } 6401 6402 if (listener != null) { 6403 listener.onScreenOn(); 6404 } 6405 6406 if (enableScreen) { 6407 try { 6408 mWindowManager.enableScreenIfNeeded(); 6409 } catch (RemoteException unhandled) { 6410 } 6411 } 6412 } 6413 6414 private void handleHideBootMessage() { 6415 synchronized (mLock) { 6416 if (!mKeyguardDrawnOnce) { 6417 mBootMessageNeedsHiding = true; 6418 return; // keyguard hasn't drawn the first time yet, not done booting 6419 } 6420 } 6421 6422 if (mBootMsgDialog != null) { 6423 if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing"); 6424 mBootMsgDialog.dismiss(); 6425 mBootMsgDialog = null; 6426 } 6427 } 6428 6429 @Override 6430 public boolean isScreenOn() { 6431 return mScreenOnFully; 6432 } 6433 6434 /** {@inheritDoc} */ 6435 @Override 6436 public void enableKeyguard(boolean enabled) { 6437 if (mKeyguardDelegate != null) { 6438 mKeyguardDelegate.setKeyguardEnabled(enabled); 6439 } 6440 } 6441 6442 /** {@inheritDoc} */ 6443 @Override 6444 public void exitKeyguardSecurely(OnKeyguardExitResult callback) { 6445 if (mKeyguardDelegate != null) { 6446 mKeyguardDelegate.verifyUnlock(callback); 6447 } 6448 } 6449 6450 @Override 6451 public boolean isKeyguardShowingAndNotOccluded() { 6452 if (mKeyguardDelegate == null) return false; 6453 return mKeyguardDelegate.isShowing() && !mKeyguardOccluded; 6454 } 6455 6456 /** {@inheritDoc} */ 6457 @Override 6458 public boolean isKeyguardLocked() { 6459 return keyguardOn(); 6460 } 6461 6462 /** {@inheritDoc} */ 6463 @Override 6464 public boolean isKeyguardSecure(int userId) { 6465 if (mKeyguardDelegate == null) return false; 6466 return mKeyguardDelegate.isSecure(userId); 6467 } 6468 6469 /** {@inheritDoc} */ 6470 @Override 6471 public boolean isKeyguardShowingOrOccluded() { 6472 return mKeyguardDelegate == null ? false : mKeyguardDelegate.isShowing(); 6473 } 6474 6475 /** {@inheritDoc} */ 6476 @Override 6477 public boolean inKeyguardRestrictedKeyInputMode() { 6478 if (mKeyguardDelegate == null) return false; 6479 return mKeyguardDelegate.isInputRestricted(); 6480 } 6481 6482 @Override 6483 public void dismissKeyguardLw() { 6484 if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) { 6485 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw"); 6486 mHandler.post(new Runnable() { 6487 @Override 6488 public void run() { 6489 // ask the keyguard to prompt the user to authenticate if necessary 6490 mKeyguardDelegate.dismiss(); 6491 } 6492 }); 6493 } 6494 } 6495 6496 @Override 6497 public void notifyActivityDrawnForKeyguardLw() { 6498 if (mKeyguardDelegate != null) { 6499 mHandler.post(new Runnable() { 6500 @Override 6501 public void run() { 6502 mKeyguardDelegate.onActivityDrawn(); 6503 } 6504 }); 6505 } 6506 } 6507 6508 @Override 6509 public boolean isKeyguardDrawnLw() { 6510 synchronized (mLock) { 6511 return mKeyguardDrawnOnce; 6512 } 6513 } 6514 6515 @Override 6516 public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) { 6517 if (mKeyguardDelegate != null) { 6518 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation"); 6519 mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration); 6520 } 6521 } 6522 6523 @Override 6524 public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6525 Rect outInsets) { 6526 outInsets.setEmpty(); 6527 6528 // Navigation bar and status bar. 6529 getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets); 6530 if (mStatusBar != null) { 6531 outInsets.top = mStatusBarHeight; 6532 } 6533 } 6534 6535 @Override 6536 public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6537 Rect outInsets) { 6538 outInsets.setEmpty(); 6539 6540 // Only navigation bar 6541 if (mNavigationBar != null) { 6542 int position = navigationBarPosition(displayWidth, displayHeight, displayRotation); 6543 if (position == NAV_BAR_BOTTOM) { 6544 outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode); 6545 } else if (position == NAV_BAR_RIGHT) { 6546 outInsets.right = getNavigationBarWidth(displayRotation, mUiMode); 6547 } else if (position == NAV_BAR_LEFT) { 6548 outInsets.left = getNavigationBarWidth(displayRotation, mUiMode); 6549 } 6550 } 6551 } 6552 6553 @Override 6554 public boolean isNavBarForcedShownLw(WindowState windowState) { 6555 return mForceShowSystemBars; 6556 } 6557 6558 @Override 6559 public boolean isDockSideAllowed(int dockSide) { 6560 6561 // We do not allow all dock sides at which the navigation bar touches the docked stack. 6562 if (!mNavigationBarCanMove) { 6563 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT; 6564 } else { 6565 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT; 6566 } 6567 } 6568 6569 void sendCloseSystemWindows() { 6570 PhoneWindow.sendCloseSystemWindows(mContext, null); 6571 } 6572 6573 void sendCloseSystemWindows(String reason) { 6574 PhoneWindow.sendCloseSystemWindows(mContext, reason); 6575 } 6576 6577 @Override 6578 public int rotationForOrientationLw(int orientation, int lastRotation) { 6579 if (false) { 6580 Slog.v(TAG, "rotationForOrientationLw(orient=" 6581 + orientation + ", last=" + lastRotation 6582 + "); user=" + mUserRotation + " " 6583 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) 6584 ? "USER_ROTATION_LOCKED" : "") 6585 ); 6586 } 6587 6588 if (mForceDefaultOrientation) { 6589 return Surface.ROTATION_0; 6590 } 6591 6592 synchronized (mLock) { 6593 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1 6594 if (sensorRotation < 0) { 6595 sensorRotation = lastRotation; 6596 } 6597 6598 final int preferredRotation; 6599 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) { 6600 // Ignore sensor when lid switch is open and rotation is forced. 6601 preferredRotation = mLidOpenRotation; 6602 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR 6603 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) { 6604 // Ignore sensor when in car dock unless explicitly enabled. 6605 // This case can override the behavior of NOSENSOR, and can also 6606 // enable 180 degree rotation while docked. 6607 preferredRotation = mCarDockEnablesAccelerometer 6608 ? sensorRotation : mCarDockRotation; 6609 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK 6610 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK 6611 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK) 6612 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) { 6613 // Ignore sensor when in desk dock unless explicitly enabled. 6614 // This case can override the behavior of NOSENSOR, and can also 6615 // enable 180 degree rotation while docked. 6616 preferredRotation = mDeskDockEnablesAccelerometer 6617 ? sensorRotation : mDeskDockRotation; 6618 } else if (mHdmiPlugged && mDemoHdmiRotationLock) { 6619 // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled. 6620 // Note that the dock orientation overrides the HDMI orientation. 6621 preferredRotation = mDemoHdmiRotation; 6622 } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED 6623 && mUndockedHdmiRotation >= 0) { 6624 // Ignore sensor when plugged into HDMI and an undocked orientation has 6625 // been specified in the configuration (only for legacy devices without 6626 // full multi-display support). 6627 // Note that the dock orientation overrides the HDMI orientation. 6628 preferredRotation = mUndockedHdmiRotation; 6629 } else if (mDemoRotationLock) { 6630 // Ignore sensor when demo rotation lock is enabled. 6631 // Note that the dock orientation and HDMI rotation lock override this. 6632 preferredRotation = mDemoRotation; 6633 } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) { 6634 // Application just wants to remain locked in the last rotation. 6635 preferredRotation = lastRotation; 6636 } else if (!mSupportAutoRotation) { 6637 // If we don't support auto-rotation then bail out here and ignore 6638 // the sensor and any rotation lock settings. 6639 preferredRotation = -1; 6640 } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE 6641 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER 6642 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 6643 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE 6644 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT 6645 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER)) 6646 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR 6647 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6648 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE 6649 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) { 6650 // Otherwise, use sensor only if requested by the application or enabled 6651 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR. 6652 if (mAllowAllRotations < 0) { 6653 // Can't read this during init() because the context doesn't 6654 // have display metrics at that time so we cannot determine 6655 // tablet vs. phone then. 6656 mAllowAllRotations = mContext.getResources().getBoolean( 6657 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0; 6658 } 6659 if (sensorRotation != Surface.ROTATION_180 6660 || mAllowAllRotations == 1 6661 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6662 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) { 6663 preferredRotation = sensorRotation; 6664 } else { 6665 preferredRotation = lastRotation; 6666 } 6667 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED 6668 && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) { 6669 // Apply rotation lock. Does not apply to NOSENSOR. 6670 // The idea is that the user rotation expresses a weak preference for the direction 6671 // of gravity and as NOSENSOR is never affected by gravity, then neither should 6672 // NOSENSOR be affected by rotation lock (although it will be affected by docks). 6673 preferredRotation = mUserRotation; 6674 } else { 6675 // No overriding preference. 6676 // We will do exactly what the application asked us to do. 6677 preferredRotation = -1; 6678 } 6679 6680 switch (orientation) { 6681 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 6682 // Return portrait unless overridden. 6683 if (isAnyPortrait(preferredRotation)) { 6684 return preferredRotation; 6685 } 6686 return mPortraitRotation; 6687 6688 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 6689 // Return landscape unless overridden. 6690 if (isLandscapeOrSeascape(preferredRotation)) { 6691 return preferredRotation; 6692 } 6693 return mLandscapeRotation; 6694 6695 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 6696 // Return reverse portrait unless overridden. 6697 if (isAnyPortrait(preferredRotation)) { 6698 return preferredRotation; 6699 } 6700 return mUpsideDownRotation; 6701 6702 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 6703 // Return seascape unless overridden. 6704 if (isLandscapeOrSeascape(preferredRotation)) { 6705 return preferredRotation; 6706 } 6707 return mSeascapeRotation; 6708 6709 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 6710 case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE: 6711 // Return either landscape rotation. 6712 if (isLandscapeOrSeascape(preferredRotation)) { 6713 return preferredRotation; 6714 } 6715 if (isLandscapeOrSeascape(lastRotation)) { 6716 return lastRotation; 6717 } 6718 return mLandscapeRotation; 6719 6720 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 6721 case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT: 6722 // Return either portrait rotation. 6723 if (isAnyPortrait(preferredRotation)) { 6724 return preferredRotation; 6725 } 6726 if (isAnyPortrait(lastRotation)) { 6727 return lastRotation; 6728 } 6729 return mPortraitRotation; 6730 6731 default: 6732 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR, 6733 // just return the preferred orientation we already calculated. 6734 if (preferredRotation >= 0) { 6735 return preferredRotation; 6736 } 6737 return Surface.ROTATION_0; 6738 } 6739 } 6740 } 6741 6742 @Override 6743 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) { 6744 switch (orientation) { 6745 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 6746 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 6747 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 6748 return isAnyPortrait(rotation); 6749 6750 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 6751 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 6752 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 6753 return isLandscapeOrSeascape(rotation); 6754 6755 default: 6756 return true; 6757 } 6758 } 6759 6760 @Override 6761 public void setRotationLw(int rotation) { 6762 mOrientationListener.setCurrentRotation(rotation); 6763 } 6764 6765 private boolean isLandscapeOrSeascape(int rotation) { 6766 return rotation == mLandscapeRotation || rotation == mSeascapeRotation; 6767 } 6768 6769 private boolean isAnyPortrait(int rotation) { 6770 return rotation == mPortraitRotation || rotation == mUpsideDownRotation; 6771 } 6772 6773 @Override 6774 public int getUserRotationMode() { 6775 return Settings.System.getIntForUser(mContext.getContentResolver(), 6776 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ? 6777 WindowManagerPolicy.USER_ROTATION_FREE : 6778 WindowManagerPolicy.USER_ROTATION_LOCKED; 6779 } 6780 6781 // User rotation: to be used when all else fails in assigning an orientation to the device 6782 @Override 6783 public void setUserRotationMode(int mode, int rot) { 6784 ContentResolver res = mContext.getContentResolver(); 6785 6786 // mUserRotationMode and mUserRotation will be assigned by the content observer 6787 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) { 6788 Settings.System.putIntForUser(res, 6789 Settings.System.USER_ROTATION, 6790 rot, 6791 UserHandle.USER_CURRENT); 6792 Settings.System.putIntForUser(res, 6793 Settings.System.ACCELEROMETER_ROTATION, 6794 0, 6795 UserHandle.USER_CURRENT); 6796 } else { 6797 Settings.System.putIntForUser(res, 6798 Settings.System.ACCELEROMETER_ROTATION, 6799 1, 6800 UserHandle.USER_CURRENT); 6801 } 6802 } 6803 6804 @Override 6805 public void setSafeMode(boolean safeMode) { 6806 mSafeMode = safeMode; 6807 performHapticFeedbackLw(null, safeMode 6808 ? HapticFeedbackConstants.SAFE_MODE_ENABLED 6809 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true); 6810 } 6811 6812 static long[] getLongIntArray(Resources r, int resid) { 6813 int[] ar = r.getIntArray(resid); 6814 if (ar == null) { 6815 return null; 6816 } 6817 long[] out = new long[ar.length]; 6818 for (int i=0; i<ar.length; i++) { 6819 out[i] = ar[i]; 6820 } 6821 return out; 6822 } 6823 6824 /** {@inheritDoc} */ 6825 @Override 6826 public void systemReady() { 6827 mKeyguardDelegate = new KeyguardServiceDelegate(mContext); 6828 mKeyguardDelegate.onSystemReady(); 6829 6830 readCameraLensCoverState(); 6831 updateUiMode(); 6832 boolean bindKeyguardNow; 6833 synchronized (mLock) { 6834 updateOrientationListenerLp(); 6835 mSystemReady = true; 6836 mHandler.post(new Runnable() { 6837 @Override 6838 public void run() { 6839 updateSettings(); 6840 } 6841 }); 6842 6843 bindKeyguardNow = mDeferBindKeyguard; 6844 if (bindKeyguardNow) { 6845 // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now. 6846 mDeferBindKeyguard = false; 6847 } 6848 } 6849 6850 if (bindKeyguardNow) { 6851 mKeyguardDelegate.bindService(mContext); 6852 mKeyguardDelegate.onBootCompleted(); 6853 } 6854 mSystemGestures.systemReady(); 6855 mImmersiveModeConfirmation.systemReady(); 6856 } 6857 6858 /** {@inheritDoc} */ 6859 @Override 6860 public void systemBooted() { 6861 boolean bindKeyguardNow = false; 6862 synchronized (mLock) { 6863 // Time to bind Keyguard; take care to only bind it once, either here if ready or 6864 // in systemReady if not. 6865 if (mKeyguardDelegate != null) { 6866 bindKeyguardNow = true; 6867 } else { 6868 // Because mKeyguardDelegate is null, we know that the synchronized block in 6869 // systemReady didn't run yet and setting this will actually have an effect. 6870 mDeferBindKeyguard = true; 6871 } 6872 } 6873 if (bindKeyguardNow) { 6874 mKeyguardDelegate.bindService(mContext); 6875 mKeyguardDelegate.onBootCompleted(); 6876 } 6877 synchronized (mLock) { 6878 mSystemBooted = true; 6879 } 6880 startedWakingUp(); 6881 screenTurningOn(null); 6882 screenTurnedOn(); 6883 } 6884 6885 ProgressDialog mBootMsgDialog = null; 6886 6887 /** {@inheritDoc} */ 6888 @Override 6889 public void showBootMessage(final CharSequence msg, final boolean always) { 6890 mHandler.post(new Runnable() { 6891 @Override public void run() { 6892 if (mBootMsgDialog == null) { 6893 int theme; 6894 if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) { 6895 theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert; 6896 } else { 6897 theme = 0; 6898 } 6899 6900 mBootMsgDialog = new ProgressDialog(mContext, theme) { 6901 // This dialog will consume all events coming in to 6902 // it, to avoid it trying to do things too early in boot. 6903 @Override public boolean dispatchKeyEvent(KeyEvent event) { 6904 return true; 6905 } 6906 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { 6907 return true; 6908 } 6909 @Override public boolean dispatchTouchEvent(MotionEvent ev) { 6910 return true; 6911 } 6912 @Override public boolean dispatchTrackballEvent(MotionEvent ev) { 6913 return true; 6914 } 6915 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) { 6916 return true; 6917 } 6918 @Override public boolean dispatchPopulateAccessibilityEvent( 6919 AccessibilityEvent event) { 6920 return true; 6921 } 6922 }; 6923 if (mContext.getPackageManager().isUpgrade()) { 6924 mBootMsgDialog.setTitle(R.string.android_upgrading_title); 6925 } else { 6926 mBootMsgDialog.setTitle(R.string.android_start_title); 6927 } 6928 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 6929 mBootMsgDialog.setIndeterminate(true); 6930 mBootMsgDialog.getWindow().setType( 6931 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS); 6932 mBootMsgDialog.getWindow().addFlags( 6933 WindowManager.LayoutParams.FLAG_DIM_BEHIND 6934 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); 6935 mBootMsgDialog.getWindow().setDimAmount(1); 6936 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes(); 6937 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 6938 mBootMsgDialog.getWindow().setAttributes(lp); 6939 mBootMsgDialog.setCancelable(false); 6940 mBootMsgDialog.show(); 6941 } 6942 mBootMsgDialog.setMessage(msg); 6943 } 6944 }); 6945 } 6946 6947 /** {@inheritDoc} */ 6948 @Override 6949 public void hideBootMessages() { 6950 mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE); 6951 } 6952 6953 /** {@inheritDoc} */ 6954 @Override 6955 public void userActivity() { 6956 // *************************************** 6957 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE 6958 // *************************************** 6959 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER 6960 // WITH ITS LOCKS HELD. 6961 // 6962 // This code must be VERY careful about the locks 6963 // it acquires. 6964 // In fact, the current code acquires way too many, 6965 // and probably has lurking deadlocks. 6966 6967 synchronized (mScreenLockTimeout) { 6968 if (mLockScreenTimerActive) { 6969 // reset the timer 6970 mHandler.removeCallbacks(mScreenLockTimeout); 6971 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 6972 } 6973 } 6974 } 6975 6976 class ScreenLockTimeout implements Runnable { 6977 Bundle options; 6978 6979 @Override 6980 public void run() { 6981 synchronized (this) { 6982 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard"); 6983 if (mKeyguardDelegate != null) { 6984 mKeyguardDelegate.doKeyguardTimeout(options); 6985 } 6986 mLockScreenTimerActive = false; 6987 options = null; 6988 } 6989 } 6990 6991 public void setLockOptions(Bundle options) { 6992 this.options = options; 6993 } 6994 } 6995 6996 ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout(); 6997 6998 @Override 6999 public void lockNow(Bundle options) { 7000 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 7001 mHandler.removeCallbacks(mScreenLockTimeout); 7002 if (options != null) { 7003 // In case multiple calls are made to lockNow, we don't wipe out the options 7004 // until the runnable actually executes. 7005 mScreenLockTimeout.setLockOptions(options); 7006 } 7007 mHandler.post(mScreenLockTimeout); 7008 } 7009 7010 private void updateLockScreenTimeout() { 7011 synchronized (mScreenLockTimeout) { 7012 boolean enable = (mAllowLockscreenWhenOn && mAwake && 7013 mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId)); 7014 if (mLockScreenTimerActive != enable) { 7015 if (enable) { 7016 if (localLOGV) Log.v(TAG, "setting lockscreen timer"); 7017 mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests 7018 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7019 } else { 7020 if (localLOGV) Log.v(TAG, "clearing lockscreen timer"); 7021 mHandler.removeCallbacks(mScreenLockTimeout); 7022 } 7023 mLockScreenTimerActive = enable; 7024 } 7025 } 7026 } 7027 7028 private void updateDreamingSleepToken(boolean acquire) { 7029 if (acquire) { 7030 if (mDreamingSleepToken == null) { 7031 mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream"); 7032 } 7033 } else { 7034 if (mDreamingSleepToken != null) { 7035 mDreamingSleepToken.release(); 7036 mDreamingSleepToken = null; 7037 } 7038 } 7039 } 7040 7041 private void updateScreenOffSleepToken(boolean acquire) { 7042 if (acquire) { 7043 if (mScreenOffSleepToken == null) { 7044 mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff"); 7045 } 7046 } else { 7047 if (mScreenOffSleepToken != null) { 7048 mScreenOffSleepToken.release(); 7049 mScreenOffSleepToken = null; 7050 } 7051 } 7052 } 7053 7054 /** {@inheritDoc} */ 7055 @Override 7056 public void enableScreenAfterBoot() { 7057 readLidState(); 7058 applyLidSwitchState(); 7059 updateRotation(true); 7060 } 7061 7062 private void applyLidSwitchState() { 7063 if (mLidState == LID_CLOSED && mLidControlsSleep) { 7064 mPowerManager.goToSleep(SystemClock.uptimeMillis(), 7065 PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH, 7066 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); 7067 } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) { 7068 mWindowManagerFuncs.lockDeviceNow(); 7069 } 7070 7071 synchronized (mLock) { 7072 updateWakeGestureListenerLp(); 7073 } 7074 } 7075 7076 void updateUiMode() { 7077 if (mUiModeManager == null) { 7078 mUiModeManager = IUiModeManager.Stub.asInterface( 7079 ServiceManager.getService(Context.UI_MODE_SERVICE)); 7080 } 7081 try { 7082 mUiMode = mUiModeManager.getCurrentModeType(); 7083 } catch (RemoteException e) { 7084 } 7085 } 7086 7087 void updateRotation(boolean alwaysSendConfiguration) { 7088 try { 7089 //set orientation on WindowManager 7090 mWindowManager.updateRotation(alwaysSendConfiguration, false); 7091 } catch (RemoteException e) { 7092 // Ignore 7093 } 7094 } 7095 7096 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 7097 try { 7098 //set orientation on WindowManager 7099 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout); 7100 } catch (RemoteException e) { 7101 // Ignore 7102 } 7103 } 7104 7105 /** 7106 * Return an Intent to launch the currently active dock app as home. Returns 7107 * null if the standard home should be launched, which is the case if any of the following is 7108 * true: 7109 * <ul> 7110 * <li>The device is not in either car mode or desk mode 7111 * <li>The device is in car mode but mEnableCarDockHomeCapture is false 7112 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false 7113 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME 7114 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME 7115 * </ul> 7116 * @return A dock intent. 7117 */ 7118 Intent createHomeDockIntent() { 7119 Intent intent = null; 7120 7121 // What home does is based on the mode, not the dock state. That 7122 // is, when in car mode you should be taken to car home regardless 7123 // of whether we are actually in a car dock. 7124 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) { 7125 if (mEnableCarDockHomeCapture) { 7126 intent = mCarDockIntent; 7127 } 7128 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) { 7129 if (ENABLE_DESK_DOCK_HOME_CAPTURE) { 7130 intent = mDeskDockIntent; 7131 } 7132 } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH 7133 && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK 7134 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK 7135 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) { 7136 // Always launch dock home from home when watch is docked, if it exists. 7137 intent = mDeskDockIntent; 7138 } 7139 7140 if (intent == null) { 7141 return null; 7142 } 7143 7144 ActivityInfo ai = null; 7145 ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser( 7146 intent, 7147 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA, 7148 mCurrentUserId); 7149 if (info != null) { 7150 ai = info.activityInfo; 7151 } 7152 if (ai != null 7153 && ai.metaData != null 7154 && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) { 7155 intent = new Intent(intent); 7156 intent.setClassName(ai.packageName, ai.name); 7157 return intent; 7158 } 7159 7160 return null; 7161 } 7162 7163 void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) { 7164 if (awakenFromDreams) { 7165 awakenDreams(); 7166 } 7167 7168 Intent dock = createHomeDockIntent(); 7169 if (dock != null) { 7170 try { 7171 if (fromHomeKey) { 7172 dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7173 } 7174 startActivityAsUser(dock, UserHandle.CURRENT); 7175 return; 7176 } catch (ActivityNotFoundException e) { 7177 } 7178 } 7179 7180 Intent intent; 7181 7182 if (fromHomeKey) { 7183 intent = new Intent(mHomeIntent); 7184 intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7185 } else { 7186 intent = mHomeIntent; 7187 } 7188 7189 startActivityAsUser(intent, UserHandle.CURRENT); 7190 } 7191 7192 /** 7193 * goes to the home screen 7194 * @return whether it did anything 7195 */ 7196 boolean goHome() { 7197 if (!isUserSetupComplete()) { 7198 Slog.i(TAG, "Not going home because user setup is in progress."); 7199 return false; 7200 } 7201 if (false) { 7202 // This code always brings home to the front. 7203 try { 7204 ActivityManagerNative.getDefault().stopAppSwitches(); 7205 } catch (RemoteException e) { 7206 } 7207 sendCloseSystemWindows(); 7208 startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */); 7209 } else { 7210 // This code brings home to the front or, if it is already 7211 // at the front, puts the device to sleep. 7212 try { 7213 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) { 7214 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry. 7215 Log.d(TAG, "UTS-TEST-MODE"); 7216 } else { 7217 ActivityManagerNative.getDefault().stopAppSwitches(); 7218 sendCloseSystemWindows(); 7219 Intent dock = createHomeDockIntent(); 7220 if (dock != null) { 7221 int result = ActivityManagerNative.getDefault() 7222 .startActivityAsUser(null, null, dock, 7223 dock.resolveTypeIfNeeded(mContext.getContentResolver()), 7224 null, null, 0, 7225 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7226 null, null, UserHandle.USER_CURRENT); 7227 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7228 return false; 7229 } 7230 } 7231 } 7232 int result = ActivityManagerNative.getDefault() 7233 .startActivityAsUser(null, null, mHomeIntent, 7234 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()), 7235 null, null, 0, 7236 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7237 null, null, UserHandle.USER_CURRENT); 7238 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7239 return false; 7240 } 7241 } catch (RemoteException ex) { 7242 // bummer, the activity manager, which is in this process, is dead 7243 } 7244 } 7245 return true; 7246 } 7247 7248 @Override 7249 public void setCurrentOrientationLw(int newOrientation) { 7250 synchronized (mLock) { 7251 if (newOrientation != mCurrentAppOrientation) { 7252 mCurrentAppOrientation = newOrientation; 7253 updateOrientationListenerLp(); 7254 } 7255 } 7256 } 7257 7258 private void performAuditoryFeedbackForAccessibilityIfNeed() { 7259 if (!isGlobalAccessibilityGestureEnabled()) { 7260 return; 7261 } 7262 AudioManager audioManager = (AudioManager) mContext.getSystemService( 7263 Context.AUDIO_SERVICE); 7264 if (audioManager.isSilentMode()) { 7265 return; 7266 } 7267 Ringtone ringTone = RingtoneManager.getRingtone(mContext, 7268 Settings.System.DEFAULT_NOTIFICATION_URI); 7269 ringTone.setStreamType(AudioManager.STREAM_MUSIC); 7270 ringTone.play(); 7271 } 7272 7273 private boolean isTheaterModeEnabled() { 7274 return Settings.Global.getInt(mContext.getContentResolver(), 7275 Settings.Global.THEATER_MODE_ON, 0) == 1; 7276 } 7277 7278 private boolean isGlobalAccessibilityGestureEnabled() { 7279 return Settings.Global.getInt(mContext.getContentResolver(), 7280 Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1; 7281 } 7282 7283 private boolean areSystemNavigationKeysEnabled() { 7284 return Settings.Secure.getInt(mContext.getContentResolver(), 7285 Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 1) == 1; 7286 } 7287 7288 @Override 7289 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) { 7290 if (!mVibrator.hasVibrator()) { 7291 return false; 7292 } 7293 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(), 7294 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0; 7295 if (hapticsDisabled && !always) { 7296 return false; 7297 } 7298 long[] pattern = null; 7299 switch (effectId) { 7300 case HapticFeedbackConstants.LONG_PRESS: 7301 pattern = mLongPressVibePattern; 7302 break; 7303 case HapticFeedbackConstants.VIRTUAL_KEY: 7304 pattern = mVirtualKeyVibePattern; 7305 break; 7306 case HapticFeedbackConstants.KEYBOARD_TAP: 7307 pattern = mKeyboardTapVibePattern; 7308 break; 7309 case HapticFeedbackConstants.CLOCK_TICK: 7310 pattern = mClockTickVibePattern; 7311 break; 7312 case HapticFeedbackConstants.CALENDAR_DATE: 7313 pattern = mCalendarDateVibePattern; 7314 break; 7315 case HapticFeedbackConstants.SAFE_MODE_DISABLED: 7316 pattern = mSafeModeDisabledVibePattern; 7317 break; 7318 case HapticFeedbackConstants.SAFE_MODE_ENABLED: 7319 pattern = mSafeModeEnabledVibePattern; 7320 break; 7321 case HapticFeedbackConstants.CONTEXT_CLICK: 7322 pattern = mContextClickVibePattern; 7323 break; 7324 default: 7325 return false; 7326 } 7327 int owningUid; 7328 String owningPackage; 7329 if (win != null) { 7330 owningUid = win.getOwningUid(); 7331 owningPackage = win.getOwningPackage(); 7332 } else { 7333 owningUid = android.os.Process.myUid(); 7334 owningPackage = mContext.getOpPackageName(); 7335 } 7336 if (pattern.length == 1) { 7337 // One-shot vibration 7338 mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES); 7339 } else { 7340 // Pattern vibration 7341 mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES); 7342 } 7343 return true; 7344 } 7345 7346 @Override 7347 public void keepScreenOnStartedLw() { 7348 } 7349 7350 @Override 7351 public void keepScreenOnStoppedLw() { 7352 if (isKeyguardShowingAndNotOccluded()) { 7353 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 7354 } 7355 } 7356 7357 private int updateSystemUiVisibilityLw() { 7358 // If there is no window focused, there will be nobody to handle the events 7359 // anyway, so just hang on in whatever state we're in until things settle down. 7360 final WindowState win = mFocusedWindow != null ? mFocusedWindow 7361 : mTopFullscreenOpaqueWindowState; 7362 if (win == null) { 7363 return 0; 7364 } 7365 if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) { 7366 // We are updating at a point where the keyguard has gotten 7367 // focus, but we were last in a state where the top window is 7368 // hiding it. This is probably because the keyguard as been 7369 // shown while the top window was displayed, so we want to ignore 7370 // it here because this is just a very transient change and it 7371 // will quickly lose focus once it correctly gets hidden. 7372 return 0; 7373 } 7374 7375 int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null) 7376 & ~mResettingSystemUiFlags 7377 & ~mForceClearedSystemUiFlags; 7378 if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) { 7379 tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS); 7380 } 7381 7382 final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */, 7383 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState); 7384 final int dockedVisibility = updateLightStatusBarLw(0 /* vis */, 7385 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState); 7386 mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds); 7387 mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds); 7388 final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility); 7389 final int diff = visibility ^ mLastSystemUiFlags; 7390 final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags; 7391 final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags; 7392 final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState); 7393 if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu 7394 && mFocusedApp == win.getAppToken() 7395 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds) 7396 && mLastDockedStackBounds.equals(mDockedStackBounds)) { 7397 return 0; 7398 } 7399 mLastSystemUiFlags = visibility; 7400 mLastFullscreenStackSysUiFlags = fullscreenVisibility; 7401 mLastDockedStackSysUiFlags = dockedVisibility; 7402 mLastFocusNeedsMenu = needsMenu; 7403 mFocusedApp = win.getAppToken(); 7404 final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds); 7405 final Rect dockedStackBounds = new Rect(mDockedStackBounds); 7406 mHandler.post(new Runnable() { 7407 @Override 7408 public void run() { 7409 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 7410 if (statusbar != null) { 7411 statusbar.setSystemUiVisibility(visibility, fullscreenVisibility, 7412 dockedVisibility, 0xffffffff, fullscreenStackBounds, 7413 dockedStackBounds, win.toString()); 7414 statusbar.topAppWindowChanged(needsMenu); 7415 } 7416 } 7417 }); 7418 return diff; 7419 } 7420 7421 private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) { 7422 WindowState statusColorWin = isStatusBarKeyguard() && !mHideLockScreen 7423 ? mStatusBar 7424 : opaqueOrDimming; 7425 7426 if (statusColorWin != null) { 7427 if (statusColorWin == opaque) { 7428 // If the top fullscreen-or-dimming window is also the top fullscreen, respect 7429 // its light flag. 7430 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7431 vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null) 7432 & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7433 } else if (statusColorWin != null && statusColorWin.isDimming()) { 7434 // Otherwise if it's dimming, clear the light flag. 7435 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7436 } 7437 } 7438 return vis; 7439 } 7440 7441 private boolean drawsSystemBarBackground(WindowState win) { 7442 return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0; 7443 } 7444 7445 private boolean forcesDrawStatusBarBackground(WindowState win) { 7446 return win == null || (win.getAttrs().privateFlags 7447 & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0; 7448 } 7449 7450 private int updateSystemBarsLw(WindowState win, int oldVis, int vis) { 7451 final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID); 7452 final boolean freeformStackVisible = 7453 mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID); 7454 final boolean resizing = mWindowManagerInternal.isDockedDividerResizing(); 7455 7456 // We need to force system bars when the docked stack is visible, when the freeform stack 7457 // is visible but also when we are resizing for the transitions when docked stack 7458 // visibility changes. 7459 mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing; 7460 final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard; 7461 7462 // apply translucent bar vis flags 7463 WindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen 7464 ? mStatusBar 7465 : mTopFullscreenOpaqueWindowState; 7466 vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7467 vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7468 final int dockedVis = mStatusBarController.applyTranslucentFlagLw( 7469 mTopDockedOpaqueWindowState, 0, 0); 7470 7471 final boolean fullscreenDrawsStatusBarBackground = 7472 (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState) 7473 && (vis & View.STATUS_BAR_TRANSLUCENT) == 0) 7474 || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState); 7475 final boolean dockedDrawsStatusBarBackground = 7476 (drawsSystemBarBackground(mTopDockedOpaqueWindowState) 7477 && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0) 7478 || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState); 7479 7480 // prevent status bar interaction from clearing certain flags 7481 int type = win.getAttrs().type; 7482 boolean statusBarHasFocus = type == TYPE_STATUS_BAR; 7483 if (statusBarHasFocus && !isStatusBarKeyguard()) { 7484 int flags = View.SYSTEM_UI_FLAG_FULLSCREEN 7485 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 7486 | View.SYSTEM_UI_FLAG_IMMERSIVE 7487 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 7488 | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7489 if (mHideLockScreen) { 7490 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT; 7491 } 7492 vis = (vis & ~flags) | (oldVis & flags); 7493 } 7494 7495 if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) { 7496 vis |= View.STATUS_BAR_TRANSPARENT; 7497 vis &= ~View.STATUS_BAR_TRANSLUCENT; 7498 } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar) 7499 || forceOpaqueStatusBar) { 7500 vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT); 7501 } 7502 7503 vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing); 7504 7505 // update status bar 7506 boolean immersiveSticky = 7507 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7508 final boolean hideStatusBarWM = 7509 mTopFullscreenOpaqueWindowState != null 7510 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null) 7511 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; 7512 final boolean hideStatusBarSysui = 7513 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 7514 final boolean hideNavBarSysui = 7515 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0; 7516 7517 final boolean transientStatusBarAllowed = mStatusBar != null 7518 && (statusBarHasFocus || (!mForceShowSystemBars 7519 && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky)))); 7520 7521 final boolean transientNavBarAllowed = mNavigationBar != null 7522 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky; 7523 7524 final long now = SystemClock.uptimeMillis(); 7525 final boolean pendingPanic = mPendingPanicGestureUptime != 0 7526 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION; 7527 if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) { 7528 // The user performed the panic gesture recently, we're about to hide the bars, 7529 // we're no longer on the Keyguard and the screen is ready. We can now request the bars. 7530 mPendingPanicGestureUptime = 0; 7531 mStatusBarController.showTransient(); 7532 mNavigationBarController.showTransient(); 7533 } 7534 7535 final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested() 7536 && !transientStatusBarAllowed && hideStatusBarSysui; 7537 final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested() 7538 && !transientNavBarAllowed; 7539 if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) { 7540 // clear the clearable flags instead 7541 clearClearableFlagsLw(); 7542 vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS; 7543 } 7544 7545 final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; 7546 immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7547 final boolean navAllowedHidden = immersive || immersiveSticky; 7548 7549 if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType()) 7550 > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) { 7551 // We can't hide the navbar from this window otherwise the input consumer would not get 7552 // the input events. 7553 vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); 7554 } 7555 7556 vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis); 7557 7558 // update navigation bar 7559 boolean oldImmersiveMode = isImmersiveMode(oldVis); 7560 boolean newImmersiveMode = isImmersiveMode(vis); 7561 if (win != null && oldImmersiveMode != newImmersiveMode) { 7562 final String pkg = win.getOwningPackage(); 7563 mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode, 7564 isUserSetupComplete()); 7565 } 7566 7567 vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis); 7568 7569 return vis; 7570 } 7571 7572 /** 7573 * @return the current visibility flags with the nav-bar opacity related flags toggled based 7574 * on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}. 7575 */ 7576 private int configureNavBarOpacity(int visibility, boolean dockedStackVisible, 7577 boolean freeformStackVisible, boolean isDockedDividerResizing) { 7578 if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) { 7579 if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) { 7580 visibility = setNavBarOpaqueFlag(visibility); 7581 } 7582 } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) { 7583 if (isDockedDividerResizing) { 7584 visibility = setNavBarOpaqueFlag(visibility); 7585 } else if (freeformStackVisible) { 7586 visibility = setNavBarTranslucentFlag(visibility); 7587 } else { 7588 visibility = setNavBarOpaqueFlag(visibility); 7589 } 7590 } 7591 7592 if (!areTranslucentBarsAllowed()) { 7593 visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT; 7594 } 7595 return visibility; 7596 } 7597 7598 private int setNavBarOpaqueFlag(int visibility) { 7599 return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT); 7600 } 7601 7602 private int setNavBarTranslucentFlag(int visibility) { 7603 visibility &= ~View.NAVIGATION_BAR_TRANSPARENT; 7604 return visibility |= View.NAVIGATION_BAR_TRANSLUCENT; 7605 } 7606 7607 private void clearClearableFlagsLw() { 7608 int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS; 7609 if (newVal != mResettingSystemUiFlags) { 7610 mResettingSystemUiFlags = newVal; 7611 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 7612 } 7613 } 7614 7615 private boolean isImmersiveMode(int vis) { 7616 final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; 7617 return mNavigationBar != null 7618 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0 7619 && (vis & flags) != 0 7620 && canHideNavigationBar(); 7621 } 7622 7623 /** 7624 * @return whether the navigation or status bar can be made translucent 7625 * 7626 * This should return true unless touch exploration is not enabled or 7627 * R.boolean.config_enableTranslucentDecor is false. 7628 */ 7629 private boolean areTranslucentBarsAllowed() { 7630 return mTranslucentDecorEnabled; 7631 } 7632 7633 // Use this instead of checking config_showNavigationBar so that it can be consistently 7634 // overridden by qemu.hw.mainkeys in the emulator. 7635 @Override 7636 public boolean hasNavigationBar() { 7637 return mHasNavigationBar; 7638 } 7639 7640 @Override 7641 public void setLastInputMethodWindowLw(WindowState ime, WindowState target) { 7642 mLastInputMethodWindow = ime; 7643 mLastInputMethodTargetWindow = target; 7644 } 7645 7646 @Override 7647 public int getInputMethodWindowVisibleHeightLw() { 7648 return mDockBottom - mCurBottom; 7649 } 7650 7651 @Override 7652 public void setCurrentUserLw(int newUserId) { 7653 mCurrentUserId = newUserId; 7654 if (mKeyguardDelegate != null) { 7655 mKeyguardDelegate.setCurrentUser(newUserId); 7656 } 7657 StatusBarManagerInternal statusBar = getStatusBarManagerInternal(); 7658 if (statusBar != null) { 7659 statusBar.setCurrentUser(newUserId); 7660 } 7661 setLastInputMethodWindowLw(null, null); 7662 } 7663 7664 @Override 7665 public boolean canMagnifyWindow(int windowType) { 7666 switch (windowType) { 7667 case WindowManager.LayoutParams.TYPE_INPUT_METHOD: 7668 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: 7669 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR: 7670 case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: { 7671 return false; 7672 } 7673 } 7674 return true; 7675 } 7676 7677 @Override 7678 public boolean isTopLevelWindow(int windowType) { 7679 if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW 7680 && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 7681 return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG); 7682 } 7683 return true; 7684 } 7685 7686 @Override 7687 public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) { 7688 // For the upside down rotation we don't rotate seamlessly as the navigation 7689 // bar moves position. 7690 // Note most apps (using orientation:sensor or user as opposed to fullSensor) 7691 // will not enter the reverse portrait orientation, so actually the 7692 // orientation won't change at all. 7693 if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) { 7694 return false; 7695 } 7696 int delta = newRotation - oldRotation; 7697 if (delta < 0) delta += 4; 7698 // Likewise we don't rotate seamlessly for 180 degree rotations 7699 // in this case the surfaces never resize, and our logic to 7700 // revert the transformations on size change will fail. We could 7701 // fix this in the future with the "tagged" frames idea. 7702 if (delta == Surface.ROTATION_180) { 7703 return false; 7704 } 7705 7706 // We only enable seamless rotation if the top window has requested 7707 // it and is in the fullscreen opaque state. Seamless rotation 7708 // requires freezing various Surface states and won't work well 7709 // with animations, so we disable it in the animation case for now. 7710 if (mTopFullscreenOpaqueWindowState != null && mTopIsFullscreen && 7711 !mTopFullscreenOpaqueWindowState.isAnimatingLw() && 7712 mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation == 7713 ROTATION_ANIMATION_JUMPCUT) { 7714 return true; 7715 } 7716 return false; 7717 } 7718 7719 @Override 7720 public void dump(String prefix, PrintWriter pw, String[] args) { 7721 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode); 7722 pw.print(" mSystemReady="); pw.print(mSystemReady); 7723 pw.print(" mSystemBooted="); pw.println(mSystemBooted); 7724 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState); 7725 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation); 7726 pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState); 7727 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged); 7728 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0 7729 || mForceClearedSystemUiFlags != 0) { 7730 pw.print(prefix); pw.print("mLastSystemUiFlags=0x"); 7731 pw.print(Integer.toHexString(mLastSystemUiFlags)); 7732 pw.print(" mResettingSystemUiFlags=0x"); 7733 pw.print(Integer.toHexString(mResettingSystemUiFlags)); 7734 pw.print(" mForceClearedSystemUiFlags=0x"); 7735 pw.println(Integer.toHexString(mForceClearedSystemUiFlags)); 7736 } 7737 if (mLastFocusNeedsMenu) { 7738 pw.print(prefix); pw.print("mLastFocusNeedsMenu="); 7739 pw.println(mLastFocusNeedsMenu); 7740 } 7741 pw.print(prefix); pw.print("mWakeGestureEnabledSetting="); 7742 pw.println(mWakeGestureEnabledSetting); 7743 7744 pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation); 7745 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode); 7746 pw.print(" mDockMode="); pw.print(mDockMode); 7747 pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture); 7748 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation); 7749 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation); 7750 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode); 7751 pw.print(" mUserRotation="); pw.print(mUserRotation); 7752 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations); 7753 pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation); 7754 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer="); 7755 pw.print(mCarDockEnablesAccelerometer); 7756 pw.print(" mDeskDockEnablesAccelerometer="); 7757 pw.println(mDeskDockEnablesAccelerometer); 7758 pw.print(prefix); pw.print("mLidKeyboardAccessibility="); 7759 pw.print(mLidKeyboardAccessibility); 7760 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility); 7761 pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock); 7762 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep); 7763 pw.print(prefix); 7764 pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior); 7765 pw.print(prefix); 7766 pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior); 7767 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior); 7768 pw.print(prefix); 7769 pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior); 7770 pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior); 7771 pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput); 7772 pw.print(prefix); pw.print("mAwake="); pw.println(mAwake); 7773 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly); 7774 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully); 7775 pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete); 7776 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete); 7777 pw.print(prefix); pw.print("mOrientationSensorEnabled="); 7778 pw.println(mOrientationSensorEnabled); 7779 pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft); 7780 pw.print(","); pw.print(mOverscanScreenTop); 7781 pw.print(") "); pw.print(mOverscanScreenWidth); 7782 pw.print("x"); pw.println(mOverscanScreenHeight); 7783 if (mOverscanLeft != 0 || mOverscanTop != 0 7784 || mOverscanRight != 0 || mOverscanBottom != 0) { 7785 pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft); 7786 pw.print(" top="); pw.print(mOverscanTop); 7787 pw.print(" right="); pw.print(mOverscanRight); 7788 pw.print(" bottom="); pw.println(mOverscanBottom); 7789 } 7790 pw.print(prefix); pw.print("mRestrictedOverscanScreen=("); 7791 pw.print(mRestrictedOverscanScreenLeft); 7792 pw.print(","); pw.print(mRestrictedOverscanScreenTop); 7793 pw.print(") "); pw.print(mRestrictedOverscanScreenWidth); 7794 pw.print("x"); pw.println(mRestrictedOverscanScreenHeight); 7795 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft); 7796 pw.print(","); pw.print(mUnrestrictedScreenTop); 7797 pw.print(") "); pw.print(mUnrestrictedScreenWidth); 7798 pw.print("x"); pw.println(mUnrestrictedScreenHeight); 7799 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft); 7800 pw.print(","); pw.print(mRestrictedScreenTop); 7801 pw.print(") "); pw.print(mRestrictedScreenWidth); 7802 pw.print("x"); pw.println(mRestrictedScreenHeight); 7803 pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft); 7804 pw.print(","); pw.print(mStableFullscreenTop); 7805 pw.print(")-("); pw.print(mStableFullscreenRight); 7806 pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")"); 7807 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft); 7808 pw.print(","); pw.print(mStableTop); 7809 pw.print(")-("); pw.print(mStableRight); 7810 pw.print(","); pw.print(mStableBottom); pw.println(")"); 7811 pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft); 7812 pw.print(","); pw.print(mSystemTop); 7813 pw.print(")-("); pw.print(mSystemRight); 7814 pw.print(","); pw.print(mSystemBottom); pw.println(")"); 7815 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft); 7816 pw.print(","); pw.print(mCurTop); 7817 pw.print(")-("); pw.print(mCurRight); 7818 pw.print(","); pw.print(mCurBottom); pw.println(")"); 7819 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft); 7820 pw.print(","); pw.print(mContentTop); 7821 pw.print(")-("); pw.print(mContentRight); 7822 pw.print(","); pw.print(mContentBottom); pw.println(")"); 7823 pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft); 7824 pw.print(","); pw.print(mVoiceContentTop); 7825 pw.print(")-("); pw.print(mVoiceContentRight); 7826 pw.print(","); pw.print(mVoiceContentBottom); pw.println(")"); 7827 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft); 7828 pw.print(","); pw.print(mDockTop); 7829 pw.print(")-("); pw.print(mDockRight); 7830 pw.print(","); pw.print(mDockBottom); pw.println(")"); 7831 pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer); 7832 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer); 7833 pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen); 7834 pw.print(" mShowingDream="); pw.print(mShowingDream); 7835 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen); 7836 pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken); 7837 if (mLastInputMethodWindow != null) { 7838 pw.print(prefix); pw.print("mLastInputMethodWindow="); 7839 pw.println(mLastInputMethodWindow); 7840 } 7841 if (mLastInputMethodTargetWindow != null) { 7842 pw.print(prefix); pw.print("mLastInputMethodTargetWindow="); 7843 pw.println(mLastInputMethodTargetWindow); 7844 } 7845 if (mStatusBar != null) { 7846 pw.print(prefix); pw.print("mStatusBar="); 7847 pw.print(mStatusBar); pw.print(" isStatusBarKeyguard="); 7848 pw.println(isStatusBarKeyguard()); 7849 } 7850 if (mNavigationBar != null) { 7851 pw.print(prefix); pw.print("mNavigationBar="); 7852 pw.println(mNavigationBar); 7853 } 7854 if (mFocusedWindow != null) { 7855 pw.print(prefix); pw.print("mFocusedWindow="); 7856 pw.println(mFocusedWindow); 7857 } 7858 if (mFocusedApp != null) { 7859 pw.print(prefix); pw.print("mFocusedApp="); 7860 pw.println(mFocusedApp); 7861 } 7862 if (mWinDismissingKeyguard != null) { 7863 pw.print(prefix); pw.print("mWinDismissingKeyguard="); 7864 pw.println(mWinDismissingKeyguard); 7865 } 7866 if (mTopFullscreenOpaqueWindowState != null) { 7867 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState="); 7868 pw.println(mTopFullscreenOpaqueWindowState); 7869 } 7870 if (mTopFullscreenOpaqueOrDimmingWindowState != null) { 7871 pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState="); 7872 pw.println(mTopFullscreenOpaqueOrDimmingWindowState); 7873 } 7874 if (mForcingShowNavBar) { 7875 pw.print(prefix); pw.print("mForcingShowNavBar="); 7876 pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer="); 7877 pw.println(mForcingShowNavBarLayer); 7878 } 7879 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen); 7880 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen); 7881 pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar); 7882 pw.print(" mForceStatusBarFromKeyguard="); 7883 pw.println(mForceStatusBarFromKeyguard); 7884 pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard); 7885 pw.print(" mWinDismissingKeyguard="); pw.print(mWinDismissingKeyguard); 7886 pw.print(" mHomePressed="); pw.println(mHomePressed); 7887 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn); 7888 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout); 7889 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive); 7890 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior); 7891 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior); 7892 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior); 7893 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation); 7894 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation); 7895 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation); 7896 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation); 7897 pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation); 7898 pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock); 7899 pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation); 7900 7901 mGlobalKeyManager.dump(prefix, pw); 7902 mStatusBarController.dump(pw, prefix); 7903 mNavigationBarController.dump(pw, prefix); 7904 PolicyControl.dump(prefix, pw); 7905 7906 if (mWakeGestureListener != null) { 7907 mWakeGestureListener.dump(pw, prefix); 7908 } 7909 if (mOrientationListener != null) { 7910 mOrientationListener.dump(pw, prefix); 7911 } 7912 if (mBurnInProtectionHelper != null) { 7913 mBurnInProtectionHelper.dump(prefix, pw); 7914 } 7915 if (mKeyguardDelegate != null) { 7916 mKeyguardDelegate.dump(prefix, pw); 7917 } 7918 } 7919} 7920