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