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