PhoneWindowManager.java revision 909fe2d4f5f9a00faa25500c012cfe475c136def
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 if (wasOccluded != isOccluded) { 5485 mKeyguardOccluded = isOccluded; 5486 mKeyguardDelegate.setOccluded(isOccluded, false /* animate */); 5487 return false; 5488 } else { 5489 return false; 5490 } 5491 } 5492 5493 private boolean isStatusBarKeyguard() { 5494 return mStatusBar != null 5495 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0; 5496 } 5497 5498 @Override 5499 public boolean allowAppAnimationsLw() { 5500 if (isStatusBarKeyguard() || mShowingDream) { 5501 // If keyguard or dreams is currently visible, no reason to animate behind it. 5502 return false; 5503 } 5504 return true; 5505 } 5506 5507 @Override 5508 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) { 5509 mFocusedWindow = newFocus; 5510 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5511 // If the navigation bar has been hidden or shown, we need to do another 5512 // layout pass to update that window. 5513 return FINISH_LAYOUT_REDO_LAYOUT; 5514 } 5515 return 0; 5516 } 5517 5518 /** {@inheritDoc} */ 5519 @Override 5520 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { 5521 // lid changed state 5522 final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED; 5523 if (newLidState == mLidState) { 5524 return; 5525 } 5526 5527 mLidState = newLidState; 5528 applyLidSwitchState(); 5529 updateRotation(true); 5530 5531 if (lidOpen) { 5532 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch, 5533 "android.policy:LID"); 5534 } else if (!mLidControlsSleep) { 5535 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 5536 } 5537 } 5538 5539 @Override 5540 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) { 5541 int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED; 5542 if (mCameraLensCoverState == lensCoverState) { 5543 return; 5544 } 5545 if (mCameraLensCoverState == CAMERA_LENS_COVERED && 5546 lensCoverState == CAMERA_LENS_UNCOVERED) { 5547 Intent intent; 5548 final boolean keyguardActive = mKeyguardDelegate == null ? false : 5549 mKeyguardDelegate.isShowing(); 5550 if (keyguardActive) { 5551 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE); 5552 } else { 5553 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); 5554 } 5555 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens, 5556 "android.policy:CAMERA_COVER"); 5557 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); 5558 } 5559 mCameraLensCoverState = lensCoverState; 5560 } 5561 5562 void setHdmiPlugged(boolean plugged) { 5563 if (mHdmiPlugged != plugged) { 5564 mHdmiPlugged = plugged; 5565 updateRotation(true, true); 5566 Intent intent = new Intent(ACTION_HDMI_PLUGGED); 5567 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5568 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged); 5569 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 5570 } 5571 } 5572 5573 void initializeHdmiState() { 5574 boolean plugged = false; 5575 // watch for HDMI plug messages if the hdmi switch exists 5576 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) { 5577 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi"); 5578 5579 final String filename = "/sys/class/switch/hdmi/state"; 5580 FileReader reader = null; 5581 try { 5582 reader = new FileReader(filename); 5583 char[] buf = new char[15]; 5584 int n = reader.read(buf); 5585 if (n > 1) { 5586 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1)); 5587 } 5588 } catch (IOException ex) { 5589 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5590 } catch (NumberFormatException ex) { 5591 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5592 } finally { 5593 if (reader != null) { 5594 try { 5595 reader.close(); 5596 } catch (IOException ex) { 5597 } 5598 } 5599 } 5600 } 5601 // This dance forces the code in setHdmiPlugged to run. 5602 // Always do this so the sticky intent is stuck (to false) if there is no hdmi. 5603 mHdmiPlugged = !plugged; 5604 setHdmiPlugged(!mHdmiPlugged); 5605 } 5606 5607 final Object mScreenshotLock = new Object(); 5608 ServiceConnection mScreenshotConnection = null; 5609 5610 final Runnable mScreenshotTimeout = new Runnable() { 5611 @Override public void run() { 5612 synchronized (mScreenshotLock) { 5613 if (mScreenshotConnection != null) { 5614 mContext.unbindService(mScreenshotConnection); 5615 mScreenshotConnection = null; 5616 notifyScreenshotError(); 5617 } 5618 } 5619 } 5620 }; 5621 5622 // Assume this is called from the Handler thread. 5623 private void takeScreenshot(final int screenshotType) { 5624 synchronized (mScreenshotLock) { 5625 if (mScreenshotConnection != null) { 5626 return; 5627 } 5628 final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE, 5629 SYSUI_SCREENSHOT_SERVICE); 5630 final Intent serviceIntent = new Intent(); 5631 serviceIntent.setComponent(serviceComponent); 5632 ServiceConnection conn = new ServiceConnection() { 5633 @Override 5634 public void onServiceConnected(ComponentName name, IBinder service) { 5635 synchronized (mScreenshotLock) { 5636 if (mScreenshotConnection != this) { 5637 return; 5638 } 5639 Messenger messenger = new Messenger(service); 5640 Message msg = Message.obtain(null, screenshotType); 5641 final ServiceConnection myConn = this; 5642 Handler h = new Handler(mHandler.getLooper()) { 5643 @Override 5644 public void handleMessage(Message msg) { 5645 synchronized (mScreenshotLock) { 5646 if (mScreenshotConnection == myConn) { 5647 mContext.unbindService(mScreenshotConnection); 5648 mScreenshotConnection = null; 5649 mHandler.removeCallbacks(mScreenshotTimeout); 5650 } 5651 } 5652 } 5653 }; 5654 msg.replyTo = new Messenger(h); 5655 msg.arg1 = msg.arg2 = 0; 5656 if (mStatusBar != null && mStatusBar.isVisibleLw()) 5657 msg.arg1 = 1; 5658 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) 5659 msg.arg2 = 1; 5660 try { 5661 messenger.send(msg); 5662 } catch (RemoteException e) { 5663 } 5664 } 5665 } 5666 5667 @Override 5668 public void onServiceDisconnected(ComponentName name) { 5669 synchronized (mScreenshotLock) { 5670 if (mScreenshotConnection != null) { 5671 mContext.unbindService(mScreenshotConnection); 5672 mScreenshotConnection = null; 5673 mHandler.removeCallbacks(mScreenshotTimeout); 5674 notifyScreenshotError(); 5675 } 5676 } 5677 } 5678 }; 5679 if (mContext.bindServiceAsUser(serviceIntent, conn, 5680 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, 5681 UserHandle.CURRENT)) { 5682 mScreenshotConnection = conn; 5683 mHandler.postDelayed(mScreenshotTimeout, 10000); 5684 } 5685 } 5686 } 5687 5688 /** 5689 * Notifies the screenshot service to show an error. 5690 */ 5691 private void notifyScreenshotError() { 5692 // If the service process is killed, then ask it to clean up after itself 5693 final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE, 5694 SYSUI_SCREENSHOT_ERROR_RECEIVER); 5695 Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT); 5696 errorIntent.setComponent(errorComponent); 5697 errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | 5698 Intent.FLAG_RECEIVER_FOREGROUND); 5699 mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT); 5700 } 5701 5702 /** {@inheritDoc} */ 5703 @Override 5704 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { 5705 if (!mSystemBooted) { 5706 // If we have not yet booted, don't let key events do anything. 5707 return 0; 5708 } 5709 5710 final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0; 5711 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; 5712 final boolean canceled = event.isCanceled(); 5713 final int keyCode = event.getKeyCode(); 5714 5715 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; 5716 5717 // If screen is off then we treat the case where the keyguard is open but hidden 5718 // the same as if it were open and in front. 5719 // This will prevent any keys other than the power button from waking the screen 5720 // when the keyguard is hidden by another activity. 5721 final boolean keyguardActive = (mKeyguardDelegate == null ? false : 5722 (interactive ? 5723 isKeyguardShowingAndNotOccluded() : 5724 mKeyguardDelegate.isShowing())); 5725 5726 if (DEBUG_INPUT) { 5727 Log.d(TAG, "interceptKeyTq keycode=" + keyCode 5728 + " interactive=" + interactive + " keyguardActive=" + keyguardActive 5729 + " policyFlags=" + Integer.toHexString(policyFlags)); 5730 } 5731 5732 // Basic policy based on interactive state. 5733 int result; 5734 boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0 5735 || event.isWakeKey(); 5736 if (interactive || (isInjected && !isWakeKey)) { 5737 // When the device is interactive or the key is injected pass the 5738 // key to the application. 5739 result = ACTION_PASS_TO_USER; 5740 isWakeKey = false; 5741 5742 if (interactive) { 5743 // If the screen is awake, but the button pressed was the one that woke the device 5744 // then don't pass it to the application 5745 if (keyCode == mPendingWakeKey && !down) { 5746 result = 0; 5747 } 5748 // Reset the pending key 5749 mPendingWakeKey = PENDING_KEY_NULL; 5750 } 5751 } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) { 5752 // If we're currently dozing with the screen on and the keyguard showing, pass the key 5753 // to the application but preserve its wake key status to make sure we still move 5754 // from dozing to fully interactive if we would normally go from off to fully 5755 // interactive. 5756 result = ACTION_PASS_TO_USER; 5757 // Since we're dispatching the input, reset the pending key 5758 mPendingWakeKey = PENDING_KEY_NULL; 5759 } else { 5760 // When the screen is off and the key is not injected, determine whether 5761 // to wake the device but don't pass the key to the application. 5762 result = 0; 5763 if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) { 5764 isWakeKey = false; 5765 } 5766 // Cache the wake key on down event so we can also avoid sending the up event to the app 5767 if (isWakeKey && down) { 5768 mPendingWakeKey = keyCode; 5769 } 5770 } 5771 5772 // If the key would be handled globally, just return the result, don't worry about special 5773 // key processing. 5774 if (isValidGlobalKey(keyCode) 5775 && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) { 5776 if (isWakeKey) { 5777 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 5778 } 5779 return result; 5780 } 5781 5782 boolean useHapticFeedback = down 5783 && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0 5784 && event.getRepeatCount() == 0; 5785 5786 // Handle special keys. 5787 switch (keyCode) { 5788 case KeyEvent.KEYCODE_BACK: { 5789 if (down) { 5790 interceptBackKeyDown(); 5791 } else { 5792 boolean handled = interceptBackKeyUp(event); 5793 5794 // Don't pass back press to app if we've already handled it via long press 5795 if (handled) { 5796 result &= ~ACTION_PASS_TO_USER; 5797 } 5798 } 5799 break; 5800 } 5801 5802 case KeyEvent.KEYCODE_VOLUME_DOWN: 5803 case KeyEvent.KEYCODE_VOLUME_UP: 5804 case KeyEvent.KEYCODE_VOLUME_MUTE: { 5805 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { 5806 if (down) { 5807 if (interactive && !mScreenshotChordVolumeDownKeyTriggered 5808 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5809 mScreenshotChordVolumeDownKeyTriggered = true; 5810 mScreenshotChordVolumeDownKeyTime = event.getDownTime(); 5811 mScreenshotChordVolumeDownKeyConsumed = false; 5812 cancelPendingPowerKeyAction(); 5813 interceptScreenshotChord(); 5814 } 5815 } else { 5816 mScreenshotChordVolumeDownKeyTriggered = false; 5817 cancelPendingScreenshotChordAction(); 5818 } 5819 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 5820 if (down) { 5821 if (interactive && !mScreenshotChordVolumeUpKeyTriggered 5822 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5823 mScreenshotChordVolumeUpKeyTriggered = true; 5824 cancelPendingPowerKeyAction(); 5825 cancelPendingScreenshotChordAction(); 5826 } 5827 } else { 5828 mScreenshotChordVolumeUpKeyTriggered = false; 5829 cancelPendingScreenshotChordAction(); 5830 } 5831 } 5832 if (down) { 5833 TelecomManager telecomManager = getTelecommService(); 5834 if (telecomManager != null) { 5835 if (telecomManager.isRinging()) { 5836 // If an incoming call is ringing, either VOLUME key means 5837 // "silence ringer". We handle these keys here, rather than 5838 // in the InCallScreen, to make sure we'll respond to them 5839 // even if the InCallScreen hasn't come to the foreground yet. 5840 // Look for the DOWN event here, to agree with the "fallback" 5841 // behavior in the InCallScreen. 5842 Log.i(TAG, "interceptKeyBeforeQueueing:" 5843 + " VOLUME key-down while ringing: Silence ringer!"); 5844 5845 // Silence the ringer. (It's safe to call this 5846 // even if the ringer has already been silenced.) 5847 telecomManager.silenceRinger(); 5848 5849 // And *don't* pass this key thru to the current activity 5850 // (which is probably the InCallScreen.) 5851 result &= ~ACTION_PASS_TO_USER; 5852 break; 5853 } 5854 if (telecomManager.isInCall() 5855 && (result & ACTION_PASS_TO_USER) == 0) { 5856 // If we are in call but we decided not to pass the key to 5857 // the application, just pass it to the session service. 5858 5859 MediaSessionLegacyHelper.getHelper(mContext) 5860 .sendVolumeKeyEvent(event, false); 5861 break; 5862 } 5863 } 5864 } 5865 if (mUseTvRouting) { 5866 // On TVs, defer special key handlings to 5867 // {@link interceptKeyBeforeDispatching()}. 5868 result |= ACTION_PASS_TO_USER; 5869 } else if ((result & ACTION_PASS_TO_USER) == 0) { 5870 // If we aren't passing to the user and no one else 5871 // handled it send it to the session manager to 5872 // figure out. 5873 MediaSessionLegacyHelper.getHelper(mContext) 5874 .sendVolumeKeyEvent(event, true); 5875 } 5876 break; 5877 } 5878 5879 case KeyEvent.KEYCODE_ENDCALL: { 5880 result &= ~ACTION_PASS_TO_USER; 5881 if (down) { 5882 TelecomManager telecomManager = getTelecommService(); 5883 boolean hungUp = false; 5884 if (telecomManager != null) { 5885 hungUp = telecomManager.endCall(); 5886 } 5887 if (interactive && !hungUp) { 5888 mEndCallKeyHandled = false; 5889 mHandler.postDelayed(mEndCallLongPress, 5890 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 5891 } else { 5892 mEndCallKeyHandled = true; 5893 } 5894 } else { 5895 if (!mEndCallKeyHandled) { 5896 mHandler.removeCallbacks(mEndCallLongPress); 5897 if (!canceled) { 5898 if ((mEndcallBehavior 5899 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) { 5900 if (goHome()) { 5901 break; 5902 } 5903 } 5904 if ((mEndcallBehavior 5905 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) { 5906 mPowerManager.goToSleep(event.getEventTime(), 5907 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); 5908 isWakeKey = false; 5909 } 5910 } 5911 } 5912 } 5913 break; 5914 } 5915 5916 case KeyEvent.KEYCODE_POWER: { 5917 result &= ~ACTION_PASS_TO_USER; 5918 isWakeKey = false; // wake-up will be handled separately 5919 if (down) { 5920 interceptPowerKeyDown(event, interactive); 5921 } else { 5922 interceptPowerKeyUp(event, interactive, canceled); 5923 } 5924 break; 5925 } 5926 5927 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN: 5928 // fall through 5929 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP: 5930 // fall through 5931 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT: 5932 // fall through 5933 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: { 5934 result &= ~ACTION_PASS_TO_USER; 5935 interceptSystemNavigationKey(event); 5936 break; 5937 } 5938 5939 case KeyEvent.KEYCODE_SLEEP: { 5940 result &= ~ACTION_PASS_TO_USER; 5941 isWakeKey = false; 5942 if (!mPowerManager.isInteractive()) { 5943 useHapticFeedback = false; // suppress feedback if already non-interactive 5944 } 5945 if (down) { 5946 sleepPress(event.getEventTime()); 5947 } else { 5948 sleepRelease(event.getEventTime()); 5949 } 5950 break; 5951 } 5952 5953 case KeyEvent.KEYCODE_SOFT_SLEEP: { 5954 result &= ~ACTION_PASS_TO_USER; 5955 isWakeKey = false; 5956 if (!down) { 5957 mPowerManagerInternal.setUserInactiveOverrideFromWindowManager(); 5958 } 5959 break; 5960 } 5961 5962 case KeyEvent.KEYCODE_WAKEUP: { 5963 result &= ~ACTION_PASS_TO_USER; 5964 isWakeKey = true; 5965 break; 5966 } 5967 5968 case KeyEvent.KEYCODE_MEDIA_PLAY: 5969 case KeyEvent.KEYCODE_MEDIA_PAUSE: 5970 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 5971 case KeyEvent.KEYCODE_HEADSETHOOK: 5972 case KeyEvent.KEYCODE_MUTE: 5973 case KeyEvent.KEYCODE_MEDIA_STOP: 5974 case KeyEvent.KEYCODE_MEDIA_NEXT: 5975 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 5976 case KeyEvent.KEYCODE_MEDIA_REWIND: 5977 case KeyEvent.KEYCODE_MEDIA_RECORD: 5978 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 5979 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { 5980 if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) { 5981 // If the global session is active pass all media keys to it 5982 // instead of the active window. 5983 result &= ~ACTION_PASS_TO_USER; 5984 } 5985 if ((result & ACTION_PASS_TO_USER) == 0) { 5986 // Only do this if we would otherwise not pass it to the user. In that 5987 // case, the PhoneWindow class will do the same thing, except it will 5988 // only do it if the showing app doesn't process the key on its own. 5989 // Note that we need to make a copy of the key event here because the 5990 // original key event will be recycled when we return. 5991 mBroadcastWakeLock.acquire(); 5992 Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK, 5993 new KeyEvent(event)); 5994 msg.setAsynchronous(true); 5995 msg.sendToTarget(); 5996 } 5997 break; 5998 } 5999 6000 case KeyEvent.KEYCODE_CALL: { 6001 if (down) { 6002 TelecomManager telecomManager = getTelecommService(); 6003 if (telecomManager != null) { 6004 if (telecomManager.isRinging()) { 6005 Log.i(TAG, "interceptKeyBeforeQueueing:" 6006 + " CALL key-down while ringing: Answer the call!"); 6007 telecomManager.acceptRingingCall(); 6008 6009 // And *don't* pass this key thru to the current activity 6010 // (which is presumably the InCallScreen.) 6011 result &= ~ACTION_PASS_TO_USER; 6012 } 6013 } 6014 } 6015 break; 6016 } 6017 case KeyEvent.KEYCODE_VOICE_ASSIST: { 6018 // Only do this if we would otherwise not pass it to the user. In that case, 6019 // interceptKeyBeforeDispatching would apply a similar but different policy in 6020 // order to invoke voice assist actions. Note that we need to make a copy of the 6021 // key event here because the original key event will be recycled when we return. 6022 if ((result & ACTION_PASS_TO_USER) == 0 && !down) { 6023 mBroadcastWakeLock.acquire(); 6024 Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK, 6025 keyguardActive ? 1 : 0, 0); 6026 msg.setAsynchronous(true); 6027 msg.sendToTarget(); 6028 } 6029 break; 6030 } 6031 case KeyEvent.KEYCODE_WINDOW: { 6032 if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) { 6033 if (mTvPictureInPictureVisible) { 6034 // Consumes the key only if picture-in-picture is visible 6035 // to show picture-in-picture control menu. 6036 // This gives a chance to the foreground activity 6037 // to customize PIP key behavior. 6038 if (!down) { 6039 showTvPictureInPictureMenu(event); 6040 } 6041 result &= ~ACTION_PASS_TO_USER; 6042 } 6043 } 6044 break; 6045 } 6046 } 6047 6048 if (useHapticFeedback) { 6049 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); 6050 } 6051 6052 if (isWakeKey) { 6053 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 6054 } 6055 6056 return result; 6057 } 6058 6059 /** 6060 * Handle statusbar expansion events. 6061 * @param event 6062 */ 6063 private void interceptSystemNavigationKey(KeyEvent event) { 6064 if (event.getAction() == KeyEvent.ACTION_UP && areSystemNavigationKeysEnabled()) { 6065 IStatusBarService sbar = getStatusBarService(); 6066 if (sbar != null) { 6067 try { 6068 sbar.handleSystemNavigationKey(event.getKeyCode()); 6069 } catch (RemoteException e1) { 6070 // oops, no statusbar. Ignore event. 6071 } 6072 } 6073 } 6074 } 6075 6076 /** 6077 * Returns true if the key can have global actions attached to it. 6078 * We reserve all power management keys for the system since they require 6079 * very careful handling. 6080 */ 6081 private static boolean isValidGlobalKey(int keyCode) { 6082 switch (keyCode) { 6083 case KeyEvent.KEYCODE_POWER: 6084 case KeyEvent.KEYCODE_WAKEUP: 6085 case KeyEvent.KEYCODE_SLEEP: 6086 return false; 6087 default: 6088 return true; 6089 } 6090 } 6091 6092 /** 6093 * When the screen is off we ignore some keys that might otherwise typically 6094 * be considered wake keys. We filter them out here. 6095 * 6096 * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it 6097 * is always considered a wake key. 6098 */ 6099 private boolean isWakeKeyWhenScreenOff(int keyCode) { 6100 switch (keyCode) { 6101 // ignore volume keys unless docked 6102 case KeyEvent.KEYCODE_VOLUME_UP: 6103 case KeyEvent.KEYCODE_VOLUME_DOWN: 6104 case KeyEvent.KEYCODE_VOLUME_MUTE: 6105 return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED; 6106 6107 // ignore media and camera keys 6108 case KeyEvent.KEYCODE_MUTE: 6109 case KeyEvent.KEYCODE_HEADSETHOOK: 6110 case KeyEvent.KEYCODE_MEDIA_PLAY: 6111 case KeyEvent.KEYCODE_MEDIA_PAUSE: 6112 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 6113 case KeyEvent.KEYCODE_MEDIA_STOP: 6114 case KeyEvent.KEYCODE_MEDIA_NEXT: 6115 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 6116 case KeyEvent.KEYCODE_MEDIA_REWIND: 6117 case KeyEvent.KEYCODE_MEDIA_RECORD: 6118 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 6119 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: 6120 case KeyEvent.KEYCODE_CAMERA: 6121 return false; 6122 } 6123 return true; 6124 } 6125 6126 6127 /** {@inheritDoc} */ 6128 @Override 6129 public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) { 6130 if ((policyFlags & FLAG_WAKE) != 0) { 6131 if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion, 6132 "android.policy:MOTION")) { 6133 return 0; 6134 } 6135 } 6136 6137 if (shouldDispatchInputWhenNonInteractive(null)) { 6138 return ACTION_PASS_TO_USER; 6139 } 6140 6141 // If we have not passed the action up and we are in theater mode without dreaming, 6142 // there will be no dream to intercept the touch and wake into ambient. The device should 6143 // wake up in this case. 6144 if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) { 6145 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming, 6146 "android.policy:MOTION"); 6147 } 6148 6149 return 0; 6150 } 6151 6152 private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) { 6153 final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF); 6154 6155 if (displayOff && !mHasFeatureWatch) { 6156 return false; 6157 } 6158 6159 // Send events to keyguard while the screen is on and it's showing. 6160 if (isKeyguardShowingAndNotOccluded() && !displayOff) { 6161 return true; 6162 } 6163 6164 // Watches handle BACK specially 6165 if (mHasFeatureWatch 6166 && event != null 6167 && (event.getKeyCode() == KeyEvent.KEYCODE_BACK 6168 || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) { 6169 return false; 6170 } 6171 6172 // Send events to a dozing dream even if the screen is off since the dream 6173 // is in control of the state of the screen. 6174 IDreamManager dreamManager = getDreamManager(); 6175 6176 try { 6177 if (dreamManager != null && dreamManager.isDreaming()) { 6178 return true; 6179 } 6180 } catch (RemoteException e) { 6181 Slog.e(TAG, "RemoteException when checking if dreaming", e); 6182 } 6183 6184 // Otherwise, consume events since the user can't see what is being 6185 // interacted with. 6186 return false; 6187 } 6188 6189 private void dispatchDirectAudioEvent(KeyEvent event) { 6190 if (event.getAction() != KeyEvent.ACTION_DOWN) { 6191 return; 6192 } 6193 int keyCode = event.getKeyCode(); 6194 int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND 6195 | AudioManager.FLAG_FROM_KEY; 6196 String pkgName = mContext.getOpPackageName(); 6197 switch (keyCode) { 6198 case KeyEvent.KEYCODE_VOLUME_UP: 6199 try { 6200 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE, 6201 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6202 } catch (RemoteException e) { 6203 Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e); 6204 } 6205 break; 6206 case KeyEvent.KEYCODE_VOLUME_DOWN: 6207 try { 6208 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER, 6209 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6210 } catch (RemoteException e) { 6211 Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e); 6212 } 6213 break; 6214 case KeyEvent.KEYCODE_VOLUME_MUTE: 6215 try { 6216 if (event.getRepeatCount() == 0) { 6217 getAudioService().adjustSuggestedStreamVolume( 6218 AudioManager.ADJUST_TOGGLE_MUTE, 6219 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6220 } 6221 } catch (RemoteException e) { 6222 Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e); 6223 } 6224 break; 6225 } 6226 } 6227 6228 void dispatchMediaKeyWithWakeLock(KeyEvent event) { 6229 if (DEBUG_INPUT) { 6230 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event); 6231 } 6232 6233 if (mHavePendingMediaKeyRepeatWithWakeLock) { 6234 if (DEBUG_INPUT) { 6235 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat"); 6236 } 6237 6238 mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK); 6239 mHavePendingMediaKeyRepeatWithWakeLock = false; 6240 mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock 6241 } 6242 6243 dispatchMediaKeyWithWakeLockToAudioService(event); 6244 6245 if (event.getAction() == KeyEvent.ACTION_DOWN 6246 && event.getRepeatCount() == 0) { 6247 mHavePendingMediaKeyRepeatWithWakeLock = true; 6248 6249 Message msg = mHandler.obtainMessage( 6250 MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event); 6251 msg.setAsynchronous(true); 6252 mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout()); 6253 } else { 6254 mBroadcastWakeLock.release(); 6255 } 6256 } 6257 6258 void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) { 6259 mHavePendingMediaKeyRepeatWithWakeLock = false; 6260 6261 KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event, 6262 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS); 6263 if (DEBUG_INPUT) { 6264 Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent); 6265 } 6266 6267 dispatchMediaKeyWithWakeLockToAudioService(repeatEvent); 6268 mBroadcastWakeLock.release(); 6269 } 6270 6271 void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) { 6272 if (ActivityManagerNative.isSystemReady()) { 6273 MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true); 6274 } 6275 } 6276 6277 void launchVoiceAssistWithWakeLock(boolean keyguardActive) { 6278 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface( 6279 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); 6280 if (dic != null) { 6281 try { 6282 dic.exitIdle("voice-search"); 6283 } catch (RemoteException e) { 6284 } 6285 } 6286 Intent voiceIntent = 6287 new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); 6288 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive); 6289 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF); 6290 mBroadcastWakeLock.release(); 6291 } 6292 6293 BroadcastReceiver mDockReceiver = new BroadcastReceiver() { 6294 @Override 6295 public void onReceive(Context context, Intent intent) { 6296 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) { 6297 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 6298 Intent.EXTRA_DOCK_STATE_UNDOCKED); 6299 } else { 6300 try { 6301 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface( 6302 ServiceManager.getService(Context.UI_MODE_SERVICE)); 6303 mUiMode = uiModeService.getCurrentModeType(); 6304 } catch (RemoteException e) { 6305 } 6306 } 6307 updateRotation(true); 6308 synchronized (mLock) { 6309 updateOrientationListenerLp(); 6310 } 6311 } 6312 }; 6313 6314 BroadcastReceiver mDreamReceiver = new BroadcastReceiver() { 6315 @Override 6316 public void onReceive(Context context, Intent intent) { 6317 if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) { 6318 if (mKeyguardDelegate != null) { 6319 mKeyguardDelegate.onDreamingStarted(); 6320 } 6321 } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) { 6322 if (mKeyguardDelegate != null) { 6323 mKeyguardDelegate.onDreamingStopped(); 6324 } 6325 } 6326 } 6327 }; 6328 6329 BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() { 6330 @Override 6331 public void onReceive(Context context, Intent intent) { 6332 if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) { 6333 // tickle the settings observer: this first ensures that we're 6334 // observing the relevant settings for the newly-active user, 6335 // and then updates our own bookkeeping based on the now- 6336 // current user. 6337 mSettingsObserver.onChange(false); 6338 6339 // force a re-application of focused window sysui visibility. 6340 // the window may never have been shown for this user 6341 // e.g. the keyguard when going through the new-user setup flow 6342 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6343 mLastSystemUiFlags = 0; 6344 updateSystemUiVisibilityLw(); 6345 } 6346 } 6347 } 6348 }; 6349 6350 private final Runnable mHiddenNavPanic = new Runnable() { 6351 @Override 6352 public void run() { 6353 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6354 if (!isUserSetupComplete()) { 6355 // Swipe-up for navigation bar is disabled during setup 6356 return; 6357 } 6358 mPendingPanicGestureUptime = SystemClock.uptimeMillis(); 6359 if (!isNavBarEmpty(mLastSystemUiFlags)) { 6360 mNavigationBarController.showTransient(); 6361 } 6362 } 6363 } 6364 }; 6365 6366 private void requestTransientBars(WindowState swipeTarget) { 6367 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6368 if (!isUserSetupComplete()) { 6369 // Swipe-up for navigation bar is disabled during setup 6370 return; 6371 } 6372 boolean sb = mStatusBarController.checkShowTransientBarLw(); 6373 boolean nb = mNavigationBarController.checkShowTransientBarLw() 6374 && !isNavBarEmpty(mLastSystemUiFlags); 6375 if (sb || nb) { 6376 // Don't show status bar when swiping on already visible navigation bar 6377 if (!nb && swipeTarget == mNavigationBar) { 6378 if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target"); 6379 return; 6380 } 6381 if (sb) mStatusBarController.showTransient(); 6382 if (nb) mNavigationBarController.showTransient(); 6383 mImmersiveModeConfirmation.confirmCurrentPrompt(); 6384 updateSystemUiVisibilityLw(); 6385 } 6386 } 6387 } 6388 6389 // Called on the PowerManager's Notifier thread. 6390 @Override 6391 public void startedGoingToSleep(int why) { 6392 if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")"); 6393 mCameraGestureTriggeredDuringGoingToSleep = false; 6394 mGoingToSleep = true; 6395 if (mKeyguardDelegate != null) { 6396 mKeyguardDelegate.onStartedGoingToSleep(why); 6397 } 6398 } 6399 6400 // Called on the PowerManager's Notifier thread. 6401 @Override 6402 public void finishedGoingToSleep(int why) { 6403 EventLog.writeEvent(70000, 0); 6404 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")"); 6405 MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000); 6406 6407 mGoingToSleep = false; 6408 6409 // We must get this work done here because the power manager will drop 6410 // the wake lock and let the system suspend once this function returns. 6411 synchronized (mLock) { 6412 mAwake = false; 6413 updateWakeGestureListenerLp(); 6414 updateOrientationListenerLp(); 6415 updateLockScreenTimeout(); 6416 } 6417 if (mKeyguardDelegate != null) { 6418 mKeyguardDelegate.onFinishedGoingToSleep(why, 6419 mCameraGestureTriggeredDuringGoingToSleep); 6420 } 6421 mCameraGestureTriggeredDuringGoingToSleep = false; 6422 } 6423 6424 // Called on the PowerManager's Notifier thread. 6425 @Override 6426 public void startedWakingUp() { 6427 EventLog.writeEvent(70000, 1); 6428 if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up..."); 6429 6430 // Since goToSleep performs these functions synchronously, we must 6431 // do the same here. We cannot post this work to a handler because 6432 // that might cause it to become reordered with respect to what 6433 // may happen in a future call to goToSleep. 6434 synchronized (mLock) { 6435 mAwake = true; 6436 6437 updateWakeGestureListenerLp(); 6438 updateOrientationListenerLp(); 6439 updateLockScreenTimeout(); 6440 } 6441 6442 if (mKeyguardDelegate != null) { 6443 mKeyguardDelegate.onStartedWakingUp(); 6444 } 6445 } 6446 6447 // Called on the PowerManager's Notifier thread. 6448 @Override 6449 public void finishedWakingUp() { 6450 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up..."); 6451 } 6452 6453 private void wakeUpFromPowerKey(long eventTime) { 6454 wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER"); 6455 } 6456 6457 private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) { 6458 final boolean theaterModeEnabled = isTheaterModeEnabled(); 6459 if (!wakeInTheaterMode && theaterModeEnabled) { 6460 return false; 6461 } 6462 6463 if (theaterModeEnabled) { 6464 Settings.Global.putInt(mContext.getContentResolver(), 6465 Settings.Global.THEATER_MODE_ON, 0); 6466 } 6467 6468 mPowerManager.wakeUp(wakeTime, reason); 6469 return true; 6470 } 6471 6472 private void finishKeyguardDrawn() { 6473 synchronized (mLock) { 6474 if (!mScreenOnEarly || mKeyguardDrawComplete) { 6475 return; // We are not awake yet or we have already informed of this event. 6476 } 6477 6478 mKeyguardDrawComplete = true; 6479 if (mKeyguardDelegate != null) { 6480 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6481 } 6482 mWindowManagerDrawComplete = false; 6483 } 6484 6485 // ... eventually calls finishWindowsDrawn which will finalize our screen turn on 6486 // as well as enabling the orientation change logic/sensor. 6487 mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback, 6488 WAITING_FOR_DRAWN_TIMEOUT); 6489 } 6490 6491 // Called on the DisplayManager's DisplayPowerController thread. 6492 @Override 6493 public void screenTurnedOff() { 6494 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off..."); 6495 6496 updateScreenOffSleepToken(true); 6497 synchronized (mLock) { 6498 mScreenOnEarly = false; 6499 mScreenOnFully = false; 6500 mKeyguardDrawComplete = false; 6501 mWindowManagerDrawComplete = false; 6502 mScreenOnListener = null; 6503 updateOrientationListenerLp(); 6504 6505 if (mKeyguardDelegate != null) { 6506 mKeyguardDelegate.onScreenTurnedOff(); 6507 } 6508 } 6509 } 6510 6511 // Called on the DisplayManager's DisplayPowerController thread. 6512 @Override 6513 public void screenTurningOn(final ScreenOnListener screenOnListener) { 6514 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on..."); 6515 6516 updateScreenOffSleepToken(false); 6517 synchronized (mLock) { 6518 mScreenOnEarly = true; 6519 mScreenOnFully = false; 6520 mKeyguardDrawComplete = false; 6521 mWindowManagerDrawComplete = false; 6522 mScreenOnListener = screenOnListener; 6523 6524 if (mKeyguardDelegate != null) { 6525 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6526 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000); 6527 mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback); 6528 } else { 6529 if (DEBUG_WAKEUP) Slog.d(TAG, 6530 "null mKeyguardDelegate: setting mKeyguardDrawComplete."); 6531 finishKeyguardDrawn(); 6532 } 6533 } 6534 } 6535 6536 // Called on the DisplayManager's DisplayPowerController thread. 6537 @Override 6538 public void screenTurnedOn() { 6539 synchronized (mLock) { 6540 if (mKeyguardDelegate != null) { 6541 mKeyguardDelegate.onScreenTurnedOn(); 6542 } 6543 } 6544 } 6545 6546 private void finishWindowsDrawn() { 6547 synchronized (mLock) { 6548 if (!mScreenOnEarly || mWindowManagerDrawComplete) { 6549 return; // Screen is not turned on or we did already handle this case earlier. 6550 } 6551 6552 mWindowManagerDrawComplete = true; 6553 } 6554 6555 finishScreenTurningOn(); 6556 } 6557 6558 private void finishScreenTurningOn() { 6559 synchronized (mLock) { 6560 // We have just finished drawing screen content. Since the orientation listener 6561 // gets only installed when all windows are drawn, we try to install it again. 6562 updateOrientationListenerLp(); 6563 } 6564 final ScreenOnListener listener; 6565 final boolean enableScreen; 6566 synchronized (mLock) { 6567 if (DEBUG_WAKEUP) Slog.d(TAG, 6568 "finishScreenTurningOn: mAwake=" + mAwake 6569 + ", mScreenOnEarly=" + mScreenOnEarly 6570 + ", mScreenOnFully=" + mScreenOnFully 6571 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete 6572 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete); 6573 6574 if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete 6575 || (mAwake && !mKeyguardDrawComplete)) { 6576 return; // spurious or not ready yet 6577 } 6578 6579 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on..."); 6580 listener = mScreenOnListener; 6581 mScreenOnListener = null; 6582 mScreenOnFully = true; 6583 6584 // Remember the first time we draw the keyguard so we know when we're done with 6585 // the main part of booting and can enable the screen and hide boot messages. 6586 if (!mKeyguardDrawnOnce && mAwake) { 6587 mKeyguardDrawnOnce = true; 6588 enableScreen = true; 6589 if (mBootMessageNeedsHiding) { 6590 mBootMessageNeedsHiding = false; 6591 hideBootMessages(); 6592 } 6593 } else { 6594 enableScreen = false; 6595 } 6596 } 6597 6598 if (listener != null) { 6599 listener.onScreenOn(); 6600 } 6601 6602 if (enableScreen) { 6603 try { 6604 mWindowManager.enableScreenIfNeeded(); 6605 } catch (RemoteException unhandled) { 6606 } 6607 } 6608 } 6609 6610 private void handleHideBootMessage() { 6611 synchronized (mLock) { 6612 if (!mKeyguardDrawnOnce) { 6613 mBootMessageNeedsHiding = true; 6614 return; // keyguard hasn't drawn the first time yet, not done booting 6615 } 6616 } 6617 6618 if (mBootMsgDialog != null) { 6619 if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing"); 6620 mBootMsgDialog.dismiss(); 6621 mBootMsgDialog = null; 6622 } 6623 } 6624 6625 @Override 6626 public boolean isScreenOn() { 6627 return mScreenOnFully; 6628 } 6629 6630 /** {@inheritDoc} */ 6631 @Override 6632 public void enableKeyguard(boolean enabled) { 6633 if (mKeyguardDelegate != null) { 6634 mKeyguardDelegate.setKeyguardEnabled(enabled); 6635 } 6636 } 6637 6638 /** {@inheritDoc} */ 6639 @Override 6640 public void exitKeyguardSecurely(OnKeyguardExitResult callback) { 6641 if (mKeyguardDelegate != null) { 6642 mKeyguardDelegate.verifyUnlock(callback); 6643 } 6644 } 6645 6646 @Override 6647 public boolean isKeyguardShowingAndNotOccluded() { 6648 if (mKeyguardDelegate == null) return false; 6649 return mKeyguardDelegate.isShowing() && !mKeyguardOccluded; 6650 } 6651 6652 /** {@inheritDoc} */ 6653 @Override 6654 public boolean isKeyguardLocked() { 6655 return keyguardOn(); 6656 } 6657 6658 /** {@inheritDoc} */ 6659 @Override 6660 public boolean isKeyguardSecure(int userId) { 6661 if (mKeyguardDelegate == null) return false; 6662 return mKeyguardDelegate.isSecure(userId); 6663 } 6664 6665 /** {@inheritDoc} */ 6666 @Override 6667 public boolean isKeyguardShowingOrOccluded() { 6668 return mKeyguardDelegate == null ? false : mKeyguardDelegate.isShowing(); 6669 } 6670 6671 /** {@inheritDoc} */ 6672 @Override 6673 public boolean inKeyguardRestrictedKeyInputMode() { 6674 if (mKeyguardDelegate == null) return false; 6675 return mKeyguardDelegate.isInputRestricted(); 6676 } 6677 6678 @Override 6679 public void dismissKeyguardLw() { 6680 if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) { 6681 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw"); 6682 mHandler.post(new Runnable() { 6683 @Override 6684 public void run() { 6685 // ask the keyguard to prompt the user to authenticate if necessary 6686 mKeyguardDelegate.dismiss(false /* allowWhileOccluded */); 6687 } 6688 }); 6689 } 6690 } 6691 6692 @Override 6693 public void notifyActivityDrawnForKeyguardLw() { 6694 if (mKeyguardDelegate != null) { 6695 mHandler.post(new Runnable() { 6696 @Override 6697 public void run() { 6698 mKeyguardDelegate.onActivityDrawn(); 6699 } 6700 }); 6701 } 6702 } 6703 6704 @Override 6705 public boolean isKeyguardDrawnLw() { 6706 synchronized (mLock) { 6707 return mKeyguardDrawnOnce; 6708 } 6709 } 6710 6711 @Override 6712 public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) { 6713 if (mKeyguardDelegate != null) { 6714 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation"); 6715 mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration); 6716 } 6717 } 6718 6719 @Override 6720 public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6721 Rect outInsets) { 6722 outInsets.setEmpty(); 6723 6724 // Navigation bar and status bar. 6725 getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets); 6726 if (mStatusBar != null) { 6727 outInsets.top = mStatusBarHeight; 6728 } 6729 } 6730 6731 @Override 6732 public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6733 Rect outInsets) { 6734 outInsets.setEmpty(); 6735 6736 // Only navigation bar 6737 if (mNavigationBar != null) { 6738 int position = navigationBarPosition(displayWidth, displayHeight, displayRotation); 6739 if (position == NAV_BAR_BOTTOM) { 6740 outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode); 6741 } else if (position == NAV_BAR_RIGHT) { 6742 outInsets.right = getNavigationBarWidth(displayRotation, mUiMode); 6743 } else if (position == NAV_BAR_LEFT) { 6744 outInsets.left = getNavigationBarWidth(displayRotation, mUiMode); 6745 } 6746 } 6747 } 6748 6749 @Override 6750 public boolean isNavBarForcedShownLw(WindowState windowState) { 6751 return mForceShowSystemBars; 6752 } 6753 6754 @Override 6755 public boolean isDockSideAllowed(int dockSide) { 6756 6757 // We do not allow all dock sides at which the navigation bar touches the docked stack. 6758 if (!mNavigationBarCanMove) { 6759 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT; 6760 } else { 6761 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT; 6762 } 6763 } 6764 6765 void sendCloseSystemWindows() { 6766 PhoneWindow.sendCloseSystemWindows(mContext, null); 6767 } 6768 6769 void sendCloseSystemWindows(String reason) { 6770 PhoneWindow.sendCloseSystemWindows(mContext, reason); 6771 } 6772 6773 @Override 6774 public int rotationForOrientationLw(int orientation, int lastRotation) { 6775 if (false) { 6776 Slog.v(TAG, "rotationForOrientationLw(orient=" 6777 + orientation + ", last=" + lastRotation 6778 + "); user=" + mUserRotation + " " 6779 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) 6780 ? "USER_ROTATION_LOCKED" : "") 6781 ); 6782 } 6783 6784 if (mForceDefaultOrientation) { 6785 return Surface.ROTATION_0; 6786 } 6787 6788 synchronized (mLock) { 6789 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1 6790 if (sensorRotation < 0) { 6791 sensorRotation = lastRotation; 6792 } 6793 6794 final int preferredRotation; 6795 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) { 6796 // Ignore sensor when lid switch is open and rotation is forced. 6797 preferredRotation = mLidOpenRotation; 6798 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR 6799 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) { 6800 // Ignore sensor when in car dock unless explicitly enabled. 6801 // This case can override the behavior of NOSENSOR, and can also 6802 // enable 180 degree rotation while docked. 6803 preferredRotation = mCarDockEnablesAccelerometer 6804 ? sensorRotation : mCarDockRotation; 6805 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK 6806 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK 6807 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK) 6808 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) { 6809 // Ignore sensor when in desk dock unless explicitly enabled. 6810 // This case can override the behavior of NOSENSOR, and can also 6811 // enable 180 degree rotation while docked. 6812 preferredRotation = mDeskDockEnablesAccelerometer 6813 ? sensorRotation : mDeskDockRotation; 6814 } else if (mHdmiPlugged && mDemoHdmiRotationLock) { 6815 // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled. 6816 // Note that the dock orientation overrides the HDMI orientation. 6817 preferredRotation = mDemoHdmiRotation; 6818 } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED 6819 && mUndockedHdmiRotation >= 0) { 6820 // Ignore sensor when plugged into HDMI and an undocked orientation has 6821 // been specified in the configuration (only for legacy devices without 6822 // full multi-display support). 6823 // Note that the dock orientation overrides the HDMI orientation. 6824 preferredRotation = mUndockedHdmiRotation; 6825 } else if (mDemoRotationLock) { 6826 // Ignore sensor when demo rotation lock is enabled. 6827 // Note that the dock orientation and HDMI rotation lock override this. 6828 preferredRotation = mDemoRotation; 6829 } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) { 6830 // Application just wants to remain locked in the last rotation. 6831 preferredRotation = lastRotation; 6832 } else if (!mSupportAutoRotation) { 6833 // If we don't support auto-rotation then bail out here and ignore 6834 // the sensor and any rotation lock settings. 6835 preferredRotation = -1; 6836 } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE 6837 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER 6838 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 6839 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE 6840 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT 6841 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER)) 6842 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR 6843 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6844 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE 6845 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) { 6846 // Otherwise, use sensor only if requested by the application or enabled 6847 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR. 6848 if (mAllowAllRotations < 0) { 6849 // Can't read this during init() because the context doesn't 6850 // have display metrics at that time so we cannot determine 6851 // tablet vs. phone then. 6852 mAllowAllRotations = mContext.getResources().getBoolean( 6853 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0; 6854 } 6855 if (sensorRotation != Surface.ROTATION_180 6856 || mAllowAllRotations == 1 6857 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6858 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) { 6859 preferredRotation = sensorRotation; 6860 } else { 6861 preferredRotation = lastRotation; 6862 } 6863 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED 6864 && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) { 6865 // Apply rotation lock. Does not apply to NOSENSOR. 6866 // The idea is that the user rotation expresses a weak preference for the direction 6867 // of gravity and as NOSENSOR is never affected by gravity, then neither should 6868 // NOSENSOR be affected by rotation lock (although it will be affected by docks). 6869 preferredRotation = mUserRotation; 6870 } else { 6871 // No overriding preference. 6872 // We will do exactly what the application asked us to do. 6873 preferredRotation = -1; 6874 } 6875 6876 switch (orientation) { 6877 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 6878 // Return portrait unless overridden. 6879 if (isAnyPortrait(preferredRotation)) { 6880 return preferredRotation; 6881 } 6882 return mPortraitRotation; 6883 6884 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 6885 // Return landscape unless overridden. 6886 if (isLandscapeOrSeascape(preferredRotation)) { 6887 return preferredRotation; 6888 } 6889 return mLandscapeRotation; 6890 6891 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 6892 // Return reverse portrait unless overridden. 6893 if (isAnyPortrait(preferredRotation)) { 6894 return preferredRotation; 6895 } 6896 return mUpsideDownRotation; 6897 6898 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 6899 // Return seascape unless overridden. 6900 if (isLandscapeOrSeascape(preferredRotation)) { 6901 return preferredRotation; 6902 } 6903 return mSeascapeRotation; 6904 6905 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 6906 case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE: 6907 // Return either landscape rotation. 6908 if (isLandscapeOrSeascape(preferredRotation)) { 6909 return preferredRotation; 6910 } 6911 if (isLandscapeOrSeascape(lastRotation)) { 6912 return lastRotation; 6913 } 6914 return mLandscapeRotation; 6915 6916 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 6917 case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT: 6918 // Return either portrait rotation. 6919 if (isAnyPortrait(preferredRotation)) { 6920 return preferredRotation; 6921 } 6922 if (isAnyPortrait(lastRotation)) { 6923 return lastRotation; 6924 } 6925 return mPortraitRotation; 6926 6927 default: 6928 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR, 6929 // just return the preferred orientation we already calculated. 6930 if (preferredRotation >= 0) { 6931 return preferredRotation; 6932 } 6933 return Surface.ROTATION_0; 6934 } 6935 } 6936 } 6937 6938 @Override 6939 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) { 6940 switch (orientation) { 6941 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 6942 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 6943 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 6944 return isAnyPortrait(rotation); 6945 6946 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 6947 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 6948 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 6949 return isLandscapeOrSeascape(rotation); 6950 6951 default: 6952 return true; 6953 } 6954 } 6955 6956 @Override 6957 public void setRotationLw(int rotation) { 6958 mOrientationListener.setCurrentRotation(rotation); 6959 } 6960 6961 private boolean isLandscapeOrSeascape(int rotation) { 6962 return rotation == mLandscapeRotation || rotation == mSeascapeRotation; 6963 } 6964 6965 private boolean isAnyPortrait(int rotation) { 6966 return rotation == mPortraitRotation || rotation == mUpsideDownRotation; 6967 } 6968 6969 @Override 6970 public int getUserRotationMode() { 6971 return Settings.System.getIntForUser(mContext.getContentResolver(), 6972 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ? 6973 WindowManagerPolicy.USER_ROTATION_FREE : 6974 WindowManagerPolicy.USER_ROTATION_LOCKED; 6975 } 6976 6977 // User rotation: to be used when all else fails in assigning an orientation to the device 6978 @Override 6979 public void setUserRotationMode(int mode, int rot) { 6980 ContentResolver res = mContext.getContentResolver(); 6981 6982 // mUserRotationMode and mUserRotation will be assigned by the content observer 6983 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) { 6984 Settings.System.putIntForUser(res, 6985 Settings.System.USER_ROTATION, 6986 rot, 6987 UserHandle.USER_CURRENT); 6988 Settings.System.putIntForUser(res, 6989 Settings.System.ACCELEROMETER_ROTATION, 6990 0, 6991 UserHandle.USER_CURRENT); 6992 } else { 6993 Settings.System.putIntForUser(res, 6994 Settings.System.ACCELEROMETER_ROTATION, 6995 1, 6996 UserHandle.USER_CURRENT); 6997 } 6998 } 6999 7000 @Override 7001 public void setSafeMode(boolean safeMode) { 7002 mSafeMode = safeMode; 7003 performHapticFeedbackLw(null, safeMode 7004 ? HapticFeedbackConstants.SAFE_MODE_ENABLED 7005 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true); 7006 } 7007 7008 static long[] getLongIntArray(Resources r, int resid) { 7009 int[] ar = r.getIntArray(resid); 7010 if (ar == null) { 7011 return null; 7012 } 7013 long[] out = new long[ar.length]; 7014 for (int i=0; i<ar.length; i++) { 7015 out[i] = ar[i]; 7016 } 7017 return out; 7018 } 7019 7020 /** {@inheritDoc} */ 7021 @Override 7022 public void systemReady() { 7023 mKeyguardDelegate = new KeyguardServiceDelegate(mContext); 7024 mKeyguardDelegate.onSystemReady(); 7025 7026 readCameraLensCoverState(); 7027 updateUiMode(); 7028 boolean bindKeyguardNow; 7029 synchronized (mLock) { 7030 updateOrientationListenerLp(); 7031 mSystemReady = true; 7032 mHandler.post(new Runnable() { 7033 @Override 7034 public void run() { 7035 updateSettings(); 7036 } 7037 }); 7038 7039 bindKeyguardNow = mDeferBindKeyguard; 7040 if (bindKeyguardNow) { 7041 // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now. 7042 mDeferBindKeyguard = false; 7043 } 7044 } 7045 7046 if (bindKeyguardNow) { 7047 mKeyguardDelegate.bindService(mContext); 7048 mKeyguardDelegate.onBootCompleted(); 7049 } 7050 mSystemGestures.systemReady(); 7051 mImmersiveModeConfirmation.systemReady(); 7052 } 7053 7054 /** {@inheritDoc} */ 7055 @Override 7056 public void systemBooted() { 7057 boolean bindKeyguardNow = false; 7058 synchronized (mLock) { 7059 // Time to bind Keyguard; take care to only bind it once, either here if ready or 7060 // in systemReady if not. 7061 if (mKeyguardDelegate != null) { 7062 bindKeyguardNow = true; 7063 } else { 7064 // Because mKeyguardDelegate is null, we know that the synchronized block in 7065 // systemReady didn't run yet and setting this will actually have an effect. 7066 mDeferBindKeyguard = true; 7067 } 7068 } 7069 if (bindKeyguardNow) { 7070 mKeyguardDelegate.bindService(mContext); 7071 mKeyguardDelegate.onBootCompleted(); 7072 } 7073 synchronized (mLock) { 7074 mSystemBooted = true; 7075 } 7076 startedWakingUp(); 7077 screenTurningOn(null); 7078 screenTurnedOn(); 7079 } 7080 7081 ProgressDialog mBootMsgDialog = null; 7082 7083 /** {@inheritDoc} */ 7084 @Override 7085 public void showBootMessage(final CharSequence msg, final boolean always) { 7086 mHandler.post(new Runnable() { 7087 @Override public void run() { 7088 if (mBootMsgDialog == null) { 7089 int theme; 7090 if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) { 7091 theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert; 7092 } else { 7093 theme = 0; 7094 } 7095 7096 mBootMsgDialog = new ProgressDialog(mContext, theme) { 7097 // This dialog will consume all events coming in to 7098 // it, to avoid it trying to do things too early in boot. 7099 @Override public boolean dispatchKeyEvent(KeyEvent event) { 7100 return true; 7101 } 7102 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { 7103 return true; 7104 } 7105 @Override public boolean dispatchTouchEvent(MotionEvent ev) { 7106 return true; 7107 } 7108 @Override public boolean dispatchTrackballEvent(MotionEvent ev) { 7109 return true; 7110 } 7111 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) { 7112 return true; 7113 } 7114 @Override public boolean dispatchPopulateAccessibilityEvent( 7115 AccessibilityEvent event) { 7116 return true; 7117 } 7118 }; 7119 if (mContext.getPackageManager().isUpgrade()) { 7120 mBootMsgDialog.setTitle(R.string.android_upgrading_title); 7121 } else { 7122 mBootMsgDialog.setTitle(R.string.android_start_title); 7123 } 7124 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 7125 mBootMsgDialog.setIndeterminate(true); 7126 mBootMsgDialog.getWindow().setType( 7127 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS); 7128 mBootMsgDialog.getWindow().addFlags( 7129 WindowManager.LayoutParams.FLAG_DIM_BEHIND 7130 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); 7131 mBootMsgDialog.getWindow().setDimAmount(1); 7132 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes(); 7133 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 7134 mBootMsgDialog.getWindow().setAttributes(lp); 7135 mBootMsgDialog.setCancelable(false); 7136 mBootMsgDialog.show(); 7137 } 7138 mBootMsgDialog.setMessage(msg); 7139 } 7140 }); 7141 } 7142 7143 /** {@inheritDoc} */ 7144 @Override 7145 public void hideBootMessages() { 7146 mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE); 7147 } 7148 7149 /** {@inheritDoc} */ 7150 @Override 7151 public void userActivity() { 7152 // *************************************** 7153 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE 7154 // *************************************** 7155 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER 7156 // WITH ITS LOCKS HELD. 7157 // 7158 // This code must be VERY careful about the locks 7159 // it acquires. 7160 // In fact, the current code acquires way too many, 7161 // and probably has lurking deadlocks. 7162 7163 synchronized (mScreenLockTimeout) { 7164 if (mLockScreenTimerActive) { 7165 // reset the timer 7166 mHandler.removeCallbacks(mScreenLockTimeout); 7167 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7168 } 7169 } 7170 } 7171 7172 class ScreenLockTimeout implements Runnable { 7173 Bundle options; 7174 7175 @Override 7176 public void run() { 7177 synchronized (this) { 7178 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard"); 7179 if (mKeyguardDelegate != null) { 7180 mKeyguardDelegate.doKeyguardTimeout(options); 7181 } 7182 mLockScreenTimerActive = false; 7183 options = null; 7184 } 7185 } 7186 7187 public void setLockOptions(Bundle options) { 7188 this.options = options; 7189 } 7190 } 7191 7192 ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout(); 7193 7194 @Override 7195 public void lockNow(Bundle options) { 7196 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 7197 mHandler.removeCallbacks(mScreenLockTimeout); 7198 if (options != null) { 7199 // In case multiple calls are made to lockNow, we don't wipe out the options 7200 // until the runnable actually executes. 7201 mScreenLockTimeout.setLockOptions(options); 7202 } 7203 mHandler.post(mScreenLockTimeout); 7204 } 7205 7206 private void updateLockScreenTimeout() { 7207 synchronized (mScreenLockTimeout) { 7208 boolean enable = (mAllowLockscreenWhenOn && mAwake && 7209 mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId)); 7210 if (mLockScreenTimerActive != enable) { 7211 if (enable) { 7212 if (localLOGV) Log.v(TAG, "setting lockscreen timer"); 7213 mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests 7214 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7215 } else { 7216 if (localLOGV) Log.v(TAG, "clearing lockscreen timer"); 7217 mHandler.removeCallbacks(mScreenLockTimeout); 7218 } 7219 mLockScreenTimerActive = enable; 7220 } 7221 } 7222 } 7223 7224 private void updateDreamingSleepToken(boolean acquire) { 7225 if (acquire) { 7226 if (mDreamingSleepToken == null) { 7227 mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream"); 7228 } 7229 } else { 7230 if (mDreamingSleepToken != null) { 7231 mDreamingSleepToken.release(); 7232 mDreamingSleepToken = null; 7233 } 7234 } 7235 } 7236 7237 private void updateScreenOffSleepToken(boolean acquire) { 7238 if (acquire) { 7239 if (mScreenOffSleepToken == null) { 7240 mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff"); 7241 } 7242 } else { 7243 if (mScreenOffSleepToken != null) { 7244 mScreenOffSleepToken.release(); 7245 mScreenOffSleepToken = null; 7246 } 7247 } 7248 } 7249 7250 /** {@inheritDoc} */ 7251 @Override 7252 public void enableScreenAfterBoot() { 7253 readLidState(); 7254 applyLidSwitchState(); 7255 updateRotation(true); 7256 } 7257 7258 private void applyLidSwitchState() { 7259 if (mLidState == LID_CLOSED && mLidControlsSleep) { 7260 mPowerManager.goToSleep(SystemClock.uptimeMillis(), 7261 PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH, 7262 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); 7263 } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) { 7264 mWindowManagerFuncs.lockDeviceNow(); 7265 } 7266 7267 synchronized (mLock) { 7268 updateWakeGestureListenerLp(); 7269 } 7270 } 7271 7272 void updateUiMode() { 7273 if (mUiModeManager == null) { 7274 mUiModeManager = IUiModeManager.Stub.asInterface( 7275 ServiceManager.getService(Context.UI_MODE_SERVICE)); 7276 } 7277 try { 7278 mUiMode = mUiModeManager.getCurrentModeType(); 7279 } catch (RemoteException e) { 7280 } 7281 } 7282 7283 void updateRotation(boolean alwaysSendConfiguration) { 7284 try { 7285 //set orientation on WindowManager 7286 mWindowManager.updateRotation(alwaysSendConfiguration, false); 7287 } catch (RemoteException e) { 7288 // Ignore 7289 } 7290 } 7291 7292 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 7293 try { 7294 //set orientation on WindowManager 7295 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout); 7296 } catch (RemoteException e) { 7297 // Ignore 7298 } 7299 } 7300 7301 /** 7302 * Return an Intent to launch the currently active dock app as home. Returns 7303 * null if the standard home should be launched, which is the case if any of the following is 7304 * true: 7305 * <ul> 7306 * <li>The device is not in either car mode or desk mode 7307 * <li>The device is in car mode but mEnableCarDockHomeCapture is false 7308 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false 7309 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME 7310 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME 7311 * </ul> 7312 * @return A dock intent. 7313 */ 7314 Intent createHomeDockIntent() { 7315 Intent intent = null; 7316 7317 // What home does is based on the mode, not the dock state. That 7318 // is, when in car mode you should be taken to car home regardless 7319 // of whether we are actually in a car dock. 7320 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) { 7321 if (mEnableCarDockHomeCapture) { 7322 intent = mCarDockIntent; 7323 } 7324 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) { 7325 if (ENABLE_DESK_DOCK_HOME_CAPTURE) { 7326 intent = mDeskDockIntent; 7327 } 7328 } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH 7329 && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK 7330 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK 7331 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) { 7332 // Always launch dock home from home when watch is docked, if it exists. 7333 intent = mDeskDockIntent; 7334 } 7335 7336 if (intent == null) { 7337 return null; 7338 } 7339 7340 ActivityInfo ai = null; 7341 ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser( 7342 intent, 7343 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA, 7344 mCurrentUserId); 7345 if (info != null) { 7346 ai = info.activityInfo; 7347 } 7348 if (ai != null 7349 && ai.metaData != null 7350 && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) { 7351 intent = new Intent(intent); 7352 intent.setClassName(ai.packageName, ai.name); 7353 return intent; 7354 } 7355 7356 return null; 7357 } 7358 7359 void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) { 7360 if (awakenFromDreams) { 7361 awakenDreams(); 7362 } 7363 7364 Intent dock = createHomeDockIntent(); 7365 if (dock != null) { 7366 try { 7367 if (fromHomeKey) { 7368 dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7369 } 7370 startActivityAsUser(dock, UserHandle.CURRENT); 7371 return; 7372 } catch (ActivityNotFoundException e) { 7373 } 7374 } 7375 7376 Intent intent; 7377 7378 if (fromHomeKey) { 7379 intent = new Intent(mHomeIntent); 7380 intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7381 } else { 7382 intent = mHomeIntent; 7383 } 7384 7385 startActivityAsUser(intent, UserHandle.CURRENT); 7386 } 7387 7388 /** 7389 * goes to the home screen 7390 * @return whether it did anything 7391 */ 7392 boolean goHome() { 7393 if (!isUserSetupComplete()) { 7394 Slog.i(TAG, "Not going home because user setup is in progress."); 7395 return false; 7396 } 7397 if (false) { 7398 // This code always brings home to the front. 7399 try { 7400 ActivityManagerNative.getDefault().stopAppSwitches(); 7401 } catch (RemoteException e) { 7402 } 7403 sendCloseSystemWindows(); 7404 startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */); 7405 } else { 7406 // This code brings home to the front or, if it is already 7407 // at the front, puts the device to sleep. 7408 try { 7409 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) { 7410 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry. 7411 Log.d(TAG, "UTS-TEST-MODE"); 7412 } else { 7413 ActivityManagerNative.getDefault().stopAppSwitches(); 7414 sendCloseSystemWindows(); 7415 Intent dock = createHomeDockIntent(); 7416 if (dock != null) { 7417 int result = ActivityManagerNative.getDefault() 7418 .startActivityAsUser(null, null, dock, 7419 dock.resolveTypeIfNeeded(mContext.getContentResolver()), 7420 null, null, 0, 7421 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7422 null, null, UserHandle.USER_CURRENT); 7423 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7424 return false; 7425 } 7426 } 7427 } 7428 int result = ActivityManagerNative.getDefault() 7429 .startActivityAsUser(null, null, mHomeIntent, 7430 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()), 7431 null, null, 0, 7432 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7433 null, null, UserHandle.USER_CURRENT); 7434 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7435 return false; 7436 } 7437 } catch (RemoteException ex) { 7438 // bummer, the activity manager, which is in this process, is dead 7439 } 7440 } 7441 return true; 7442 } 7443 7444 @Override 7445 public void setCurrentOrientationLw(int newOrientation) { 7446 synchronized (mLock) { 7447 if (newOrientation != mCurrentAppOrientation) { 7448 mCurrentAppOrientation = newOrientation; 7449 updateOrientationListenerLp(); 7450 } 7451 } 7452 } 7453 7454 private void performAuditoryFeedbackForAccessibilityIfNeed() { 7455 if (!isGlobalAccessibilityGestureEnabled()) { 7456 return; 7457 } 7458 AudioManager audioManager = (AudioManager) mContext.getSystemService( 7459 Context.AUDIO_SERVICE); 7460 if (audioManager.isSilentMode()) { 7461 return; 7462 } 7463 Ringtone ringTone = RingtoneManager.getRingtone(mContext, 7464 Settings.System.DEFAULT_NOTIFICATION_URI); 7465 ringTone.setStreamType(AudioManager.STREAM_MUSIC); 7466 ringTone.play(); 7467 } 7468 7469 private boolean isTheaterModeEnabled() { 7470 return Settings.Global.getInt(mContext.getContentResolver(), 7471 Settings.Global.THEATER_MODE_ON, 0) == 1; 7472 } 7473 7474 private boolean isGlobalAccessibilityGestureEnabled() { 7475 return Settings.Global.getInt(mContext.getContentResolver(), 7476 Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1; 7477 } 7478 7479 private boolean areSystemNavigationKeysEnabled() { 7480 return Settings.Secure.getIntForUser(mContext.getContentResolver(), 7481 Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1; 7482 } 7483 7484 @Override 7485 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) { 7486 if (!mVibrator.hasVibrator()) { 7487 return false; 7488 } 7489 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(), 7490 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0; 7491 if (hapticsDisabled && !always) { 7492 return false; 7493 } 7494 long[] pattern = null; 7495 switch (effectId) { 7496 case HapticFeedbackConstants.LONG_PRESS: 7497 pattern = mLongPressVibePattern; 7498 break; 7499 case HapticFeedbackConstants.VIRTUAL_KEY: 7500 pattern = mVirtualKeyVibePattern; 7501 break; 7502 case HapticFeedbackConstants.KEYBOARD_TAP: 7503 pattern = mKeyboardTapVibePattern; 7504 break; 7505 case HapticFeedbackConstants.CLOCK_TICK: 7506 pattern = mClockTickVibePattern; 7507 break; 7508 case HapticFeedbackConstants.CALENDAR_DATE: 7509 pattern = mCalendarDateVibePattern; 7510 break; 7511 case HapticFeedbackConstants.SAFE_MODE_DISABLED: 7512 pattern = mSafeModeDisabledVibePattern; 7513 break; 7514 case HapticFeedbackConstants.SAFE_MODE_ENABLED: 7515 pattern = mSafeModeEnabledVibePattern; 7516 break; 7517 case HapticFeedbackConstants.CONTEXT_CLICK: 7518 pattern = mContextClickVibePattern; 7519 break; 7520 default: 7521 return false; 7522 } 7523 int owningUid; 7524 String owningPackage; 7525 if (win != null) { 7526 owningUid = win.getOwningUid(); 7527 owningPackage = win.getOwningPackage(); 7528 } else { 7529 owningUid = android.os.Process.myUid(); 7530 owningPackage = mContext.getOpPackageName(); 7531 } 7532 if (pattern.length == 1) { 7533 // One-shot vibration 7534 mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES); 7535 } else { 7536 // Pattern vibration 7537 mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES); 7538 } 7539 return true; 7540 } 7541 7542 @Override 7543 public void keepScreenOnStartedLw() { 7544 } 7545 7546 @Override 7547 public void keepScreenOnStoppedLw() { 7548 if (isKeyguardShowingAndNotOccluded()) { 7549 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 7550 } 7551 } 7552 7553 private int updateSystemUiVisibilityLw() { 7554 // If there is no window focused, there will be nobody to handle the events 7555 // anyway, so just hang on in whatever state we're in until things settle down. 7556 WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow 7557 : mTopFullscreenOpaqueWindowState; 7558 if (winCandidate == null) { 7559 return 0; 7560 } 7561 if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) { 7562 // The immersive mode confirmation should never affect the system bar visibility, 7563 // otherwise it will unhide the navigation bar and hide itself. 7564 winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState; 7565 if (winCandidate == null) { 7566 return 0; 7567 } 7568 } 7569 final WindowState win = winCandidate; 7570 if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) { 7571 // We are updating at a point where the keyguard has gotten 7572 // focus, but we were last in a state where the top window is 7573 // hiding it. This is probably because the keyguard as been 7574 // shown while the top window was displayed, so we want to ignore 7575 // it here because this is just a very transient change and it 7576 // will quickly lose focus once it correctly gets hidden. 7577 return 0; 7578 } 7579 7580 int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null) 7581 & ~mResettingSystemUiFlags 7582 & ~mForceClearedSystemUiFlags; 7583 if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) { 7584 tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS); 7585 } 7586 7587 final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */, 7588 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState); 7589 final int dockedVisibility = updateLightStatusBarLw(0 /* vis */, 7590 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState); 7591 mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds); 7592 mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds); 7593 final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility); 7594 final int diff = visibility ^ mLastSystemUiFlags; 7595 final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags; 7596 final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags; 7597 final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState); 7598 if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu 7599 && mFocusedApp == win.getAppToken() 7600 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds) 7601 && mLastDockedStackBounds.equals(mDockedStackBounds)) { 7602 return 0; 7603 } 7604 mLastSystemUiFlags = visibility; 7605 mLastFullscreenStackSysUiFlags = fullscreenVisibility; 7606 mLastDockedStackSysUiFlags = dockedVisibility; 7607 mLastFocusNeedsMenu = needsMenu; 7608 mFocusedApp = win.getAppToken(); 7609 final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds); 7610 final Rect dockedStackBounds = new Rect(mDockedStackBounds); 7611 mHandler.post(new Runnable() { 7612 @Override 7613 public void run() { 7614 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 7615 if (statusbar != null) { 7616 statusbar.setSystemUiVisibility(visibility, fullscreenVisibility, 7617 dockedVisibility, 0xffffffff, fullscreenStackBounds, 7618 dockedStackBounds, win.toString()); 7619 statusbar.topAppWindowChanged(needsMenu); 7620 } 7621 } 7622 }); 7623 return diff; 7624 } 7625 7626 private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) { 7627 WindowState statusColorWin = isStatusBarKeyguard() && !mHideLockScreen 7628 ? mStatusBar 7629 : opaqueOrDimming; 7630 7631 if (statusColorWin != null) { 7632 if (statusColorWin == opaque) { 7633 // If the top fullscreen-or-dimming window is also the top fullscreen, respect 7634 // its light flag. 7635 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7636 vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null) 7637 & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7638 } else if (statusColorWin != null && statusColorWin.isDimming()) { 7639 // Otherwise if it's dimming, clear the light flag. 7640 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7641 } 7642 } 7643 return vis; 7644 } 7645 7646 private boolean drawsSystemBarBackground(WindowState win) { 7647 return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0; 7648 } 7649 7650 private boolean forcesDrawStatusBarBackground(WindowState win) { 7651 return win == null || (win.getAttrs().privateFlags 7652 & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0; 7653 } 7654 7655 private int updateSystemBarsLw(WindowState win, int oldVis, int vis) { 7656 final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID); 7657 final boolean freeformStackVisible = 7658 mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID); 7659 final boolean resizing = mWindowManagerInternal.isDockedDividerResizing(); 7660 7661 // We need to force system bars when the docked stack is visible, when the freeform stack 7662 // is visible but also when we are resizing for the transitions when docked stack 7663 // visibility changes. 7664 mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing; 7665 final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard; 7666 7667 // apply translucent bar vis flags 7668 WindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen 7669 ? mStatusBar 7670 : mTopFullscreenOpaqueWindowState; 7671 vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7672 vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7673 final int dockedVis = mStatusBarController.applyTranslucentFlagLw( 7674 mTopDockedOpaqueWindowState, 0, 0); 7675 7676 final boolean fullscreenDrawsStatusBarBackground = 7677 (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState) 7678 && (vis & View.STATUS_BAR_TRANSLUCENT) == 0) 7679 || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState); 7680 final boolean dockedDrawsStatusBarBackground = 7681 (drawsSystemBarBackground(mTopDockedOpaqueWindowState) 7682 && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0) 7683 || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState); 7684 7685 // prevent status bar interaction from clearing certain flags 7686 int type = win.getAttrs().type; 7687 boolean statusBarHasFocus = type == TYPE_STATUS_BAR; 7688 if (statusBarHasFocus && !isStatusBarKeyguard()) { 7689 int flags = View.SYSTEM_UI_FLAG_FULLSCREEN 7690 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 7691 | View.SYSTEM_UI_FLAG_IMMERSIVE 7692 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 7693 | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7694 if (mHideLockScreen) { 7695 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT; 7696 } 7697 vis = (vis & ~flags) | (oldVis & flags); 7698 } 7699 7700 if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) { 7701 vis |= View.STATUS_BAR_TRANSPARENT; 7702 vis &= ~View.STATUS_BAR_TRANSLUCENT; 7703 } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar) 7704 || forceOpaqueStatusBar) { 7705 vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT); 7706 } 7707 7708 vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing); 7709 7710 // update status bar 7711 boolean immersiveSticky = 7712 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7713 final boolean hideStatusBarWM = 7714 mTopFullscreenOpaqueWindowState != null 7715 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null) 7716 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; 7717 final boolean hideStatusBarSysui = 7718 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 7719 final boolean hideNavBarSysui = 7720 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0; 7721 7722 final boolean transientStatusBarAllowed = mStatusBar != null 7723 && (statusBarHasFocus || (!mForceShowSystemBars 7724 && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky)))); 7725 7726 final boolean transientNavBarAllowed = mNavigationBar != null 7727 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky; 7728 7729 final long now = SystemClock.uptimeMillis(); 7730 final boolean pendingPanic = mPendingPanicGestureUptime != 0 7731 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION; 7732 if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) { 7733 // The user performed the panic gesture recently, we're about to hide the bars, 7734 // we're no longer on the Keyguard and the screen is ready. We can now request the bars. 7735 mPendingPanicGestureUptime = 0; 7736 mStatusBarController.showTransient(); 7737 if (!isNavBarEmpty(vis)) { 7738 mNavigationBarController.showTransient(); 7739 } 7740 } 7741 7742 final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested() 7743 && !transientStatusBarAllowed && hideStatusBarSysui; 7744 final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested() 7745 && !transientNavBarAllowed; 7746 if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) { 7747 // clear the clearable flags instead 7748 clearClearableFlagsLw(); 7749 vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS; 7750 } 7751 7752 final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; 7753 immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7754 final boolean navAllowedHidden = immersive || immersiveSticky; 7755 7756 if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType()) 7757 > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) { 7758 // We can't hide the navbar from this window otherwise the input consumer would not get 7759 // the input events. 7760 vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); 7761 } 7762 7763 vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis); 7764 7765 // update navigation bar 7766 boolean oldImmersiveMode = isImmersiveMode(oldVis); 7767 boolean newImmersiveMode = isImmersiveMode(vis); 7768 if (win != null && oldImmersiveMode != newImmersiveMode) { 7769 final String pkg = win.getOwningPackage(); 7770 mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode, 7771 isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility())); 7772 } 7773 7774 vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis); 7775 7776 return vis; 7777 } 7778 7779 /** 7780 * @return the current visibility flags with the nav-bar opacity related flags toggled based 7781 * on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}. 7782 */ 7783 private int configureNavBarOpacity(int visibility, boolean dockedStackVisible, 7784 boolean freeformStackVisible, boolean isDockedDividerResizing) { 7785 if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) { 7786 if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) { 7787 visibility = setNavBarOpaqueFlag(visibility); 7788 } 7789 } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) { 7790 if (isDockedDividerResizing) { 7791 visibility = setNavBarOpaqueFlag(visibility); 7792 } else if (freeformStackVisible) { 7793 visibility = setNavBarTranslucentFlag(visibility); 7794 } else { 7795 visibility = setNavBarOpaqueFlag(visibility); 7796 } 7797 } 7798 7799 if (!areTranslucentBarsAllowed()) { 7800 visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT; 7801 } 7802 return visibility; 7803 } 7804 7805 private int setNavBarOpaqueFlag(int visibility) { 7806 return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT); 7807 } 7808 7809 private int setNavBarTranslucentFlag(int visibility) { 7810 visibility &= ~View.NAVIGATION_BAR_TRANSPARENT; 7811 return visibility |= View.NAVIGATION_BAR_TRANSLUCENT; 7812 } 7813 7814 private void clearClearableFlagsLw() { 7815 int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS; 7816 if (newVal != mResettingSystemUiFlags) { 7817 mResettingSystemUiFlags = newVal; 7818 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 7819 } 7820 } 7821 7822 private boolean isImmersiveMode(int vis) { 7823 final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; 7824 return mNavigationBar != null 7825 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0 7826 && (vis & flags) != 0 7827 && canHideNavigationBar(); 7828 } 7829 7830 private static boolean isNavBarEmpty(int systemUiFlags) { 7831 final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME 7832 | View.STATUS_BAR_DISABLE_BACK 7833 | View.STATUS_BAR_DISABLE_RECENT); 7834 7835 return (systemUiFlags & disableNavigationBar) == disableNavigationBar; 7836 } 7837 7838 /** 7839 * @return whether the navigation or status bar can be made translucent 7840 * 7841 * This should return true unless touch exploration is not enabled or 7842 * R.boolean.config_enableTranslucentDecor is false. 7843 */ 7844 private boolean areTranslucentBarsAllowed() { 7845 return mTranslucentDecorEnabled; 7846 } 7847 7848 // Use this instead of checking config_showNavigationBar so that it can be consistently 7849 // overridden by qemu.hw.mainkeys in the emulator. 7850 @Override 7851 public boolean hasNavigationBar() { 7852 return mHasNavigationBar; 7853 } 7854 7855 @Override 7856 public void setLastInputMethodWindowLw(WindowState ime, WindowState target) { 7857 mLastInputMethodWindow = ime; 7858 mLastInputMethodTargetWindow = target; 7859 } 7860 7861 @Override 7862 public int getInputMethodWindowVisibleHeightLw() { 7863 return mDockBottom - mCurBottom; 7864 } 7865 7866 @Override 7867 public void setCurrentUserLw(int newUserId) { 7868 mCurrentUserId = newUserId; 7869 if (mKeyguardDelegate != null) { 7870 mKeyguardDelegate.setCurrentUser(newUserId); 7871 } 7872 StatusBarManagerInternal statusBar = getStatusBarManagerInternal(); 7873 if (statusBar != null) { 7874 statusBar.setCurrentUser(newUserId); 7875 } 7876 setLastInputMethodWindowLw(null, null); 7877 } 7878 7879 @Override 7880 public void setSwitchingUser(boolean switching) { 7881 mKeyguardDelegate.setSwitchingUser(switching); 7882 } 7883 7884 @Override 7885 public boolean canMagnifyWindow(int windowType) { 7886 switch (windowType) { 7887 case WindowManager.LayoutParams.TYPE_INPUT_METHOD: 7888 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: 7889 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR: 7890 case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: { 7891 return false; 7892 } 7893 } 7894 return true; 7895 } 7896 7897 @Override 7898 public boolean isTopLevelWindow(int windowType) { 7899 if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW 7900 && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 7901 return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG); 7902 } 7903 return true; 7904 } 7905 7906 @Override 7907 public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) { 7908 // For the upside down rotation we don't rotate seamlessly as the navigation 7909 // bar moves position. 7910 // Note most apps (using orientation:sensor or user as opposed to fullSensor) 7911 // will not enter the reverse portrait orientation, so actually the 7912 // orientation won't change at all. 7913 if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) { 7914 return false; 7915 } 7916 int delta = newRotation - oldRotation; 7917 if (delta < 0) delta += 4; 7918 // Likewise we don't rotate seamlessly for 180 degree rotations 7919 // in this case the surfaces never resize, and our logic to 7920 // revert the transformations on size change will fail. We could 7921 // fix this in the future with the "tagged" frames idea. 7922 if (delta == Surface.ROTATION_180) { 7923 return false; 7924 } 7925 7926 final WindowState w = mTopFullscreenOpaqueWindowState; 7927 if (w != mFocusedWindow) { 7928 return false; 7929 } 7930 7931 // We only enable seamless rotation if the top window has requested 7932 // it and is in the fullscreen opaque state. Seamless rotation 7933 // requires freezing various Surface states and won't work well 7934 // with animations, so we disable it in the animation case for now. 7935 if (w != null && !w.isAnimatingLw() && 7936 ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) || 7937 (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) { 7938 return true; 7939 } 7940 return false; 7941 } 7942 7943 @Override 7944 public void dump(String prefix, PrintWriter pw, String[] args) { 7945 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode); 7946 pw.print(" mSystemReady="); pw.print(mSystemReady); 7947 pw.print(" mSystemBooted="); pw.println(mSystemBooted); 7948 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState); 7949 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation); 7950 pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState); 7951 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged); 7952 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0 7953 || mForceClearedSystemUiFlags != 0) { 7954 pw.print(prefix); pw.print("mLastSystemUiFlags=0x"); 7955 pw.print(Integer.toHexString(mLastSystemUiFlags)); 7956 pw.print(" mResettingSystemUiFlags=0x"); 7957 pw.print(Integer.toHexString(mResettingSystemUiFlags)); 7958 pw.print(" mForceClearedSystemUiFlags=0x"); 7959 pw.println(Integer.toHexString(mForceClearedSystemUiFlags)); 7960 } 7961 if (mLastFocusNeedsMenu) { 7962 pw.print(prefix); pw.print("mLastFocusNeedsMenu="); 7963 pw.println(mLastFocusNeedsMenu); 7964 } 7965 pw.print(prefix); pw.print("mWakeGestureEnabledSetting="); 7966 pw.println(mWakeGestureEnabledSetting); 7967 7968 pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation); 7969 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode); 7970 pw.print(" mDockMode="); pw.print(mDockMode); 7971 pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture); 7972 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation); 7973 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation); 7974 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode); 7975 pw.print(" mUserRotation="); pw.print(mUserRotation); 7976 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations); 7977 pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation); 7978 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer="); 7979 pw.print(mCarDockEnablesAccelerometer); 7980 pw.print(" mDeskDockEnablesAccelerometer="); 7981 pw.println(mDeskDockEnablesAccelerometer); 7982 pw.print(prefix); pw.print("mLidKeyboardAccessibility="); 7983 pw.print(mLidKeyboardAccessibility); 7984 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility); 7985 pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock); 7986 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep); 7987 pw.print(prefix); 7988 pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior); 7989 pw.print(prefix); 7990 pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior); 7991 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior); 7992 pw.print(prefix); 7993 pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior); 7994 pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior); 7995 pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput); 7996 pw.print(prefix); pw.print("mAwake="); pw.println(mAwake); 7997 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly); 7998 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully); 7999 pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete); 8000 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete); 8001 pw.print(prefix); pw.print("mOrientationSensorEnabled="); 8002 pw.println(mOrientationSensorEnabled); 8003 pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft); 8004 pw.print(","); pw.print(mOverscanScreenTop); 8005 pw.print(") "); pw.print(mOverscanScreenWidth); 8006 pw.print("x"); pw.println(mOverscanScreenHeight); 8007 if (mOverscanLeft != 0 || mOverscanTop != 0 8008 || mOverscanRight != 0 || mOverscanBottom != 0) { 8009 pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft); 8010 pw.print(" top="); pw.print(mOverscanTop); 8011 pw.print(" right="); pw.print(mOverscanRight); 8012 pw.print(" bottom="); pw.println(mOverscanBottom); 8013 } 8014 pw.print(prefix); pw.print("mRestrictedOverscanScreen=("); 8015 pw.print(mRestrictedOverscanScreenLeft); 8016 pw.print(","); pw.print(mRestrictedOverscanScreenTop); 8017 pw.print(") "); pw.print(mRestrictedOverscanScreenWidth); 8018 pw.print("x"); pw.println(mRestrictedOverscanScreenHeight); 8019 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft); 8020 pw.print(","); pw.print(mUnrestrictedScreenTop); 8021 pw.print(") "); pw.print(mUnrestrictedScreenWidth); 8022 pw.print("x"); pw.println(mUnrestrictedScreenHeight); 8023 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft); 8024 pw.print(","); pw.print(mRestrictedScreenTop); 8025 pw.print(") "); pw.print(mRestrictedScreenWidth); 8026 pw.print("x"); pw.println(mRestrictedScreenHeight); 8027 pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft); 8028 pw.print(","); pw.print(mStableFullscreenTop); 8029 pw.print(")-("); pw.print(mStableFullscreenRight); 8030 pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")"); 8031 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft); 8032 pw.print(","); pw.print(mStableTop); 8033 pw.print(")-("); pw.print(mStableRight); 8034 pw.print(","); pw.print(mStableBottom); pw.println(")"); 8035 pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft); 8036 pw.print(","); pw.print(mSystemTop); 8037 pw.print(")-("); pw.print(mSystemRight); 8038 pw.print(","); pw.print(mSystemBottom); pw.println(")"); 8039 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft); 8040 pw.print(","); pw.print(mCurTop); 8041 pw.print(")-("); pw.print(mCurRight); 8042 pw.print(","); pw.print(mCurBottom); pw.println(")"); 8043 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft); 8044 pw.print(","); pw.print(mContentTop); 8045 pw.print(")-("); pw.print(mContentRight); 8046 pw.print(","); pw.print(mContentBottom); pw.println(")"); 8047 pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft); 8048 pw.print(","); pw.print(mVoiceContentTop); 8049 pw.print(")-("); pw.print(mVoiceContentRight); 8050 pw.print(","); pw.print(mVoiceContentBottom); pw.println(")"); 8051 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft); 8052 pw.print(","); pw.print(mDockTop); 8053 pw.print(")-("); pw.print(mDockRight); 8054 pw.print(","); pw.print(mDockBottom); pw.println(")"); 8055 pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer); 8056 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer); 8057 pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen); 8058 pw.print(" mShowingDream="); pw.print(mShowingDream); 8059 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen); 8060 pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken); 8061 if (mLastInputMethodWindow != null) { 8062 pw.print(prefix); pw.print("mLastInputMethodWindow="); 8063 pw.println(mLastInputMethodWindow); 8064 } 8065 if (mLastInputMethodTargetWindow != null) { 8066 pw.print(prefix); pw.print("mLastInputMethodTargetWindow="); 8067 pw.println(mLastInputMethodTargetWindow); 8068 } 8069 if (mStatusBar != null) { 8070 pw.print(prefix); pw.print("mStatusBar="); 8071 pw.print(mStatusBar); pw.print(" isStatusBarKeyguard="); 8072 pw.println(isStatusBarKeyguard()); 8073 } 8074 if (mNavigationBar != null) { 8075 pw.print(prefix); pw.print("mNavigationBar="); 8076 pw.println(mNavigationBar); 8077 } 8078 if (mFocusedWindow != null) { 8079 pw.print(prefix); pw.print("mFocusedWindow="); 8080 pw.println(mFocusedWindow); 8081 } 8082 if (mFocusedApp != null) { 8083 pw.print(prefix); pw.print("mFocusedApp="); 8084 pw.println(mFocusedApp); 8085 } 8086 if (mWinDismissingKeyguard != null) { 8087 pw.print(prefix); pw.print("mWinDismissingKeyguard="); 8088 pw.println(mWinDismissingKeyguard); 8089 } 8090 if (mTopFullscreenOpaqueWindowState != null) { 8091 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState="); 8092 pw.println(mTopFullscreenOpaqueWindowState); 8093 } 8094 if (mTopFullscreenOpaqueOrDimmingWindowState != null) { 8095 pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState="); 8096 pw.println(mTopFullscreenOpaqueOrDimmingWindowState); 8097 } 8098 if (mForcingShowNavBar) { 8099 pw.print(prefix); pw.print("mForcingShowNavBar="); 8100 pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer="); 8101 pw.println(mForcingShowNavBarLayer); 8102 } 8103 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen); 8104 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen); 8105 pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar); 8106 pw.print(" mForceStatusBarFromKeyguard="); 8107 pw.println(mForceStatusBarFromKeyguard); 8108 pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard); 8109 pw.print(" mWinDismissingKeyguard="); pw.print(mWinDismissingKeyguard); 8110 pw.print(" mHomePressed="); pw.println(mHomePressed); 8111 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn); 8112 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout); 8113 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive); 8114 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior); 8115 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior); 8116 pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior); 8117 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior); 8118 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation); 8119 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation); 8120 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation); 8121 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation); 8122 pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation); 8123 pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock); 8124 pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation); 8125 8126 mGlobalKeyManager.dump(prefix, pw); 8127 mStatusBarController.dump(pw, prefix); 8128 mNavigationBarController.dump(pw, prefix); 8129 PolicyControl.dump(prefix, pw); 8130 8131 if (mWakeGestureListener != null) { 8132 mWakeGestureListener.dump(pw, prefix); 8133 } 8134 if (mOrientationListener != null) { 8135 mOrientationListener.dump(pw, prefix); 8136 } 8137 if (mBurnInProtectionHelper != null) { 8138 mBurnInProtectionHelper.dump(prefix, pw); 8139 } 8140 if (mKeyguardDelegate != null) { 8141 mKeyguardDelegate.dump(prefix, pw); 8142 } 8143 } 8144} 8145