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