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