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