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