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