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