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