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