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