PhoneWindowManager.java revision aa07653d2eea38a7a5bda5944c8a353586916ae9
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 return R.anim.dock_bottom_exit; 2825 } else if (transit == TRANSIT_ENTER 2826 || transit == TRANSIT_SHOW) { 2827 return R.anim.dock_bottom_enter; 2828 } 2829 } else if (mNavigationBarPosition == NAV_BAR_RIGHT) { 2830 if (transit == TRANSIT_EXIT 2831 || transit == TRANSIT_HIDE) { 2832 return R.anim.dock_right_exit; 2833 } else if (transit == TRANSIT_ENTER 2834 || transit == TRANSIT_SHOW) { 2835 return R.anim.dock_right_enter; 2836 } 2837 } else if (mNavigationBarPosition == NAV_BAR_LEFT) { 2838 if (transit == TRANSIT_EXIT 2839 || transit == TRANSIT_HIDE) { 2840 return R.anim.dock_left_exit; 2841 } else if (transit == TRANSIT_ENTER 2842 || transit == TRANSIT_SHOW) { 2843 return R.anim.dock_left_enter; 2844 } 2845 } 2846 } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) { 2847 return selectDockedDividerAnimationLw(win, transit); 2848 } 2849 2850 if (transit == TRANSIT_PREVIEW_DONE) { 2851 if (win.hasAppShownWindows()) { 2852 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT"); 2853 return com.android.internal.R.anim.app_starting_exit; 2854 } 2855 } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen 2856 && transit == TRANSIT_ENTER) { 2857 // Special case: we are animating in a dream, while the keyguard 2858 // is shown. We don't want an animation on the dream, because 2859 // we need it shown immediately with the keyguard animating away 2860 // to reveal it. 2861 return -1; 2862 } 2863 2864 return 0; 2865 } 2866 2867 private int selectDockedDividerAnimationLw(WindowState win, int transit) { 2868 int insets = mWindowManagerFuncs.getDockedDividerInsetsLw(); 2869 2870 // If the divider is behind the navigation bar, don't animate. 2871 final Rect frame = win.getFrameLw(); 2872 final boolean behindNavBar = mNavigationBar != null 2873 && ((mNavigationBarPosition == NAV_BAR_BOTTOM 2874 && frame.top + insets >= mNavigationBar.getFrameLw().top) 2875 || (mNavigationBarPosition == NAV_BAR_RIGHT 2876 && frame.left + insets >= mNavigationBar.getFrameLw().left) 2877 || (mNavigationBarPosition == NAV_BAR_LEFT 2878 && frame.right - insets <= mNavigationBar.getFrameLw().right)); 2879 final boolean landscape = frame.height() > frame.width(); 2880 final boolean offscreenLandscape = landscape && (frame.right - insets <= 0 2881 || frame.left + insets >= win.getDisplayFrameLw().right); 2882 final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0 2883 || frame.bottom + insets >= win.getDisplayFrameLw().bottom); 2884 final boolean offscreen = offscreenLandscape || offscreenPortrait; 2885 if (behindNavBar || offscreen) { 2886 return 0; 2887 } 2888 if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) { 2889 return R.anim.fade_in; 2890 } else if (transit == TRANSIT_EXIT) { 2891 return R.anim.fade_out; 2892 } else { 2893 return 0; 2894 } 2895 } 2896 2897 @Override 2898 public void selectRotationAnimationLw(int anim[]) { 2899 if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen=" 2900 + mTopFullscreenOpaqueWindowState + " rotationAnimation=" 2901 + (mTopFullscreenOpaqueWindowState == null ? 2902 "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation)); 2903 if (mTopFullscreenOpaqueWindowState != null) { 2904 int animationHint = mTopFullscreenOpaqueWindowState.getRotationAnimationHint(); 2905 if (animationHint < 0 && mTopIsFullscreen) { 2906 animationHint = mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation; 2907 } 2908 switch (animationHint) { 2909 case ROTATION_ANIMATION_CROSSFADE: 2910 case ROTATION_ANIMATION_SEAMLESS: // Crossfade is fallback for seamless. 2911 anim[0] = R.anim.rotation_animation_xfade_exit; 2912 anim[1] = R.anim.rotation_animation_enter; 2913 break; 2914 case ROTATION_ANIMATION_JUMPCUT: 2915 anim[0] = R.anim.rotation_animation_jump_exit; 2916 anim[1] = R.anim.rotation_animation_enter; 2917 break; 2918 case ROTATION_ANIMATION_ROTATE: 2919 default: 2920 anim[0] = anim[1] = 0; 2921 break; 2922 } 2923 } else { 2924 anim[0] = anim[1] = 0; 2925 } 2926 } 2927 2928 @Override 2929 public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId, 2930 boolean forceDefault) { 2931 switch (exitAnimId) { 2932 case R.anim.rotation_animation_xfade_exit: 2933 case R.anim.rotation_animation_jump_exit: 2934 // These are the only cases that matter. 2935 if (forceDefault) { 2936 return false; 2937 } 2938 int anim[] = new int[2]; 2939 selectRotationAnimationLw(anim); 2940 return (exitAnimId == anim[0] && enterAnimId == anim[1]); 2941 default: 2942 return true; 2943 } 2944 } 2945 2946 @Override 2947 public Animation createForceHideEnterAnimation(boolean onWallpaper, 2948 boolean goingToNotificationShade) { 2949 if (goingToNotificationShade) { 2950 return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in); 2951 } 2952 2953 AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ? 2954 R.anim.lock_screen_behind_enter_wallpaper : 2955 R.anim.lock_screen_behind_enter); 2956 2957 // TODO: Use XML interpolators when we have log interpolators available in XML. 2958 final List<Animation> animations = set.getAnimations(); 2959 for (int i = animations.size() - 1; i >= 0; --i) { 2960 animations.get(i).setInterpolator(mLogDecelerateInterpolator); 2961 } 2962 2963 return set; 2964 } 2965 2966 2967 @Override 2968 public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade) { 2969 if (goingToNotificationShade) { 2970 return null; 2971 } else { 2972 return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit); 2973 } 2974 } 2975 2976 private static void awakenDreams() { 2977 IDreamManager dreamManager = getDreamManager(); 2978 if (dreamManager != null) { 2979 try { 2980 dreamManager.awaken(); 2981 } catch (RemoteException e) { 2982 // fine, stay asleep then 2983 } 2984 } 2985 } 2986 2987 static IDreamManager getDreamManager() { 2988 return IDreamManager.Stub.asInterface( 2989 ServiceManager.checkService(DreamService.DREAM_SERVICE)); 2990 } 2991 2992 TelecomManager getTelecommService() { 2993 return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); 2994 } 2995 2996 static IAudioService getAudioService() { 2997 IAudioService audioService = IAudioService.Stub.asInterface( 2998 ServiceManager.checkService(Context.AUDIO_SERVICE)); 2999 if (audioService == null) { 3000 Log.w(TAG, "Unable to find IAudioService interface."); 3001 } 3002 return audioService; 3003 } 3004 3005 boolean keyguardOn() { 3006 return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode(); 3007 } 3008 3009 private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = { 3010 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, 3011 WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, 3012 }; 3013 3014 /** {@inheritDoc} */ 3015 @Override 3016 public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) { 3017 final boolean keyguardOn = keyguardOn(); 3018 final int keyCode = event.getKeyCode(); 3019 final int repeatCount = event.getRepeatCount(); 3020 final int metaState = event.getMetaState(); 3021 final int flags = event.getFlags(); 3022 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; 3023 final boolean canceled = event.isCanceled(); 3024 3025 if (DEBUG_INPUT) { 3026 Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount=" 3027 + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed 3028 + " canceled=" + canceled); 3029 } 3030 3031 // If we think we might have a volume down & power key chord on the way 3032 // but we're not sure, then tell the dispatcher to wait a little while and 3033 // try again later before dispatching. 3034 if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) { 3035 if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) { 3036 final long now = SystemClock.uptimeMillis(); 3037 final long timeoutTime = mScreenshotChordVolumeDownKeyTime 3038 + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS; 3039 if (now < timeoutTime) { 3040 return timeoutTime - now; 3041 } 3042 } 3043 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN 3044 && mScreenshotChordVolumeDownKeyConsumed) { 3045 if (!down) { 3046 mScreenshotChordVolumeDownKeyConsumed = false; 3047 } 3048 return -1; 3049 } 3050 } 3051 3052 // Cancel any pending meta actions if we see any other keys being pressed between the down 3053 // of the meta key and its corresponding up. 3054 if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) { 3055 mPendingMetaAction = false; 3056 } 3057 // Any key that is not Alt or Meta cancels Caps Lock combo tracking. 3058 if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) { 3059 mPendingCapsLockToggle = false; 3060 } 3061 3062 // First we always handle the home key here, so applications 3063 // can never break it, although if keyguard is on, we do let 3064 // it handle it, because that gives us the correct 5 second 3065 // timeout. 3066 if (keyCode == KeyEvent.KEYCODE_HOME) { 3067 3068 // If we have released the home key, and didn't do anything else 3069 // while it was pressed, then it is time to go home! 3070 if (!down) { 3071 cancelPreloadRecentApps(); 3072 3073 mHomePressed = false; 3074 if (mHomeConsumed) { 3075 mHomeConsumed = false; 3076 return -1; 3077 } 3078 3079 if (canceled) { 3080 Log.i(TAG, "Ignoring HOME; event canceled."); 3081 return -1; 3082 } 3083 3084 // Delay handling home if a double-tap is possible. 3085 if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) { 3086 mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case 3087 mHomeDoubleTapPending = true; 3088 mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable, 3089 ViewConfiguration.getDoubleTapTimeout()); 3090 return -1; 3091 } 3092 3093 handleShortPressOnHome(); 3094 return -1; 3095 } 3096 3097 // If a system window has focus, then it doesn't make sense 3098 // right now to interact with applications. 3099 WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null; 3100 if (attrs != null) { 3101 final int type = attrs.type; 3102 if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM 3103 || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG 3104 || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 3105 // the "app" is keyguard, so give it the key 3106 return 0; 3107 } 3108 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length; 3109 for (int i=0; i<typeCount; i++) { 3110 if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) { 3111 // don't do anything, but also don't pass it to the app 3112 return -1; 3113 } 3114 } 3115 } 3116 3117 // Remember that home is pressed and handle special actions. 3118 if (repeatCount == 0) { 3119 mHomePressed = true; 3120 if (mHomeDoubleTapPending) { 3121 mHomeDoubleTapPending = false; 3122 mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); 3123 handleDoubleTapOnHome(); 3124 } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI 3125 || mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) { 3126 preloadRecentApps(); 3127 } 3128 } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { 3129 if (!keyguardOn) { 3130 handleLongPressOnHome(event.getDeviceId()); 3131 } 3132 } 3133 return -1; 3134 } else if (keyCode == KeyEvent.KEYCODE_MENU) { 3135 // Hijack modified menu keys for debugging features 3136 final int chordBug = KeyEvent.META_SHIFT_ON; 3137 3138 if (down && repeatCount == 0) { 3139 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) { 3140 Intent intent = new Intent(Intent.ACTION_BUG_REPORT); 3141 mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, 3142 null, null, null, 0, null, null); 3143 return -1; 3144 } else if (SHOW_PROCESSES_ON_ALT_MENU && 3145 (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) { 3146 Intent service = new Intent(); 3147 service.setClassName(mContext, "com.android.server.LoadAverageService"); 3148 ContentResolver res = mContext.getContentResolver(); 3149 boolean shown = Settings.Global.getInt( 3150 res, Settings.Global.SHOW_PROCESSES, 0) != 0; 3151 if (!shown) { 3152 mContext.startService(service); 3153 } else { 3154 mContext.stopService(service); 3155 } 3156 Settings.Global.putInt( 3157 res, Settings.Global.SHOW_PROCESSES, shown ? 0 : 1); 3158 return -1; 3159 } 3160 } 3161 } else if (keyCode == KeyEvent.KEYCODE_SEARCH) { 3162 if (down) { 3163 if (repeatCount == 0) { 3164 mSearchKeyShortcutPending = true; 3165 mConsumeSearchKeyUp = false; 3166 } 3167 } else { 3168 mSearchKeyShortcutPending = false; 3169 if (mConsumeSearchKeyUp) { 3170 mConsumeSearchKeyUp = false; 3171 return -1; 3172 } 3173 } 3174 return 0; 3175 } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) { 3176 if (!keyguardOn) { 3177 if (down && repeatCount == 0) { 3178 preloadRecentApps(); 3179 } else if (!down) { 3180 toggleRecentApps(); 3181 } 3182 } 3183 return -1; 3184 } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) { 3185 if (down) { 3186 IStatusBarService service = getStatusBarService(); 3187 if (service != null) { 3188 try { 3189 service.expandNotificationsPanel(); 3190 } catch (RemoteException e) { 3191 // do nothing. 3192 } 3193 } 3194 } 3195 } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed() 3196 && event.isCtrlPressed()) { 3197 if (down && repeatCount == 0) { 3198 int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION 3199 : TAKE_SCREENSHOT_FULLSCREEN; 3200 mScreenshotRunnable.setScreenshotType(type); 3201 mHandler.post(mScreenshotRunnable); 3202 return -1; 3203 } 3204 } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) { 3205 if (down && repeatCount == 0 && !isKeyguardLocked()) { 3206 toggleKeyboardShortcutsMenu(event.getDeviceId()); 3207 } 3208 } else if (keyCode == KeyEvent.KEYCODE_ASSIST) { 3209 if (down) { 3210 if (repeatCount == 0) { 3211 mAssistKeyLongPressed = false; 3212 } else if (repeatCount == 1) { 3213 mAssistKeyLongPressed = true; 3214 if (!keyguardOn) { 3215 launchAssistLongPressAction(); 3216 } 3217 } 3218 } else { 3219 if (mAssistKeyLongPressed) { 3220 mAssistKeyLongPressed = false; 3221 } else { 3222 if (!keyguardOn) { 3223 launchAssistAction(null, event.getDeviceId()); 3224 } 3225 } 3226 } 3227 return -1; 3228 } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) { 3229 if (!down) { 3230 Intent voiceIntent; 3231 if (!keyguardOn) { 3232 voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH); 3233 } else { 3234 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface( 3235 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); 3236 if (dic != null) { 3237 try { 3238 dic.exitIdle("voice-search"); 3239 } catch (RemoteException e) { 3240 } 3241 } 3242 voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); 3243 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true); 3244 } 3245 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF); 3246 } 3247 } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) { 3248 if (down && repeatCount == 0) { 3249 mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN); 3250 mHandler.post(mScreenshotRunnable); 3251 } 3252 return -1; 3253 } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP 3254 || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) { 3255 if (down) { 3256 int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1; 3257 3258 // Disable autobrightness if it's on 3259 int auto = Settings.System.getIntForUser( 3260 mContext.getContentResolver(), 3261 Settings.System.SCREEN_BRIGHTNESS_MODE, 3262 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, 3263 UserHandle.USER_CURRENT_OR_SELF); 3264 if (auto != 0) { 3265 Settings.System.putIntForUser(mContext.getContentResolver(), 3266 Settings.System.SCREEN_BRIGHTNESS_MODE, 3267 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, 3268 UserHandle.USER_CURRENT_OR_SELF); 3269 } 3270 3271 int min = mPowerManager.getMinimumScreenBrightnessSetting(); 3272 int max = mPowerManager.getMaximumScreenBrightnessSetting(); 3273 int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction; 3274 int brightness = Settings.System.getIntForUser(mContext.getContentResolver(), 3275 Settings.System.SCREEN_BRIGHTNESS, 3276 mPowerManager.getDefaultScreenBrightnessSetting(), 3277 UserHandle.USER_CURRENT_OR_SELF); 3278 brightness += step; 3279 // Make sure we don't go beyond the limits. 3280 brightness = Math.min(max, brightness); 3281 brightness = Math.max(min, brightness); 3282 3283 Settings.System.putIntForUser(mContext.getContentResolver(), 3284 Settings.System.SCREEN_BRIGHTNESS, brightness, 3285 UserHandle.USER_CURRENT_OR_SELF); 3286 startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG), 3287 UserHandle.CURRENT_OR_SELF); 3288 } 3289 return -1; 3290 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP 3291 || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN 3292 || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) { 3293 if (mUseTvRouting) { 3294 // On TVs volume keys never go to the foreground app. 3295 dispatchDirectAudioEvent(event); 3296 return -1; 3297 } 3298 } 3299 3300 // Toggle Caps Lock on META-ALT. 3301 boolean actionTriggered = false; 3302 if (KeyEvent.isModifierKey(keyCode)) { 3303 if (!mPendingCapsLockToggle) { 3304 // Start tracking meta state for combo. 3305 mInitialMetaState = mMetaState; 3306 mPendingCapsLockToggle = true; 3307 } else if (event.getAction() == KeyEvent.ACTION_UP) { 3308 int altOnMask = mMetaState & KeyEvent.META_ALT_MASK; 3309 int metaOnMask = mMetaState & KeyEvent.META_META_MASK; 3310 3311 // Check for Caps Lock toggle 3312 if ((metaOnMask != 0) && (altOnMask != 0)) { 3313 // Check if nothing else is pressed 3314 if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) { 3315 // Handle Caps Lock Toggle 3316 mInputManagerInternal.toggleCapsLock(event.getDeviceId()); 3317 actionTriggered = true; 3318 } 3319 } 3320 3321 // Always stop tracking when key goes up. 3322 mPendingCapsLockToggle = false; 3323 } 3324 } 3325 // Store current meta state to be able to evaluate it later. 3326 mMetaState = metaState; 3327 3328 if (actionTriggered) { 3329 return -1; 3330 } 3331 3332 if (KeyEvent.isMetaKey(keyCode)) { 3333 if (down) { 3334 mPendingMetaAction = true; 3335 } else if (mPendingMetaAction) { 3336 launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId()); 3337 } 3338 return -1; 3339 } 3340 3341 // Shortcuts are invoked through Search+key, so intercept those here 3342 // Any printing key that is chorded with Search should be consumed 3343 // even if no shortcut was invoked. This prevents text from being 3344 // inadvertently inserted when using a keyboard that has built-in macro 3345 // shortcut keys (that emit Search+x) and some of them are not registered. 3346 if (mSearchKeyShortcutPending) { 3347 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 3348 if (kcm.isPrintingKey(keyCode)) { 3349 mConsumeSearchKeyUp = true; 3350 mSearchKeyShortcutPending = false; 3351 if (down && repeatCount == 0 && !keyguardOn) { 3352 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState); 3353 if (shortcutIntent != null) { 3354 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3355 try { 3356 startActivityAsUser(shortcutIntent, UserHandle.CURRENT); 3357 dismissKeyboardShortcutsMenu(); 3358 } catch (ActivityNotFoundException ex) { 3359 Slog.w(TAG, "Dropping shortcut key combination because " 3360 + "the activity to which it is registered was not found: " 3361 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex); 3362 } 3363 } else { 3364 Slog.i(TAG, "Dropping unregistered shortcut key combination: " 3365 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode)); 3366 } 3367 } 3368 return -1; 3369 } 3370 } 3371 3372 // Invoke shortcuts using Meta. 3373 if (down && repeatCount == 0 && !keyguardOn 3374 && (metaState & KeyEvent.META_META_ON) != 0) { 3375 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 3376 if (kcm.isPrintingKey(keyCode)) { 3377 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, 3378 metaState & ~(KeyEvent.META_META_ON 3379 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON)); 3380 if (shortcutIntent != null) { 3381 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3382 try { 3383 startActivityAsUser(shortcutIntent, UserHandle.CURRENT); 3384 dismissKeyboardShortcutsMenu(); 3385 } catch (ActivityNotFoundException ex) { 3386 Slog.w(TAG, "Dropping shortcut key combination because " 3387 + "the activity to which it is registered was not found: " 3388 + "META+" + KeyEvent.keyCodeToString(keyCode), ex); 3389 } 3390 return -1; 3391 } 3392 } 3393 } 3394 3395 // Handle application launch keys. 3396 if (down && repeatCount == 0 && !keyguardOn) { 3397 String category = sApplicationLaunchKeyCategories.get(keyCode); 3398 if (category != null) { 3399 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category); 3400 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3401 try { 3402 startActivityAsUser(intent, UserHandle.CURRENT); 3403 dismissKeyboardShortcutsMenu(); 3404 } catch (ActivityNotFoundException ex) { 3405 Slog.w(TAG, "Dropping application launch key because " 3406 + "the activity to which it is registered was not found: " 3407 + "keyCode=" + keyCode + ", category=" + category, ex); 3408 } 3409 return -1; 3410 } 3411 } 3412 3413 // Display task switcher for ALT-TAB. 3414 if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) { 3415 if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) { 3416 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK; 3417 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) { 3418 mRecentAppsHeldModifiers = shiftlessModifiers; 3419 showRecentApps(true, false); 3420 return -1; 3421 } 3422 } 3423 } else if (!down && mRecentAppsHeldModifiers != 0 3424 && (metaState & mRecentAppsHeldModifiers) == 0) { 3425 mRecentAppsHeldModifiers = 0; 3426 hideRecentApps(true, false); 3427 } 3428 3429 // Handle input method switching. 3430 if (down && repeatCount == 0 3431 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH 3432 || (keyCode == KeyEvent.KEYCODE_SPACE 3433 && (metaState & KeyEvent.META_META_MASK) != 0))) { 3434 final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0; 3435 mWindowManagerFuncs.switchInputMethod(forwardDirection); 3436 return -1; 3437 } 3438 if (mLanguageSwitchKeyPressed && !down 3439 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH 3440 || keyCode == KeyEvent.KEYCODE_SPACE)) { 3441 mLanguageSwitchKeyPressed = false; 3442 return -1; 3443 } 3444 3445 if (isValidGlobalKey(keyCode) 3446 && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) { 3447 return -1; 3448 } 3449 3450 if (down) { 3451 long shortcutCode = keyCode; 3452 if (event.isCtrlPressed()) { 3453 shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE; 3454 } 3455 3456 if (event.isAltPressed()) { 3457 shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE; 3458 } 3459 3460 if (event.isShiftPressed()) { 3461 shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE; 3462 } 3463 3464 if (event.isMetaPressed()) { 3465 shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE; 3466 } 3467 3468 IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode); 3469 if (shortcutService != null) { 3470 try { 3471 if (isUserSetupComplete()) { 3472 shortcutService.notifyShortcutKeyPressed(shortcutCode); 3473 } 3474 } catch (RemoteException e) { 3475 mShortcutKeyServices.delete(shortcutCode); 3476 } 3477 return -1; 3478 } 3479 } 3480 3481 // Reserve all the META modifier combos for system behavior 3482 if ((metaState & KeyEvent.META_META_ON) != 0) { 3483 return -1; 3484 } 3485 3486 // Let the application handle the key. 3487 return 0; 3488 } 3489 3490 /** {@inheritDoc} */ 3491 @Override 3492 public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) { 3493 // Note: This method is only called if the initial down was unhandled. 3494 if (DEBUG_INPUT) { 3495 Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction() 3496 + ", flags=" + event.getFlags() 3497 + ", keyCode=" + event.getKeyCode() 3498 + ", scanCode=" + event.getScanCode() 3499 + ", metaState=" + event.getMetaState() 3500 + ", repeatCount=" + event.getRepeatCount() 3501 + ", policyFlags=" + policyFlags); 3502 } 3503 3504 KeyEvent fallbackEvent = null; 3505 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 3506 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 3507 final int keyCode = event.getKeyCode(); 3508 final int metaState = event.getMetaState(); 3509 final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN 3510 && event.getRepeatCount() == 0; 3511 3512 // Check for fallback actions specified by the key character map. 3513 final FallbackAction fallbackAction; 3514 if (initialDown) { 3515 fallbackAction = kcm.getFallbackAction(keyCode, metaState); 3516 } else { 3517 fallbackAction = mFallbackActions.get(keyCode); 3518 } 3519 3520 if (fallbackAction != null) { 3521 if (DEBUG_INPUT) { 3522 Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode 3523 + " metaState=" + Integer.toHexString(fallbackAction.metaState)); 3524 } 3525 3526 final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK; 3527 fallbackEvent = KeyEvent.obtain( 3528 event.getDownTime(), event.getEventTime(), 3529 event.getAction(), fallbackAction.keyCode, 3530 event.getRepeatCount(), fallbackAction.metaState, 3531 event.getDeviceId(), event.getScanCode(), 3532 flags, event.getSource(), null); 3533 3534 if (!interceptFallback(win, fallbackEvent, policyFlags)) { 3535 fallbackEvent.recycle(); 3536 fallbackEvent = null; 3537 } 3538 3539 if (initialDown) { 3540 mFallbackActions.put(keyCode, fallbackAction); 3541 } else if (event.getAction() == KeyEvent.ACTION_UP) { 3542 mFallbackActions.remove(keyCode); 3543 fallbackAction.recycle(); 3544 } 3545 } 3546 } 3547 3548 if (DEBUG_INPUT) { 3549 if (fallbackEvent == null) { 3550 Slog.d(TAG, "No fallback."); 3551 } else { 3552 Slog.d(TAG, "Performing fallback: " + fallbackEvent); 3553 } 3554 } 3555 return fallbackEvent; 3556 } 3557 3558 private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) { 3559 int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags); 3560 if ((actions & ACTION_PASS_TO_USER) != 0) { 3561 long delayMillis = interceptKeyBeforeDispatching( 3562 win, fallbackEvent, policyFlags); 3563 if (delayMillis == 0) { 3564 return true; 3565 } 3566 } 3567 return false; 3568 } 3569 3570 @Override 3571 public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService) 3572 throws RemoteException { 3573 synchronized (mLock) { 3574 IShortcutService service = mShortcutKeyServices.get(shortcutCode); 3575 if (service != null && service.asBinder().pingBinder()) { 3576 throw new RemoteException("Key already exists."); 3577 } 3578 3579 mShortcutKeyServices.put(shortcutCode, shortcutService); 3580 } 3581 } 3582 3583 @Override 3584 public boolean canShowDismissingWindowWhileLockedLw() { 3585 // If the keyguard is trusted, it will unlock without a challange. Therefore, windows with 3586 // FLAG_DISMISS_KEYGUARD don't need to be force hidden, as they will unlock the phone right 3587 // away anyways. 3588 return mKeyguardDelegate != null && mKeyguardDelegate.isTrusted(); 3589 } 3590 3591 private void launchAssistLongPressAction() { 3592 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); 3593 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST); 3594 3595 // launch the search activity 3596 Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS); 3597 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3598 try { 3599 // TODO: This only stops the factory-installed search manager. 3600 // Need to formalize an API to handle others 3601 SearchManager searchManager = getSearchManager(); 3602 if (searchManager != null) { 3603 searchManager.stopSearch(); 3604 } 3605 startActivityAsUser(intent, UserHandle.CURRENT); 3606 } catch (ActivityNotFoundException e) { 3607 Slog.w(TAG, "No activity to handle assist long press action.", e); 3608 } 3609 } 3610 3611 private void launchAssistAction(String hint, int deviceId) { 3612 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST); 3613 if (!isUserSetupComplete()) { 3614 // Disable opening assist window during setup 3615 return; 3616 } 3617 Bundle args = null; 3618 if (deviceId > Integer.MIN_VALUE) { 3619 args = new Bundle(); 3620 args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId); 3621 } 3622 if ((mContext.getResources().getConfiguration().uiMode 3623 & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) { 3624 // On TV, use legacy handling until assistants are implemented in the proper way. 3625 ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE)) 3626 .launchLegacyAssist(hint, UserHandle.myUserId(), args); 3627 } else { 3628 if (hint != null) { 3629 if (args == null) { 3630 args = new Bundle(); 3631 } 3632 args.putBoolean(hint, true); 3633 } 3634 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3635 if (statusbar != null) { 3636 statusbar.startAssist(args); 3637 } 3638 } 3639 } 3640 3641 private void startActivityAsUser(Intent intent, UserHandle handle) { 3642 if (isUserSetupComplete()) { 3643 mContext.startActivityAsUser(intent, handle); 3644 } else { 3645 Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent); 3646 } 3647 } 3648 3649 private SearchManager getSearchManager() { 3650 if (mSearchManager == null) { 3651 mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); 3652 } 3653 return mSearchManager; 3654 } 3655 3656 private void preloadRecentApps() { 3657 mPreloadedRecentApps = true; 3658 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3659 if (statusbar != null) { 3660 statusbar.preloadRecentApps(); 3661 } 3662 } 3663 3664 private void cancelPreloadRecentApps() { 3665 if (mPreloadedRecentApps) { 3666 mPreloadedRecentApps = false; 3667 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3668 if (statusbar != null) { 3669 statusbar.cancelPreloadRecentApps(); 3670 } 3671 } 3672 } 3673 3674 private void toggleRecentApps() { 3675 mPreloadedRecentApps = false; // preloading no longer needs to be canceled 3676 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3677 if (statusbar != null) { 3678 statusbar.toggleRecentApps(); 3679 } 3680 } 3681 3682 @Override 3683 public void showRecentApps(boolean fromHome) { 3684 mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS); 3685 mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget(); 3686 } 3687 3688 private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) { 3689 mPreloadedRecentApps = false; // preloading no longer needs to be canceled 3690 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3691 if (statusbar != null) { 3692 statusbar.showRecentApps(triggeredFromAltTab, fromHome); 3693 } 3694 } 3695 3696 private void toggleKeyboardShortcutsMenu(int deviceId) { 3697 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3698 if (statusbar != null) { 3699 statusbar.toggleKeyboardShortcutsMenu(deviceId); 3700 } 3701 } 3702 3703 private void dismissKeyboardShortcutsMenu() { 3704 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3705 if (statusbar != null) { 3706 statusbar.dismissKeyboardShortcutsMenu(); 3707 } 3708 } 3709 3710 private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) { 3711 mPreloadedRecentApps = false; // preloading no longer needs to be canceled 3712 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3713 if (statusbar != null) { 3714 statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome); 3715 } 3716 } 3717 3718 void launchHomeFromHotKey() { 3719 launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/); 3720 } 3721 3722 /** 3723 * A home key -> launch home action was detected. Take the appropriate action 3724 * given the situation with the keyguard. 3725 */ 3726 void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) { 3727 if (respectKeyguard) { 3728 if (isKeyguardShowingAndNotOccluded()) { 3729 // don't launch home if keyguard showing 3730 return; 3731 } 3732 3733 if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) { 3734 // when in keyguard restricted mode, must first verify unlock 3735 // before launching home 3736 mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() { 3737 @Override 3738 public void onKeyguardExitResult(boolean success) { 3739 if (success) { 3740 try { 3741 ActivityManagerNative.getDefault().stopAppSwitches(); 3742 } catch (RemoteException e) { 3743 } 3744 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY); 3745 startDockOrHome(true /*fromHomeKey*/, awakenFromDreams); 3746 } 3747 } 3748 }); 3749 return; 3750 } 3751 } 3752 3753 // no keyguard stuff to worry about, just launch home! 3754 try { 3755 ActivityManagerNative.getDefault().stopAppSwitches(); 3756 } catch (RemoteException e) { 3757 } 3758 if (mRecentsVisible) { 3759 // Hide Recents and notify it to launch Home 3760 if (awakenFromDreams) { 3761 awakenDreams(); 3762 } 3763 hideRecentApps(false, true); 3764 } else { 3765 // Otherwise, just launch Home 3766 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY); 3767 startDockOrHome(true /*fromHomeKey*/, awakenFromDreams); 3768 } 3769 } 3770 3771 private final Runnable mClearHideNavigationFlag = new Runnable() { 3772 @Override 3773 public void run() { 3774 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 3775 // Clear flags. 3776 mForceClearedSystemUiFlags &= 3777 ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; 3778 } 3779 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 3780 } 3781 }; 3782 3783 /** 3784 * Input handler used while nav bar is hidden. Captures any touch on the screen, 3785 * to determine when the nav bar should be shown and prevent applications from 3786 * receiving those touches. 3787 */ 3788 final class HideNavInputEventReceiver extends InputEventReceiver { 3789 public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) { 3790 super(inputChannel, looper); 3791 } 3792 3793 @Override 3794 public void onInputEvent(InputEvent event) { 3795 boolean handled = false; 3796 try { 3797 if (event instanceof MotionEvent 3798 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { 3799 final MotionEvent motionEvent = (MotionEvent)event; 3800 if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { 3801 // When the user taps down, we re-show the nav bar. 3802 boolean changed = false; 3803 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 3804 if (mInputConsumer == null) { 3805 return; 3806 } 3807 // Any user activity always causes us to show the 3808 // navigation controls, if they had been hidden. 3809 // We also clear the low profile and only content 3810 // flags so that tapping on the screen will atomically 3811 // restore all currently hidden screen decorations. 3812 int newVal = mResettingSystemUiFlags | 3813 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | 3814 View.SYSTEM_UI_FLAG_LOW_PROFILE | 3815 View.SYSTEM_UI_FLAG_FULLSCREEN; 3816 if (mResettingSystemUiFlags != newVal) { 3817 mResettingSystemUiFlags = newVal; 3818 changed = true; 3819 } 3820 // We don't allow the system's nav bar to be hidden 3821 // again for 1 second, to prevent applications from 3822 // spamming us and keeping it from being shown. 3823 newVal = mForceClearedSystemUiFlags | 3824 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; 3825 if (mForceClearedSystemUiFlags != newVal) { 3826 mForceClearedSystemUiFlags = newVal; 3827 changed = true; 3828 mHandler.postDelayed(mClearHideNavigationFlag, 1000); 3829 } 3830 } 3831 if (changed) { 3832 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 3833 } 3834 } 3835 } 3836 } finally { 3837 finishInputEvent(event, handled); 3838 } 3839 } 3840 } 3841 final InputEventReceiver.Factory mHideNavInputEventReceiverFactory = 3842 new InputEventReceiver.Factory() { 3843 @Override 3844 public InputEventReceiver createInputEventReceiver( 3845 InputChannel inputChannel, Looper looper) { 3846 return new HideNavInputEventReceiver(inputChannel, looper); 3847 } 3848 }; 3849 3850 @Override 3851 public int adjustSystemUiVisibilityLw(int visibility) { 3852 mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility); 3853 mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility); 3854 mRecentsVisible = (visibility & View.RECENT_APPS_VISIBLE) > 0; 3855 mTvPictureInPictureVisible = (visibility & View.TV_PICTURE_IN_PICTURE_VISIBLE) > 0; 3856 3857 // Reset any bits in mForceClearingStatusBarVisibility that 3858 // are now clear. 3859 mResettingSystemUiFlags &= visibility; 3860 // Clear any bits in the new visibility that are currently being 3861 // force cleared, before reporting it. 3862 return visibility & ~mResettingSystemUiFlags 3863 & ~mForceClearedSystemUiFlags; 3864 } 3865 3866 @Override 3867 public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds, 3868 int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets, 3869 Rect outStableInsets, Rect outOutsets) { 3870 final int fl = PolicyControl.getWindowFlags(null, attrs); 3871 final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs); 3872 final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility); 3873 3874 final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl); 3875 if (useOutsets) { 3876 int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources()); 3877 if (outset > 0) { 3878 if (displayRotation == Surface.ROTATION_0) { 3879 outOutsets.bottom += outset; 3880 } else if (displayRotation == Surface.ROTATION_90) { 3881 outOutsets.right += outset; 3882 } else if (displayRotation == Surface.ROTATION_180) { 3883 outOutsets.top += outset; 3884 } else if (displayRotation == Surface.ROTATION_270) { 3885 outOutsets.left += outset; 3886 } 3887 } 3888 } 3889 3890 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) 3891 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { 3892 int availRight, availBottom; 3893 if (canHideNavigationBar() && 3894 (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) { 3895 availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 3896 availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 3897 } else { 3898 availRight = mRestrictedScreenLeft + mRestrictedScreenWidth; 3899 availBottom = mRestrictedScreenTop + mRestrictedScreenHeight; 3900 } 3901 if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) { 3902 if ((fl & FLAG_FULLSCREEN) != 0) { 3903 outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop, 3904 availRight - mStableFullscreenRight, 3905 availBottom - mStableFullscreenBottom); 3906 } else { 3907 outContentInsets.set(mStableLeft, mStableTop, 3908 availRight - mStableRight, availBottom - mStableBottom); 3909 } 3910 } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) { 3911 outContentInsets.setEmpty(); 3912 } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN 3913 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) { 3914 outContentInsets.set(mCurLeft, mCurTop, 3915 availRight - mCurRight, availBottom - mCurBottom); 3916 } else { 3917 outContentInsets.set(mCurLeft, mCurTop, 3918 availRight - mCurRight, availBottom - mCurBottom); 3919 } 3920 3921 outStableInsets.set(mStableLeft, mStableTop, 3922 availRight - mStableRight, availBottom - mStableBottom); 3923 if (taskBounds != null) { 3924 calculateRelevantTaskInsets(taskBounds, outContentInsets, 3925 displayWidth, displayHeight); 3926 calculateRelevantTaskInsets(taskBounds, outStableInsets, 3927 displayWidth, displayHeight); 3928 } 3929 return mForceShowSystemBars; 3930 } 3931 outContentInsets.setEmpty(); 3932 outStableInsets.setEmpty(); 3933 return mForceShowSystemBars; 3934 } 3935 3936 /** 3937 * For any given task bounds, the insets relevant for these bounds given the insets relevant 3938 * for the entire display. 3939 */ 3940 private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth, 3941 int displayHeight) { 3942 mTmpRect.set(0, 0, displayWidth, displayHeight); 3943 mTmpRect.inset(inOutInsets); 3944 mTmpRect.intersect(taskBounds); 3945 int leftInset = mTmpRect.left - taskBounds.left; 3946 int topInset = mTmpRect.top - taskBounds.top; 3947 int rightInset = taskBounds.right - mTmpRect.right; 3948 int bottomInset = taskBounds.bottom - mTmpRect.bottom; 3949 inOutInsets.set(leftInset, topInset, rightInset, bottomInset); 3950 } 3951 3952 private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) { 3953 return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN 3954 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0; 3955 } 3956 3957 /** {@inheritDoc} */ 3958 @Override 3959 public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight, 3960 int displayRotation, int uiMode) { 3961 mDisplayRotation = displayRotation; 3962 final int overscanLeft, overscanTop, overscanRight, overscanBottom; 3963 if (isDefaultDisplay) { 3964 switch (displayRotation) { 3965 case Surface.ROTATION_90: 3966 overscanLeft = mOverscanTop; 3967 overscanTop = mOverscanRight; 3968 overscanRight = mOverscanBottom; 3969 overscanBottom = mOverscanLeft; 3970 break; 3971 case Surface.ROTATION_180: 3972 overscanLeft = mOverscanRight; 3973 overscanTop = mOverscanBottom; 3974 overscanRight = mOverscanLeft; 3975 overscanBottom = mOverscanTop; 3976 break; 3977 case Surface.ROTATION_270: 3978 overscanLeft = mOverscanBottom; 3979 overscanTop = mOverscanLeft; 3980 overscanRight = mOverscanTop; 3981 overscanBottom = mOverscanRight; 3982 break; 3983 default: 3984 overscanLeft = mOverscanLeft; 3985 overscanTop = mOverscanTop; 3986 overscanRight = mOverscanRight; 3987 overscanBottom = mOverscanBottom; 3988 break; 3989 } 3990 } else { 3991 overscanLeft = 0; 3992 overscanTop = 0; 3993 overscanRight = 0; 3994 overscanBottom = 0; 3995 } 3996 mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0; 3997 mOverscanScreenTop = mRestrictedOverscanScreenTop = 0; 3998 mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth; 3999 mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight; 4000 mSystemLeft = 0; 4001 mSystemTop = 0; 4002 mSystemRight = displayWidth; 4003 mSystemBottom = displayHeight; 4004 mUnrestrictedScreenLeft = overscanLeft; 4005 mUnrestrictedScreenTop = overscanTop; 4006 mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight; 4007 mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom; 4008 mRestrictedScreenLeft = mUnrestrictedScreenLeft; 4009 mRestrictedScreenTop = mUnrestrictedScreenTop; 4010 mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth; 4011 mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight; 4012 mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft 4013 = mCurLeft = mUnrestrictedScreenLeft; 4014 mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop 4015 = mCurTop = mUnrestrictedScreenTop; 4016 mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight 4017 = mCurRight = displayWidth - overscanRight; 4018 mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom 4019 = mCurBottom = displayHeight - overscanBottom; 4020 mDockLayer = 0x10000000; 4021 mStatusBarLayer = -1; 4022 4023 // start with the current dock rect, which will be (0,0,displayWidth,displayHeight) 4024 final Rect pf = mTmpParentFrame; 4025 final Rect df = mTmpDisplayFrame; 4026 final Rect of = mTmpOverscanFrame; 4027 final Rect vf = mTmpVisibleFrame; 4028 final Rect dcf = mTmpDecorFrame; 4029 pf.left = df.left = of.left = vf.left = mDockLeft; 4030 pf.top = df.top = of.top = vf.top = mDockTop; 4031 pf.right = df.right = of.right = vf.right = mDockRight; 4032 pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom; 4033 dcf.setEmpty(); // Decor frame N/A for system bars. 4034 4035 if (isDefaultDisplay) { 4036 // For purposes of putting out fake window up to steal focus, we will 4037 // drive nav being hidden only by whether it is requested. 4038 final int sysui = mLastSystemUiFlags; 4039 boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0; 4040 boolean navTranslucent = (sysui 4041 & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0; 4042 boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; 4043 boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 4044 boolean navAllowedHidden = immersive || immersiveSticky; 4045 navTranslucent &= !immersiveSticky; // transient trumps translucent 4046 boolean isKeyguardShowing = isStatusBarKeyguard() && !mHideLockScreen; 4047 if (!isKeyguardShowing) { 4048 navTranslucent &= areTranslucentBarsAllowed(); 4049 } 4050 boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null 4051 && mStatusBar.getAttrs().height == MATCH_PARENT 4052 && mStatusBar.getAttrs().width == MATCH_PARENT; 4053 4054 // When the navigation bar isn't visible, we put up a fake 4055 // input window to catch all touch events. This way we can 4056 // detect when the user presses anywhere to bring back the nav 4057 // bar and ensure the application doesn't see the event. 4058 if (navVisible || navAllowedHidden) { 4059 if (mInputConsumer != null) { 4060 mHandler.sendMessage( 4061 mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer)); 4062 mInputConsumer = null; 4063 } 4064 } else if (mInputConsumer == null) { 4065 mInputConsumer = mWindowManagerFuncs.addInputConsumer(mHandler.getLooper(), 4066 mHideNavInputEventReceiverFactory); 4067 } 4068 4069 // For purposes of positioning and showing the nav bar, if we have 4070 // decided that it can't be hidden (because of the screen aspect ratio), 4071 // then take that into account. 4072 navVisible |= !canHideNavigationBar(); 4073 4074 boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight, 4075 displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom, dcf, navVisible, navTranslucent, 4076 navAllowedHidden, statusBarExpandedNotKeyguard); 4077 if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)", 4078 mDockLeft, mDockTop, mDockRight, mDockBottom)); 4079 updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing); 4080 if (updateSysUiVisibility) { 4081 updateSystemUiVisibilityLw(); 4082 } 4083 } 4084 } 4085 4086 private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui, 4087 boolean isKeyguardShowing) { 4088 // decide where the status bar goes ahead of time 4089 if (mStatusBar != null) { 4090 // apply any navigation bar insets 4091 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4092 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4093 pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft; 4094 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight 4095 + mUnrestrictedScreenTop; 4096 vf.left = mStableLeft; 4097 vf.top = mStableTop; 4098 vf.right = mStableRight; 4099 vf.bottom = mStableBottom; 4100 4101 mStatusBarLayer = mStatusBar.getSurfaceLayer(); 4102 4103 // Let the status bar determine its size. 4104 mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */, 4105 vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */, 4106 dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */); 4107 4108 // For layout, the status bar is always at the top with our fixed height. 4109 mStableTop = mUnrestrictedScreenTop + mStatusBarHeight; 4110 4111 boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0; 4112 boolean statusBarTranslucent = (sysui 4113 & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0; 4114 if (!isKeyguardShowing) { 4115 statusBarTranslucent &= areTranslucentBarsAllowed(); 4116 } 4117 4118 // If the status bar is hidden, we don't want to cause 4119 // windows behind it to scroll. 4120 if (mStatusBar.isVisibleLw() && !statusBarTransient) { 4121 // Status bar may go away, so the screen area it occupies 4122 // is available to apps but just covering them when the 4123 // status bar is visible. 4124 mDockTop = mUnrestrictedScreenTop + mStatusBarHeight; 4125 4126 mContentTop = mVoiceContentTop = mCurTop = mDockTop; 4127 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom; 4128 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft; 4129 mContentRight = mVoiceContentRight = mCurRight = mDockRight; 4130 4131 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " + 4132 String.format( 4133 "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]", 4134 mDockLeft, mDockTop, mDockRight, mDockBottom, 4135 mContentLeft, mContentTop, mContentRight, mContentBottom, 4136 mCurLeft, mCurTop, mCurRight, mCurBottom)); 4137 } 4138 if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw() 4139 && !statusBarTransient && !statusBarTranslucent 4140 && !mStatusBarController.wasRecentlyTranslucent()) { 4141 // If the opaque status bar is currently requested to be visible, 4142 // and not in the process of animating on or off, then 4143 // we can tell the app that it is covered by it. 4144 mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight; 4145 } 4146 if (mStatusBarController.checkHiddenLw()) { 4147 return true; 4148 } 4149 } 4150 return false; 4151 } 4152 4153 private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation, 4154 int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf, 4155 boolean navVisible, boolean navTranslucent, boolean navAllowedHidden, 4156 boolean statusBarExpandedNotKeyguard) { 4157 if (mNavigationBar != null) { 4158 boolean transientNavBarShowing = mNavigationBarController.isTransientShowing(); 4159 // Force the navigation bar to its appropriate place and 4160 // size. We need to do this directly, instead of relying on 4161 // it to bubble up from the nav bar, because this needs to 4162 // change atomically with screen rotations. 4163 mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight, 4164 displayRotation); 4165 if (mNavigationBarPosition == NAV_BAR_BOTTOM) { 4166 // It's a system nav bar or a portrait screen; nav bar goes on bottom. 4167 int top = displayHeight - overscanBottom 4168 - getNavigationBarHeight(displayRotation, uiMode); 4169 mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom); 4170 mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top; 4171 if (transientNavBarShowing) { 4172 mNavigationBarController.setBarShowingLw(true); 4173 } else if (navVisible) { 4174 mNavigationBarController.setBarShowingLw(true); 4175 mDockBottom = mTmpNavigationFrame.top; 4176 mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop; 4177 mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop; 4178 } else { 4179 // We currently want to hide the navigation UI - unless we expanded the status 4180 // bar. 4181 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); 4182 } 4183 if (navVisible && !navTranslucent && !navAllowedHidden 4184 && !mNavigationBar.isAnimatingLw() 4185 && !mNavigationBarController.wasRecentlyTranslucent()) { 4186 // If the opaque nav bar is currently requested to be visible, 4187 // and not in the process of animating on or off, then 4188 // we can tell the app that it is covered by it. 4189 mSystemBottom = mTmpNavigationFrame.top; 4190 } 4191 } else if (mNavigationBarPosition == NAV_BAR_RIGHT) { 4192 // Landscape screen; nav bar goes to the right. 4193 int left = displayWidth - overscanRight 4194 - getNavigationBarWidth(displayRotation, uiMode); 4195 mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight); 4196 mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left; 4197 if (transientNavBarShowing) { 4198 mNavigationBarController.setBarShowingLw(true); 4199 } else if (navVisible) { 4200 mNavigationBarController.setBarShowingLw(true); 4201 mDockRight = mTmpNavigationFrame.left; 4202 mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft; 4203 mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft; 4204 } else { 4205 // We currently want to hide the navigation UI - unless we expanded the status 4206 // bar. 4207 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); 4208 } 4209 if (navVisible && !navTranslucent && !navAllowedHidden 4210 && !mNavigationBar.isAnimatingLw() 4211 && !mNavigationBarController.wasRecentlyTranslucent()) { 4212 // If the nav bar is currently requested to be visible, 4213 // and not in the process of animating on or off, then 4214 // we can tell the app that it is covered by it. 4215 mSystemRight = mTmpNavigationFrame.left; 4216 } 4217 } else if (mNavigationBarPosition == NAV_BAR_LEFT) { 4218 // Seascape screen; nav bar goes to the left. 4219 int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode); 4220 mTmpNavigationFrame.set(overscanLeft, 0, right, displayHeight); 4221 mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right; 4222 if (transientNavBarShowing) { 4223 mNavigationBarController.setBarShowingLw(true); 4224 } else if (navVisible) { 4225 mNavigationBarController.setBarShowingLw(true); 4226 mDockLeft = mTmpNavigationFrame.right; 4227 // TODO: not so sure about those: 4228 mRestrictedScreenLeft = mRestrictedOverscanScreenLeft = mDockLeft; 4229 mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft; 4230 mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft; 4231 } else { 4232 // We currently want to hide the navigation UI - unless we expanded the status 4233 // bar. 4234 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); 4235 } 4236 if (navVisible && !navTranslucent && !navAllowedHidden 4237 && !mNavigationBar.isAnimatingLw() 4238 && !mNavigationBarController.wasRecentlyTranslucent()) { 4239 // If the nav bar is currently requested to be visible, 4240 // and not in the process of animating on or off, then 4241 // we can tell the app that it is covered by it. 4242 mSystemLeft = mTmpNavigationFrame.right; 4243 } 4244 } 4245 // Make sure the content and current rectangles are updated to 4246 // account for the restrictions from the navigation bar. 4247 mContentTop = mVoiceContentTop = mCurTop = mDockTop; 4248 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom; 4249 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft; 4250 mContentRight = mVoiceContentRight = mCurRight = mDockRight; 4251 mStatusBarLayer = mNavigationBar.getSurfaceLayer(); 4252 // And compute the final frame. 4253 mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame, 4254 mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf, 4255 mTmpNavigationFrame, mTmpNavigationFrame); 4256 if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame); 4257 if (mNavigationBarController.checkHiddenLw()) { 4258 return true; 4259 } 4260 } 4261 return false; 4262 } 4263 4264 private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) { 4265 if (mNavigationBarCanMove && displayWidth > displayHeight) { 4266 if (displayRotation == Surface.ROTATION_270) { 4267 return NAV_BAR_LEFT; 4268 } else { 4269 return NAV_BAR_RIGHT; 4270 } 4271 } 4272 return NAV_BAR_BOTTOM; 4273 } 4274 4275 /** {@inheritDoc} */ 4276 @Override 4277 public int getSystemDecorLayerLw() { 4278 if (mStatusBar != null && mStatusBar.isVisibleLw()) { 4279 return mStatusBar.getSurfaceLayer(); 4280 } 4281 4282 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) { 4283 return mNavigationBar.getSurfaceLayer(); 4284 } 4285 4286 return 0; 4287 } 4288 4289 @Override 4290 public void getContentRectLw(Rect r) { 4291 r.set(mContentLeft, mContentTop, mContentRight, mContentBottom); 4292 } 4293 4294 void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached, 4295 boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) { 4296 if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) { 4297 // Here's a special case: if this attached window is a panel that is 4298 // above the dock window, and the window it is attached to is below 4299 // the dock window, then the frames we computed for the window it is 4300 // attached to can not be used because the dock is effectively part 4301 // of the underlying window and the attached window is floating on top 4302 // of the whole thing. So, we ignore the attached window and explicitly 4303 // compute the frames that would be appropriate without the dock. 4304 df.left = of.left = cf.left = vf.left = mDockLeft; 4305 df.top = of.top = cf.top = vf.top = mDockTop; 4306 df.right = of.right = cf.right = vf.right = mDockRight; 4307 df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom; 4308 } else { 4309 // The effective display frame of the attached window depends on 4310 // whether it is taking care of insetting its content. If not, 4311 // we need to use the parent's content frame so that the entire 4312 // window is positioned within that content. Otherwise we can use 4313 // the overscan frame and let the attached window take care of 4314 // positioning its content appropriately. 4315 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4316 // Set the content frame of the attached window to the parent's decor frame 4317 // (same as content frame when IME isn't present) if specifically requested by 4318 // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag. 4319 // Otherwise, use the overscan frame. 4320 cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0 4321 ? attached.getContentFrameLw() : attached.getOverscanFrameLw()); 4322 } else { 4323 // If the window is resizing, then we want to base the content 4324 // frame on our attached content frame to resize... however, 4325 // things can be tricky if the attached window is NOT in resize 4326 // mode, in which case its content frame will be larger. 4327 // Ungh. So to deal with that, make sure the content frame 4328 // we end up using is not covering the IM dock. 4329 cf.set(attached.getContentFrameLw()); 4330 if (attached.isVoiceInteraction()) { 4331 if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft; 4332 if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop; 4333 if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight; 4334 if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom; 4335 } else if (attached.getSurfaceLayer() < mDockLayer) { 4336 if (cf.left < mContentLeft) cf.left = mContentLeft; 4337 if (cf.top < mContentTop) cf.top = mContentTop; 4338 if (cf.right > mContentRight) cf.right = mContentRight; 4339 if (cf.bottom > mContentBottom) cf.bottom = mContentBottom; 4340 } 4341 } 4342 df.set(insetDecors ? attached.getDisplayFrameLw() : cf); 4343 of.set(insetDecors ? attached.getOverscanFrameLw() : cf); 4344 vf.set(attached.getVisibleFrameLw()); 4345 } 4346 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached 4347 // window should be positioned relative to its parent or the entire 4348 // screen. 4349 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 4350 ? attached.getFrameLw() : df); 4351 } 4352 4353 private void applyStableConstraints(int sysui, int fl, Rect r) { 4354 if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) { 4355 // If app is requesting a stable layout, don't let the 4356 // content insets go below the stable values. 4357 if ((fl & FLAG_FULLSCREEN) != 0) { 4358 if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft; 4359 if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop; 4360 if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight; 4361 if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom; 4362 } else { 4363 if (r.left < mStableLeft) r.left = mStableLeft; 4364 if (r.top < mStableTop) r.top = mStableTop; 4365 if (r.right > mStableRight) r.right = mStableRight; 4366 if (r.bottom > mStableBottom) r.bottom = mStableBottom; 4367 } 4368 } 4369 } 4370 4371 private boolean canReceiveInput(WindowState win) { 4372 boolean notFocusable = 4373 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0; 4374 boolean altFocusableIm = 4375 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0; 4376 boolean notFocusableForIm = notFocusable ^ altFocusableIm; 4377 return !notFocusableForIm; 4378 } 4379 4380 /** {@inheritDoc} */ 4381 @Override 4382 public void layoutWindowLw(WindowState win, WindowState attached) { 4383 // We've already done the navigation bar and status bar. If the status bar can receive 4384 // input, we need to layout it again to accomodate for the IME window. 4385 if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) { 4386 return; 4387 } 4388 final WindowManager.LayoutParams attrs = win.getAttrs(); 4389 final boolean isDefaultDisplay = win.isDefaultDisplay(); 4390 final boolean needsToOffsetInputMethodTarget = isDefaultDisplay && 4391 (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null); 4392 if (needsToOffsetInputMethodTarget) { 4393 if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state"); 4394 offsetInputMethodWindowLw(mLastInputMethodWindow); 4395 } 4396 4397 final int fl = PolicyControl.getWindowFlags(win, attrs); 4398 final int pfl = attrs.privateFlags; 4399 final int sim = attrs.softInputMode; 4400 final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null); 4401 4402 final Rect pf = mTmpParentFrame; 4403 final Rect df = mTmpDisplayFrame; 4404 final Rect of = mTmpOverscanFrame; 4405 final Rect cf = mTmpContentFrame; 4406 final Rect vf = mTmpVisibleFrame; 4407 final Rect dcf = mTmpDecorFrame; 4408 final Rect sf = mTmpStableFrame; 4409 Rect osf = null; 4410 dcf.setEmpty(); 4411 4412 final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar 4413 && mNavigationBar != null && mNavigationBar.isVisibleLw()); 4414 4415 final int adjust = sim & SOFT_INPUT_MASK_ADJUST; 4416 4417 if (isDefaultDisplay) { 4418 sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom); 4419 } else { 4420 sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom); 4421 } 4422 4423 if (!isDefaultDisplay) { 4424 if (attached != null) { 4425 // If this window is attached to another, our display 4426 // frame is the same as the one we are attached to. 4427 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf); 4428 } else { 4429 // Give the window full screen. 4430 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 4431 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 4432 pf.right = df.right = of.right = cf.right 4433 = mOverscanScreenLeft + mOverscanScreenWidth; 4434 pf.bottom = df.bottom = of.bottom = cf.bottom 4435 = mOverscanScreenTop + mOverscanScreenHeight; 4436 } 4437 } else if (attrs.type == TYPE_INPUT_METHOD) { 4438 pf.left = df.left = of.left = cf.left = vf.left = mDockLeft; 4439 pf.top = df.top = of.top = cf.top = vf.top = mDockTop; 4440 pf.right = df.right = of.right = cf.right = vf.right = mDockRight; 4441 // IM dock windows layout below the nav bar... 4442 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4443 // ...with content insets above the nav bar 4444 cf.bottom = vf.bottom = mStableBottom; 4445 if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) { 4446 // The status bar forces the navigation bar while it's visible. Make sure the IME 4447 // avoids the navigation bar in that case. 4448 if (mNavigationBarPosition == NAV_BAR_RIGHT) { 4449 pf.right = df.right = of.right = cf.right = vf.right = mStableRight; 4450 } else if (mNavigationBarPosition == NAV_BAR_LEFT) { 4451 pf.left = df.left = of.left = cf.left = vf.left = mStableLeft; 4452 } 4453 } 4454 // IM dock windows always go to the bottom of the screen. 4455 attrs.gravity = Gravity.BOTTOM; 4456 mDockLayer = win.getSurfaceLayer(); 4457 } else if (attrs.type == TYPE_VOICE_INTERACTION) { 4458 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4459 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4460 pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4461 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4462 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4463 cf.left = mDockLeft; 4464 cf.top = mDockTop; 4465 cf.right = mDockRight; 4466 cf.bottom = mDockBottom; 4467 } else { 4468 cf.left = mContentLeft; 4469 cf.top = mContentTop; 4470 cf.right = mContentRight; 4471 cf.bottom = mContentBottom; 4472 } 4473 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 4474 vf.left = mCurLeft; 4475 vf.top = mCurTop; 4476 vf.right = mCurRight; 4477 vf.bottom = mCurBottom; 4478 } else { 4479 vf.set(cf); 4480 } 4481 } else if (attrs.type == TYPE_WALLPAPER) { 4482 layoutWallpaper(win, pf, df, of, cf); 4483 } else if (win == mStatusBar) { 4484 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4485 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4486 pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft; 4487 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop; 4488 cf.left = vf.left = mStableLeft; 4489 cf.top = vf.top = mStableTop; 4490 cf.right = vf.right = mStableRight; 4491 vf.bottom = mStableBottom; 4492 4493 if (adjust == SOFT_INPUT_ADJUST_RESIZE) { 4494 cf.bottom = mContentBottom; 4495 } else { 4496 cf.bottom = mDockBottom; 4497 vf.bottom = mContentBottom; 4498 } 4499 } else { 4500 4501 // Default policy decor for the default display 4502 dcf.left = mSystemLeft; 4503 dcf.top = mSystemTop; 4504 dcf.right = mSystemRight; 4505 dcf.bottom = mSystemBottom; 4506 final boolean inheritTranslucentDecor = (attrs.privateFlags 4507 & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0; 4508 final boolean isAppWindow = 4509 attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW && 4510 attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; 4511 final boolean topAtRest = 4512 win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw(); 4513 if (isAppWindow && !inheritTranslucentDecor && !topAtRest) { 4514 if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0 4515 && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0 4516 && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0 4517 && (fl & WindowManager.LayoutParams. 4518 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0 4519 && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) { 4520 // Ensure policy decor includes status bar 4521 dcf.top = mStableTop; 4522 } 4523 if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0 4524 && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0 4525 && (fl & WindowManager.LayoutParams. 4526 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) { 4527 // Ensure policy decor includes navigation bar 4528 dcf.bottom = mStableBottom; 4529 dcf.right = mStableRight; 4530 } 4531 } 4532 4533 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) 4534 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { 4535 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() 4536 + "): IN_SCREEN, INSET_DECOR"); 4537 // This is the case for a normal activity window: we want it 4538 // to cover all of the screen space, and it can take care of 4539 // moving its contents to account for screen decorations that 4540 // intrude into that space. 4541 if (attached != null) { 4542 // If this window is attached to another, our display 4543 // frame is the same as the one we are attached to. 4544 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf); 4545 } else { 4546 if (attrs.type == TYPE_STATUS_BAR_PANEL 4547 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) { 4548 // Status bar panels are the only windows who can go on top of 4549 // the status bar. They are protected by the STATUS_BAR_SERVICE 4550 // permission, so they have the same privileges as the status 4551 // bar itself. 4552 // 4553 // However, they should still dodge the navigation bar if it exists. 4554 4555 pf.left = df.left = of.left = hasNavBar 4556 ? mDockLeft : mUnrestrictedScreenLeft; 4557 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4558 pf.right = df.right = of.right = hasNavBar 4559 ? mRestrictedScreenLeft+mRestrictedScreenWidth 4560 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4561 pf.bottom = df.bottom = of.bottom = hasNavBar 4562 ? mRestrictedScreenTop+mRestrictedScreenHeight 4563 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4564 4565 if (DEBUG_LAYOUT) Slog.v(TAG, String.format( 4566 "Laying out status bar window: (%d,%d - %d,%d)", 4567 pf.left, pf.top, pf.right, pf.bottom)); 4568 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0 4569 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 4570 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 4571 // Asking to layout into the overscan region, so give it that pure 4572 // unrestricted area. 4573 pf.left = df.left = of.left = mOverscanScreenLeft; 4574 pf.top = df.top = of.top = mOverscanScreenTop; 4575 pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth; 4576 pf.bottom = df.bottom = of.bottom = mOverscanScreenTop 4577 + mOverscanScreenHeight; 4578 } else if (canHideNavigationBar() 4579 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 4580 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 4581 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 4582 // Asking for layout as if the nav bar is hidden, lets the 4583 // application extend into the unrestricted overscan screen area. We 4584 // only do this for application windows to ensure no window that 4585 // can be above the nav bar can do this. 4586 pf.left = df.left = mOverscanScreenLeft; 4587 pf.top = df.top = mOverscanScreenTop; 4588 pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth; 4589 pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight; 4590 // We need to tell the app about where the frame inside the overscan 4591 // is, so it can inset its content by that amount -- it didn't ask 4592 // to actually extend itself into the overscan region. 4593 of.left = mUnrestrictedScreenLeft; 4594 of.top = mUnrestrictedScreenTop; 4595 of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4596 of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4597 } else { 4598 pf.left = df.left = mRestrictedOverscanScreenLeft; 4599 pf.top = df.top = mRestrictedOverscanScreenTop; 4600 pf.right = df.right = mRestrictedOverscanScreenLeft 4601 + mRestrictedOverscanScreenWidth; 4602 pf.bottom = df.bottom = mRestrictedOverscanScreenTop 4603 + mRestrictedOverscanScreenHeight; 4604 // We need to tell the app about where the frame inside the overscan 4605 // is, so it can inset its content by that amount -- it didn't ask 4606 // to actually extend itself into the overscan region. 4607 of.left = mUnrestrictedScreenLeft; 4608 of.top = mUnrestrictedScreenTop; 4609 of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4610 of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4611 } 4612 4613 if ((fl & FLAG_FULLSCREEN) == 0) { 4614 if (win.isVoiceInteraction()) { 4615 cf.left = mVoiceContentLeft; 4616 cf.top = mVoiceContentTop; 4617 cf.right = mVoiceContentRight; 4618 cf.bottom = mVoiceContentBottom; 4619 } else { 4620 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4621 cf.left = mDockLeft; 4622 cf.top = mDockTop; 4623 cf.right = mDockRight; 4624 cf.bottom = mDockBottom; 4625 } else { 4626 cf.left = mContentLeft; 4627 cf.top = mContentTop; 4628 cf.right = mContentRight; 4629 cf.bottom = mContentBottom; 4630 } 4631 } 4632 } else { 4633 // Full screen windows are always given a layout that is as if the 4634 // status bar and other transient decors are gone. This is to avoid 4635 // bad states when moving from a window that is not hding the 4636 // status bar to one that is. 4637 cf.left = mRestrictedScreenLeft; 4638 cf.top = mRestrictedScreenTop; 4639 cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth; 4640 cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight; 4641 } 4642 applyStableConstraints(sysUiFl, fl, cf); 4643 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 4644 vf.left = mCurLeft; 4645 vf.top = mCurTop; 4646 vf.right = mCurRight; 4647 vf.bottom = mCurBottom; 4648 } else { 4649 vf.set(cf); 4650 } 4651 } 4652 } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl 4653 & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 4654 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) { 4655 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + 4656 "): IN_SCREEN"); 4657 // A window that has requested to fill the entire screen just 4658 // gets everything, period. 4659 if (attrs.type == TYPE_STATUS_BAR_PANEL 4660 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL 4661 || attrs.type == TYPE_VOLUME_OVERLAY) { 4662 pf.left = df.left = of.left = cf.left = hasNavBar 4663 ? mDockLeft : mUnrestrictedScreenLeft; 4664 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop; 4665 pf.right = df.right = of.right = cf.right = hasNavBar 4666 ? mRestrictedScreenLeft+mRestrictedScreenWidth 4667 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4668 pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar 4669 ? mRestrictedScreenTop+mRestrictedScreenHeight 4670 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4671 if (DEBUG_LAYOUT) Slog.v(TAG, String.format( 4672 "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)", 4673 pf.left, pf.top, pf.right, pf.bottom)); 4674 } else if (attrs.type == TYPE_NAVIGATION_BAR 4675 || attrs.type == TYPE_NAVIGATION_BAR_PANEL) { 4676 // The navigation bar has Real Ultimate Power. 4677 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4678 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4679 pf.right = df.right = of.right = mUnrestrictedScreenLeft 4680 + mUnrestrictedScreenWidth; 4681 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop 4682 + mUnrestrictedScreenHeight; 4683 if (DEBUG_LAYOUT) Slog.v(TAG, String.format( 4684 "Laying out navigation bar window: (%d,%d - %d,%d)", 4685 pf.left, pf.top, pf.right, pf.bottom)); 4686 } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY 4687 || attrs.type == TYPE_BOOT_PROGRESS 4688 || attrs.type == TYPE_SCREENSHOT) 4689 && ((fl & FLAG_FULLSCREEN) != 0)) { 4690 // Fullscreen secure system overlays get what they ask for. Screenshot region 4691 // selection overlay should also expand to full screen. 4692 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 4693 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 4694 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft 4695 + mOverscanScreenWidth; 4696 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop 4697 + mOverscanScreenHeight; 4698 } else if (attrs.type == TYPE_BOOT_PROGRESS) { 4699 // Boot progress screen always covers entire display. 4700 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 4701 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 4702 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft 4703 + mOverscanScreenWidth; 4704 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop 4705 + mOverscanScreenHeight; 4706 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0 4707 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 4708 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 4709 // Asking to layout into the overscan region, so give it that pure 4710 // unrestricted area. 4711 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 4712 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 4713 pf.right = df.right = of.right = cf.right 4714 = mOverscanScreenLeft + mOverscanScreenWidth; 4715 pf.bottom = df.bottom = of.bottom = cf.bottom 4716 = mOverscanScreenTop + mOverscanScreenHeight; 4717 } else if (canHideNavigationBar() 4718 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 4719 && (attrs.type == TYPE_STATUS_BAR 4720 || attrs.type == TYPE_TOAST 4721 || attrs.type == TYPE_DOCK_DIVIDER 4722 || attrs.type == TYPE_VOICE_INTERACTION_STARTING 4723 || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 4724 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) { 4725 // Asking for layout as if the nav bar is hidden, lets the 4726 // application extend into the unrestricted screen area. We 4727 // only do this for application windows (or toasts) to ensure no window that 4728 // can be above the nav bar can do this. 4729 // XXX This assumes that an app asking for this will also 4730 // ask for layout in only content. We can't currently figure out 4731 // what the screen would be if only laying out to hide the nav bar. 4732 pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft; 4733 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop; 4734 pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft 4735 + mUnrestrictedScreenWidth; 4736 pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop 4737 + mUnrestrictedScreenHeight; 4738 } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) { 4739 pf.left = df.left = of.left = mRestrictedScreenLeft; 4740 pf.top = df.top = of.top = mRestrictedScreenTop; 4741 pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth; 4742 pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop 4743 + mRestrictedScreenHeight; 4744 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4745 cf.left = mDockLeft; 4746 cf.top = mDockTop; 4747 cf.right = mDockRight; 4748 cf.bottom = mDockBottom; 4749 } else { 4750 cf.left = mContentLeft; 4751 cf.top = mContentTop; 4752 cf.right = mContentRight; 4753 cf.bottom = mContentBottom; 4754 } 4755 } else { 4756 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft; 4757 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop; 4758 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft 4759 + mRestrictedScreenWidth; 4760 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop 4761 + mRestrictedScreenHeight; 4762 } 4763 4764 applyStableConstraints(sysUiFl, fl, cf); 4765 4766 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 4767 vf.left = mCurLeft; 4768 vf.top = mCurTop; 4769 vf.right = mCurRight; 4770 vf.bottom = mCurBottom; 4771 } else { 4772 vf.set(cf); 4773 } 4774 } else if (attached != null) { 4775 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + 4776 "): attached to " + attached); 4777 // A child window should be placed inside of the same visible 4778 // frame that its parent had. 4779 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf); 4780 } else { 4781 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + 4782 "): normal window"); 4783 // Otherwise, a normal window must be placed inside the content 4784 // of all screen decorations. 4785 if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) { 4786 // Status bar panels and the volume dialog are the only windows who can go on 4787 // top of the status bar. They are protected by the STATUS_BAR_SERVICE 4788 // permission, so they have the same privileges as the status 4789 // bar itself. 4790 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft; 4791 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop; 4792 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft 4793 + mRestrictedScreenWidth; 4794 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop 4795 + mRestrictedScreenHeight; 4796 } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) { 4797 // These dialogs are stable to interim decor changes. 4798 pf.left = df.left = of.left = cf.left = mStableLeft; 4799 pf.top = df.top = of.top = cf.top = mStableTop; 4800 pf.right = df.right = of.right = cf.right = mStableRight; 4801 pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom; 4802 } else { 4803 pf.left = mContentLeft; 4804 pf.top = mContentTop; 4805 pf.right = mContentRight; 4806 pf.bottom = mContentBottom; 4807 if (win.isVoiceInteraction()) { 4808 df.left = of.left = cf.left = mVoiceContentLeft; 4809 df.top = of.top = cf.top = mVoiceContentTop; 4810 df.right = of.right = cf.right = mVoiceContentRight; 4811 df.bottom = of.bottom = cf.bottom = mVoiceContentBottom; 4812 } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4813 df.left = of.left = cf.left = mDockLeft; 4814 df.top = of.top = cf.top = mDockTop; 4815 df.right = of.right = cf.right = mDockRight; 4816 df.bottom = of.bottom = cf.bottom = mDockBottom; 4817 } else { 4818 df.left = of.left = cf.left = mContentLeft; 4819 df.top = of.top = cf.top = mContentTop; 4820 df.right = of.right = cf.right = mContentRight; 4821 df.bottom = of.bottom = cf.bottom = mContentBottom; 4822 } 4823 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 4824 vf.left = mCurLeft; 4825 vf.top = mCurTop; 4826 vf.right = mCurRight; 4827 vf.bottom = mCurBottom; 4828 } else { 4829 vf.set(cf); 4830 } 4831 } 4832 } 4833 } 4834 4835 // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it. 4836 // Also, we don't allow windows in multi-window mode to extend out of the screen. 4837 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR 4838 && !win.isInMultiWindowMode()) { 4839 df.left = df.top = -10000; 4840 df.right = df.bottom = 10000; 4841 if (attrs.type != TYPE_WALLPAPER) { 4842 of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000; 4843 of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000; 4844 } 4845 } 4846 4847 // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we 4848 // need to provide information to the clients that want to pretend that you can draw there. 4849 // We only want to apply outsets to certain types of windows. For example, we never want to 4850 // apply the outsets to floating dialogs, because they wouldn't make sense there. 4851 final boolean useOutsets = shouldUseOutsets(attrs, fl); 4852 if (isDefaultDisplay && useOutsets) { 4853 osf = mTmpOutsetFrame; 4854 osf.set(cf.left, cf.top, cf.right, cf.bottom); 4855 int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources()); 4856 if (outset > 0) { 4857 int rotation = mDisplayRotation; 4858 if (rotation == Surface.ROTATION_0) { 4859 osf.bottom += outset; 4860 } else if (rotation == Surface.ROTATION_90) { 4861 osf.right += outset; 4862 } else if (rotation == Surface.ROTATION_180) { 4863 osf.top -= outset; 4864 } else if (rotation == Surface.ROTATION_270) { 4865 osf.left -= outset; 4866 } 4867 if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset 4868 + " with rotation " + rotation + ", result: " + osf); 4869 } 4870 } 4871 4872 if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle() 4873 + ": sim=#" + Integer.toHexString(sim) 4874 + " attach=" + attached + " type=" + attrs.type 4875 + String.format(" flags=0x%08x", fl) 4876 + " pf=" + pf.toShortString() + " df=" + df.toShortString() 4877 + " of=" + of.toShortString() 4878 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString() 4879 + " dcf=" + dcf.toShortString() 4880 + " sf=" + sf.toShortString() 4881 + " osf=" + (osf == null ? "null" : osf.toShortString())); 4882 4883 win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf); 4884 4885 // Dock windows carve out the bottom of the screen, so normal windows 4886 // can't appear underneath them. 4887 if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleOrBehindKeyguardLw() 4888 && win.isDisplayedLw() && !win.getGivenInsetsPendingLw()) { 4889 setLastInputMethodWindowLw(null, null); 4890 offsetInputMethodWindowLw(win); 4891 } 4892 if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleOrBehindKeyguardLw() 4893 && !win.getGivenInsetsPendingLw()) { 4894 offsetVoiceInputWindowLw(win); 4895 } 4896 } 4897 4898 private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) { 4899 4900 // The wallpaper also has Real Ultimate Power, but we want to tell 4901 // it about the overscan area. 4902 pf.left = df.left = mOverscanScreenLeft; 4903 pf.top = df.top = mOverscanScreenTop; 4904 pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth; 4905 pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight; 4906 of.left = cf.left = mUnrestrictedScreenLeft; 4907 of.top = cf.top = mUnrestrictedScreenTop; 4908 of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4909 of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4910 } 4911 4912 private void offsetInputMethodWindowLw(WindowState win) { 4913 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top); 4914 top += win.getGivenContentInsetsLw().top; 4915 if (mContentBottom > top) { 4916 mContentBottom = top; 4917 } 4918 if (mVoiceContentBottom > top) { 4919 mVoiceContentBottom = top; 4920 } 4921 top = win.getVisibleFrameLw().top; 4922 top += win.getGivenVisibleInsetsLw().top; 4923 if (mCurBottom > top) { 4924 mCurBottom = top; 4925 } 4926 if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom=" 4927 + mDockBottom + " mContentBottom=" 4928 + mContentBottom + " mCurBottom=" + mCurBottom); 4929 } 4930 4931 private void offsetVoiceInputWindowLw(WindowState win) { 4932 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top); 4933 top += win.getGivenContentInsetsLw().top; 4934 if (mVoiceContentBottom > top) { 4935 mVoiceContentBottom = top; 4936 } 4937 } 4938 4939 /** {@inheritDoc} */ 4940 @Override 4941 public void finishLayoutLw() { 4942 return; 4943 } 4944 4945 /** {@inheritDoc} */ 4946 @Override 4947 public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) { 4948 mTopFullscreenOpaqueWindowState = null; 4949 mTopFullscreenOpaqueOrDimmingWindowState = null; 4950 mTopDockedOpaqueWindowState = null; 4951 mTopDockedOpaqueOrDimmingWindowState = null; 4952 mAppsToBeHidden.clear(); 4953 mAppsThatDismissKeyguard.clear(); 4954 mForceStatusBar = false; 4955 mForceStatusBarFromKeyguard = false; 4956 mForceStatusBarTransparent = false; 4957 mForcingShowNavBar = false; 4958 mForcingShowNavBarLayer = -1; 4959 4960 mHideLockScreen = false; 4961 mAllowLockscreenWhenOn = false; 4962 mDismissKeyguard = DISMISS_KEYGUARD_NONE; 4963 mShowingLockscreen = false; 4964 mShowingDream = false; 4965 mWinShowWhenLocked = null; 4966 mKeyguardSecure = isKeyguardSecure(mCurrentUserId); 4967 mKeyguardSecureIncludingHidden = mKeyguardSecure 4968 && (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()); 4969 } 4970 4971 /** {@inheritDoc} */ 4972 @Override 4973 public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs, 4974 WindowState attached) { 4975 if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw=" 4976 + win.isVisibleOrBehindKeyguardLw()); 4977 final int fl = PolicyControl.getWindowFlags(win, attrs); 4978 if (mTopFullscreenOpaqueWindowState == null 4979 && win.isVisibleLw() && attrs.type == TYPE_INPUT_METHOD) { 4980 mForcingShowNavBar = true; 4981 mForcingShowNavBarLayer = win.getSurfaceLayer(); 4982 } 4983 if (attrs.type == TYPE_STATUS_BAR) { 4984 if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 4985 mForceStatusBarFromKeyguard = true; 4986 mShowingLockscreen = true; 4987 } 4988 if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) { 4989 mForceStatusBarTransparent = true; 4990 } 4991 } 4992 4993 boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW 4994 && attrs.type < FIRST_SYSTEM_WINDOW; 4995 final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0; 4996 final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0; 4997 final int stackId = win.getStackId(); 4998 if (mTopFullscreenOpaqueWindowState == null && 4999 win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) { 5000 if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) { 5001 if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 5002 mForceStatusBarFromKeyguard = true; 5003 } else { 5004 mForceStatusBar = true; 5005 } 5006 } 5007 if (attrs.type == TYPE_DREAM) { 5008 // If the lockscreen was showing when the dream started then wait 5009 // for the dream to draw before hiding the lockscreen. 5010 if (!mDreamingLockscreen 5011 || (win.isVisibleLw() && win.hasDrawnLw())) { 5012 mShowingDream = true; 5013 appWindow = true; 5014 } 5015 } 5016 5017 final IApplicationToken appToken = win.getAppToken(); 5018 5019 // For app windows that are not attached, we decide if all windows in the app they 5020 // represent should be hidden or if we should hide the lockscreen. For attached app 5021 // windows we defer the decision to the window it is attached to. 5022 if (appWindow && attached == null) { 5023 if (showWhenLocked) { 5024 // Remove any previous windows with the same appToken. 5025 mAppsToBeHidden.remove(appToken); 5026 mAppsThatDismissKeyguard.remove(appToken); 5027 if (mAppsToBeHidden.isEmpty()) { 5028 if (dismissKeyguard && !mKeyguardSecure) { 5029 mAppsThatDismissKeyguard.add(appToken); 5030 } else if (win.isDrawnLw() || win.hasAppShownWindows()) { 5031 mWinShowWhenLocked = win; 5032 mHideLockScreen = true; 5033 mForceStatusBarFromKeyguard = false; 5034 } 5035 } 5036 } else if (dismissKeyguard) { 5037 if (mKeyguardSecure) { 5038 mAppsToBeHidden.add(appToken); 5039 } else { 5040 mAppsToBeHidden.remove(appToken); 5041 } 5042 mAppsThatDismissKeyguard.add(appToken); 5043 } else { 5044 mAppsToBeHidden.add(appToken); 5045 } 5046 if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) { 5047 if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win); 5048 mTopFullscreenOpaqueWindowState = win; 5049 if (mTopFullscreenOpaqueOrDimmingWindowState == null) { 5050 mTopFullscreenOpaqueOrDimmingWindowState = win; 5051 } 5052 if (!mAppsThatDismissKeyguard.isEmpty() && 5053 mDismissKeyguard == DISMISS_KEYGUARD_NONE) { 5054 if (DEBUG_LAYOUT) Slog.v(TAG, 5055 "Setting mDismissKeyguard true by win " + win); 5056 mDismissKeyguard = (mWinDismissingKeyguard == win 5057 && mSecureDismissingKeyguard == mKeyguardSecure) 5058 ? DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START; 5059 mWinDismissingKeyguard = win; 5060 mSecureDismissingKeyguard = mKeyguardSecure; 5061 mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure; 5062 } else if (mAppsToBeHidden.isEmpty() && showWhenLocked 5063 && (win.isDrawnLw() || win.hasAppShownWindows())) { 5064 if (DEBUG_LAYOUT) Slog.v(TAG, 5065 "Setting mHideLockScreen to true by win " + win); 5066 mHideLockScreen = true; 5067 mForceStatusBarFromKeyguard = false; 5068 } 5069 if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) { 5070 mAllowLockscreenWhenOn = true; 5071 } 5072 } 5073 5074 if (!mKeyguardHidden && mWinShowWhenLocked != null && 5075 mWinShowWhenLocked.getAppToken() != win.getAppToken() && 5076 (attrs.flags & FLAG_SHOW_WHEN_LOCKED) == 0) { 5077 win.hideLw(false); 5078 } 5079 } 5080 } else if (mTopFullscreenOpaqueWindowState == null && mWinShowWhenLocked == null) { 5081 // No TopFullscreenOpaqueWindow is showing, but we found a SHOW_WHEN_LOCKED window 5082 // that is being hidden in an animation - keep the 5083 // keyguard hidden until the new window shows up and 5084 // we know whether to show the keyguard or not. 5085 if (win.isAnimatingLw() && appWindow && showWhenLocked && mKeyguardHidden) { 5086 mHideLockScreen = true; 5087 mWinShowWhenLocked = win; 5088 } 5089 } 5090 5091 final boolean reallyVisible = win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw(); 5092 5093 // Voice interaction overrides both top fullscreen and top docked. 5094 if (reallyVisible && win.getAttrs().type == TYPE_VOICE_INTERACTION) { 5095 if (mTopFullscreenOpaqueWindowState == null) { 5096 mTopFullscreenOpaqueWindowState = win; 5097 if (mTopFullscreenOpaqueOrDimmingWindowState == null) { 5098 mTopFullscreenOpaqueOrDimmingWindowState = win; 5099 } 5100 } 5101 if (mTopDockedOpaqueWindowState == null) { 5102 mTopDockedOpaqueWindowState = win; 5103 if (mTopDockedOpaqueOrDimmingWindowState == null) { 5104 mTopDockedOpaqueOrDimmingWindowState = win; 5105 } 5106 } 5107 } 5108 5109 // Keep track of the window if it's dimming but not necessarily fullscreen. 5110 if (mTopFullscreenOpaqueOrDimmingWindowState == null && reallyVisible 5111 && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) { 5112 mTopFullscreenOpaqueOrDimmingWindowState = win; 5113 } 5114 5115 // We need to keep track of the top "fullscreen" opaque window for the docked stack 5116 // separately, because both the "real fullscreen" opaque window and the one for the docked 5117 // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR. 5118 if (mTopDockedOpaqueWindowState == null && reallyVisible && appWindow && attached == null 5119 && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) { 5120 mTopDockedOpaqueWindowState = win; 5121 if (mTopDockedOpaqueOrDimmingWindowState == null) { 5122 mTopDockedOpaqueOrDimmingWindowState = win; 5123 } 5124 } 5125 5126 // Also keep track of any windows that are dimming but not necessarily fullscreen in the 5127 // docked stack. 5128 if (mTopDockedOpaqueOrDimmingWindowState == null && reallyVisible && win.isDimming() 5129 && stackId == DOCKED_STACK_ID) { 5130 mTopDockedOpaqueOrDimmingWindowState = win; 5131 } 5132 } 5133 5134 private boolean isFullscreen(WindowManager.LayoutParams attrs) { 5135 return attrs.x == 0 && attrs.y == 0 5136 && attrs.width == WindowManager.LayoutParams.MATCH_PARENT 5137 && attrs.height == WindowManager.LayoutParams.MATCH_PARENT; 5138 } 5139 5140 /** {@inheritDoc} */ 5141 @Override 5142 public int finishPostLayoutPolicyLw() { 5143 if (mWinShowWhenLocked != null && mTopFullscreenOpaqueWindowState != null && 5144 mWinShowWhenLocked.getAppToken() != mTopFullscreenOpaqueWindowState.getAppToken() 5145 && isKeyguardLocked()) { 5146 // A dialog is dismissing the keyguard. Put the wallpaper behind it and hide the 5147 // fullscreen window. 5148 // TODO: Make sure FLAG_SHOW_WALLPAPER is restored when dialog is dismissed. Or not. 5149 mWinShowWhenLocked.getAttrs().flags |= FLAG_SHOW_WALLPAPER; 5150 mTopFullscreenOpaqueWindowState.hideLw(false); 5151 mTopFullscreenOpaqueWindowState = mWinShowWhenLocked; 5152 } 5153 5154 int changes = 0; 5155 boolean topIsFullscreen = false; 5156 5157 final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null) 5158 ? mTopFullscreenOpaqueWindowState.getAttrs() 5159 : null; 5160 5161 // If we are not currently showing a dream then remember the current 5162 // lockscreen state. We will use this to determine whether the dream 5163 // started while the lockscreen was showing and remember this state 5164 // while the dream is showing. 5165 if (!mShowingDream) { 5166 mDreamingLockscreen = mShowingLockscreen; 5167 if (mDreamingSleepTokenNeeded) { 5168 mDreamingSleepTokenNeeded = false; 5169 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget(); 5170 } 5171 } else { 5172 if (!mDreamingSleepTokenNeeded) { 5173 mDreamingSleepTokenNeeded = true; 5174 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget(); 5175 } 5176 } 5177 5178 if (mStatusBar != null) { 5179 if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar 5180 + " forcefkg=" + mForceStatusBarFromKeyguard 5181 + " top=" + mTopFullscreenOpaqueWindowState); 5182 boolean shouldBeTransparent = mForceStatusBarTransparent 5183 && !mForceStatusBar 5184 && !mForceStatusBarFromKeyguard; 5185 if (!shouldBeTransparent) { 5186 mStatusBarController.setShowTransparent(false /* transparent */); 5187 } else if (!mStatusBar.isVisibleLw()) { 5188 mStatusBarController.setShowTransparent(true /* transparent */); 5189 } 5190 5191 WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs(); 5192 boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT 5193 && statusBarAttrs.width == MATCH_PARENT; 5194 if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent 5195 || statusBarExpanded) { 5196 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced"); 5197 if (mStatusBarController.setBarShowingLw(true)) { 5198 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5199 } 5200 // Maintain fullscreen layout until incoming animation is complete. 5201 topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw(); 5202 // Transient status bar on the lockscreen is not allowed 5203 if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) { 5204 mStatusBarController.updateVisibilityLw(false /*transientAllowed*/, 5205 mLastSystemUiFlags, mLastSystemUiFlags); 5206 } 5207 if (statusBarExpanded && mNavigationBar != null) { 5208 if (mNavigationBarController.setBarShowingLw(true)) { 5209 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5210 } 5211 } 5212 } else if (mTopFullscreenOpaqueWindowState != null) { 5213 final int fl = PolicyControl.getWindowFlags(null, lp); 5214 if (localLOGV) { 5215 Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() 5216 + " shown position: " 5217 + mTopFullscreenOpaqueWindowState.getShownPositionLw()); 5218 Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs() 5219 + " lp.flags=0x" + Integer.toHexString(fl)); 5220 } 5221 topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0 5222 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 5223 // The subtle difference between the window for mTopFullscreenOpaqueWindowState 5224 // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window 5225 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the 5226 // case though. 5227 if (mStatusBarController.isTransientShowing()) { 5228 if (mStatusBarController.setBarShowingLw(true)) { 5229 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5230 } 5231 } else if (topIsFullscreen 5232 && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID) 5233 && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) { 5234 if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar"); 5235 if (mStatusBarController.setBarShowingLw(false)) { 5236 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5237 } else { 5238 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding"); 5239 } 5240 } else { 5241 if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen"); 5242 if (mStatusBarController.setBarShowingLw(true)) { 5243 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5244 } 5245 } 5246 } 5247 } 5248 5249 if (mTopIsFullscreen != topIsFullscreen) { 5250 if (!topIsFullscreen) { 5251 // Force another layout when status bar becomes fully shown. 5252 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5253 } 5254 mTopIsFullscreen = topIsFullscreen; 5255 } 5256 5257 // Hide the key guard if a visible window explicitly specifies that it wants to be 5258 // displayed when the screen is locked. 5259 if (mKeyguardDelegate != null && mStatusBar != null) { 5260 if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard=" 5261 + mHideLockScreen); 5262 if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardSecure) { 5263 mKeyguardHidden = true; 5264 if (setKeyguardOccludedLw(true)) { 5265 changes |= FINISH_LAYOUT_REDO_LAYOUT 5266 | FINISH_LAYOUT_REDO_CONFIG 5267 | FINISH_LAYOUT_REDO_WALLPAPER; 5268 } 5269 if (mKeyguardDelegate.isShowing()) { 5270 mHandler.post(new Runnable() { 5271 @Override 5272 public void run() { 5273 mKeyguardDelegate.keyguardDone(false, false); 5274 } 5275 }); 5276 } 5277 } else if (mHideLockScreen) { 5278 mKeyguardHidden = true; 5279 mWinDismissingKeyguard = null; 5280 if (setKeyguardOccludedLw(true)) { 5281 changes |= FINISH_LAYOUT_REDO_LAYOUT 5282 | FINISH_LAYOUT_REDO_CONFIG 5283 | FINISH_LAYOUT_REDO_WALLPAPER; 5284 } 5285 } else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) { 5286 mKeyguardHidden = false; 5287 final boolean trusted = mKeyguardDelegate.isTrusted(); 5288 if (trusted) { 5289 // No need to un-occlude keyguard - we'll dimiss it right away anyways. 5290 } else if (setKeyguardOccludedLw(false)) { 5291 changes |= FINISH_LAYOUT_REDO_LAYOUT 5292 | FINISH_LAYOUT_REDO_CONFIG 5293 | FINISH_LAYOUT_REDO_WALLPAPER; 5294 } 5295 if (mDismissKeyguard == DISMISS_KEYGUARD_START) { 5296 // Only launch the next keyguard unlock window once per window. 5297 mHandler.post(new Runnable() { 5298 @Override 5299 public void run() { 5300 mKeyguardDelegate.dismiss(trusted /* allowWhileOccluded */); 5301 } 5302 }); 5303 } 5304 } else { 5305 mWinDismissingKeyguard = null; 5306 mSecureDismissingKeyguard = false; 5307 mKeyguardHidden = false; 5308 if (setKeyguardOccludedLw(false)) { 5309 changes |= FINISH_LAYOUT_REDO_LAYOUT 5310 | FINISH_LAYOUT_REDO_CONFIG 5311 | FINISH_LAYOUT_REDO_WALLPAPER; 5312 } 5313 } 5314 } 5315 5316 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5317 // If the navigation bar has been hidden or shown, we need to do another 5318 // layout pass to update that window. 5319 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5320 } 5321 5322 // update since mAllowLockscreenWhenOn might have changed 5323 updateLockScreenTimeout(); 5324 return changes; 5325 } 5326 5327 /** 5328 * Updates the occluded state of the Keyguard. 5329 * 5330 * @return Whether the flags have changed and we have to redo the layout. 5331 */ 5332 private boolean setKeyguardOccludedLw(boolean isOccluded) { 5333 boolean wasOccluded = mKeyguardOccluded; 5334 boolean showing = mKeyguardDelegate.isShowing(); 5335 if (wasOccluded && !isOccluded && showing) { 5336 mKeyguardOccluded = false; 5337 mKeyguardDelegate.setOccluded(false, true /* animate */); 5338 mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD; 5339 if (!mKeyguardDelegate.hasLockscreenWallpaper()) { 5340 mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER; 5341 } 5342 Animation anim = AnimationUtils.loadAnimation(mContext, 5343 com.android.internal.R.anim.wallpaper_open_exit); 5344 mWindowManagerFuncs.overridePlayingAppAnimationsLw(anim); 5345 return true; 5346 } else if (!wasOccluded && isOccluded && showing) { 5347 mKeyguardOccluded = true; 5348 mKeyguardDelegate.setOccluded(true, false /* animate */); 5349 mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD; 5350 mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER; 5351 return true; 5352 } else { 5353 return false; 5354 } 5355 } 5356 5357 private boolean isStatusBarKeyguard() { 5358 return mStatusBar != null 5359 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0; 5360 } 5361 5362 @Override 5363 public boolean allowAppAnimationsLw() { 5364 if (isStatusBarKeyguard() || mShowingDream) { 5365 // If keyguard or dreams is currently visible, no reason to animate behind it. 5366 return false; 5367 } 5368 return true; 5369 } 5370 5371 @Override 5372 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) { 5373 mFocusedWindow = newFocus; 5374 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5375 // If the navigation bar has been hidden or shown, we need to do another 5376 // layout pass to update that window. 5377 return FINISH_LAYOUT_REDO_LAYOUT; 5378 } 5379 return 0; 5380 } 5381 5382 /** {@inheritDoc} */ 5383 @Override 5384 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { 5385 // lid changed state 5386 final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED; 5387 if (newLidState == mLidState) { 5388 return; 5389 } 5390 5391 mLidState = newLidState; 5392 applyLidSwitchState(); 5393 updateRotation(true); 5394 5395 if (lidOpen) { 5396 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch, 5397 "android.policy:LID"); 5398 } else if (!mLidControlsSleep) { 5399 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 5400 } 5401 } 5402 5403 @Override 5404 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) { 5405 int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED; 5406 if (mCameraLensCoverState == lensCoverState) { 5407 return; 5408 } 5409 if (mCameraLensCoverState == CAMERA_LENS_COVERED && 5410 lensCoverState == CAMERA_LENS_UNCOVERED) { 5411 Intent intent; 5412 final boolean keyguardActive = mKeyguardDelegate == null ? false : 5413 mKeyguardDelegate.isShowing(); 5414 if (keyguardActive) { 5415 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE); 5416 } else { 5417 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); 5418 } 5419 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens, 5420 "android.policy:CAMERA_COVER"); 5421 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); 5422 } 5423 mCameraLensCoverState = lensCoverState; 5424 } 5425 5426 void setHdmiPlugged(boolean plugged) { 5427 if (mHdmiPlugged != plugged) { 5428 mHdmiPlugged = plugged; 5429 updateRotation(true, true); 5430 Intent intent = new Intent(ACTION_HDMI_PLUGGED); 5431 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5432 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged); 5433 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 5434 } 5435 } 5436 5437 void initializeHdmiState() { 5438 boolean plugged = false; 5439 // watch for HDMI plug messages if the hdmi switch exists 5440 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) { 5441 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi"); 5442 5443 final String filename = "/sys/class/switch/hdmi/state"; 5444 FileReader reader = null; 5445 try { 5446 reader = new FileReader(filename); 5447 char[] buf = new char[15]; 5448 int n = reader.read(buf); 5449 if (n > 1) { 5450 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1)); 5451 } 5452 } catch (IOException ex) { 5453 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5454 } catch (NumberFormatException ex) { 5455 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5456 } finally { 5457 if (reader != null) { 5458 try { 5459 reader.close(); 5460 } catch (IOException ex) { 5461 } 5462 } 5463 } 5464 } 5465 // This dance forces the code in setHdmiPlugged to run. 5466 // Always do this so the sticky intent is stuck (to false) if there is no hdmi. 5467 mHdmiPlugged = !plugged; 5468 setHdmiPlugged(!mHdmiPlugged); 5469 } 5470 5471 final Object mScreenshotLock = new Object(); 5472 ServiceConnection mScreenshotConnection = null; 5473 5474 final Runnable mScreenshotTimeout = new Runnable() { 5475 @Override public void run() { 5476 synchronized (mScreenshotLock) { 5477 if (mScreenshotConnection != null) { 5478 mContext.unbindService(mScreenshotConnection); 5479 mScreenshotConnection = null; 5480 notifyScreenshotError(); 5481 } 5482 } 5483 } 5484 }; 5485 5486 // Assume this is called from the Handler thread. 5487 private void takeScreenshot(final int screenshotType) { 5488 synchronized (mScreenshotLock) { 5489 if (mScreenshotConnection != null) { 5490 return; 5491 } 5492 final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE, 5493 SYSUI_SCREENSHOT_SERVICE); 5494 final Intent serviceIntent = new Intent(); 5495 serviceIntent.setComponent(serviceComponent); 5496 ServiceConnection conn = new ServiceConnection() { 5497 @Override 5498 public void onServiceConnected(ComponentName name, IBinder service) { 5499 synchronized (mScreenshotLock) { 5500 if (mScreenshotConnection != this) { 5501 return; 5502 } 5503 Messenger messenger = new Messenger(service); 5504 Message msg = Message.obtain(null, screenshotType); 5505 final ServiceConnection myConn = this; 5506 Handler h = new Handler(mHandler.getLooper()) { 5507 @Override 5508 public void handleMessage(Message msg) { 5509 synchronized (mScreenshotLock) { 5510 if (mScreenshotConnection == myConn) { 5511 mContext.unbindService(mScreenshotConnection); 5512 mScreenshotConnection = null; 5513 mHandler.removeCallbacks(mScreenshotTimeout); 5514 } 5515 } 5516 } 5517 }; 5518 msg.replyTo = new Messenger(h); 5519 msg.arg1 = msg.arg2 = 0; 5520 if (mStatusBar != null && mStatusBar.isVisibleLw()) 5521 msg.arg1 = 1; 5522 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) 5523 msg.arg2 = 1; 5524 try { 5525 messenger.send(msg); 5526 } catch (RemoteException e) { 5527 } 5528 } 5529 } 5530 5531 @Override 5532 public void onServiceDisconnected(ComponentName name) { 5533 notifyScreenshotError(); 5534 } 5535 }; 5536 if (mContext.bindServiceAsUser(serviceIntent, conn, 5537 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, 5538 UserHandle.CURRENT)) { 5539 mScreenshotConnection = conn; 5540 mHandler.postDelayed(mScreenshotTimeout, 10000); 5541 } 5542 } 5543 } 5544 5545 /** 5546 * Notifies the screenshot service to show an error. 5547 */ 5548 private void notifyScreenshotError() { 5549 // If the service process is killed, then ask it to clean up after itself 5550 final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE, 5551 SYSUI_SCREENSHOT_ERROR_RECEIVER); 5552 Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT); 5553 errorIntent.setComponent(errorComponent); 5554 errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | 5555 Intent.FLAG_RECEIVER_FOREGROUND); 5556 mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT); 5557 } 5558 5559 /** {@inheritDoc} */ 5560 @Override 5561 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { 5562 if (!mSystemBooted) { 5563 // If we have not yet booted, don't let key events do anything. 5564 return 0; 5565 } 5566 5567 final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0; 5568 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; 5569 final boolean canceled = event.isCanceled(); 5570 final int keyCode = event.getKeyCode(); 5571 5572 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; 5573 5574 // If screen is off then we treat the case where the keyguard is open but hidden 5575 // the same as if it were open and in front. 5576 // This will prevent any keys other than the power button from waking the screen 5577 // when the keyguard is hidden by another activity. 5578 final boolean keyguardActive = (mKeyguardDelegate == null ? false : 5579 (interactive ? 5580 isKeyguardShowingAndNotOccluded() : 5581 mKeyguardDelegate.isShowing())); 5582 5583 if (DEBUG_INPUT) { 5584 Log.d(TAG, "interceptKeyTq keycode=" + keyCode 5585 + " interactive=" + interactive + " keyguardActive=" + keyguardActive 5586 + " policyFlags=" + Integer.toHexString(policyFlags)); 5587 } 5588 5589 // Basic policy based on interactive state. 5590 int result; 5591 boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0 5592 || event.isWakeKey(); 5593 if (interactive || (isInjected && !isWakeKey)) { 5594 // When the device is interactive or the key is injected pass the 5595 // key to the application. 5596 result = ACTION_PASS_TO_USER; 5597 isWakeKey = false; 5598 5599 if (interactive) { 5600 // If the screen is awake, but the button pressed was the one that woke the device 5601 // then don't pass it to the application 5602 if (keyCode == mPendingWakeKey && !down) { 5603 result = 0; 5604 } 5605 // Reset the pending key 5606 mPendingWakeKey = PENDING_KEY_NULL; 5607 } 5608 } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) { 5609 // If we're currently dozing with the screen on and the keyguard showing, pass the key 5610 // to the application but preserve its wake key status to make sure we still move 5611 // from dozing to fully interactive if we would normally go from off to fully 5612 // interactive. 5613 result = ACTION_PASS_TO_USER; 5614 // Since we're dispatching the input, reset the pending key 5615 mPendingWakeKey = PENDING_KEY_NULL; 5616 } else { 5617 // When the screen is off and the key is not injected, determine whether 5618 // to wake the device but don't pass the key to the application. 5619 result = 0; 5620 if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) { 5621 isWakeKey = false; 5622 } 5623 // Cache the wake key on down event so we can also avoid sending the up event to the app 5624 if (isWakeKey && down) { 5625 mPendingWakeKey = keyCode; 5626 } 5627 } 5628 5629 // If the key would be handled globally, just return the result, don't worry about special 5630 // key processing. 5631 if (isValidGlobalKey(keyCode) 5632 && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) { 5633 if (isWakeKey) { 5634 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 5635 } 5636 return result; 5637 } 5638 5639 boolean useHapticFeedback = down 5640 && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0 5641 && event.getRepeatCount() == 0; 5642 5643 // Handle special keys. 5644 switch (keyCode) { 5645 case KeyEvent.KEYCODE_BACK: { 5646 if (down) { 5647 mBackKeyHandled = false; 5648 if (hasLongPressOnBackBehavior()) { 5649 Message msg = mHandler.obtainMessage(MSG_BACK_LONG_PRESS); 5650 msg.setAsynchronous(true); 5651 mHandler.sendMessageDelayed(msg, 5652 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 5653 } 5654 } else { 5655 boolean handled = mBackKeyHandled; 5656 5657 // Reset back key state 5658 cancelPendingBackKeyAction(); 5659 5660 // Don't pass back press to app if we've already handled it 5661 if (handled) { 5662 result &= ~ACTION_PASS_TO_USER; 5663 } 5664 } 5665 break; 5666 } 5667 5668 case KeyEvent.KEYCODE_VOLUME_DOWN: 5669 case KeyEvent.KEYCODE_VOLUME_UP: 5670 case KeyEvent.KEYCODE_VOLUME_MUTE: { 5671 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { 5672 if (down) { 5673 if (interactive && !mScreenshotChordVolumeDownKeyTriggered 5674 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5675 mScreenshotChordVolumeDownKeyTriggered = true; 5676 mScreenshotChordVolumeDownKeyTime = event.getDownTime(); 5677 mScreenshotChordVolumeDownKeyConsumed = false; 5678 cancelPendingPowerKeyAction(); 5679 interceptScreenshotChord(); 5680 } 5681 } else { 5682 mScreenshotChordVolumeDownKeyTriggered = false; 5683 cancelPendingScreenshotChordAction(); 5684 } 5685 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 5686 if (down) { 5687 if (interactive && !mScreenshotChordVolumeUpKeyTriggered 5688 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5689 mScreenshotChordVolumeUpKeyTriggered = true; 5690 cancelPendingPowerKeyAction(); 5691 cancelPendingScreenshotChordAction(); 5692 } 5693 } else { 5694 mScreenshotChordVolumeUpKeyTriggered = false; 5695 cancelPendingScreenshotChordAction(); 5696 } 5697 } 5698 if (down) { 5699 TelecomManager telecomManager = getTelecommService(); 5700 if (telecomManager != null) { 5701 if (telecomManager.isRinging()) { 5702 // If an incoming call is ringing, either VOLUME key means 5703 // "silence ringer". We handle these keys here, rather than 5704 // in the InCallScreen, to make sure we'll respond to them 5705 // even if the InCallScreen hasn't come to the foreground yet. 5706 // Look for the DOWN event here, to agree with the "fallback" 5707 // behavior in the InCallScreen. 5708 Log.i(TAG, "interceptKeyBeforeQueueing:" 5709 + " VOLUME key-down while ringing: Silence ringer!"); 5710 5711 // Silence the ringer. (It's safe to call this 5712 // even if the ringer has already been silenced.) 5713 telecomManager.silenceRinger(); 5714 5715 // And *don't* pass this key thru to the current activity 5716 // (which is probably the InCallScreen.) 5717 result &= ~ACTION_PASS_TO_USER; 5718 break; 5719 } 5720 if (telecomManager.isInCall() 5721 && (result & ACTION_PASS_TO_USER) == 0) { 5722 // If we are in call but we decided not to pass the key to 5723 // the application, just pass it to the session service. 5724 5725 MediaSessionLegacyHelper.getHelper(mContext) 5726 .sendVolumeKeyEvent(event, false); 5727 break; 5728 } 5729 } 5730 } 5731 if (mUseTvRouting) { 5732 // On TVs, defer special key handlings to 5733 // {@link interceptKeyBeforeDispatching()}. 5734 result |= ACTION_PASS_TO_USER; 5735 } else if ((result & ACTION_PASS_TO_USER) == 0) { 5736 // If we aren't passing to the user and no one else 5737 // handled it send it to the session manager to 5738 // figure out. 5739 MediaSessionLegacyHelper.getHelper(mContext) 5740 .sendVolumeKeyEvent(event, true); 5741 } 5742 break; 5743 } 5744 5745 case KeyEvent.KEYCODE_ENDCALL: { 5746 result &= ~ACTION_PASS_TO_USER; 5747 if (down) { 5748 TelecomManager telecomManager = getTelecommService(); 5749 boolean hungUp = false; 5750 if (telecomManager != null) { 5751 hungUp = telecomManager.endCall(); 5752 } 5753 if (interactive && !hungUp) { 5754 mEndCallKeyHandled = false; 5755 mHandler.postDelayed(mEndCallLongPress, 5756 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 5757 } else { 5758 mEndCallKeyHandled = true; 5759 } 5760 } else { 5761 if (!mEndCallKeyHandled) { 5762 mHandler.removeCallbacks(mEndCallLongPress); 5763 if (!canceled) { 5764 if ((mEndcallBehavior 5765 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) { 5766 if (goHome()) { 5767 break; 5768 } 5769 } 5770 if ((mEndcallBehavior 5771 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) { 5772 mPowerManager.goToSleep(event.getEventTime(), 5773 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); 5774 isWakeKey = false; 5775 } 5776 } 5777 } 5778 } 5779 break; 5780 } 5781 5782 case KeyEvent.KEYCODE_POWER: { 5783 result &= ~ACTION_PASS_TO_USER; 5784 isWakeKey = false; // wake-up will be handled separately 5785 if (down) { 5786 interceptPowerKeyDown(event, interactive); 5787 } else { 5788 interceptPowerKeyUp(event, interactive, canceled); 5789 } 5790 break; 5791 } 5792 5793 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN: 5794 // fall through 5795 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP: 5796 // fall through 5797 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT: 5798 // fall through 5799 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: { 5800 result &= ~ACTION_PASS_TO_USER; 5801 interceptSystemNavigationKey(event); 5802 break; 5803 } 5804 5805 case KeyEvent.KEYCODE_SLEEP: { 5806 result &= ~ACTION_PASS_TO_USER; 5807 isWakeKey = false; 5808 if (!mPowerManager.isInteractive()) { 5809 useHapticFeedback = false; // suppress feedback if already non-interactive 5810 } 5811 if (down) { 5812 sleepPress(event.getEventTime()); 5813 } else { 5814 sleepRelease(event.getEventTime()); 5815 } 5816 break; 5817 } 5818 5819 case KeyEvent.KEYCODE_SOFT_SLEEP: { 5820 result &= ~ACTION_PASS_TO_USER; 5821 isWakeKey = false; 5822 if (!down) { 5823 mPowerManagerInternal.setUserInactiveOverrideFromWindowManager(); 5824 } 5825 break; 5826 } 5827 5828 case KeyEvent.KEYCODE_WAKEUP: { 5829 result &= ~ACTION_PASS_TO_USER; 5830 isWakeKey = true; 5831 break; 5832 } 5833 5834 case KeyEvent.KEYCODE_MEDIA_PLAY: 5835 case KeyEvent.KEYCODE_MEDIA_PAUSE: 5836 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 5837 case KeyEvent.KEYCODE_HEADSETHOOK: 5838 case KeyEvent.KEYCODE_MUTE: 5839 case KeyEvent.KEYCODE_MEDIA_STOP: 5840 case KeyEvent.KEYCODE_MEDIA_NEXT: 5841 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 5842 case KeyEvent.KEYCODE_MEDIA_REWIND: 5843 case KeyEvent.KEYCODE_MEDIA_RECORD: 5844 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 5845 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { 5846 if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) { 5847 // If the global session is active pass all media keys to it 5848 // instead of the active window. 5849 result &= ~ACTION_PASS_TO_USER; 5850 } 5851 if ((result & ACTION_PASS_TO_USER) == 0) { 5852 // Only do this if we would otherwise not pass it to the user. In that 5853 // case, the PhoneWindow class will do the same thing, except it will 5854 // only do it if the showing app doesn't process the key on its own. 5855 // Note that we need to make a copy of the key event here because the 5856 // original key event will be recycled when we return. 5857 mBroadcastWakeLock.acquire(); 5858 Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK, 5859 new KeyEvent(event)); 5860 msg.setAsynchronous(true); 5861 msg.sendToTarget(); 5862 } 5863 break; 5864 } 5865 5866 case KeyEvent.KEYCODE_CALL: { 5867 if (down) { 5868 TelecomManager telecomManager = getTelecommService(); 5869 if (telecomManager != null) { 5870 if (telecomManager.isRinging()) { 5871 Log.i(TAG, "interceptKeyBeforeQueueing:" 5872 + " CALL key-down while ringing: Answer the call!"); 5873 telecomManager.acceptRingingCall(); 5874 5875 // And *don't* pass this key thru to the current activity 5876 // (which is presumably the InCallScreen.) 5877 result &= ~ACTION_PASS_TO_USER; 5878 } 5879 } 5880 } 5881 break; 5882 } 5883 case KeyEvent.KEYCODE_VOICE_ASSIST: { 5884 // Only do this if we would otherwise not pass it to the user. In that case, 5885 // interceptKeyBeforeDispatching would apply a similar but different policy in 5886 // order to invoke voice assist actions. Note that we need to make a copy of the 5887 // key event here because the original key event will be recycled when we return. 5888 if ((result & ACTION_PASS_TO_USER) == 0 && !down) { 5889 mBroadcastWakeLock.acquire(); 5890 Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK, 5891 keyguardActive ? 1 : 0, 0); 5892 msg.setAsynchronous(true); 5893 msg.sendToTarget(); 5894 } 5895 break; 5896 } 5897 case KeyEvent.KEYCODE_WINDOW: { 5898 if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) { 5899 if (mTvPictureInPictureVisible) { 5900 // Consumes the key only if picture-in-picture is visible 5901 // to show picture-in-picture control menu. 5902 // This gives a chance to the foreground activity 5903 // to customize PIP key behavior. 5904 if (!down) { 5905 showTvPictureInPictureMenu(event); 5906 } 5907 result &= ~ACTION_PASS_TO_USER; 5908 } 5909 } 5910 break; 5911 } 5912 } 5913 5914 if (useHapticFeedback) { 5915 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); 5916 } 5917 5918 if (isWakeKey) { 5919 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 5920 } 5921 5922 return result; 5923 } 5924 5925 /** 5926 * Handle statusbar expansion events. 5927 * @param event 5928 */ 5929 private void interceptSystemNavigationKey(KeyEvent event) { 5930 if (event.getAction() == KeyEvent.ACTION_UP && areSystemNavigationKeysEnabled()) { 5931 IStatusBarService sbar = getStatusBarService(); 5932 if (sbar != null) { 5933 try { 5934 sbar.handleSystemNavigationKey(event.getKeyCode()); 5935 } catch (RemoteException e1) { 5936 // oops, no statusbar. Ignore event. 5937 } 5938 } 5939 } 5940 } 5941 5942 /** 5943 * Returns true if the key can have global actions attached to it. 5944 * We reserve all power management keys for the system since they require 5945 * very careful handling. 5946 */ 5947 private static boolean isValidGlobalKey(int keyCode) { 5948 switch (keyCode) { 5949 case KeyEvent.KEYCODE_POWER: 5950 case KeyEvent.KEYCODE_WAKEUP: 5951 case KeyEvent.KEYCODE_SLEEP: 5952 return false; 5953 default: 5954 return true; 5955 } 5956 } 5957 5958 /** 5959 * When the screen is off we ignore some keys that might otherwise typically 5960 * be considered wake keys. We filter them out here. 5961 * 5962 * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it 5963 * is always considered a wake key. 5964 */ 5965 private boolean isWakeKeyWhenScreenOff(int keyCode) { 5966 switch (keyCode) { 5967 // ignore volume keys unless docked 5968 case KeyEvent.KEYCODE_VOLUME_UP: 5969 case KeyEvent.KEYCODE_VOLUME_DOWN: 5970 case KeyEvent.KEYCODE_VOLUME_MUTE: 5971 return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED; 5972 5973 // ignore media and camera keys 5974 case KeyEvent.KEYCODE_MUTE: 5975 case KeyEvent.KEYCODE_HEADSETHOOK: 5976 case KeyEvent.KEYCODE_MEDIA_PLAY: 5977 case KeyEvent.KEYCODE_MEDIA_PAUSE: 5978 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 5979 case KeyEvent.KEYCODE_MEDIA_STOP: 5980 case KeyEvent.KEYCODE_MEDIA_NEXT: 5981 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 5982 case KeyEvent.KEYCODE_MEDIA_REWIND: 5983 case KeyEvent.KEYCODE_MEDIA_RECORD: 5984 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 5985 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: 5986 case KeyEvent.KEYCODE_CAMERA: 5987 return false; 5988 } 5989 return true; 5990 } 5991 5992 5993 /** {@inheritDoc} */ 5994 @Override 5995 public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) { 5996 if ((policyFlags & FLAG_WAKE) != 0) { 5997 if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion, 5998 "android.policy:MOTION")) { 5999 return 0; 6000 } 6001 } 6002 6003 if (shouldDispatchInputWhenNonInteractive(null)) { 6004 return ACTION_PASS_TO_USER; 6005 } 6006 6007 // If we have not passed the action up and we are in theater mode without dreaming, 6008 // there will be no dream to intercept the touch and wake into ambient. The device should 6009 // wake up in this case. 6010 if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) { 6011 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming, 6012 "android.policy:MOTION"); 6013 } 6014 6015 return 0; 6016 } 6017 6018 private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) { 6019 final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF); 6020 6021 if (displayOff && !mHasFeatureWatch) { 6022 return false; 6023 } 6024 6025 // Send events to keyguard while the screen is on and it's showing. 6026 if (isKeyguardShowingAndNotOccluded() && !displayOff) { 6027 return true; 6028 } 6029 6030 // Watches handle BACK specially 6031 if (mHasFeatureWatch 6032 && event != null 6033 && (event.getKeyCode() == KeyEvent.KEYCODE_BACK 6034 || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) { 6035 return false; 6036 } 6037 6038 // Send events to a dozing dream even if the screen is off since the dream 6039 // is in control of the state of the screen. 6040 IDreamManager dreamManager = getDreamManager(); 6041 6042 try { 6043 if (dreamManager != null && dreamManager.isDreaming()) { 6044 return true; 6045 } 6046 } catch (RemoteException e) { 6047 Slog.e(TAG, "RemoteException when checking if dreaming", e); 6048 } 6049 6050 // Otherwise, consume events since the user can't see what is being 6051 // interacted with. 6052 return false; 6053 } 6054 6055 private void dispatchDirectAudioEvent(KeyEvent event) { 6056 if (event.getAction() != KeyEvent.ACTION_DOWN) { 6057 return; 6058 } 6059 int keyCode = event.getKeyCode(); 6060 int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND 6061 | AudioManager.FLAG_FROM_KEY; 6062 String pkgName = mContext.getOpPackageName(); 6063 switch (keyCode) { 6064 case KeyEvent.KEYCODE_VOLUME_UP: 6065 try { 6066 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE, 6067 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6068 } catch (RemoteException e) { 6069 Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e); 6070 } 6071 break; 6072 case KeyEvent.KEYCODE_VOLUME_DOWN: 6073 try { 6074 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER, 6075 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6076 } catch (RemoteException e) { 6077 Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e); 6078 } 6079 break; 6080 case KeyEvent.KEYCODE_VOLUME_MUTE: 6081 try { 6082 if (event.getRepeatCount() == 0) { 6083 getAudioService().adjustSuggestedStreamVolume( 6084 AudioManager.ADJUST_TOGGLE_MUTE, 6085 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6086 } 6087 } catch (RemoteException e) { 6088 Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e); 6089 } 6090 break; 6091 } 6092 } 6093 6094 void dispatchMediaKeyWithWakeLock(KeyEvent event) { 6095 if (DEBUG_INPUT) { 6096 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event); 6097 } 6098 6099 if (mHavePendingMediaKeyRepeatWithWakeLock) { 6100 if (DEBUG_INPUT) { 6101 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat"); 6102 } 6103 6104 mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK); 6105 mHavePendingMediaKeyRepeatWithWakeLock = false; 6106 mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock 6107 } 6108 6109 dispatchMediaKeyWithWakeLockToAudioService(event); 6110 6111 if (event.getAction() == KeyEvent.ACTION_DOWN 6112 && event.getRepeatCount() == 0) { 6113 mHavePendingMediaKeyRepeatWithWakeLock = true; 6114 6115 Message msg = mHandler.obtainMessage( 6116 MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event); 6117 msg.setAsynchronous(true); 6118 mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout()); 6119 } else { 6120 mBroadcastWakeLock.release(); 6121 } 6122 } 6123 6124 void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) { 6125 mHavePendingMediaKeyRepeatWithWakeLock = false; 6126 6127 KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event, 6128 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS); 6129 if (DEBUG_INPUT) { 6130 Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent); 6131 } 6132 6133 dispatchMediaKeyWithWakeLockToAudioService(repeatEvent); 6134 mBroadcastWakeLock.release(); 6135 } 6136 6137 void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) { 6138 if (ActivityManagerNative.isSystemReady()) { 6139 MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true); 6140 } 6141 } 6142 6143 void launchVoiceAssistWithWakeLock(boolean keyguardActive) { 6144 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface( 6145 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); 6146 if (dic != null) { 6147 try { 6148 dic.exitIdle("voice-search"); 6149 } catch (RemoteException e) { 6150 } 6151 } 6152 Intent voiceIntent = 6153 new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); 6154 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive); 6155 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF); 6156 mBroadcastWakeLock.release(); 6157 } 6158 6159 BroadcastReceiver mDockReceiver = new BroadcastReceiver() { 6160 @Override 6161 public void onReceive(Context context, Intent intent) { 6162 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) { 6163 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 6164 Intent.EXTRA_DOCK_STATE_UNDOCKED); 6165 } else { 6166 try { 6167 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface( 6168 ServiceManager.getService(Context.UI_MODE_SERVICE)); 6169 mUiMode = uiModeService.getCurrentModeType(); 6170 } catch (RemoteException e) { 6171 } 6172 } 6173 updateRotation(true); 6174 synchronized (mLock) { 6175 updateOrientationListenerLp(); 6176 } 6177 } 6178 }; 6179 6180 BroadcastReceiver mDreamReceiver = new BroadcastReceiver() { 6181 @Override 6182 public void onReceive(Context context, Intent intent) { 6183 if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) { 6184 if (mKeyguardDelegate != null) { 6185 mKeyguardDelegate.onDreamingStarted(); 6186 } 6187 } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) { 6188 if (mKeyguardDelegate != null) { 6189 mKeyguardDelegate.onDreamingStopped(); 6190 } 6191 } 6192 } 6193 }; 6194 6195 BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() { 6196 @Override 6197 public void onReceive(Context context, Intent intent) { 6198 if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) { 6199 // tickle the settings observer: this first ensures that we're 6200 // observing the relevant settings for the newly-active user, 6201 // and then updates our own bookkeeping based on the now- 6202 // current user. 6203 mSettingsObserver.onChange(false); 6204 6205 // force a re-application of focused window sysui visibility. 6206 // the window may never have been shown for this user 6207 // e.g. the keyguard when going through the new-user setup flow 6208 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6209 mLastSystemUiFlags = 0; 6210 updateSystemUiVisibilityLw(); 6211 } 6212 } 6213 } 6214 }; 6215 6216 private final Runnable mHiddenNavPanic = new Runnable() { 6217 @Override 6218 public void run() { 6219 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6220 if (!isUserSetupComplete()) { 6221 // Swipe-up for navigation bar is disabled during setup 6222 return; 6223 } 6224 mPendingPanicGestureUptime = SystemClock.uptimeMillis(); 6225 if (!isNavBarEmpty(mLastSystemUiFlags)) { 6226 mNavigationBarController.showTransient(); 6227 } 6228 } 6229 } 6230 }; 6231 6232 private void requestTransientBars(WindowState swipeTarget) { 6233 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6234 if (!isUserSetupComplete()) { 6235 // Swipe-up for navigation bar is disabled during setup 6236 return; 6237 } 6238 boolean sb = mStatusBarController.checkShowTransientBarLw(); 6239 boolean nb = mNavigationBarController.checkShowTransientBarLw() 6240 && !isNavBarEmpty(mLastSystemUiFlags); 6241 if (sb || nb) { 6242 // Don't show status bar when swiping on already visible navigation bar 6243 if (!nb && swipeTarget == mNavigationBar) { 6244 if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target"); 6245 return; 6246 } 6247 if (sb) mStatusBarController.showTransient(); 6248 if (nb) mNavigationBarController.showTransient(); 6249 mImmersiveModeConfirmation.confirmCurrentPrompt(); 6250 updateSystemUiVisibilityLw(); 6251 } 6252 } 6253 } 6254 6255 // Called on the PowerManager's Notifier thread. 6256 @Override 6257 public void startedGoingToSleep(int why) { 6258 if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")"); 6259 mCameraGestureTriggeredDuringGoingToSleep = false; 6260 mGoingToSleep = true; 6261 if (mKeyguardDelegate != null) { 6262 mKeyguardDelegate.onStartedGoingToSleep(why); 6263 } 6264 } 6265 6266 // Called on the PowerManager's Notifier thread. 6267 @Override 6268 public void finishedGoingToSleep(int why) { 6269 EventLog.writeEvent(70000, 0); 6270 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")"); 6271 MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000); 6272 6273 mGoingToSleep = false; 6274 6275 // We must get this work done here because the power manager will drop 6276 // the wake lock and let the system suspend once this function returns. 6277 synchronized (mLock) { 6278 mAwake = false; 6279 updateWakeGestureListenerLp(); 6280 updateOrientationListenerLp(); 6281 updateLockScreenTimeout(); 6282 } 6283 if (mKeyguardDelegate != null) { 6284 mKeyguardDelegate.onFinishedGoingToSleep(why, 6285 mCameraGestureTriggeredDuringGoingToSleep); 6286 } 6287 mCameraGestureTriggeredDuringGoingToSleep = false; 6288 } 6289 6290 // Called on the PowerManager's Notifier thread. 6291 @Override 6292 public void startedWakingUp() { 6293 EventLog.writeEvent(70000, 1); 6294 if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up..."); 6295 6296 // Since goToSleep performs these functions synchronously, we must 6297 // do the same here. We cannot post this work to a handler because 6298 // that might cause it to become reordered with respect to what 6299 // may happen in a future call to goToSleep. 6300 synchronized (mLock) { 6301 mAwake = true; 6302 6303 updateWakeGestureListenerLp(); 6304 updateOrientationListenerLp(); 6305 updateLockScreenTimeout(); 6306 } 6307 6308 if (mKeyguardDelegate != null) { 6309 mKeyguardDelegate.onStartedWakingUp(); 6310 } 6311 } 6312 6313 // Called on the PowerManager's Notifier thread. 6314 @Override 6315 public void finishedWakingUp() { 6316 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up..."); 6317 } 6318 6319 private void wakeUpFromPowerKey(long eventTime) { 6320 wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER"); 6321 } 6322 6323 private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) { 6324 final boolean theaterModeEnabled = isTheaterModeEnabled(); 6325 if (!wakeInTheaterMode && theaterModeEnabled) { 6326 return false; 6327 } 6328 6329 if (theaterModeEnabled) { 6330 Settings.Global.putInt(mContext.getContentResolver(), 6331 Settings.Global.THEATER_MODE_ON, 0); 6332 } 6333 6334 mPowerManager.wakeUp(wakeTime, reason); 6335 return true; 6336 } 6337 6338 private void finishKeyguardDrawn() { 6339 synchronized (mLock) { 6340 if (!mScreenOnEarly || mKeyguardDrawComplete) { 6341 return; // We are not awake yet or we have already informed of this event. 6342 } 6343 6344 mKeyguardDrawComplete = true; 6345 if (mKeyguardDelegate != null) { 6346 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6347 } 6348 mWindowManagerDrawComplete = false; 6349 } 6350 6351 // ... eventually calls finishWindowsDrawn which will finalize our screen turn on 6352 // as well as enabling the orientation change logic/sensor. 6353 mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback, 6354 WAITING_FOR_DRAWN_TIMEOUT); 6355 } 6356 6357 // Called on the DisplayManager's DisplayPowerController thread. 6358 @Override 6359 public void screenTurnedOff() { 6360 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off..."); 6361 6362 updateScreenOffSleepToken(true); 6363 synchronized (mLock) { 6364 mScreenOnEarly = false; 6365 mScreenOnFully = false; 6366 mKeyguardDrawComplete = false; 6367 mWindowManagerDrawComplete = false; 6368 mScreenOnListener = null; 6369 updateOrientationListenerLp(); 6370 6371 if (mKeyguardDelegate != null) { 6372 mKeyguardDelegate.onScreenTurnedOff(); 6373 } 6374 } 6375 } 6376 6377 // Called on the DisplayManager's DisplayPowerController thread. 6378 @Override 6379 public void screenTurningOn(final ScreenOnListener screenOnListener) { 6380 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on..."); 6381 6382 updateScreenOffSleepToken(false); 6383 synchronized (mLock) { 6384 mScreenOnEarly = true; 6385 mScreenOnFully = false; 6386 mKeyguardDrawComplete = false; 6387 mWindowManagerDrawComplete = false; 6388 mScreenOnListener = screenOnListener; 6389 6390 if (mKeyguardDelegate != null) { 6391 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6392 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000); 6393 mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback); 6394 } else { 6395 if (DEBUG_WAKEUP) Slog.d(TAG, 6396 "null mKeyguardDelegate: setting mKeyguardDrawComplete."); 6397 finishKeyguardDrawn(); 6398 } 6399 } 6400 } 6401 6402 // Called on the DisplayManager's DisplayPowerController thread. 6403 @Override 6404 public void screenTurnedOn() { 6405 synchronized (mLock) { 6406 if (mKeyguardDelegate != null) { 6407 mKeyguardDelegate.onScreenTurnedOn(); 6408 } 6409 } 6410 } 6411 6412 private void finishWindowsDrawn() { 6413 synchronized (mLock) { 6414 if (!mScreenOnEarly || mWindowManagerDrawComplete) { 6415 return; // Screen is not turned on or we did already handle this case earlier. 6416 } 6417 6418 mWindowManagerDrawComplete = true; 6419 } 6420 6421 finishScreenTurningOn(); 6422 } 6423 6424 private void finishScreenTurningOn() { 6425 synchronized (mLock) { 6426 // We have just finished drawing screen content. Since the orientation listener 6427 // gets only installed when all windows are drawn, we try to install it again. 6428 updateOrientationListenerLp(); 6429 } 6430 final ScreenOnListener listener; 6431 final boolean enableScreen; 6432 synchronized (mLock) { 6433 if (DEBUG_WAKEUP) Slog.d(TAG, 6434 "finishScreenTurningOn: mAwake=" + mAwake 6435 + ", mScreenOnEarly=" + mScreenOnEarly 6436 + ", mScreenOnFully=" + mScreenOnFully 6437 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete 6438 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete); 6439 6440 if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete 6441 || (mAwake && !mKeyguardDrawComplete)) { 6442 return; // spurious or not ready yet 6443 } 6444 6445 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on..."); 6446 listener = mScreenOnListener; 6447 mScreenOnListener = null; 6448 mScreenOnFully = true; 6449 6450 // Remember the first time we draw the keyguard so we know when we're done with 6451 // the main part of booting and can enable the screen and hide boot messages. 6452 if (!mKeyguardDrawnOnce && mAwake) { 6453 mKeyguardDrawnOnce = true; 6454 enableScreen = true; 6455 if (mBootMessageNeedsHiding) { 6456 mBootMessageNeedsHiding = false; 6457 hideBootMessages(); 6458 } 6459 } else { 6460 enableScreen = false; 6461 } 6462 } 6463 6464 if (listener != null) { 6465 listener.onScreenOn(); 6466 } 6467 6468 if (enableScreen) { 6469 try { 6470 mWindowManager.enableScreenIfNeeded(); 6471 } catch (RemoteException unhandled) { 6472 } 6473 } 6474 } 6475 6476 private void handleHideBootMessage() { 6477 synchronized (mLock) { 6478 if (!mKeyguardDrawnOnce) { 6479 mBootMessageNeedsHiding = true; 6480 return; // keyguard hasn't drawn the first time yet, not done booting 6481 } 6482 } 6483 6484 if (mBootMsgDialog != null) { 6485 if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing"); 6486 mBootMsgDialog.dismiss(); 6487 mBootMsgDialog = null; 6488 } 6489 } 6490 6491 @Override 6492 public boolean isScreenOn() { 6493 return mScreenOnFully; 6494 } 6495 6496 /** {@inheritDoc} */ 6497 @Override 6498 public void enableKeyguard(boolean enabled) { 6499 if (mKeyguardDelegate != null) { 6500 mKeyguardDelegate.setKeyguardEnabled(enabled); 6501 } 6502 } 6503 6504 /** {@inheritDoc} */ 6505 @Override 6506 public void exitKeyguardSecurely(OnKeyguardExitResult callback) { 6507 if (mKeyguardDelegate != null) { 6508 mKeyguardDelegate.verifyUnlock(callback); 6509 } 6510 } 6511 6512 private boolean isKeyguardShowingAndNotOccluded() { 6513 if (mKeyguardDelegate == null) return false; 6514 return mKeyguardDelegate.isShowing() && !mKeyguardOccluded; 6515 } 6516 6517 /** {@inheritDoc} */ 6518 @Override 6519 public boolean isKeyguardLocked() { 6520 return keyguardOn(); 6521 } 6522 6523 /** {@inheritDoc} */ 6524 @Override 6525 public boolean isKeyguardSecure(int userId) { 6526 if (mKeyguardDelegate == null) return false; 6527 return mKeyguardDelegate.isSecure(userId); 6528 } 6529 6530 /** {@inheritDoc} */ 6531 @Override 6532 public boolean isKeyguardShowingOrOccluded() { 6533 return mKeyguardDelegate == null ? false : mKeyguardDelegate.isShowing(); 6534 } 6535 6536 /** {@inheritDoc} */ 6537 @Override 6538 public boolean inKeyguardRestrictedKeyInputMode() { 6539 if (mKeyguardDelegate == null) return false; 6540 return mKeyguardDelegate.isInputRestricted(); 6541 } 6542 6543 @Override 6544 public void dismissKeyguardLw() { 6545 if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) { 6546 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw"); 6547 mHandler.post(new Runnable() { 6548 @Override 6549 public void run() { 6550 // ask the keyguard to prompt the user to authenticate if necessary 6551 mKeyguardDelegate.dismiss(false /* allowWhileOccluded */); 6552 } 6553 }); 6554 } 6555 } 6556 6557 @Override 6558 public void notifyActivityDrawnForKeyguardLw() { 6559 if (mKeyguardDelegate != null) { 6560 mHandler.post(new Runnable() { 6561 @Override 6562 public void run() { 6563 mKeyguardDelegate.onActivityDrawn(); 6564 } 6565 }); 6566 } 6567 } 6568 6569 @Override 6570 public boolean isKeyguardDrawnLw() { 6571 synchronized (mLock) { 6572 return mKeyguardDrawnOnce; 6573 } 6574 } 6575 6576 @Override 6577 public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) { 6578 if (mKeyguardDelegate != null) { 6579 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation"); 6580 mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration); 6581 } 6582 } 6583 6584 @Override 6585 public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6586 Rect outInsets) { 6587 outInsets.setEmpty(); 6588 6589 // Navigation bar and status bar. 6590 getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets); 6591 if (mStatusBar != null) { 6592 outInsets.top = mStatusBarHeight; 6593 } 6594 } 6595 6596 @Override 6597 public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6598 Rect outInsets) { 6599 outInsets.setEmpty(); 6600 6601 // Only navigation bar 6602 if (mNavigationBar != null) { 6603 int position = navigationBarPosition(displayWidth, displayHeight, displayRotation); 6604 if (position == NAV_BAR_BOTTOM) { 6605 outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode); 6606 } else if (position == NAV_BAR_RIGHT) { 6607 outInsets.right = getNavigationBarWidth(displayRotation, mUiMode); 6608 } else if (position == NAV_BAR_LEFT) { 6609 outInsets.left = getNavigationBarWidth(displayRotation, mUiMode); 6610 } 6611 } 6612 } 6613 6614 @Override 6615 public boolean isNavBarForcedShownLw(WindowState windowState) { 6616 return mForceShowSystemBars; 6617 } 6618 6619 @Override 6620 public boolean isDockSideAllowed(int dockSide) { 6621 6622 // We do not allow all dock sides at which the navigation bar touches the docked stack. 6623 if (!mNavigationBarCanMove) { 6624 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT; 6625 } else { 6626 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT; 6627 } 6628 } 6629 6630 void sendCloseSystemWindows() { 6631 PhoneWindow.sendCloseSystemWindows(mContext, null); 6632 } 6633 6634 void sendCloseSystemWindows(String reason) { 6635 PhoneWindow.sendCloseSystemWindows(mContext, reason); 6636 } 6637 6638 @Override 6639 public int rotationForOrientationLw(int orientation, int lastRotation) { 6640 if (false) { 6641 Slog.v(TAG, "rotationForOrientationLw(orient=" 6642 + orientation + ", last=" + lastRotation 6643 + "); user=" + mUserRotation + " " 6644 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) 6645 ? "USER_ROTATION_LOCKED" : "") 6646 ); 6647 } 6648 6649 if (mForceDefaultOrientation) { 6650 return Surface.ROTATION_0; 6651 } 6652 6653 synchronized (mLock) { 6654 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1 6655 if (sensorRotation < 0) { 6656 sensorRotation = lastRotation; 6657 } 6658 6659 final int preferredRotation; 6660 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) { 6661 // Ignore sensor when lid switch is open and rotation is forced. 6662 preferredRotation = mLidOpenRotation; 6663 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR 6664 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) { 6665 // Ignore sensor when in car dock unless explicitly enabled. 6666 // This case can override the behavior of NOSENSOR, and can also 6667 // enable 180 degree rotation while docked. 6668 preferredRotation = mCarDockEnablesAccelerometer 6669 ? sensorRotation : mCarDockRotation; 6670 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK 6671 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK 6672 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK) 6673 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) { 6674 // Ignore sensor when in desk dock unless explicitly enabled. 6675 // This case can override the behavior of NOSENSOR, and can also 6676 // enable 180 degree rotation while docked. 6677 preferredRotation = mDeskDockEnablesAccelerometer 6678 ? sensorRotation : mDeskDockRotation; 6679 } else if (mHdmiPlugged && mDemoHdmiRotationLock) { 6680 // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled. 6681 // Note that the dock orientation overrides the HDMI orientation. 6682 preferredRotation = mDemoHdmiRotation; 6683 } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED 6684 && mUndockedHdmiRotation >= 0) { 6685 // Ignore sensor when plugged into HDMI and an undocked orientation has 6686 // been specified in the configuration (only for legacy devices without 6687 // full multi-display support). 6688 // Note that the dock orientation overrides the HDMI orientation. 6689 preferredRotation = mUndockedHdmiRotation; 6690 } else if (mDemoRotationLock) { 6691 // Ignore sensor when demo rotation lock is enabled. 6692 // Note that the dock orientation and HDMI rotation lock override this. 6693 preferredRotation = mDemoRotation; 6694 } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) { 6695 // Application just wants to remain locked in the last rotation. 6696 preferredRotation = lastRotation; 6697 } else if (!mSupportAutoRotation) { 6698 // If we don't support auto-rotation then bail out here and ignore 6699 // the sensor and any rotation lock settings. 6700 preferredRotation = -1; 6701 } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE 6702 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER 6703 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 6704 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE 6705 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT 6706 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER)) 6707 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR 6708 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6709 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE 6710 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) { 6711 // Otherwise, use sensor only if requested by the application or enabled 6712 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR. 6713 if (mAllowAllRotations < 0) { 6714 // Can't read this during init() because the context doesn't 6715 // have display metrics at that time so we cannot determine 6716 // tablet vs. phone then. 6717 mAllowAllRotations = mContext.getResources().getBoolean( 6718 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0; 6719 } 6720 if (sensorRotation != Surface.ROTATION_180 6721 || mAllowAllRotations == 1 6722 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6723 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) { 6724 preferredRotation = sensorRotation; 6725 } else { 6726 preferredRotation = lastRotation; 6727 } 6728 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED 6729 && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) { 6730 // Apply rotation lock. Does not apply to NOSENSOR. 6731 // The idea is that the user rotation expresses a weak preference for the direction 6732 // of gravity and as NOSENSOR is never affected by gravity, then neither should 6733 // NOSENSOR be affected by rotation lock (although it will be affected by docks). 6734 preferredRotation = mUserRotation; 6735 } else { 6736 // No overriding preference. 6737 // We will do exactly what the application asked us to do. 6738 preferredRotation = -1; 6739 } 6740 6741 switch (orientation) { 6742 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 6743 // Return portrait unless overridden. 6744 if (isAnyPortrait(preferredRotation)) { 6745 return preferredRotation; 6746 } 6747 return mPortraitRotation; 6748 6749 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 6750 // Return landscape unless overridden. 6751 if (isLandscapeOrSeascape(preferredRotation)) { 6752 return preferredRotation; 6753 } 6754 return mLandscapeRotation; 6755 6756 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 6757 // Return reverse portrait unless overridden. 6758 if (isAnyPortrait(preferredRotation)) { 6759 return preferredRotation; 6760 } 6761 return mUpsideDownRotation; 6762 6763 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 6764 // Return seascape unless overridden. 6765 if (isLandscapeOrSeascape(preferredRotation)) { 6766 return preferredRotation; 6767 } 6768 return mSeascapeRotation; 6769 6770 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 6771 case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE: 6772 // Return either landscape rotation. 6773 if (isLandscapeOrSeascape(preferredRotation)) { 6774 return preferredRotation; 6775 } 6776 if (isLandscapeOrSeascape(lastRotation)) { 6777 return lastRotation; 6778 } 6779 return mLandscapeRotation; 6780 6781 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 6782 case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT: 6783 // Return either portrait rotation. 6784 if (isAnyPortrait(preferredRotation)) { 6785 return preferredRotation; 6786 } 6787 if (isAnyPortrait(lastRotation)) { 6788 return lastRotation; 6789 } 6790 return mPortraitRotation; 6791 6792 default: 6793 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR, 6794 // just return the preferred orientation we already calculated. 6795 if (preferredRotation >= 0) { 6796 return preferredRotation; 6797 } 6798 return Surface.ROTATION_0; 6799 } 6800 } 6801 } 6802 6803 @Override 6804 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) { 6805 switch (orientation) { 6806 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 6807 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 6808 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 6809 return isAnyPortrait(rotation); 6810 6811 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 6812 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 6813 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 6814 return isLandscapeOrSeascape(rotation); 6815 6816 default: 6817 return true; 6818 } 6819 } 6820 6821 @Override 6822 public void setRotationLw(int rotation) { 6823 mOrientationListener.setCurrentRotation(rotation); 6824 } 6825 6826 private boolean isLandscapeOrSeascape(int rotation) { 6827 return rotation == mLandscapeRotation || rotation == mSeascapeRotation; 6828 } 6829 6830 private boolean isAnyPortrait(int rotation) { 6831 return rotation == mPortraitRotation || rotation == mUpsideDownRotation; 6832 } 6833 6834 @Override 6835 public int getUserRotationMode() { 6836 return Settings.System.getIntForUser(mContext.getContentResolver(), 6837 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ? 6838 WindowManagerPolicy.USER_ROTATION_FREE : 6839 WindowManagerPolicy.USER_ROTATION_LOCKED; 6840 } 6841 6842 // User rotation: to be used when all else fails in assigning an orientation to the device 6843 @Override 6844 public void setUserRotationMode(int mode, int rot) { 6845 ContentResolver res = mContext.getContentResolver(); 6846 6847 // mUserRotationMode and mUserRotation will be assigned by the content observer 6848 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) { 6849 Settings.System.putIntForUser(res, 6850 Settings.System.USER_ROTATION, 6851 rot, 6852 UserHandle.USER_CURRENT); 6853 Settings.System.putIntForUser(res, 6854 Settings.System.ACCELEROMETER_ROTATION, 6855 0, 6856 UserHandle.USER_CURRENT); 6857 } else { 6858 Settings.System.putIntForUser(res, 6859 Settings.System.ACCELEROMETER_ROTATION, 6860 1, 6861 UserHandle.USER_CURRENT); 6862 } 6863 } 6864 6865 @Override 6866 public void setSafeMode(boolean safeMode) { 6867 mSafeMode = safeMode; 6868 performHapticFeedbackLw(null, safeMode 6869 ? HapticFeedbackConstants.SAFE_MODE_ENABLED 6870 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true); 6871 } 6872 6873 static long[] getLongIntArray(Resources r, int resid) { 6874 int[] ar = r.getIntArray(resid); 6875 if (ar == null) { 6876 return null; 6877 } 6878 long[] out = new long[ar.length]; 6879 for (int i=0; i<ar.length; i++) { 6880 out[i] = ar[i]; 6881 } 6882 return out; 6883 } 6884 6885 /** {@inheritDoc} */ 6886 @Override 6887 public void systemReady() { 6888 mKeyguardDelegate = new KeyguardServiceDelegate(mContext); 6889 mKeyguardDelegate.onSystemReady(); 6890 6891 readCameraLensCoverState(); 6892 updateUiMode(); 6893 boolean bindKeyguardNow; 6894 synchronized (mLock) { 6895 updateOrientationListenerLp(); 6896 mSystemReady = true; 6897 mHandler.post(new Runnable() { 6898 @Override 6899 public void run() { 6900 updateSettings(); 6901 } 6902 }); 6903 6904 bindKeyguardNow = mDeferBindKeyguard; 6905 if (bindKeyguardNow) { 6906 // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now. 6907 mDeferBindKeyguard = false; 6908 } 6909 } 6910 6911 if (bindKeyguardNow) { 6912 mKeyguardDelegate.bindService(mContext); 6913 mKeyguardDelegate.onBootCompleted(); 6914 } 6915 mSystemGestures.systemReady(); 6916 mImmersiveModeConfirmation.systemReady(); 6917 } 6918 6919 /** {@inheritDoc} */ 6920 @Override 6921 public void systemBooted() { 6922 boolean bindKeyguardNow = false; 6923 synchronized (mLock) { 6924 // Time to bind Keyguard; take care to only bind it once, either here if ready or 6925 // in systemReady if not. 6926 if (mKeyguardDelegate != null) { 6927 bindKeyguardNow = true; 6928 } else { 6929 // Because mKeyguardDelegate is null, we know that the synchronized block in 6930 // systemReady didn't run yet and setting this will actually have an effect. 6931 mDeferBindKeyguard = true; 6932 } 6933 } 6934 if (bindKeyguardNow) { 6935 mKeyguardDelegate.bindService(mContext); 6936 mKeyguardDelegate.onBootCompleted(); 6937 } 6938 synchronized (mLock) { 6939 mSystemBooted = true; 6940 } 6941 startedWakingUp(); 6942 screenTurningOn(null); 6943 screenTurnedOn(); 6944 } 6945 6946 ProgressDialog mBootMsgDialog = null; 6947 6948 /** {@inheritDoc} */ 6949 @Override 6950 public void showBootMessage(final CharSequence msg, final boolean always) { 6951 mHandler.post(new Runnable() { 6952 @Override public void run() { 6953 if (mBootMsgDialog == null) { 6954 int theme; 6955 if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) { 6956 theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert; 6957 } else { 6958 theme = 0; 6959 } 6960 6961 mBootMsgDialog = new ProgressDialog(mContext, theme) { 6962 // This dialog will consume all events coming in to 6963 // it, to avoid it trying to do things too early in boot. 6964 @Override public boolean dispatchKeyEvent(KeyEvent event) { 6965 return true; 6966 } 6967 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { 6968 return true; 6969 } 6970 @Override public boolean dispatchTouchEvent(MotionEvent ev) { 6971 return true; 6972 } 6973 @Override public boolean dispatchTrackballEvent(MotionEvent ev) { 6974 return true; 6975 } 6976 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) { 6977 return true; 6978 } 6979 @Override public boolean dispatchPopulateAccessibilityEvent( 6980 AccessibilityEvent event) { 6981 return true; 6982 } 6983 }; 6984 if (mContext.getPackageManager().isUpgrade()) { 6985 mBootMsgDialog.setTitle(R.string.android_upgrading_title); 6986 } else { 6987 mBootMsgDialog.setTitle(R.string.android_start_title); 6988 } 6989 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 6990 mBootMsgDialog.setIndeterminate(true); 6991 mBootMsgDialog.getWindow().setType( 6992 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS); 6993 mBootMsgDialog.getWindow().addFlags( 6994 WindowManager.LayoutParams.FLAG_DIM_BEHIND 6995 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); 6996 mBootMsgDialog.getWindow().setDimAmount(1); 6997 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes(); 6998 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 6999 mBootMsgDialog.getWindow().setAttributes(lp); 7000 mBootMsgDialog.setCancelable(false); 7001 mBootMsgDialog.show(); 7002 } 7003 mBootMsgDialog.setMessage(msg); 7004 } 7005 }); 7006 } 7007 7008 /** {@inheritDoc} */ 7009 @Override 7010 public void hideBootMessages() { 7011 mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE); 7012 } 7013 7014 /** {@inheritDoc} */ 7015 @Override 7016 public void userActivity() { 7017 // *************************************** 7018 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE 7019 // *************************************** 7020 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER 7021 // WITH ITS LOCKS HELD. 7022 // 7023 // This code must be VERY careful about the locks 7024 // it acquires. 7025 // In fact, the current code acquires way too many, 7026 // and probably has lurking deadlocks. 7027 7028 synchronized (mScreenLockTimeout) { 7029 if (mLockScreenTimerActive) { 7030 // reset the timer 7031 mHandler.removeCallbacks(mScreenLockTimeout); 7032 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7033 } 7034 } 7035 } 7036 7037 class ScreenLockTimeout implements Runnable { 7038 Bundle options; 7039 7040 @Override 7041 public void run() { 7042 synchronized (this) { 7043 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard"); 7044 if (mKeyguardDelegate != null) { 7045 mKeyguardDelegate.doKeyguardTimeout(options); 7046 } 7047 mLockScreenTimerActive = false; 7048 options = null; 7049 } 7050 } 7051 7052 public void setLockOptions(Bundle options) { 7053 this.options = options; 7054 } 7055 } 7056 7057 ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout(); 7058 7059 @Override 7060 public void lockNow(Bundle options) { 7061 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 7062 mHandler.removeCallbacks(mScreenLockTimeout); 7063 if (options != null) { 7064 // In case multiple calls are made to lockNow, we don't wipe out the options 7065 // until the runnable actually executes. 7066 mScreenLockTimeout.setLockOptions(options); 7067 } 7068 mHandler.post(mScreenLockTimeout); 7069 } 7070 7071 private void updateLockScreenTimeout() { 7072 synchronized (mScreenLockTimeout) { 7073 boolean enable = (mAllowLockscreenWhenOn && mAwake && 7074 mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId)); 7075 if (mLockScreenTimerActive != enable) { 7076 if (enable) { 7077 if (localLOGV) Log.v(TAG, "setting lockscreen timer"); 7078 mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests 7079 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7080 } else { 7081 if (localLOGV) Log.v(TAG, "clearing lockscreen timer"); 7082 mHandler.removeCallbacks(mScreenLockTimeout); 7083 } 7084 mLockScreenTimerActive = enable; 7085 } 7086 } 7087 } 7088 7089 private void updateDreamingSleepToken(boolean acquire) { 7090 if (acquire) { 7091 if (mDreamingSleepToken == null) { 7092 mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream"); 7093 } 7094 } else { 7095 if (mDreamingSleepToken != null) { 7096 mDreamingSleepToken.release(); 7097 mDreamingSleepToken = null; 7098 } 7099 } 7100 } 7101 7102 private void updateScreenOffSleepToken(boolean acquire) { 7103 if (acquire) { 7104 if (mScreenOffSleepToken == null) { 7105 mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff"); 7106 } 7107 } else { 7108 if (mScreenOffSleepToken != null) { 7109 mScreenOffSleepToken.release(); 7110 mScreenOffSleepToken = null; 7111 } 7112 } 7113 } 7114 7115 /** {@inheritDoc} */ 7116 @Override 7117 public void enableScreenAfterBoot() { 7118 readLidState(); 7119 applyLidSwitchState(); 7120 updateRotation(true); 7121 } 7122 7123 private void applyLidSwitchState() { 7124 if (mLidState == LID_CLOSED && mLidControlsSleep) { 7125 mPowerManager.goToSleep(SystemClock.uptimeMillis(), 7126 PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH, 7127 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); 7128 } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) { 7129 mWindowManagerFuncs.lockDeviceNow(); 7130 } 7131 7132 synchronized (mLock) { 7133 updateWakeGestureListenerLp(); 7134 } 7135 } 7136 7137 void updateUiMode() { 7138 if (mUiModeManager == null) { 7139 mUiModeManager = IUiModeManager.Stub.asInterface( 7140 ServiceManager.getService(Context.UI_MODE_SERVICE)); 7141 } 7142 try { 7143 mUiMode = mUiModeManager.getCurrentModeType(); 7144 } catch (RemoteException e) { 7145 } 7146 } 7147 7148 void updateRotation(boolean alwaysSendConfiguration) { 7149 try { 7150 //set orientation on WindowManager 7151 mWindowManager.updateRotation(alwaysSendConfiguration, false); 7152 } catch (RemoteException e) { 7153 // Ignore 7154 } 7155 } 7156 7157 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 7158 try { 7159 //set orientation on WindowManager 7160 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout); 7161 } catch (RemoteException e) { 7162 // Ignore 7163 } 7164 } 7165 7166 /** 7167 * Return an Intent to launch the currently active dock app as home. Returns 7168 * null if the standard home should be launched, which is the case if any of the following is 7169 * true: 7170 * <ul> 7171 * <li>The device is not in either car mode or desk mode 7172 * <li>The device is in car mode but mEnableCarDockHomeCapture is false 7173 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false 7174 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME 7175 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME 7176 * </ul> 7177 * @return A dock intent. 7178 */ 7179 Intent createHomeDockIntent() { 7180 Intent intent = null; 7181 7182 // What home does is based on the mode, not the dock state. That 7183 // is, when in car mode you should be taken to car home regardless 7184 // of whether we are actually in a car dock. 7185 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) { 7186 if (mEnableCarDockHomeCapture) { 7187 intent = mCarDockIntent; 7188 } 7189 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) { 7190 if (ENABLE_DESK_DOCK_HOME_CAPTURE) { 7191 intent = mDeskDockIntent; 7192 } 7193 } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH 7194 && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK 7195 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK 7196 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) { 7197 // Always launch dock home from home when watch is docked, if it exists. 7198 intent = mDeskDockIntent; 7199 } 7200 7201 if (intent == null) { 7202 return null; 7203 } 7204 7205 ActivityInfo ai = null; 7206 ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser( 7207 intent, 7208 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA, 7209 mCurrentUserId); 7210 if (info != null) { 7211 ai = info.activityInfo; 7212 } 7213 if (ai != null 7214 && ai.metaData != null 7215 && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) { 7216 intent = new Intent(intent); 7217 intent.setClassName(ai.packageName, ai.name); 7218 return intent; 7219 } 7220 7221 return null; 7222 } 7223 7224 void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) { 7225 if (awakenFromDreams) { 7226 awakenDreams(); 7227 } 7228 7229 Intent dock = createHomeDockIntent(); 7230 if (dock != null) { 7231 try { 7232 if (fromHomeKey) { 7233 dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7234 } 7235 startActivityAsUser(dock, UserHandle.CURRENT); 7236 return; 7237 } catch (ActivityNotFoundException e) { 7238 } 7239 } 7240 7241 Intent intent; 7242 7243 if (fromHomeKey) { 7244 intent = new Intent(mHomeIntent); 7245 intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7246 } else { 7247 intent = mHomeIntent; 7248 } 7249 7250 startActivityAsUser(intent, UserHandle.CURRENT); 7251 } 7252 7253 /** 7254 * goes to the home screen 7255 * @return whether it did anything 7256 */ 7257 boolean goHome() { 7258 if (!isUserSetupComplete()) { 7259 Slog.i(TAG, "Not going home because user setup is in progress."); 7260 return false; 7261 } 7262 if (false) { 7263 // This code always brings home to the front. 7264 try { 7265 ActivityManagerNative.getDefault().stopAppSwitches(); 7266 } catch (RemoteException e) { 7267 } 7268 sendCloseSystemWindows(); 7269 startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */); 7270 } else { 7271 // This code brings home to the front or, if it is already 7272 // at the front, puts the device to sleep. 7273 try { 7274 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) { 7275 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry. 7276 Log.d(TAG, "UTS-TEST-MODE"); 7277 } else { 7278 ActivityManagerNative.getDefault().stopAppSwitches(); 7279 sendCloseSystemWindows(); 7280 Intent dock = createHomeDockIntent(); 7281 if (dock != null) { 7282 int result = ActivityManagerNative.getDefault() 7283 .startActivityAsUser(null, null, dock, 7284 dock.resolveTypeIfNeeded(mContext.getContentResolver()), 7285 null, null, 0, 7286 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7287 null, null, UserHandle.USER_CURRENT); 7288 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7289 return false; 7290 } 7291 } 7292 } 7293 int result = ActivityManagerNative.getDefault() 7294 .startActivityAsUser(null, null, mHomeIntent, 7295 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()), 7296 null, null, 0, 7297 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7298 null, null, UserHandle.USER_CURRENT); 7299 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7300 return false; 7301 } 7302 } catch (RemoteException ex) { 7303 // bummer, the activity manager, which is in this process, is dead 7304 } 7305 } 7306 return true; 7307 } 7308 7309 @Override 7310 public void setCurrentOrientationLw(int newOrientation) { 7311 synchronized (mLock) { 7312 if (newOrientation != mCurrentAppOrientation) { 7313 mCurrentAppOrientation = newOrientation; 7314 updateOrientationListenerLp(); 7315 } 7316 } 7317 } 7318 7319 private void performAuditoryFeedbackForAccessibilityIfNeed() { 7320 if (!isGlobalAccessibilityGestureEnabled()) { 7321 return; 7322 } 7323 AudioManager audioManager = (AudioManager) mContext.getSystemService( 7324 Context.AUDIO_SERVICE); 7325 if (audioManager.isSilentMode()) { 7326 return; 7327 } 7328 Ringtone ringTone = RingtoneManager.getRingtone(mContext, 7329 Settings.System.DEFAULT_NOTIFICATION_URI); 7330 ringTone.setStreamType(AudioManager.STREAM_MUSIC); 7331 ringTone.play(); 7332 } 7333 7334 private boolean isTheaterModeEnabled() { 7335 return Settings.Global.getInt(mContext.getContentResolver(), 7336 Settings.Global.THEATER_MODE_ON, 0) == 1; 7337 } 7338 7339 private boolean isGlobalAccessibilityGestureEnabled() { 7340 return Settings.Global.getInt(mContext.getContentResolver(), 7341 Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1; 7342 } 7343 7344 private boolean areSystemNavigationKeysEnabled() { 7345 return Settings.Secure.getIntForUser(mContext.getContentResolver(), 7346 Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1; 7347 } 7348 7349 @Override 7350 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) { 7351 if (!mVibrator.hasVibrator()) { 7352 return false; 7353 } 7354 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(), 7355 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0; 7356 if (hapticsDisabled && !always) { 7357 return false; 7358 } 7359 long[] pattern = null; 7360 switch (effectId) { 7361 case HapticFeedbackConstants.LONG_PRESS: 7362 pattern = mLongPressVibePattern; 7363 break; 7364 case HapticFeedbackConstants.VIRTUAL_KEY: 7365 pattern = mVirtualKeyVibePattern; 7366 break; 7367 case HapticFeedbackConstants.KEYBOARD_TAP: 7368 pattern = mKeyboardTapVibePattern; 7369 break; 7370 case HapticFeedbackConstants.CLOCK_TICK: 7371 pattern = mClockTickVibePattern; 7372 break; 7373 case HapticFeedbackConstants.CALENDAR_DATE: 7374 pattern = mCalendarDateVibePattern; 7375 break; 7376 case HapticFeedbackConstants.SAFE_MODE_DISABLED: 7377 pattern = mSafeModeDisabledVibePattern; 7378 break; 7379 case HapticFeedbackConstants.SAFE_MODE_ENABLED: 7380 pattern = mSafeModeEnabledVibePattern; 7381 break; 7382 case HapticFeedbackConstants.CONTEXT_CLICK: 7383 pattern = mContextClickVibePattern; 7384 break; 7385 default: 7386 return false; 7387 } 7388 int owningUid; 7389 String owningPackage; 7390 if (win != null) { 7391 owningUid = win.getOwningUid(); 7392 owningPackage = win.getOwningPackage(); 7393 } else { 7394 owningUid = android.os.Process.myUid(); 7395 owningPackage = mContext.getOpPackageName(); 7396 } 7397 if (pattern.length == 1) { 7398 // One-shot vibration 7399 mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES); 7400 } else { 7401 // Pattern vibration 7402 mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES); 7403 } 7404 return true; 7405 } 7406 7407 @Override 7408 public void keepScreenOnStartedLw() { 7409 } 7410 7411 @Override 7412 public void keepScreenOnStoppedLw() { 7413 if (isKeyguardShowingAndNotOccluded()) { 7414 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 7415 } 7416 } 7417 7418 private int updateSystemUiVisibilityLw() { 7419 // If there is no window focused, there will be nobody to handle the events 7420 // anyway, so just hang on in whatever state we're in until things settle down. 7421 final WindowState win = mFocusedWindow != null ? mFocusedWindow 7422 : mTopFullscreenOpaqueWindowState; 7423 if (win == null) { 7424 return 0; 7425 } 7426 if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) { 7427 // We are updating at a point where the keyguard has gotten 7428 // focus, but we were last in a state where the top window is 7429 // hiding it. This is probably because the keyguard as been 7430 // shown while the top window was displayed, so we want to ignore 7431 // it here because this is just a very transient change and it 7432 // will quickly lose focus once it correctly gets hidden. 7433 return 0; 7434 } 7435 7436 int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null) 7437 & ~mResettingSystemUiFlags 7438 & ~mForceClearedSystemUiFlags; 7439 if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) { 7440 tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS); 7441 } 7442 7443 final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */, 7444 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState); 7445 final int dockedVisibility = updateLightStatusBarLw(0 /* vis */, 7446 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState); 7447 mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds); 7448 mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds); 7449 final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility); 7450 final int diff = visibility ^ mLastSystemUiFlags; 7451 final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags; 7452 final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags; 7453 final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState); 7454 if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu 7455 && mFocusedApp == win.getAppToken() 7456 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds) 7457 && mLastDockedStackBounds.equals(mDockedStackBounds)) { 7458 return 0; 7459 } 7460 mLastSystemUiFlags = visibility; 7461 mLastFullscreenStackSysUiFlags = fullscreenVisibility; 7462 mLastDockedStackSysUiFlags = dockedVisibility; 7463 mLastFocusNeedsMenu = needsMenu; 7464 mFocusedApp = win.getAppToken(); 7465 final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds); 7466 final Rect dockedStackBounds = new Rect(mDockedStackBounds); 7467 mHandler.post(new Runnable() { 7468 @Override 7469 public void run() { 7470 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 7471 if (statusbar != null) { 7472 statusbar.setSystemUiVisibility(visibility, fullscreenVisibility, 7473 dockedVisibility, 0xffffffff, fullscreenStackBounds, 7474 dockedStackBounds, win.toString()); 7475 statusbar.topAppWindowChanged(needsMenu); 7476 } 7477 } 7478 }); 7479 return diff; 7480 } 7481 7482 private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) { 7483 WindowState statusColorWin = isStatusBarKeyguard() && !mHideLockScreen 7484 ? mStatusBar 7485 : opaqueOrDimming; 7486 7487 if (statusColorWin != null) { 7488 if (statusColorWin == opaque) { 7489 // If the top fullscreen-or-dimming window is also the top fullscreen, respect 7490 // its light flag. 7491 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7492 vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null) 7493 & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7494 } else if (statusColorWin != null && statusColorWin.isDimming()) { 7495 // Otherwise if it's dimming, clear the light flag. 7496 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7497 } 7498 } 7499 return vis; 7500 } 7501 7502 private boolean drawsSystemBarBackground(WindowState win) { 7503 return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0; 7504 } 7505 7506 private boolean forcesDrawStatusBarBackground(WindowState win) { 7507 return win == null || (win.getAttrs().privateFlags 7508 & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0; 7509 } 7510 7511 private int updateSystemBarsLw(WindowState win, int oldVis, int vis) { 7512 final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID); 7513 final boolean freeformStackVisible = 7514 mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID); 7515 final boolean resizing = mWindowManagerInternal.isDockedDividerResizing(); 7516 7517 // We need to force system bars when the docked stack is visible, when the freeform stack 7518 // is visible but also when we are resizing for the transitions when docked stack 7519 // visibility changes. 7520 mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing; 7521 final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard; 7522 7523 // apply translucent bar vis flags 7524 WindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen 7525 ? mStatusBar 7526 : mTopFullscreenOpaqueWindowState; 7527 vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7528 vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7529 final int dockedVis = mStatusBarController.applyTranslucentFlagLw( 7530 mTopDockedOpaqueWindowState, 0, 0); 7531 7532 final boolean fullscreenDrawsStatusBarBackground = 7533 (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState) 7534 && (vis & View.STATUS_BAR_TRANSLUCENT) == 0) 7535 || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState); 7536 final boolean dockedDrawsStatusBarBackground = 7537 (drawsSystemBarBackground(mTopDockedOpaqueWindowState) 7538 && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0) 7539 || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState); 7540 7541 // prevent status bar interaction from clearing certain flags 7542 int type = win.getAttrs().type; 7543 boolean statusBarHasFocus = type == TYPE_STATUS_BAR; 7544 if (statusBarHasFocus && !isStatusBarKeyguard()) { 7545 int flags = View.SYSTEM_UI_FLAG_FULLSCREEN 7546 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 7547 | View.SYSTEM_UI_FLAG_IMMERSIVE 7548 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 7549 | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7550 if (mHideLockScreen) { 7551 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT; 7552 } 7553 vis = (vis & ~flags) | (oldVis & flags); 7554 } 7555 7556 if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) { 7557 vis |= View.STATUS_BAR_TRANSPARENT; 7558 vis &= ~View.STATUS_BAR_TRANSLUCENT; 7559 } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar) 7560 || forceOpaqueStatusBar) { 7561 vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT); 7562 } 7563 7564 vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing); 7565 7566 // update status bar 7567 boolean immersiveSticky = 7568 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7569 final boolean hideStatusBarWM = 7570 mTopFullscreenOpaqueWindowState != null 7571 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null) 7572 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; 7573 final boolean hideStatusBarSysui = 7574 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 7575 final boolean hideNavBarSysui = 7576 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0; 7577 7578 final boolean transientStatusBarAllowed = mStatusBar != null 7579 && (statusBarHasFocus || (!mForceShowSystemBars 7580 && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky)))); 7581 7582 final boolean transientNavBarAllowed = mNavigationBar != null 7583 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky; 7584 7585 final long now = SystemClock.uptimeMillis(); 7586 final boolean pendingPanic = mPendingPanicGestureUptime != 0 7587 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION; 7588 if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) { 7589 // The user performed the panic gesture recently, we're about to hide the bars, 7590 // we're no longer on the Keyguard and the screen is ready. We can now request the bars. 7591 mPendingPanicGestureUptime = 0; 7592 mStatusBarController.showTransient(); 7593 if (!isNavBarEmpty(vis)) { 7594 mNavigationBarController.showTransient(); 7595 } 7596 } 7597 7598 final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested() 7599 && !transientStatusBarAllowed && hideStatusBarSysui; 7600 final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested() 7601 && !transientNavBarAllowed; 7602 if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) { 7603 // clear the clearable flags instead 7604 clearClearableFlagsLw(); 7605 vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS; 7606 } 7607 7608 final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; 7609 immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7610 final boolean navAllowedHidden = immersive || immersiveSticky; 7611 7612 if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType()) 7613 > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) { 7614 // We can't hide the navbar from this window otherwise the input consumer would not get 7615 // the input events. 7616 vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); 7617 } 7618 7619 vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis); 7620 7621 // update navigation bar 7622 boolean oldImmersiveMode = isImmersiveMode(oldVis); 7623 boolean newImmersiveMode = isImmersiveMode(vis); 7624 if (win != null && oldImmersiveMode != newImmersiveMode) { 7625 final String pkg = win.getOwningPackage(); 7626 mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode, 7627 isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility())); 7628 } 7629 7630 vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis); 7631 7632 return vis; 7633 } 7634 7635 /** 7636 * @return the current visibility flags with the nav-bar opacity related flags toggled based 7637 * on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}. 7638 */ 7639 private int configureNavBarOpacity(int visibility, boolean dockedStackVisible, 7640 boolean freeformStackVisible, boolean isDockedDividerResizing) { 7641 if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) { 7642 if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) { 7643 visibility = setNavBarOpaqueFlag(visibility); 7644 } 7645 } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) { 7646 if (isDockedDividerResizing) { 7647 visibility = setNavBarOpaqueFlag(visibility); 7648 } else if (freeformStackVisible) { 7649 visibility = setNavBarTranslucentFlag(visibility); 7650 } else { 7651 visibility = setNavBarOpaqueFlag(visibility); 7652 } 7653 } 7654 7655 if (!areTranslucentBarsAllowed()) { 7656 visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT; 7657 } 7658 return visibility; 7659 } 7660 7661 private int setNavBarOpaqueFlag(int visibility) { 7662 return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT); 7663 } 7664 7665 private int setNavBarTranslucentFlag(int visibility) { 7666 visibility &= ~View.NAVIGATION_BAR_TRANSPARENT; 7667 return visibility |= View.NAVIGATION_BAR_TRANSLUCENT; 7668 } 7669 7670 private void clearClearableFlagsLw() { 7671 int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS; 7672 if (newVal != mResettingSystemUiFlags) { 7673 mResettingSystemUiFlags = newVal; 7674 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 7675 } 7676 } 7677 7678 private boolean isImmersiveMode(int vis) { 7679 final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; 7680 return mNavigationBar != null 7681 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0 7682 && (vis & flags) != 0 7683 && canHideNavigationBar(); 7684 } 7685 7686 private static boolean isNavBarEmpty(int systemUiFlags) { 7687 final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME 7688 | View.STATUS_BAR_DISABLE_BACK 7689 | View.STATUS_BAR_DISABLE_RECENT); 7690 7691 return (systemUiFlags & disableNavigationBar) == disableNavigationBar; 7692 } 7693 7694 /** 7695 * @return whether the navigation or status bar can be made translucent 7696 * 7697 * This should return true unless touch exploration is not enabled or 7698 * R.boolean.config_enableTranslucentDecor is false. 7699 */ 7700 private boolean areTranslucentBarsAllowed() { 7701 return mTranslucentDecorEnabled; 7702 } 7703 7704 // Use this instead of checking config_showNavigationBar so that it can be consistently 7705 // overridden by qemu.hw.mainkeys in the emulator. 7706 @Override 7707 public boolean hasNavigationBar() { 7708 return mHasNavigationBar; 7709 } 7710 7711 @Override 7712 public void setLastInputMethodWindowLw(WindowState ime, WindowState target) { 7713 mLastInputMethodWindow = ime; 7714 mLastInputMethodTargetWindow = target; 7715 } 7716 7717 @Override 7718 public int getInputMethodWindowVisibleHeightLw() { 7719 return mDockBottom - mCurBottom; 7720 } 7721 7722 @Override 7723 public void setCurrentUserLw(int newUserId) { 7724 mCurrentUserId = newUserId; 7725 if (mKeyguardDelegate != null) { 7726 mKeyguardDelegate.setCurrentUser(newUserId); 7727 } 7728 StatusBarManagerInternal statusBar = getStatusBarManagerInternal(); 7729 if (statusBar != null) { 7730 statusBar.setCurrentUser(newUserId); 7731 } 7732 setLastInputMethodWindowLw(null, null); 7733 } 7734 7735 @Override 7736 public boolean canMagnifyWindow(int windowType) { 7737 switch (windowType) { 7738 case WindowManager.LayoutParams.TYPE_INPUT_METHOD: 7739 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: 7740 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR: 7741 case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: { 7742 return false; 7743 } 7744 } 7745 return true; 7746 } 7747 7748 @Override 7749 public boolean isTopLevelWindow(int windowType) { 7750 if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW 7751 && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 7752 return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG); 7753 } 7754 return true; 7755 } 7756 7757 @Override 7758 public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) { 7759 // For the upside down rotation we don't rotate seamlessly as the navigation 7760 // bar moves position. 7761 // Note most apps (using orientation:sensor or user as opposed to fullSensor) 7762 // will not enter the reverse portrait orientation, so actually the 7763 // orientation won't change at all. 7764 if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) { 7765 return false; 7766 } 7767 int delta = newRotation - oldRotation; 7768 if (delta < 0) delta += 4; 7769 // Likewise we don't rotate seamlessly for 180 degree rotations 7770 // in this case the surfaces never resize, and our logic to 7771 // revert the transformations on size change will fail. We could 7772 // fix this in the future with the "tagged" frames idea. 7773 if (delta == Surface.ROTATION_180) { 7774 return false; 7775 } 7776 7777 final WindowState w = mTopFullscreenOpaqueWindowState; 7778 if (w != mFocusedWindow) { 7779 return false; 7780 } 7781 7782 // We only enable seamless rotation if the top window has requested 7783 // it and is in the fullscreen opaque state. Seamless rotation 7784 // requires freezing various Surface states and won't work well 7785 // with animations, so we disable it in the animation case for now. 7786 if (w != null && !w.isAnimatingLw() && 7787 ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) || 7788 (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) { 7789 return true; 7790 } 7791 return false; 7792 } 7793 7794 @Override 7795 public void dump(String prefix, PrintWriter pw, String[] args) { 7796 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode); 7797 pw.print(" mSystemReady="); pw.print(mSystemReady); 7798 pw.print(" mSystemBooted="); pw.println(mSystemBooted); 7799 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState); 7800 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation); 7801 pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState); 7802 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged); 7803 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0 7804 || mForceClearedSystemUiFlags != 0) { 7805 pw.print(prefix); pw.print("mLastSystemUiFlags=0x"); 7806 pw.print(Integer.toHexString(mLastSystemUiFlags)); 7807 pw.print(" mResettingSystemUiFlags=0x"); 7808 pw.print(Integer.toHexString(mResettingSystemUiFlags)); 7809 pw.print(" mForceClearedSystemUiFlags=0x"); 7810 pw.println(Integer.toHexString(mForceClearedSystemUiFlags)); 7811 } 7812 if (mLastFocusNeedsMenu) { 7813 pw.print(prefix); pw.print("mLastFocusNeedsMenu="); 7814 pw.println(mLastFocusNeedsMenu); 7815 } 7816 pw.print(prefix); pw.print("mWakeGestureEnabledSetting="); 7817 pw.println(mWakeGestureEnabledSetting); 7818 7819 pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation); 7820 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode); 7821 pw.print(" mDockMode="); pw.print(mDockMode); 7822 pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture); 7823 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation); 7824 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation); 7825 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode); 7826 pw.print(" mUserRotation="); pw.print(mUserRotation); 7827 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations); 7828 pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation); 7829 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer="); 7830 pw.print(mCarDockEnablesAccelerometer); 7831 pw.print(" mDeskDockEnablesAccelerometer="); 7832 pw.println(mDeskDockEnablesAccelerometer); 7833 pw.print(prefix); pw.print("mLidKeyboardAccessibility="); 7834 pw.print(mLidKeyboardAccessibility); 7835 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility); 7836 pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock); 7837 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep); 7838 pw.print(prefix); 7839 pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior); 7840 pw.print(prefix); 7841 pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior); 7842 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior); 7843 pw.print(prefix); 7844 pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior); 7845 pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior); 7846 pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput); 7847 pw.print(prefix); pw.print("mAwake="); pw.println(mAwake); 7848 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly); 7849 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully); 7850 pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete); 7851 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete); 7852 pw.print(prefix); pw.print("mOrientationSensorEnabled="); 7853 pw.println(mOrientationSensorEnabled); 7854 pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft); 7855 pw.print(","); pw.print(mOverscanScreenTop); 7856 pw.print(") "); pw.print(mOverscanScreenWidth); 7857 pw.print("x"); pw.println(mOverscanScreenHeight); 7858 if (mOverscanLeft != 0 || mOverscanTop != 0 7859 || mOverscanRight != 0 || mOverscanBottom != 0) { 7860 pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft); 7861 pw.print(" top="); pw.print(mOverscanTop); 7862 pw.print(" right="); pw.print(mOverscanRight); 7863 pw.print(" bottom="); pw.println(mOverscanBottom); 7864 } 7865 pw.print(prefix); pw.print("mRestrictedOverscanScreen=("); 7866 pw.print(mRestrictedOverscanScreenLeft); 7867 pw.print(","); pw.print(mRestrictedOverscanScreenTop); 7868 pw.print(") "); pw.print(mRestrictedOverscanScreenWidth); 7869 pw.print("x"); pw.println(mRestrictedOverscanScreenHeight); 7870 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft); 7871 pw.print(","); pw.print(mUnrestrictedScreenTop); 7872 pw.print(") "); pw.print(mUnrestrictedScreenWidth); 7873 pw.print("x"); pw.println(mUnrestrictedScreenHeight); 7874 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft); 7875 pw.print(","); pw.print(mRestrictedScreenTop); 7876 pw.print(") "); pw.print(mRestrictedScreenWidth); 7877 pw.print("x"); pw.println(mRestrictedScreenHeight); 7878 pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft); 7879 pw.print(","); pw.print(mStableFullscreenTop); 7880 pw.print(")-("); pw.print(mStableFullscreenRight); 7881 pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")"); 7882 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft); 7883 pw.print(","); pw.print(mStableTop); 7884 pw.print(")-("); pw.print(mStableRight); 7885 pw.print(","); pw.print(mStableBottom); pw.println(")"); 7886 pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft); 7887 pw.print(","); pw.print(mSystemTop); 7888 pw.print(")-("); pw.print(mSystemRight); 7889 pw.print(","); pw.print(mSystemBottom); pw.println(")"); 7890 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft); 7891 pw.print(","); pw.print(mCurTop); 7892 pw.print(")-("); pw.print(mCurRight); 7893 pw.print(","); pw.print(mCurBottom); pw.println(")"); 7894 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft); 7895 pw.print(","); pw.print(mContentTop); 7896 pw.print(")-("); pw.print(mContentRight); 7897 pw.print(","); pw.print(mContentBottom); pw.println(")"); 7898 pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft); 7899 pw.print(","); pw.print(mVoiceContentTop); 7900 pw.print(")-("); pw.print(mVoiceContentRight); 7901 pw.print(","); pw.print(mVoiceContentBottom); pw.println(")"); 7902 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft); 7903 pw.print(","); pw.print(mDockTop); 7904 pw.print(")-("); pw.print(mDockRight); 7905 pw.print(","); pw.print(mDockBottom); pw.println(")"); 7906 pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer); 7907 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer); 7908 pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen); 7909 pw.print(" mShowingDream="); pw.print(mShowingDream); 7910 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen); 7911 pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken); 7912 if (mLastInputMethodWindow != null) { 7913 pw.print(prefix); pw.print("mLastInputMethodWindow="); 7914 pw.println(mLastInputMethodWindow); 7915 } 7916 if (mLastInputMethodTargetWindow != null) { 7917 pw.print(prefix); pw.print("mLastInputMethodTargetWindow="); 7918 pw.println(mLastInputMethodTargetWindow); 7919 } 7920 if (mStatusBar != null) { 7921 pw.print(prefix); pw.print("mStatusBar="); 7922 pw.print(mStatusBar); pw.print(" isStatusBarKeyguard="); 7923 pw.println(isStatusBarKeyguard()); 7924 } 7925 if (mNavigationBar != null) { 7926 pw.print(prefix); pw.print("mNavigationBar="); 7927 pw.println(mNavigationBar); 7928 } 7929 if (mFocusedWindow != null) { 7930 pw.print(prefix); pw.print("mFocusedWindow="); 7931 pw.println(mFocusedWindow); 7932 } 7933 if (mFocusedApp != null) { 7934 pw.print(prefix); pw.print("mFocusedApp="); 7935 pw.println(mFocusedApp); 7936 } 7937 if (mWinDismissingKeyguard != null) { 7938 pw.print(prefix); pw.print("mWinDismissingKeyguard="); 7939 pw.println(mWinDismissingKeyguard); 7940 } 7941 if (mTopFullscreenOpaqueWindowState != null) { 7942 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState="); 7943 pw.println(mTopFullscreenOpaqueWindowState); 7944 } 7945 if (mTopFullscreenOpaqueOrDimmingWindowState != null) { 7946 pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState="); 7947 pw.println(mTopFullscreenOpaqueOrDimmingWindowState); 7948 } 7949 if (mForcingShowNavBar) { 7950 pw.print(prefix); pw.print("mForcingShowNavBar="); 7951 pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer="); 7952 pw.println(mForcingShowNavBarLayer); 7953 } 7954 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen); 7955 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen); 7956 pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar); 7957 pw.print(" mForceStatusBarFromKeyguard="); 7958 pw.println(mForceStatusBarFromKeyguard); 7959 pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard); 7960 pw.print(" mWinDismissingKeyguard="); pw.print(mWinDismissingKeyguard); 7961 pw.print(" mHomePressed="); pw.println(mHomePressed); 7962 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn); 7963 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout); 7964 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive); 7965 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior); 7966 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior); 7967 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior); 7968 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation); 7969 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation); 7970 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation); 7971 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation); 7972 pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation); 7973 pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock); 7974 pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation); 7975 7976 mGlobalKeyManager.dump(prefix, pw); 7977 mStatusBarController.dump(pw, prefix); 7978 mNavigationBarController.dump(pw, prefix); 7979 PolicyControl.dump(prefix, pw); 7980 7981 if (mWakeGestureListener != null) { 7982 mWakeGestureListener.dump(pw, prefix); 7983 } 7984 if (mOrientationListener != null) { 7985 mOrientationListener.dump(pw, prefix); 7986 } 7987 if (mBurnInProtectionHelper != null) { 7988 mBurnInProtectionHelper.dump(prefix, pw); 7989 } 7990 if (mKeyguardDelegate != null) { 7991 mKeyguardDelegate.dump(prefix, pw); 7992 } 7993 } 7994} 7995