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