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