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