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