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