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