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