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