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