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