1 /* 2 * Copyright (C) 2010 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 17 package com.android.server.input; 18 19 import static android.Manifest.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW; 20 import static android.content.PermissionChecker.PERMISSION_GRANTED; 21 import static android.content.PermissionChecker.PID_UNKNOWN; 22 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL; 23 import static android.provider.DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT; 24 import static android.view.KeyEvent.KEYCODE_UNKNOWN; 25 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 26 27 import static com.android.hardware.input.Flags.enableCustomizableInputGestures; 28 import static com.android.hardware.input.Flags.fixSearchModifierFallbacks; 29 import static com.android.hardware.input.Flags.keyEventActivityDetection; 30 import static com.android.hardware.input.Flags.touchpadVisualizer; 31 import static com.android.hardware.input.Flags.useKeyGestureEventHandler; 32 import static com.android.server.policy.WindowManagerPolicy.ACTION_PASS_TO_USER; 33 34 import android.Manifest; 35 import android.annotation.EnforcePermission; 36 import android.annotation.NonNull; 37 import android.annotation.Nullable; 38 import android.annotation.PermissionManuallyEnforced; 39 import android.annotation.RequiresPermission; 40 import android.annotation.SuppressLint; 41 import android.annotation.UserIdInt; 42 import android.app.ActivityManagerInternal; 43 import android.bluetooth.BluetoothAdapter; 44 import android.bluetooth.BluetoothDevice; 45 import android.content.BroadcastReceiver; 46 import android.content.Context; 47 import android.content.Intent; 48 import android.content.IntentFilter; 49 import android.content.PermissionChecker; 50 import android.content.pm.PackageManager; 51 import android.content.pm.PackageManagerInternal; 52 import android.graphics.PixelFormat; 53 import android.graphics.PointF; 54 import android.hardware.SensorPrivacyManager; 55 import android.hardware.SensorPrivacyManager.Sensors; 56 import android.hardware.SensorPrivacyManagerInternal; 57 import android.hardware.display.DisplayManagerInternal; 58 import android.hardware.display.DisplayTopologyGraph; 59 import android.hardware.display.DisplayViewport; 60 import android.hardware.input.AidlInputGestureData; 61 import android.hardware.input.HostUsiVersion; 62 import android.hardware.input.IInputDeviceBatteryListener; 63 import android.hardware.input.IInputDeviceBatteryState; 64 import android.hardware.input.IInputDevicesChangedListener; 65 import android.hardware.input.IInputManager; 66 import android.hardware.input.IInputSensorEventListener; 67 import android.hardware.input.IKeyEventActivityListener; 68 import android.hardware.input.IKeyGestureEventListener; 69 import android.hardware.input.IKeyGestureHandler; 70 import android.hardware.input.IKeyboardBacklightListener; 71 import android.hardware.input.IStickyModifierStateListener; 72 import android.hardware.input.ITabletModeChangedListener; 73 import android.hardware.input.InputDeviceIdentifier; 74 import android.hardware.input.InputGestureData; 75 import android.hardware.input.InputManager; 76 import android.hardware.input.InputSensorInfo; 77 import android.hardware.input.InputSettings; 78 import android.hardware.input.KeyGestureEvent; 79 import android.hardware.input.KeyGlyphMap; 80 import android.hardware.input.KeyboardLayout; 81 import android.hardware.input.KeyboardLayoutSelectionResult; 82 import android.hardware.input.TouchCalibration; 83 import android.hardware.lights.Light; 84 import android.hardware.lights.LightState; 85 import android.media.AudioManager; 86 import android.os.Binder; 87 import android.os.CombinedVibration; 88 import android.os.Environment; 89 import android.os.Handler; 90 import android.os.IBinder; 91 import android.os.IVibratorStateListener; 92 import android.os.InputEventInjectionResult; 93 import android.os.InputEventInjectionSync; 94 import android.os.Looper; 95 import android.os.Message; 96 import android.os.PermissionEnforcer; 97 import android.os.Process; 98 import android.os.RemoteCallbackList; 99 import android.os.RemoteException; 100 import android.os.ResultReceiver; 101 import android.os.ShellCallback; 102 import android.os.SystemClock; 103 import android.os.UserHandle; 104 import android.os.VibrationEffect; 105 import android.os.vibrator.StepSegment; 106 import android.os.vibrator.VibrationEffectSegment; 107 import android.provider.DeviceConfig; 108 import android.text.TextUtils; 109 import android.util.ArrayMap; 110 import android.util.ArraySet; 111 import android.util.IndentingPrintWriter; 112 import android.util.Log; 113 import android.util.Slog; 114 import android.util.SparseArray; 115 import android.util.SparseBooleanArray; 116 import android.view.Display; 117 import android.view.IInputFilter; 118 import android.view.IInputFilterHost; 119 import android.view.IInputMonitorHost; 120 import android.view.InputApplicationHandle; 121 import android.view.InputChannel; 122 import android.view.InputDevice; 123 import android.view.InputEvent; 124 import android.view.InputMonitor; 125 import android.view.KeyCharacterMap; 126 import android.view.KeyEvent; 127 import android.view.PointerIcon; 128 import android.view.Surface; 129 import android.view.SurfaceControl; 130 import android.view.VerifiedInputEvent; 131 import android.view.ViewConfiguration; 132 import android.view.WindowManager; 133 import android.view.WindowManagerPolicyConstants; 134 import android.view.inputmethod.InputMethodInfo; 135 import android.view.inputmethod.InputMethodSubtype; 136 137 import com.android.internal.R; 138 import com.android.internal.annotations.GuardedBy; 139 import com.android.internal.annotations.VisibleForTesting; 140 import com.android.internal.inputmethod.InputMethodSubtypeHandle; 141 import com.android.internal.os.SomeArgs; 142 import com.android.internal.policy.IShortcutService; 143 import com.android.internal.policy.KeyInterceptionInfo; 144 import com.android.internal.util.DumpUtils; 145 import com.android.internal.util.Preconditions; 146 import com.android.server.DisplayThread; 147 import com.android.server.IoThread; 148 import com.android.server.LocalServices; 149 import com.android.server.SystemService; 150 import com.android.server.Watchdog; 151 import com.android.server.input.InputManagerInternal.LidSwitchCallback; 152 import com.android.server.input.debug.FocusEventDebugView; 153 import com.android.server.input.debug.TouchpadDebugViewController; 154 import com.android.server.policy.WindowManagerPolicy; 155 import com.android.server.wm.WindowManagerInternal; 156 157 import libcore.io.IoUtils; 158 159 import org.xmlpull.v1.XmlPullParserException; 160 161 import java.io.File; 162 import java.io.FileDescriptor; 163 import java.io.FileInputStream; 164 import java.io.FileNotFoundException; 165 import java.io.FileWriter; 166 import java.io.IOException; 167 import java.io.InputStream; 168 import java.io.PrintWriter; 169 import java.util.ArrayList; 170 import java.util.Arrays; 171 import java.util.HashMap; 172 import java.util.List; 173 import java.util.Map; 174 import java.util.Objects; 175 import java.util.OptionalInt; 176 import java.util.function.Consumer; 177 178 /** The system implementation of {@link IInputManager} that manages input devices. */ 179 public class InputManagerService extends IInputManager.Stub 180 implements Watchdog.Monitor { 181 static final String TAG = "InputManager"; 182 // To enable these logs, run: 'adb shell setprop log.tag.InputManager DEBUG' (requires restart) 183 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 184 185 private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml"; 186 private static final String PORT_ASSOCIATIONS_PATH = "etc/input-port-associations.xml"; 187 188 // Feature flag name for the strategy to be used in VelocityTracker 189 private static final String VELOCITYTRACKER_STRATEGY_PROPERTY = "velocitytracker_strategy"; 190 191 private static final int MSG_DELIVER_INPUT_DEVICES_CHANGED = 1; 192 private static final int MSG_RELOAD_DEVICE_ALIASES = 2; 193 private static final int MSG_DELIVER_TABLET_MODE_CHANGED = 3; 194 private static final int MSG_CURRENT_USER_CHANGED = 4; 195 private static final int MSG_SYSTEM_READY = 5; 196 197 private static final int DEFAULT_VIBRATION_MAGNITUDE = 192; 198 199 private final NativeInputManagerService mNative; 200 201 private final Context mContext; 202 private final InputManagerHandler mHandler; 203 private DisplayManagerInternal mDisplayManagerInternal; 204 205 private WindowManagerInternal mWindowManagerInternal; 206 207 private final File mDoubleTouchGestureEnableFile; 208 209 private WindowManagerCallbacks mWindowManagerCallbacks; 210 private WiredAccessoryCallbacks mWiredAccessoryCallbacks; 211 private boolean mSystemReady; 212 213 private final Object mTabletModeLock = new Object(); 214 // List of currently registered tablet mode changed listeners by process id 215 @GuardedBy("mTabletModeLock") 216 private final SparseArray<TabletModeChangedListenerRecord> mTabletModeChangedListeners = 217 new SparseArray<>(); 218 private final List<TabletModeChangedListenerRecord> mTempTabletModeChangedListenersToNotify = 219 new ArrayList<>(); 220 221 private final Object mSensorEventLock = new Object(); 222 // List of currently registered sensor event listeners by process id 223 @GuardedBy("mSensorEventLock") 224 private final SparseArray<SensorEventListenerRecord> mSensorEventListeners = 225 new SparseArray<>(); 226 private final List<SensorEventListenerRecord> mSensorEventListenersToNotify = 227 new ArrayList<>(); 228 private final List<SensorEventListenerRecord> mSensorAccuracyListenersToNotify = 229 new ArrayList<>(); 230 231 // Persistent data store. Must be locked each time during use. 232 private final PersistentDataStore mDataStore = new PersistentDataStore(); 233 234 // List of currently registered input devices changed listeners by process id. 235 private final Object mInputDevicesLock = new Object(); 236 @GuardedBy("mInputDevicesLock") 237 private boolean mInputDevicesChangedPending; 238 @GuardedBy("mInputDevicesLock") 239 private InputDevice[] mInputDevices = new InputDevice[0]; 240 @GuardedBy("mInputDevicesLock") 241 private final SparseArray<InputDevicesChangedListenerRecord> mInputDevicesChangedListeners = 242 new SparseArray<>(); 243 private final ArrayList<InputDevicesChangedListenerRecord> 244 mTempInputDevicesChangedListenersToNotify = new ArrayList<>(); // handler thread only 245 246 // State for vibrator tokens. 247 private final Object mVibratorLock = new Object(); 248 private final Map<IBinder, VibratorToken> mVibratorTokens = new ArrayMap<>(); 249 private int mNextVibratorTokenValue; 250 251 // List of currently registered vibrator state changed listeners by device id. 252 @GuardedBy("mVibratorLock") 253 private final SparseArray<RemoteCallbackList<IVibratorStateListener>> mVibratorStateListeners = 254 new SparseArray<>(); 255 // List of vibrator states by device id. 256 @GuardedBy("mVibratorLock") 257 private final SparseBooleanArray mIsVibrating = new SparseBooleanArray(); 258 private final Object mLightLock = new Object(); 259 // State for light tokens. A light token marks a lights manager session, it is generated 260 // by light session open() and deleted in session close(). 261 // When lights session requests light states, the token will be used to find the light session. 262 @GuardedBy("mLightLock") 263 private final ArrayMap<IBinder, LightSession> mLightSessions = new ArrayMap<>(); 264 265 // State for lid switch 266 // Lock for the lid switch state. Held when triggering callbacks to guarantee lid switch events 267 // are delivered in order. For ex, when a new lid switch callback is registered the lock is held 268 // while the callback is processing the initial lid switch event which guarantees that any 269 // events that occur at the same time are delivered after the callback has returned. 270 private final Object mLidSwitchLock = new Object(); 271 @GuardedBy("mLidSwitchLock") 272 private final List<LidSwitchCallback> mLidSwitchCallbacks = new ArrayList<>(); 273 274 // State for the currently installed input filter. 275 final Object mInputFilterLock = new Object(); 276 @GuardedBy("mInputFilterLock") 277 IInputFilter mInputFilter; 278 @GuardedBy("mInputFilterLock") 279 InputFilterHost mInputFilterHost; 280 281 // The associations of input devices to displays by port. Maps from input device port (String) 282 // to display id (int). Currently only accessed by InputReader. 283 private final Map<String, Integer> mStaticAssociations; 284 private final Object mAssociationsLock = new Object(); 285 @GuardedBy("mAssociationsLock") 286 private final Map<String, Integer> mRuntimeAssociations = new ArrayMap<>(); 287 288 final Object mKeyEventActivityLock = new Object(); 289 @GuardedBy("mKeyEventActivityLock") 290 private final List<IKeyEventActivityListener> mKeyEventActivityListenersToNotify = 291 new ArrayList<>(); 292 293 // Rate limit for key event activity detection. Prevent the listener from being notified 294 // too frequently. 295 private static final long KEY_EVENT_ACTIVITY_RATE_LIMIT_INTERVAL_MS = 1000; 296 private long mLastKeyEventActivityTimeMs = 0; 297 298 // The associations of input devices to displays by port. Maps from {InputDevice#mName} (String) 299 // to {DisplayInfo#uniqueId} (String) so that events from the Input Device go to a 300 // specific display. 301 @GuardedBy("mAssociationsLock") 302 private final Map<String, String> mUniqueIdAssociationsByPort = new ArrayMap<>(); 303 304 // The associations of input devices to displays by descriptor. Maps from 305 // {InputDevice#mDescriptor} to {DisplayInfo#uniqueId} (String) so that events from the 306 // input device go to a specific display. 307 @GuardedBy("mAssociationsLock") 308 private final Map<String, String> mUniqueIdAssociationsByDescriptor = new ArrayMap<>(); 309 310 // The map from input port (String) to the keyboard layout identifiers (comma separated string 311 // containing language tag and layout type) associated with the corresponding keyboard device. 312 // Currently only accessed by InputReader. 313 @GuardedBy("mAssociationsLock") 314 private final Map<String, String> mKeyboardLayoutAssociations = new ArrayMap<>(); 315 316 // Stores input ports associated with device types. For example, adding an association 317 // {"123", "touchNavigation"} here would mean that a touch device appearing at port "123" would 318 // enumerate as a "touch navigation" device rather than the default "touchpad as a mouse 319 // pointer" device. 320 @GuardedBy("mAssociationsLock") 321 private final Map<String, String> mDeviceTypeAssociations = new ArrayMap<>(); 322 323 // Guards per-display input properties and properties relating to the mouse pointer. 324 // Threads can wait on this lock to be notified the next time the display on which the mouse 325 // pointer is shown has changed. 326 // WARNING: Do not call other services outside of input while holding this lock. 327 private final Object mAdditionalDisplayInputPropertiesLock = new Object(); 328 329 @GuardedBy("mAdditionalDisplayInputPropertiesLock") 330 private final SparseArray<AdditionalDisplayInputProperties> mAdditionalDisplayInputProperties = 331 new SparseArray<>(); 332 333 // Holds all the registered gesture monitors that are implemented as spy windows. The spy 334 // windows are mapped by their InputChannel tokens. 335 @GuardedBy("mInputMonitors") 336 final Map<IBinder, GestureMonitorSpyWindow> mInputMonitors = new HashMap<>(); 337 338 // Watches for settings changes and updates the native side appropriately. 339 private final InputSettingsObserver mSettingsObserver; 340 341 // Manages Keyboard layouts for Physical keyboards 342 private final KeyboardLayoutManager mKeyboardLayoutManager; 343 344 // Manages battery state for input devices. 345 private final BatteryController mBatteryController; 346 347 // Monitors any changes to the sysfs nodes when an input device is connected. 348 private final SysfsNodeMonitor mSysfsNodeMonitor; 349 350 @Nullable 351 private final TouchpadDebugViewController mTouchpadDebugViewController; 352 353 // Manages Keyboard backlight 354 private final KeyboardBacklightControllerInterface mKeyboardBacklightController; 355 356 // Manages Sticky modifier state 357 private final StickyModifierStateController mStickyModifierStateController; 358 private final KeyGestureController mKeyGestureController; 359 /** Fallback actions by key code */ 360 private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions = 361 new SparseArray<>(); 362 363 // Manages Keyboard microphone mute led 364 private final KeyboardLedController mKeyboardLedController; 365 366 // Manages Keyboard modifier keys remapping 367 private final KeyRemapper mKeyRemapper; 368 369 // Manages Keyboard glyphs for specific keyboards 370 private final KeyboardGlyphManager mKeyboardGlyphManager; 371 372 // Manages loading PointerIcons 373 private final PointerIconCache mPointerIconCache; 374 375 // Manages storage and retrieval of input data. 376 private final InputDataStore mInputDataStore; 377 378 // Maximum number of milliseconds to wait for input event injection. 379 private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000; 380 381 // Key states (may be returned by queries about the current state of a 382 // particular key code, scan code or switch). 383 384 /** The key state is unknown or the requested key itself is not supported. */ 385 public static final int KEY_STATE_UNKNOWN = -1; 386 387 /** The key is up. /*/ 388 public static final int KEY_STATE_UP = 0; 389 390 /** The key is down. */ 391 public static final int KEY_STATE_DOWN = 1; 392 393 /** The key is down but is a virtual key press that is being emulated by the system. */ 394 public static final int KEY_STATE_VIRTUAL = 2; 395 396 /** Scan code: Mouse / trackball button. */ 397 public static final int BTN_MOUSE = 0x110; 398 399 // Switch code values must match bionic/libc/kernel/common/linux/input.h 400 /** Switch code: Lid switch. When set, lid is shut. */ 401 public static final int SW_LID = 0x00; 402 403 /** Switch code: Tablet mode switch. 404 * When set, the device is in tablet mode (i.e. no keyboard is connected). 405 */ 406 public static final int SW_TABLET_MODE = 0x01; 407 408 /** Switch code: Keypad slide. When set, keyboard is exposed. */ 409 public static final int SW_KEYPAD_SLIDE = 0x0a; 410 411 /** Switch code: Headphone. When set, headphone is inserted. */ 412 public static final int SW_HEADPHONE_INSERT = 0x02; 413 414 /** Switch code: Microphone. When set, microphone is inserted. */ 415 public static final int SW_MICROPHONE_INSERT = 0x04; 416 417 /** Switch code: Line out. When set, Line out (hi-Z) is inserted. */ 418 public static final int SW_LINEOUT_INSERT = 0x06; 419 420 /** Switch code: Headphone/Microphone Jack. When set, something is inserted. */ 421 public static final int SW_JACK_PHYSICAL_INSERT = 0x07; 422 423 /** Switch code: Camera lens cover. When set the lens is covered. */ 424 public static final int SW_CAMERA_LENS_COVER = 0x09; 425 426 /** Switch code: Microphone. When set, the mic is muted. */ 427 public static final int SW_MUTE_DEVICE = 0x0e; 428 429 public static final int SW_LID_BIT = 1 << SW_LID; 430 public static final int SW_TABLET_MODE_BIT = 1 << SW_TABLET_MODE; 431 public static final int SW_KEYPAD_SLIDE_BIT = 1 << SW_KEYPAD_SLIDE; 432 public static final int SW_HEADPHONE_INSERT_BIT = 1 << SW_HEADPHONE_INSERT; 433 public static final int SW_MICROPHONE_INSERT_BIT = 1 << SW_MICROPHONE_INSERT; 434 public static final int SW_LINEOUT_INSERT_BIT = 1 << SW_LINEOUT_INSERT; 435 public static final int SW_JACK_PHYSICAL_INSERT_BIT = 1 << SW_JACK_PHYSICAL_INSERT; 436 public static final int SW_JACK_BITS = 437 SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_JACK_PHYSICAL_INSERT_BIT | SW_LINEOUT_INSERT_BIT; 438 public static final int SW_CAMERA_LENS_COVER_BIT = 1 << SW_CAMERA_LENS_COVER; 439 public static final int SW_MUTE_DEVICE_BIT = 1 << SW_MUTE_DEVICE; 440 441 // The following are layer numbers used for z-ordering the input overlay layers on the display. 442 // This is used for ordering layers inside {@code DisplayContent#getInputOverlayLayer()}. 443 // 444 // The layer where gesture monitors are added. 445 public static final int INPUT_OVERLAY_LAYER_GESTURE_MONITOR = 1; 446 // Place the handwriting layer above gesture monitors so that styluses cannot trigger 447 // system gestures (e.g. navigation bar, edge-back, etc) while there is an active 448 // handwriting session. 449 public static final int INPUT_OVERLAY_LAYER_HANDWRITING_SURFACE = 2; 450 451 452 private final String mVelocityTrackerStrategy; 453 454 /** Whether to use the dev/input/event or uevent subsystem for the audio jack. */ 455 final boolean mUseDevInputEventForAudioJack; 456 457 private final Object mFocusEventDebugViewLock = new Object(); 458 @GuardedBy("mFocusEventDebugViewLock") 459 @Nullable 460 private FocusEventDebugView mFocusEventDebugView; 461 private boolean mShowKeyPresses = false; 462 private boolean mShowRotaryInput = false; 463 464 /** 465 * A lock for the accessibility pointer motion filter. Don't call native methods while holding 466 * this lock. 467 */ 468 private final Object mAccessibilityPointerMotionFilterLock = new Object(); 469 private InputManagerInternal.AccessibilityPointerMotionFilter 470 mAccessibilityPointerMotionFilter = null; 471 472 /** Point of injection for test dependencies. */ 473 @VisibleForTesting 474 static class Injector { 475 private final Context mContext; 476 private final Looper mLooper; 477 private final Looper mIoLooper; 478 private final UEventManager mUEventManager; 479 Injector(Context context, Looper looper, Looper ioLooper, UEventManager uEventManager)480 Injector(Context context, Looper looper, Looper ioLooper, UEventManager uEventManager) { 481 mContext = context; 482 mLooper = looper; 483 mIoLooper = ioLooper; 484 mUEventManager = uEventManager; 485 } 486 getContext()487 Context getContext() { 488 return mContext; 489 } 490 getLooper()491 Looper getLooper() { 492 return mLooper; 493 } 494 getIoLooper()495 Looper getIoLooper() { 496 return mIoLooper; 497 } 498 getUEventManager()499 UEventManager getUEventManager() { 500 return mUEventManager; 501 } 502 getNativeService(InputManagerService service)503 NativeInputManagerService getNativeService(InputManagerService service) { 504 return new NativeInputManagerService.NativeImpl(service, mLooper.getQueue()); 505 } 506 registerLocalService(InputManagerInternal localService)507 void registerLocalService(InputManagerInternal localService) { 508 LocalServices.addService(InputManagerInternal.class, localService); 509 } 510 getKeyboardBacklightController( NativeInputManagerService nativeService)511 KeyboardBacklightControllerInterface getKeyboardBacklightController( 512 NativeInputManagerService nativeService) { 513 return new KeyboardBacklightController(mContext, nativeService, mLooper); 514 } 515 } 516 InputManagerService(Context context)517 public InputManagerService(Context context) { 518 this(new Injector(context, DisplayThread.get().getLooper(), IoThread.get().getLooper(), 519 new UEventManager() {}), context.getSystemService(PermissionEnforcer.class)); 520 } 521 522 @VisibleForTesting InputManagerService(Injector injector, PermissionEnforcer permissionEnforcer)523 InputManagerService(Injector injector, PermissionEnforcer permissionEnforcer) { 524 // The static association map is accessed by both java and native code, so it must be 525 // initialized before initializing the native service. 526 super(permissionEnforcer); 527 528 mStaticAssociations = loadStaticInputPortAssociations(); 529 530 mContext = injector.getContext(); 531 mHandler = new InputManagerHandler(injector.getLooper()); 532 mNative = injector.getNativeService(this); 533 mSettingsObserver = new InputSettingsObserver(mContext, mHandler, this, mNative); 534 mKeyboardLayoutManager = new KeyboardLayoutManager(mContext, mNative, mDataStore, 535 injector.getLooper()); 536 mTouchpadDebugViewController = 537 touchpadVisualizer() ? new TouchpadDebugViewController(mContext, 538 injector.getLooper(), this) : null; 539 mBatteryController = new BatteryController(mContext, mNative, injector.getLooper(), 540 injector.getUEventManager()); 541 mSysfsNodeMonitor = new SysfsNodeMonitor(mContext, mNative, injector.getLooper(), 542 injector.getUEventManager()); 543 mKeyboardBacklightController = injector.getKeyboardBacklightController(mNative); 544 mStickyModifierStateController = new StickyModifierStateController(); 545 mInputDataStore = new InputDataStore(); 546 mKeyGestureController = new KeyGestureController(mContext, injector.getLooper(), 547 injector.getIoLooper(), mInputDataStore); 548 mKeyboardLedController = new KeyboardLedController(mContext, injector.getLooper(), 549 mNative); 550 mKeyRemapper = new KeyRemapper(mContext, mNative, mDataStore, injector.getLooper()); 551 mKeyboardGlyphManager = new KeyboardGlyphManager(mContext, injector.getLooper()); 552 mPointerIconCache = new PointerIconCache(mContext, mNative); 553 554 mUseDevInputEventForAudioJack = 555 mContext.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack); 556 Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack=" 557 + mUseDevInputEventForAudioJack); 558 559 String doubleTouchGestureEnablePath = mContext.getResources().getString( 560 R.string.config_doubleTouchGestureEnableFile); 561 mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null : 562 new File(doubleTouchGestureEnablePath); 563 564 mVelocityTrackerStrategy = DeviceConfig.getProperty( 565 NAMESPACE_INPUT_NATIVE_BOOT, VELOCITYTRACKER_STRATEGY_PROPERTY); 566 567 injector.registerLocalService(new LocalService()); 568 } 569 setWindowManagerCallbacks(WindowManagerCallbacks callbacks)570 public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) { 571 if (mWindowManagerCallbacks != null) { 572 unregisterLidSwitchCallbackInternal(mWindowManagerCallbacks); 573 } 574 mWindowManagerCallbacks = callbacks; 575 registerLidSwitchCallbackInternal(mWindowManagerCallbacks); 576 mKeyGestureController.setWindowManagerCallbacks(callbacks); 577 } 578 setWiredAccessoryCallbacks(WiredAccessoryCallbacks callbacks)579 public void setWiredAccessoryCallbacks(WiredAccessoryCallbacks callbacks) { 580 mWiredAccessoryCallbacks = callbacks; 581 } 582 registerLidSwitchCallbackInternal(@onNull LidSwitchCallback callback)583 void registerLidSwitchCallbackInternal(@NonNull LidSwitchCallback callback) { 584 synchronized (mLidSwitchLock) { 585 mLidSwitchCallbacks.add(callback); 586 587 // Skip triggering the initial callback if the system is not yet ready as the switch 588 // state will be reported as KEY_STATE_UNKNOWN. The callback will be triggered in 589 // systemRunning(). 590 if (mSystemReady) { 591 boolean lidOpen = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, SW_LID) 592 == KEY_STATE_UP; 593 callback.notifyLidSwitchChanged(0 /* whenNanos */, lidOpen); 594 } 595 } 596 } 597 unregisterLidSwitchCallbackInternal(@onNull LidSwitchCallback callback)598 void unregisterLidSwitchCallbackInternal(@NonNull LidSwitchCallback callback) { 599 synchronized (mLidSwitchLock) { 600 mLidSwitchCallbacks.remove(callback); 601 } 602 } 603 start()604 public void start() { 605 Slog.i(TAG, "Starting input manager"); 606 mNative.start(); 607 608 // Add ourselves to the Watchdog monitors. 609 Watchdog.getInstance().addMonitor(this); 610 } 611 onBootPhase(int phase)612 private void onBootPhase(int phase) { 613 // On ActivityManager thread, shift to handler to avoid blocking other system services in 614 // this boot phase. 615 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) { 616 mHandler.sendEmptyMessage(MSG_SYSTEM_READY); 617 } 618 } 619 620 // TODO(BT) Pass in parameter for bluetooth system systemRunning()621 public void systemRunning() { 622 if (DEBUG) { 623 Slog.d(TAG, "System ready."); 624 } 625 626 mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); 627 mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); 628 629 mSettingsObserver.registerAndUpdate(); 630 631 synchronized (mLidSwitchLock) { 632 mSystemReady = true; 633 634 // Send the initial lid switch state to any callback registered before the system was 635 // ready. 636 int switchState = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, SW_LID); 637 for (int i = 0; i < mLidSwitchCallbacks.size(); i++) { 638 LidSwitchCallback callback = mLidSwitchCallbacks.get(i); 639 callback.notifyLidSwitchChanged(0 /* whenNanos */, switchState == KEY_STATE_UP); 640 } 641 } 642 643 // Set the HW mic toggle switch state 644 final int micMuteState = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, 645 SW_MUTE_DEVICE); 646 if (micMuteState == InputManager.SWITCH_STATE_ON) { 647 setSensorPrivacy(Sensors.MICROPHONE, true); 648 } 649 // Set the HW camera toggle switch state 650 final int cameraMuteState = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, 651 SW_CAMERA_LENS_COVER); 652 if (cameraMuteState == InputManager.SWITCH_STATE_ON) { 653 setSensorPrivacy(Sensors.CAMERA, true); 654 } 655 656 IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_ALIAS_CHANGED); 657 mContext.registerReceiver(new BroadcastReceiver() { 658 @Override 659 public void onReceive(Context context, Intent intent) { 660 reloadDeviceAliases(); 661 } 662 }, filter, null, mHandler); 663 664 mHandler.sendEmptyMessage(MSG_RELOAD_DEVICE_ALIASES); 665 666 if (mWiredAccessoryCallbacks != null) { 667 mWiredAccessoryCallbacks.systemReady(); 668 } 669 670 mKeyboardLayoutManager.systemRunning(); 671 mBatteryController.systemRunning(); 672 mSysfsNodeMonitor.systemRunning(); 673 mKeyboardBacklightController.systemRunning(); 674 mKeyboardLedController.systemRunning(); 675 mKeyRemapper.systemRunning(); 676 mPointerIconCache.systemRunning(); 677 mKeyboardGlyphManager.systemRunning(); 678 if (useKeyGestureEventHandler()) { 679 mKeyGestureController.systemRunning(); 680 initKeyGestures(); 681 } 682 } 683 reloadDeviceAliases()684 private void reloadDeviceAliases() { 685 if (DEBUG) { 686 Slog.d(TAG, "Reloading device names."); 687 } 688 mNative.reloadDeviceAliases(); 689 } 690 setDisplayViewportsInternal(List<DisplayViewport> viewports)691 private void setDisplayViewportsInternal(List<DisplayViewport> viewports) { 692 final DisplayViewport[] vArray = new DisplayViewport[viewports.size()]; 693 for (int i = viewports.size() - 1; i >= 0; --i) { 694 vArray[i] = viewports.get(i); 695 } 696 mNative.setDisplayViewports(vArray); 697 698 // Attempt to update the default pointer display when the viewports change. 699 // Take care to not make calls to window manager while holding internal locks. 700 mNative.setPointerDisplayId(mWindowManagerCallbacks.getPointerDisplayId()); 701 } 702 setDisplayTopologyInternal(DisplayTopologyGraph topology)703 private void setDisplayTopologyInternal(DisplayTopologyGraph topology) { 704 mNative.setDisplayTopology(topology); 705 } 706 707 /** 708 * Gets the current state of a key or button by key code. 709 * @param deviceId The input device id, or -1 to consult all devices. 710 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to 711 * consider all input sources. An input device is consulted if at least one of its 712 * non-class input source bits matches the specified source mask. 713 * @param keyCode The key code to check. 714 * @return The key state. 715 */ getKeyCodeState(int deviceId, int sourceMask, int keyCode)716 public int getKeyCodeState(int deviceId, int sourceMask, int keyCode) { 717 return mNative.getKeyCodeState(deviceId, sourceMask, keyCode); 718 } 719 720 /** 721 * Gets the current state of a key or button by scan code. 722 * @param deviceId The input device id, or -1 to consult all devices. 723 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to 724 * consider all input sources. An input device is consulted if at least one of its 725 * non-class input source bits matches the specified source mask. 726 * @param scanCode The scan code to check. 727 * @return The key state. 728 */ getScanCodeState(int deviceId, int sourceMask, int scanCode)729 public int getScanCodeState(int deviceId, int sourceMask, int scanCode) { 730 return mNative.getScanCodeState(deviceId, sourceMask, scanCode); 731 } 732 733 /** 734 * Gets the current state of a switch by switch code. 735 * @param deviceId The input device id, or -1 to consult all devices. 736 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to 737 * consider all input sources. An input device is consulted if at least one of its 738 * non-class input source bits matches the specified source mask. 739 * @param switchCode The switch code to check. 740 * @return The switch state. 741 */ getSwitchState(int deviceId, int sourceMask, int switchCode)742 public int getSwitchState(int deviceId, int sourceMask, int switchCode) { 743 return mNative.getSwitchState(deviceId, sourceMask, switchCode); 744 } 745 746 /** 747 * Determines whether the specified key codes are supported by a particular device. 748 * @param deviceId The input device id, or -1 to consult all devices. 749 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to 750 * consider all input sources. An input device is consulted if at least one of its 751 * non-class input source bits matches the specified source mask. 752 * @param keyCodes The array of key codes to check. 753 * @param keyExists An array at least as large as keyCodes whose entries will be set 754 * to true or false based on the presence or absence of support for the corresponding 755 * key codes. 756 * @return True if the lookup was successful, false otherwise. 757 */ 758 @Override // Binder call hasKeys(int deviceId, int sourceMask, @NonNull int[] keyCodes, @NonNull boolean[] keyExists)759 public boolean hasKeys(int deviceId, int sourceMask, @NonNull int[] keyCodes, 760 @NonNull boolean[] keyExists) { 761 Objects.requireNonNull(keyCodes, "keyCodes must not be null"); 762 Objects.requireNonNull(keyExists, "keyExists must not be null"); 763 if (keyExists.length < keyCodes.length) { 764 throw new IllegalArgumentException("keyExists must be at least as large as keyCodes"); 765 } 766 767 return mNative.hasKeys(deviceId, sourceMask, keyCodes, keyExists); 768 } 769 770 /** 771 * Returns the keyCode generated by the specified location on a US keyboard layout. 772 * This takes into consideration the currently active keyboard layout. 773 * 774 * @param deviceId The input device id. 775 * @param locationKeyCode The location of a key on a US keyboard layout. 776 * @return The KeyCode this physical key location produces. 777 */ 778 @Override // Binder call getKeyCodeForKeyLocation(int deviceId, int locationKeyCode)779 public int getKeyCodeForKeyLocation(int deviceId, int locationKeyCode) { 780 if (locationKeyCode <= KEYCODE_UNKNOWN || locationKeyCode > KeyEvent.getMaxKeyCode()) { 781 return KEYCODE_UNKNOWN; 782 } 783 return mNative.getKeyCodeForKeyLocation(deviceId, locationKeyCode); 784 } 785 786 @Override // Binder call getKeyCharacterMap(@onNull String layoutDescriptor)787 public KeyCharacterMap getKeyCharacterMap(@NonNull String layoutDescriptor) { 788 Objects.requireNonNull(layoutDescriptor, "layoutDescriptor must not be null"); 789 return mKeyboardLayoutManager.getKeyCharacterMap(layoutDescriptor); 790 } 791 792 /** 793 * Transfer the current touch gesture to the provided window. 794 * 795 * @param destChannelToken The token of the window or input channel that should receive the 796 * gesture 797 * @return True if the transfer succeeded, false if there was no active touch gesture happening 798 * @deprecated Use {@link #transferTouchGesture(IBinder, IBinder)} 799 */ 800 @Deprecated transferTouch(@onNull IBinder destChannelToken, int displayId)801 public boolean transferTouch(@NonNull IBinder destChannelToken, int displayId) { 802 // TODO(b/162194035): Replace this with a SPY window 803 Objects.requireNonNull(destChannelToken, "destChannelToken must not be null"); 804 return mNative.transferTouch(destChannelToken, displayId); 805 } 806 807 /** 808 * Creates an input channel that will receive all input from the input dispatcher. 809 * @param inputChannelName The input channel name. 810 * @param displayId Target display id. 811 * @return The input channel. 812 */ monitorInput(@onNull String inputChannelName, int displayId)813 public InputChannel monitorInput(@NonNull String inputChannelName, int displayId) { 814 Objects.requireNonNull(inputChannelName, "inputChannelName not be null"); 815 816 if (displayId < Display.DEFAULT_DISPLAY) { 817 throw new IllegalArgumentException("displayId must >= 0."); 818 } 819 820 return mNative.createInputMonitor(displayId, inputChannelName, Binder.getCallingPid()); 821 } 822 823 @NonNull createSpyWindowGestureMonitor(IBinder monitorToken, String name, SurfaceControl sc, int displayId, int pid, int uid)824 private InputChannel createSpyWindowGestureMonitor(IBinder monitorToken, String name, 825 SurfaceControl sc, int displayId, int pid, int uid) { 826 final InputChannel channel = createInputChannel(name); 827 828 try { 829 monitorToken.linkToDeath(() -> removeSpyWindowGestureMonitor(channel.getToken()), 0); 830 } catch (RemoteException e) { 831 Slog.i(TAG, "Client died before '" + name + "' could be created."); 832 return null; 833 } 834 synchronized (mInputMonitors) { 835 mInputMonitors.put(channel.getToken(), 836 new GestureMonitorSpyWindow(monitorToken, name, displayId, pid, uid, sc, 837 channel)); 838 } 839 840 final InputChannel outInputChannel = new InputChannel(); 841 channel.copyTo(outInputChannel); 842 return outInputChannel; 843 } 844 removeSpyWindowGestureMonitor(@onNull IBinder inputChannelToken)845 private void removeSpyWindowGestureMonitor(@NonNull IBinder inputChannelToken) { 846 final GestureMonitorSpyWindow monitor; 847 synchronized (mInputMonitors) { 848 monitor = mInputMonitors.remove(inputChannelToken); 849 } 850 removeInputChannel(inputChannelToken); 851 if (monitor == null) return; 852 monitor.remove(); 853 } 854 855 /** 856 * Creates an input monitor that will receive pointer events for the purposes of system-wide 857 * gesture interpretation. 858 * 859 * @param requestedName The input channel name. 860 * @param displayId Target display id. 861 * @return The input channel. 862 */ 863 @Override // Binder call monitorGestureInput(@onNull IBinder monitorToken, @NonNull String requestedName, int displayId)864 public InputMonitor monitorGestureInput(@NonNull IBinder monitorToken, 865 @NonNull String requestedName, int displayId) { 866 if (!checkCallingPermission(android.Manifest.permission.MONITOR_INPUT, 867 "monitorGestureInput()")) { 868 throw new SecurityException("Requires MONITOR_INPUT permission"); 869 } 870 Objects.requireNonNull(requestedName, "name must not be null."); 871 Objects.requireNonNull(monitorToken, "token must not be null."); 872 873 if (displayId < Display.DEFAULT_DISPLAY) { 874 throw new IllegalArgumentException("displayId must >= 0."); 875 } 876 final String name = "[Gesture Monitor] " + requestedName; 877 final int pid = Binder.getCallingPid(); 878 final int uid = Binder.getCallingUid(); 879 880 final long ident = Binder.clearCallingIdentity(); 881 try { 882 final SurfaceControl sc = mWindowManagerCallbacks.createSurfaceForGestureMonitor(name, 883 displayId); 884 if (sc == null) { 885 throw new IllegalArgumentException( 886 "Could not create gesture monitor surface on display: " + displayId); 887 } 888 889 final InputChannel inputChannel = createSpyWindowGestureMonitor( 890 monitorToken, name, sc, displayId, pid, uid); 891 return new InputMonitor(inputChannel, 892 new InputMonitorHost(inputChannel.getToken()), 893 new SurfaceControl(sc, "IMS.monitorGestureInput")); 894 } finally { 895 Binder.restoreCallingIdentity(ident); 896 } 897 } 898 899 /** 900 * Creates an input channel to be used as an input event target. 901 * 902 * @param name The name of this input channel 903 */ createInputChannel(String name)904 public InputChannel createInputChannel(String name) { 905 return mNative.createInputChannel(name); 906 } 907 908 /** 909 * Removes an input channel. 910 * @param connectionToken The input channel to unregister. 911 */ removeInputChannel(@onNull IBinder connectionToken)912 public void removeInputChannel(@NonNull IBinder connectionToken) { 913 Objects.requireNonNull(connectionToken, "connectionToken must not be null"); 914 mNative.removeInputChannel(connectionToken); 915 } 916 917 /** 918 * Sets an input filter that will receive all input events before they are dispatched. 919 * The input filter may then reinterpret input events or inject new ones. 920 * 921 * To ensure consistency, the input dispatcher automatically drops all events 922 * in progress whenever an input filter is installed or uninstalled. After an input 923 * filter is uninstalled, it can no longer send input events unless it is reinstalled. 924 * Any events it attempts to send after it has been uninstalled will be dropped. 925 * 926 * @param filter The input filter, or null to remove the current filter. 927 */ setInputFilter(IInputFilter filter)928 public void setInputFilter(IInputFilter filter) { 929 synchronized (mInputFilterLock) { 930 final IInputFilter oldFilter = mInputFilter; 931 if (oldFilter == filter) { 932 return; // nothing to do 933 } 934 935 if (oldFilter != null) { 936 mInputFilter = null; 937 mInputFilterHost.disconnectLocked(); 938 mInputFilterHost = null; 939 try { 940 oldFilter.uninstall(); 941 } catch (RemoteException re) { 942 /* ignore */ 943 } 944 } 945 946 if (filter != null) { 947 mInputFilter = filter; 948 mInputFilterHost = new InputFilterHost(); 949 try { 950 filter.install(mInputFilterHost); 951 } catch (RemoteException re) { 952 /* ignore */ 953 } 954 } 955 956 mNative.setInputFilterEnabled(filter != null); 957 } 958 } 959 960 /** 961 * Set the state of the touch mode. 962 * 963 * WindowManager remains the source of truth of the touch mode state. 964 * However, we need to keep a copy of this state in input. 965 * 966 * The apps determine the touch mode state. Therefore, a single app will 967 * affect the global state. That state change needs to be propagated to 968 * other apps, when they become focused. 969 * 970 * When input dispatches focus to the apps, the touch mode state 971 * will be sent together with the focus change (but each one in its own event). 972 * 973 * @param inTouchMode true if the device is in touch mode 974 * @param pid the pid of the process that requested to switch touch mode state 975 * @param uid the uid of the process that requested to switch touch mode state 976 * @param hasPermission if set to {@code true} then no further authorization will be performed 977 * @param displayId the target display (ignored if device is configured with per display 978 * touch mode enabled) 979 * @return {@code true} if the touch mode was successfully changed, {@code false} otherwise 980 */ setInTouchMode(boolean inTouchMode, int pid, int uid, boolean hasPermission, int displayId)981 public boolean setInTouchMode(boolean inTouchMode, int pid, int uid, boolean hasPermission, 982 int displayId) { 983 return mNative.setInTouchMode(inTouchMode, pid, uid, hasPermission, displayId); 984 } 985 986 @Override // Binder call injectInputEvent(@onNull InputEvent event, int mode)987 public boolean injectInputEvent(@NonNull InputEvent event, int mode) { 988 return injectInputEventToTarget(event, mode, Process.INVALID_UID); 989 } 990 991 @Override // Binder call injectInputEventToTarget(@onNull InputEvent event, int mode, int targetUid)992 public boolean injectInputEventToTarget(@NonNull InputEvent event, int mode, int targetUid) { 993 if (!checkCallingPermission(android.Manifest.permission.INJECT_EVENTS, 994 "injectInputEvent()", true /*checkInstrumentationSource*/)) { 995 throw new SecurityException( 996 "Injecting input events requires the caller (or the source of the " 997 + "instrumentation, if any) to have the INJECT_EVENTS permission."); 998 } 999 // We are not checking if targetUid matches the callingUid, since having the permission 1000 // already means you can inject into any window. 1001 Objects.requireNonNull(event, "event must not be null"); 1002 if (mode != InputEventInjectionSync.NONE 1003 && mode != InputEventInjectionSync.WAIT_FOR_FINISHED 1004 && mode != InputEventInjectionSync.WAIT_FOR_RESULT) { 1005 throw new IllegalArgumentException("mode is invalid"); 1006 } 1007 1008 final int pid = Binder.getCallingPid(); 1009 final long ident = Binder.clearCallingIdentity(); 1010 final boolean injectIntoUid = targetUid != Process.INVALID_UID; 1011 final int result; 1012 try { 1013 result = mNative.injectInputEvent(event, injectIntoUid, 1014 targetUid, mode, INJECTION_TIMEOUT_MILLIS, 1015 WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT); 1016 } finally { 1017 Binder.restoreCallingIdentity(ident); 1018 } 1019 switch (result) { 1020 case InputEventInjectionResult.SUCCEEDED: 1021 return true; 1022 case InputEventInjectionResult.TARGET_MISMATCH: 1023 if (!injectIntoUid) { 1024 throw new IllegalStateException("Injection should not result in TARGET_MISMATCH" 1025 + " when it is not targeted into to a specific uid."); 1026 } 1027 throw new IllegalArgumentException( 1028 "Targeted input event injection from pid " + pid 1029 + " was not directed at a window owned by uid " 1030 + targetUid + "."); 1031 case InputEventInjectionResult.TIMED_OUT: 1032 Slog.w(TAG, "Input event injection from pid " + pid + " timed out."); 1033 return false; 1034 case InputEventInjectionResult.FAILED: 1035 default: 1036 Slog.w(TAG, "Input event injection from pid " + pid + " failed."); 1037 return false; 1038 } 1039 } 1040 1041 @Override // Binder call verifyInputEvent(@onNull InputEvent event)1042 public VerifiedInputEvent verifyInputEvent(@NonNull InputEvent event) { 1043 Objects.requireNonNull(event, "event must not be null"); 1044 return mNative.verifyInputEvent(event); 1045 } 1046 1047 @Override // Binder call getVelocityTrackerStrategy()1048 public String getVelocityTrackerStrategy() { 1049 return mVelocityTrackerStrategy; 1050 } 1051 1052 /** 1053 * Gets information about the input device with the specified id. 1054 * @param deviceId The device id. 1055 * @return The input device or null if not found. 1056 */ 1057 @Override // Binder call getInputDevice(int deviceId)1058 public InputDevice getInputDevice(int deviceId) { 1059 synchronized (mInputDevicesLock) { 1060 for (final InputDevice inputDevice : mInputDevices) { 1061 if (inputDevice.getId() == deviceId) { 1062 return inputDevice; 1063 } 1064 } 1065 } 1066 return null; 1067 } 1068 1069 // Binder call 1070 @Override enableInputDevice(int deviceId)1071 public void enableInputDevice(int deviceId) { 1072 if (!checkCallingPermission(android.Manifest.permission.DISABLE_INPUT_DEVICE, 1073 "enableInputDevice()")) { 1074 throw new SecurityException("Requires DISABLE_INPUT_DEVICE permission"); 1075 } 1076 mNative.enableInputDevice(deviceId); 1077 } 1078 1079 // Binder call 1080 @Override disableInputDevice(int deviceId)1081 public void disableInputDevice(int deviceId) { 1082 if (!checkCallingPermission(android.Manifest.permission.DISABLE_INPUT_DEVICE, 1083 "disableInputDevice()")) { 1084 throw new SecurityException("Requires DISABLE_INPUT_DEVICE permission"); 1085 } 1086 mNative.disableInputDevice(deviceId); 1087 } 1088 1089 /** 1090 * Gets the ids of all input devices in the system. 1091 * @return The input device ids. 1092 */ 1093 @Override // Binder call getInputDeviceIds()1094 public int[] getInputDeviceIds() { 1095 synchronized (mInputDevicesLock) { 1096 final int count = mInputDevices.length; 1097 int[] ids = new int[count]; 1098 for (int i = 0; i < count; i++) { 1099 ids[i] = mInputDevices[i].getId(); 1100 } 1101 return ids; 1102 } 1103 } 1104 1105 /** 1106 * Gets all input devices in the system. 1107 * @return The array of input devices. 1108 */ getInputDevices()1109 public InputDevice[] getInputDevices() { 1110 synchronized (mInputDevicesLock) { 1111 return mInputDevices; 1112 } 1113 } 1114 1115 @Override // Binder call registerInputDevicesChangedListener( @onNull IInputDevicesChangedListener listener)1116 public void registerInputDevicesChangedListener( 1117 @NonNull IInputDevicesChangedListener listener) { 1118 Objects.requireNonNull(listener, "listener must not be null"); 1119 1120 synchronized (mInputDevicesLock) { 1121 int callingPid = Binder.getCallingPid(); 1122 if (mInputDevicesChangedListeners.get(callingPid) != null) { 1123 throw new SecurityException("The calling process has already " 1124 + "registered an InputDevicesChangedListener."); 1125 } 1126 1127 InputDevicesChangedListenerRecord record = 1128 new InputDevicesChangedListenerRecord(callingPid, listener); 1129 try { 1130 IBinder binder = listener.asBinder(); 1131 binder.linkToDeath(record, 0); 1132 } catch (RemoteException ex) { 1133 // give up 1134 throw new RuntimeException(ex); 1135 } 1136 1137 mInputDevicesChangedListeners.put(callingPid, record); 1138 } 1139 } 1140 onInputDevicesChangedListenerDied(int pid)1141 private void onInputDevicesChangedListenerDied(int pid) { 1142 synchronized (mInputDevicesLock) { 1143 mInputDevicesChangedListeners.remove(pid); 1144 } 1145 } 1146 1147 // Must be called on handler. deliverInputDevicesChanged(InputDevice[] oldInputDevices)1148 private void deliverInputDevicesChanged(InputDevice[] oldInputDevices) { 1149 // Scan for changes. 1150 mTempInputDevicesChangedListenersToNotify.clear(); 1151 final int numListeners; 1152 final int[] deviceIdAndGeneration; 1153 synchronized (mInputDevicesLock) { 1154 if (!mInputDevicesChangedPending) { 1155 return; 1156 } 1157 mInputDevicesChangedPending = false; 1158 1159 numListeners = mInputDevicesChangedListeners.size(); 1160 for (int i = 0; i < numListeners; i++) { 1161 mTempInputDevicesChangedListenersToNotify.add( 1162 mInputDevicesChangedListeners.valueAt(i)); 1163 } 1164 1165 final int numDevices = mInputDevices.length; 1166 deviceIdAndGeneration = new int[numDevices * 2]; 1167 for (int i = 0; i < numDevices; i++) { 1168 final InputDevice inputDevice = mInputDevices[i]; 1169 deviceIdAndGeneration[i * 2] = inputDevice.getId(); 1170 deviceIdAndGeneration[i * 2 + 1] = inputDevice.getGeneration(); 1171 if (DEBUG) { 1172 Log.d(TAG, "device " + inputDevice.getId() + " generation " 1173 + inputDevice.getGeneration()); 1174 } 1175 } 1176 } 1177 1178 // Notify listeners. 1179 for (int i = 0; i < numListeners; i++) { 1180 mTempInputDevicesChangedListenersToNotify.get(i).notifyInputDevicesChanged( 1181 deviceIdAndGeneration); 1182 } 1183 mTempInputDevicesChangedListenersToNotify.clear(); 1184 } 1185 1186 @Override // Binder call & native callback getTouchCalibrationForInputDevice(@onNull String inputDeviceDescriptor, int surfaceRotation)1187 public TouchCalibration getTouchCalibrationForInputDevice(@NonNull String inputDeviceDescriptor, 1188 int surfaceRotation) { 1189 Objects.requireNonNull(inputDeviceDescriptor, "inputDeviceDescriptor must not be null"); 1190 1191 synchronized (mDataStore) { 1192 return mDataStore.getTouchCalibration(inputDeviceDescriptor, surfaceRotation); 1193 } 1194 } 1195 1196 @Override // Binder call setTouchCalibrationForInputDevice(@onNull String inputDeviceDescriptor, int surfaceRotation, @NonNull TouchCalibration calibration)1197 public void setTouchCalibrationForInputDevice(@NonNull String inputDeviceDescriptor, 1198 int surfaceRotation, @NonNull TouchCalibration calibration) { 1199 if (!checkCallingPermission(android.Manifest.permission.SET_INPUT_CALIBRATION, 1200 "setTouchCalibrationForInputDevice()")) { 1201 throw new SecurityException("Requires SET_INPUT_CALIBRATION permission"); 1202 } 1203 Objects.requireNonNull(inputDeviceDescriptor, "inputDeviceDescriptor must not be null"); 1204 Objects.requireNonNull(calibration, "calibration must not be null"); 1205 if (surfaceRotation < Surface.ROTATION_0 || surfaceRotation > Surface.ROTATION_270) { 1206 throw new IllegalArgumentException("surfaceRotation value out of bounds"); 1207 } 1208 1209 synchronized (mDataStore) { 1210 try { 1211 if (mDataStore.setTouchCalibration(inputDeviceDescriptor, surfaceRotation, 1212 calibration)) { 1213 mNative.reloadCalibration(); 1214 } 1215 } finally { 1216 mDataStore.saveIfNeeded(); 1217 } 1218 } 1219 } 1220 1221 @Override // Binder call isInTabletMode()1222 public int isInTabletMode() { 1223 if (!checkCallingPermission(android.Manifest.permission.TABLET_MODE, 1224 "isInTabletMode()")) { 1225 throw new SecurityException("Requires TABLET_MODE permission"); 1226 } 1227 return getSwitchState(-1, InputDevice.SOURCE_ANY, SW_TABLET_MODE); 1228 } 1229 1230 @Override // Binder call isMicMuted()1231 public int isMicMuted() { 1232 return getSwitchState(-1, InputDevice.SOURCE_ANY, SW_MUTE_DEVICE); 1233 } 1234 1235 @Override // Binder call registerTabletModeChangedListener(@onNull ITabletModeChangedListener listener)1236 public void registerTabletModeChangedListener(@NonNull ITabletModeChangedListener listener) { 1237 if (!checkCallingPermission(android.Manifest.permission.TABLET_MODE, 1238 "registerTabletModeChangedListener()")) { 1239 throw new SecurityException("Requires TABLET_MODE_LISTENER permission"); 1240 } 1241 Objects.requireNonNull(listener, "listener must not be null"); 1242 1243 synchronized (mTabletModeLock) { 1244 final int callingPid = Binder.getCallingPid(); 1245 if (mTabletModeChangedListeners.get(callingPid) != null) { 1246 throw new IllegalStateException("The calling process has already registered " 1247 + "a TabletModeChangedListener."); 1248 } 1249 TabletModeChangedListenerRecord record = 1250 new TabletModeChangedListenerRecord(callingPid, listener); 1251 try { 1252 IBinder binder = listener.asBinder(); 1253 binder.linkToDeath(record, 0); 1254 } catch (RemoteException ex) { 1255 throw new RuntimeException(ex); 1256 } 1257 mTabletModeChangedListeners.put(callingPid, record); 1258 } 1259 } 1260 onTabletModeChangedListenerDied(int pid)1261 private void onTabletModeChangedListenerDied(int pid) { 1262 synchronized (mTabletModeLock) { 1263 mTabletModeChangedListeners.remove(pid); 1264 } 1265 } 1266 1267 // Must be called on handler deliverTabletModeChanged(long whenNanos, boolean inTabletMode)1268 private void deliverTabletModeChanged(long whenNanos, boolean inTabletMode) { 1269 mTempTabletModeChangedListenersToNotify.clear(); 1270 final int numListeners; 1271 synchronized (mTabletModeLock) { 1272 numListeners = mTabletModeChangedListeners.size(); 1273 for (int i = 0; i < numListeners; i++) { 1274 mTempTabletModeChangedListenersToNotify.add( 1275 mTabletModeChangedListeners.valueAt(i)); 1276 } 1277 } 1278 for (int i = 0; i < numListeners; i++) { 1279 mTempTabletModeChangedListenersToNotify.get(i).notifyTabletModeChanged( 1280 whenNanos, inTabletMode); 1281 } 1282 } 1283 1284 @Override // Binder call getKeyboardLayouts()1285 public KeyboardLayout[] getKeyboardLayouts() { 1286 return mKeyboardLayoutManager.getKeyboardLayouts(); 1287 } 1288 1289 @Override // Binder call getKeyboardLayout(String keyboardLayoutDescriptor)1290 public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) { 1291 return mKeyboardLayoutManager.getKeyboardLayout(keyboardLayoutDescriptor); 1292 } 1293 1294 @Override // Binder call getKeyboardLayoutForInputDevice( InputDeviceIdentifier identifier, @UserIdInt int userId, @NonNull InputMethodInfo imeInfo, @Nullable InputMethodSubtype imeSubtype)1295 public KeyboardLayoutSelectionResult getKeyboardLayoutForInputDevice( 1296 InputDeviceIdentifier identifier, @UserIdInt int userId, 1297 @NonNull InputMethodInfo imeInfo, @Nullable InputMethodSubtype imeSubtype) { 1298 return mKeyboardLayoutManager.getKeyboardLayoutForInputDevice(identifier, userId, 1299 imeInfo, imeSubtype); 1300 } 1301 1302 @EnforcePermission(Manifest.permission.SET_KEYBOARD_LAYOUT) 1303 @Override // Binder call setKeyboardLayoutOverrideForInputDevice(InputDeviceIdentifier identifier, String keyboardLayoutDescriptor)1304 public void setKeyboardLayoutOverrideForInputDevice(InputDeviceIdentifier identifier, 1305 String keyboardLayoutDescriptor) { 1306 super.setKeyboardLayoutOverrideForInputDevice_enforcePermission(); 1307 mKeyboardLayoutManager.setKeyboardLayoutOverrideForInputDevice(identifier, 1308 keyboardLayoutDescriptor); 1309 } 1310 1311 @EnforcePermission(Manifest.permission.SET_KEYBOARD_LAYOUT) 1312 @Override // Binder call setKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier, @UserIdInt int userId, @NonNull InputMethodInfo imeInfo, @Nullable InputMethodSubtype imeSubtype, String keyboardLayoutDescriptor)1313 public void setKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier, 1314 @UserIdInt int userId, @NonNull InputMethodInfo imeInfo, 1315 @Nullable InputMethodSubtype imeSubtype, String keyboardLayoutDescriptor) { 1316 super.setKeyboardLayoutForInputDevice_enforcePermission(); 1317 mKeyboardLayoutManager.setKeyboardLayoutForInputDevice(identifier, userId, imeInfo, 1318 imeSubtype, keyboardLayoutDescriptor); 1319 } 1320 1321 @Override // Binder call getKeyboardLayoutListForInputDevice(InputDeviceIdentifier identifier, @UserIdInt int userId, @NonNull InputMethodInfo imeInfo, @Nullable InputMethodSubtype imeSubtype)1322 public KeyboardLayout[] getKeyboardLayoutListForInputDevice(InputDeviceIdentifier identifier, 1323 @UserIdInt int userId, @NonNull InputMethodInfo imeInfo, 1324 @Nullable InputMethodSubtype imeSubtype) { 1325 return mKeyboardLayoutManager.getKeyboardLayoutListForInputDevice(identifier, userId, 1326 imeInfo, imeSubtype); 1327 } 1328 1329 @Override // Binder call getKeyGlyphMap(int deviceId)1330 public KeyGlyphMap getKeyGlyphMap(int deviceId) { 1331 return mKeyboardGlyphManager.getKeyGlyphMap(deviceId); 1332 } 1333 setFocusedApplication(int displayId, InputApplicationHandle application)1334 public void setFocusedApplication(int displayId, InputApplicationHandle application) { 1335 mNative.setFocusedApplication(displayId, application); 1336 } 1337 setFocusedDisplay(int displayId)1338 public void setFocusedDisplay(int displayId) { 1339 mNative.setFocusedDisplay(displayId); 1340 } 1341 1342 /** Clean up input window handles of the given display. */ onDisplayRemoved(int displayId)1343 public void onDisplayRemoved(int displayId) { 1344 updateAdditionalDisplayInputProperties(displayId, AdditionalDisplayInputProperties::reset); 1345 1346 // TODO(b/320763728): Rely on WindowInfosListener to determine when a display has been 1347 // removed in InputDispatcher instead of this callback. 1348 mNative.displayRemoved(displayId); 1349 } 1350 1351 @Override requestPointerCapture(@onNull IBinder inputChannelToken, boolean enabled)1352 public void requestPointerCapture(@NonNull IBinder inputChannelToken, boolean enabled) { 1353 Objects.requireNonNull(inputChannelToken, "inputChannelToken must not be null"); 1354 1355 mNative.requestPointerCapture(inputChannelToken, enabled); 1356 } 1357 setInputDispatchMode(boolean enabled, boolean frozen)1358 public void setInputDispatchMode(boolean enabled, boolean frozen) { 1359 mNative.setInputDispatchMode(enabled, frozen); 1360 } 1361 setSystemUiLightsOut(boolean lightsOut)1362 public void setSystemUiLightsOut(boolean lightsOut) { 1363 mNative.setSystemUiLightsOut(lightsOut); 1364 } 1365 1366 /** 1367 * Start drag and drop. 1368 * 1369 * @param fromChannelToken The token of the input channel that is currently receiving a touch 1370 * gesture that should be turned into the drag pointer. 1371 * @param dragAndDropChannelToken The token of the input channel associated with the system drag 1372 * window. 1373 * @return true if drag and drop was successfully started, false otherwise. 1374 */ startDragAndDrop(@onNull IBinder fromChannelToken, @NonNull IBinder dragAndDropChannelToken)1375 public boolean startDragAndDrop(@NonNull IBinder fromChannelToken, 1376 @NonNull IBinder dragAndDropChannelToken) { 1377 return mNative.transferTouchGesture(fromChannelToken, dragAndDropChannelToken, 1378 true /* isDragDrop */, false /* transferEntireGesture */); 1379 } 1380 1381 /** 1382 * Atomically transfers an active touch gesture from one window to another, as identified by 1383 * their input channels. 1384 * 1385 * <p>Only the touch gesture that is currently being dispatched to a window associated with 1386 * {@code fromChannelToken} will be effected. That window will no longer receive 1387 * the touch gesture (i.e. it will receive {@link android.view.MotionEvent#ACTION_CANCEL}). 1388 * A window associated with the {@code toChannelToken} will receive the rest of the gesture 1389 * (i.e. beginning with {@link android.view.MotionEvent#ACTION_DOWN} or 1390 * {@link android.view.MotionEvent#ACTION_POINTER_DOWN}). 1391 * 1392 * <p>Transferring touch gestures will have no impact on focused windows. If the {@code 1393 * toChannelToken} window is focusable, this will not bring focus to that window. 1394 * 1395 * @param fromChannelToken The channel token of a window that has an active touch gesture. 1396 * @param toChannelToken The channel token of the window that should receive the gesture in 1397 * place of the first. 1398 * @return True if the transfer was successful. False if the specified windows don't exist, or 1399 * if the source window is not actively receiving a touch gesture at the time of the request. 1400 */ transferTouchGesture(@onNull IBinder fromChannelToken, @NonNull IBinder toChannelToken, boolean transferEntireGesture)1401 public boolean transferTouchGesture(@NonNull IBinder fromChannelToken, 1402 @NonNull IBinder toChannelToken, boolean transferEntireGesture) { 1403 Objects.requireNonNull(fromChannelToken); 1404 Objects.requireNonNull(toChannelToken); 1405 return mNative.transferTouchGesture(fromChannelToken, toChannelToken, 1406 false /* isDragDrop */, transferEntireGesture); 1407 } 1408 1409 @Override // Binder call getMousePointerSpeed()1410 public int getMousePointerSpeed() { 1411 return mNative.getMousePointerSpeed(); 1412 } 1413 1414 @Override // Binder call tryPointerSpeed(int speed)1415 public void tryPointerSpeed(int speed) { 1416 if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED, 1417 "tryPointerSpeed()")) { 1418 throw new SecurityException("Requires SET_POINTER_SPEED permission"); 1419 } 1420 1421 if (speed < InputSettings.MIN_POINTER_SPEED || speed > InputSettings.MAX_POINTER_SPEED) { 1422 throw new IllegalArgumentException("speed out of range"); 1423 } 1424 1425 setPointerSpeedUnchecked(speed); 1426 } 1427 setPointerSpeedUnchecked(int speed)1428 private void setPointerSpeedUnchecked(int speed) { 1429 speed = Math.min(Math.max(speed, InputSettings.MIN_POINTER_SPEED), 1430 InputSettings.MAX_POINTER_SPEED); 1431 mNative.setPointerSpeed(speed); 1432 } 1433 setMouseScalingEnabled(boolean enabled, int displayId)1434 private void setMouseScalingEnabled(boolean enabled, int displayId) { 1435 updateAdditionalDisplayInputProperties(displayId, 1436 properties -> properties.mouseScalingEnabled = enabled); 1437 } 1438 setPointerIconVisible(boolean visible, int displayId)1439 private void setPointerIconVisible(boolean visible, int displayId) { 1440 updateAdditionalDisplayInputProperties(displayId, 1441 properties -> properties.pointerIconVisible = visible); 1442 } 1443 setDisplayEligibilityForPointerCapture(int displayId, boolean isEligible)1444 private void setDisplayEligibilityForPointerCapture(int displayId, boolean isEligible) { 1445 mNative.setDisplayEligibilityForPointerCapture(displayId, isEligible); 1446 } 1447 1448 private static class VibrationInfo { 1449 private final long[] mPattern; 1450 private final int[] mAmplitudes; 1451 private final int mRepeat; 1452 getPattern()1453 public long[] getPattern() { 1454 return mPattern; 1455 } 1456 getAmplitudes()1457 public int[] getAmplitudes() { 1458 return mAmplitudes; 1459 } 1460 getRepeatIndex()1461 public int getRepeatIndex() { 1462 return mRepeat; 1463 } 1464 VibrationInfo(VibrationEffect effect)1465 VibrationInfo(VibrationEffect effect) { 1466 long[] pattern = null; 1467 int[] amplitudes = null; 1468 int patternRepeatIndex = -1; 1469 int amplitudeCount = -1; 1470 1471 if (effect instanceof VibrationEffect.Composed composed) { 1472 int segmentCount = composed.getSegments().size(); 1473 pattern = new long[segmentCount]; 1474 amplitudes = new int[segmentCount]; 1475 patternRepeatIndex = composed.getRepeatIndex(); 1476 amplitudeCount = 0; 1477 for (int i = 0; i < segmentCount; i++) { 1478 VibrationEffectSegment segment = composed.getSegments().get(i); 1479 if (composed.getRepeatIndex() == i) { 1480 patternRepeatIndex = amplitudeCount; 1481 } 1482 if (!(segment instanceof StepSegment)) { 1483 Slog.w(TAG, "Input devices don't support segment " + segment); 1484 amplitudeCount = -1; 1485 break; 1486 } 1487 float amplitude = ((StepSegment) segment).getAmplitude(); 1488 if (Float.compare(amplitude, VibrationEffect.DEFAULT_AMPLITUDE) == 0) { 1489 amplitudes[amplitudeCount] = DEFAULT_VIBRATION_MAGNITUDE; 1490 } else { 1491 amplitudes[amplitudeCount] = 1492 (int) (amplitude * VibrationEffect.MAX_AMPLITUDE); 1493 } 1494 pattern[amplitudeCount++] = segment.getDuration(); 1495 } 1496 } else { 1497 Slog.w(TAG, "Input devices don't support effect " + effect); 1498 } 1499 1500 if (amplitudeCount < 0) { 1501 Slog.w(TAG, "Only oneshot and step waveforms are supported on input devices"); 1502 mPattern = new long[0]; 1503 mAmplitudes = new int[0]; 1504 mRepeat = -1; 1505 } else { 1506 mRepeat = patternRepeatIndex; 1507 mPattern = new long[amplitudeCount]; 1508 mAmplitudes = new int[amplitudeCount]; 1509 System.arraycopy(pattern, 0, mPattern, 0, amplitudeCount); 1510 System.arraycopy(amplitudes, 0, mAmplitudes, 0, amplitudeCount); 1511 if (mRepeat >= mPattern.length) { 1512 throw new ArrayIndexOutOfBoundsException("Repeat index " + mRepeat 1513 + " must be within the bounds of the pattern.length " 1514 + mPattern.length); 1515 } 1516 } 1517 } 1518 } 1519 getVibratorToken(int deviceId, IBinder token)1520 private VibratorToken getVibratorToken(int deviceId, IBinder token) { 1521 VibratorToken v; 1522 synchronized (mVibratorLock) { 1523 v = mVibratorTokens.get(token); 1524 if (v == null) { 1525 v = new VibratorToken(deviceId, token, mNextVibratorTokenValue++); 1526 try { 1527 token.linkToDeath(v, 0); 1528 } catch (RemoteException ex) { 1529 // give up 1530 throw new RuntimeException(ex); 1531 } 1532 mVibratorTokens.put(token, v); 1533 } 1534 } 1535 return v; 1536 } 1537 1538 // Binder call 1539 @Override vibrate(int deviceId, VibrationEffect effect, IBinder token)1540 public void vibrate(int deviceId, VibrationEffect effect, IBinder token) { 1541 VibrationInfo info = new VibrationInfo(effect); 1542 VibratorToken v = getVibratorToken(deviceId, token); 1543 synchronized (v) { 1544 v.mVibrating = true; 1545 mNative.vibrate(deviceId, info.getPattern(), info.getAmplitudes(), 1546 info.getRepeatIndex(), v.mTokenValue); 1547 } 1548 } 1549 1550 // Binder call 1551 @Override getVibratorIds(int deviceId)1552 public int[] getVibratorIds(int deviceId) { 1553 return mNative.getVibratorIds(deviceId); 1554 } 1555 1556 // Binder call 1557 @Override isVibrating(int deviceId)1558 public boolean isVibrating(int deviceId) { 1559 return mNative.isVibrating(deviceId); 1560 } 1561 1562 // Binder call 1563 @Override vibrateCombined(int deviceId, CombinedVibration effect, IBinder token)1564 public void vibrateCombined(int deviceId, CombinedVibration effect, IBinder token) { 1565 VibratorToken v = getVibratorToken(deviceId, token); 1566 synchronized (v) { 1567 if (!(effect instanceof CombinedVibration.Mono) 1568 && !(effect instanceof CombinedVibration.Stereo)) { 1569 Slog.e(TAG, "Only Mono and Stereo effects are supported"); 1570 return; 1571 } 1572 1573 v.mVibrating = true; 1574 if (effect instanceof CombinedVibration.Mono) { 1575 CombinedVibration.Mono mono = (CombinedVibration.Mono) effect; 1576 VibrationInfo info = new VibrationInfo(mono.getEffect()); 1577 mNative.vibrate(deviceId, info.getPattern(), info.getAmplitudes(), 1578 info.getRepeatIndex(), v.mTokenValue); 1579 } else if (effect instanceof CombinedVibration.Stereo) { 1580 CombinedVibration.Stereo stereo = (CombinedVibration.Stereo) effect; 1581 SparseArray<VibrationEffect> effects = stereo.getEffects(); 1582 long[] pattern = new long[0]; 1583 int repeat = Integer.MIN_VALUE; 1584 SparseArray<int[]> amplitudes = new SparseArray<>(effects.size()); 1585 for (int i = 0; i < effects.size(); i++) { 1586 VibrationInfo info = new VibrationInfo(effects.valueAt(i)); 1587 // Pattern of all effects should be same 1588 if (pattern.length == 0) { 1589 pattern = info.getPattern(); 1590 } 1591 if (repeat == Integer.MIN_VALUE) { 1592 repeat = info.getRepeatIndex(); 1593 } 1594 amplitudes.put(effects.keyAt(i), info.getAmplitudes()); 1595 } 1596 mNative.vibrateCombined(deviceId, pattern, amplitudes, repeat, 1597 v.mTokenValue); 1598 } 1599 } 1600 } 1601 1602 // Binder call 1603 @Override cancelVibrate(int deviceId, IBinder token)1604 public void cancelVibrate(int deviceId, IBinder token) { 1605 VibratorToken v; 1606 synchronized (mVibratorLock) { 1607 v = mVibratorTokens.get(token); 1608 if (v == null || v.mDeviceId != deviceId) { 1609 return; // nothing to cancel 1610 } 1611 } 1612 1613 cancelVibrateIfNeeded(v); 1614 } 1615 onVibratorTokenDied(VibratorToken v)1616 void onVibratorTokenDied(VibratorToken v) { 1617 synchronized (mVibratorLock) { 1618 mVibratorTokens.remove(v.mToken); 1619 } 1620 1621 cancelVibrateIfNeeded(v); 1622 } 1623 cancelVibrateIfNeeded(VibratorToken v)1624 private void cancelVibrateIfNeeded(VibratorToken v) { 1625 synchronized (v) { 1626 if (v.mVibrating) { 1627 mNative.cancelVibrate(v.mDeviceId, v.mTokenValue); 1628 v.mVibrating = false; 1629 } 1630 } 1631 } 1632 1633 // Native callback. 1634 @SuppressWarnings("unused") notifyVibratorState(int deviceId, boolean isOn)1635 private void notifyVibratorState(int deviceId, boolean isOn) { 1636 if (DEBUG) { 1637 Slog.d(TAG, "notifyVibratorState: deviceId=" + deviceId + " isOn=" + isOn); 1638 } 1639 synchronized (mVibratorLock) { 1640 mIsVibrating.put(deviceId, isOn); 1641 notifyVibratorStateListenersLocked(deviceId); 1642 } 1643 } 1644 1645 @GuardedBy("mVibratorLock") notifyVibratorStateListenersLocked(int deviceId)1646 private void notifyVibratorStateListenersLocked(int deviceId) { 1647 if (!mVibratorStateListeners.contains(deviceId)) { 1648 if (DEBUG) { 1649 Slog.v(TAG, "Device " + deviceId + " doesn't have vibrator state listener."); 1650 } 1651 return; 1652 } 1653 RemoteCallbackList<IVibratorStateListener> listeners = 1654 mVibratorStateListeners.get(deviceId); 1655 final int length = listeners.beginBroadcast(); 1656 try { 1657 for (int i = 0; i < length; i++) { 1658 notifyVibratorStateListenerLocked(deviceId, listeners.getBroadcastItem(i)); 1659 } 1660 } finally { 1661 listeners.finishBroadcast(); 1662 } 1663 } 1664 1665 @GuardedBy("mVibratorLock") notifyVibratorStateListenerLocked(int deviceId, IVibratorStateListener listener)1666 private void notifyVibratorStateListenerLocked(int deviceId, IVibratorStateListener listener) { 1667 try { 1668 listener.onVibrating(mIsVibrating.get(deviceId)); 1669 } catch (RemoteException | RuntimeException e) { 1670 Slog.e(TAG, "Vibrator state listener failed to call", e); 1671 } 1672 } 1673 1674 @Override // Binder call registerVibratorStateListener(int deviceId, @NonNull IVibratorStateListener listener)1675 public boolean registerVibratorStateListener(int deviceId, 1676 @NonNull IVibratorStateListener listener) { 1677 Objects.requireNonNull(listener, "listener must not be null"); 1678 1679 RemoteCallbackList<IVibratorStateListener> listeners; 1680 synchronized (mVibratorLock) { 1681 if (!mVibratorStateListeners.contains(deviceId)) { 1682 listeners = new RemoteCallbackList<>(); 1683 mVibratorStateListeners.put(deviceId, listeners); 1684 } else { 1685 listeners = mVibratorStateListeners.get(deviceId); 1686 } 1687 1688 final long token = Binder.clearCallingIdentity(); 1689 try { 1690 if (!listeners.register(listener)) { 1691 Slog.e(TAG, "Could not register vibrator state listener " + listener); 1692 return false; 1693 } 1694 // Notify its callback after new client registered. 1695 notifyVibratorStateListenerLocked(deviceId, listener); 1696 return true; 1697 } finally { 1698 Binder.restoreCallingIdentity(token); 1699 } 1700 } 1701 } 1702 1703 @Override // Binder call unregisterVibratorStateListener(int deviceId, IVibratorStateListener listener)1704 public boolean unregisterVibratorStateListener(int deviceId, IVibratorStateListener listener) { 1705 synchronized (mVibratorLock) { 1706 final long token = Binder.clearCallingIdentity(); 1707 try { 1708 if (!mVibratorStateListeners.contains(deviceId)) { 1709 Slog.w(TAG, "Vibrator state listener " + deviceId + " doesn't exist"); 1710 return false; 1711 } 1712 RemoteCallbackList<IVibratorStateListener> listeners = 1713 mVibratorStateListeners.get(deviceId); 1714 return listeners.unregister(listener); 1715 } finally { 1716 Binder.restoreCallingIdentity(token); 1717 } 1718 } 1719 } 1720 1721 // Binder call 1722 @Override getBatteryState(int deviceId)1723 public IInputDeviceBatteryState getBatteryState(int deviceId) { 1724 return mBatteryController.getBatteryState(deviceId); 1725 } 1726 1727 // Binder call 1728 @Override setPointerIcon(@onNull PointerIcon icon, int displayId, int deviceId, int pointerId, IBinder inputToken)1729 public boolean setPointerIcon(@NonNull PointerIcon icon, int displayId, int deviceId, 1730 int pointerId, IBinder inputToken) { 1731 Objects.requireNonNull(icon); 1732 return mNative.setPointerIcon(icon, displayId, deviceId, pointerId, inputToken); 1733 } 1734 1735 /** 1736 * Add a runtime association between the input port and the display port. This overrides any 1737 * static associations. 1738 * @param inputPort the port of the input device 1739 * @param displayPort the physical port of the associated display 1740 */ 1741 @Override // Binder call addPortAssociation(@onNull String inputPort, int displayPort)1742 public void addPortAssociation(@NonNull String inputPort, int displayPort) { 1743 if (!checkCallingPermission( 1744 android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY, 1745 "addPortAssociation()")) { 1746 throw new SecurityException( 1747 "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission"); 1748 } 1749 1750 Objects.requireNonNull(inputPort); 1751 synchronized (mAssociationsLock) { 1752 mRuntimeAssociations.put(inputPort, displayPort); 1753 } 1754 mNative.notifyPortAssociationsChanged(); 1755 } 1756 1757 /** 1758 * Remove the runtime association between the input port and the display port. Any existing 1759 * static association for the cleared input port will be restored. 1760 * @param inputPort the port of the input device to be cleared 1761 */ 1762 @Override // Binder call removePortAssociation(@onNull String inputPort)1763 public void removePortAssociation(@NonNull String inputPort) { 1764 if (!checkCallingPermission( 1765 android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY, 1766 "removePortAssociation()")) { 1767 throw new SecurityException( 1768 "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission"); 1769 } 1770 1771 Objects.requireNonNull(inputPort); 1772 synchronized (mAssociationsLock) { 1773 mRuntimeAssociations.remove(inputPort); 1774 } 1775 mNative.notifyPortAssociationsChanged(); 1776 } 1777 1778 @Override // Binder call addUniqueIdAssociationByPort(@onNull String inputPort, @NonNull String displayUniqueId)1779 public void addUniqueIdAssociationByPort(@NonNull String inputPort, 1780 @NonNull String displayUniqueId) { 1781 if (!checkCallingPermission( 1782 android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY, 1783 "addUniqueIdAssociation()")) { 1784 throw new SecurityException( 1785 "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission"); 1786 } 1787 1788 Objects.requireNonNull(inputPort); 1789 Objects.requireNonNull(displayUniqueId); 1790 synchronized (mAssociationsLock) { 1791 mUniqueIdAssociationsByPort.put(inputPort, displayUniqueId); 1792 } 1793 mNative.changeUniqueIdAssociation(); 1794 } 1795 1796 @Override // Binder call removeUniqueIdAssociationByPort(@onNull String inputPort)1797 public void removeUniqueIdAssociationByPort(@NonNull String inputPort) { 1798 if (!checkCallingPermission( 1799 android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY, 1800 "removeUniqueIdAssociation()")) { 1801 throw new SecurityException("Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission"); 1802 } 1803 1804 Objects.requireNonNull(inputPort); 1805 synchronized (mAssociationsLock) { 1806 mUniqueIdAssociationsByPort.remove(inputPort); 1807 } 1808 mNative.changeUniqueIdAssociation(); 1809 } 1810 1811 /** 1812 * Adds a runtime association between the input device descriptor and the display unique id. 1813 * @param inputDeviceDescriptor the descriptor of the input device 1814 * @param displayUniqueId the unique ID of the display 1815 */ 1816 @Override // Binder call addUniqueIdAssociationByDescriptor(@onNull String inputDeviceDescriptor, @NonNull String displayUniqueId)1817 public void addUniqueIdAssociationByDescriptor(@NonNull String inputDeviceDescriptor, 1818 @NonNull String displayUniqueId) { 1819 if (!checkCallingPermission( 1820 android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY, 1821 "addUniqueIdAssociationByDescriptor()")) { 1822 throw new SecurityException( 1823 "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission"); 1824 } 1825 1826 Objects.requireNonNull(inputDeviceDescriptor); 1827 Objects.requireNonNull(displayUniqueId); 1828 synchronized (mAssociationsLock) { 1829 mUniqueIdAssociationsByDescriptor.put(inputDeviceDescriptor, displayUniqueId); 1830 } 1831 mNative.changeUniqueIdAssociation(); 1832 } 1833 1834 /** 1835 * Removes the runtime association between the input device and the display. 1836 * @param inputDeviceDescriptor the descriptor of the input device 1837 */ 1838 @Override // Binder call removeUniqueIdAssociationByDescriptor(@onNull String inputDeviceDescriptor)1839 public void removeUniqueIdAssociationByDescriptor(@NonNull String inputDeviceDescriptor) { 1840 if (!checkCallingPermission( 1841 android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY, 1842 "removeUniqueIdAssociationByDescriptor()")) { 1843 throw new SecurityException( 1844 "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission"); 1845 } 1846 1847 Objects.requireNonNull(inputDeviceDescriptor); 1848 synchronized (mAssociationsLock) { 1849 mUniqueIdAssociationsByDescriptor.remove(inputDeviceDescriptor); 1850 } 1851 mNative.changeUniqueIdAssociation(); 1852 } 1853 setTypeAssociationInternal(@onNull String inputPort, @NonNull String type)1854 void setTypeAssociationInternal(@NonNull String inputPort, @NonNull String type) { 1855 Objects.requireNonNull(inputPort); 1856 Objects.requireNonNull(type); 1857 synchronized (mAssociationsLock) { 1858 mDeviceTypeAssociations.put(inputPort, type); 1859 } 1860 mNative.changeTypeAssociation(); 1861 } 1862 unsetTypeAssociationInternal(@onNull String inputPort)1863 void unsetTypeAssociationInternal(@NonNull String inputPort) { 1864 Objects.requireNonNull(inputPort); 1865 synchronized (mAssociationsLock) { 1866 mDeviceTypeAssociations.remove(inputPort); 1867 } 1868 mNative.changeTypeAssociation(); 1869 } 1870 addKeyboardLayoutAssociation(@onNull String inputPort, @NonNull String languageTag, @NonNull String layoutType)1871 private void addKeyboardLayoutAssociation(@NonNull String inputPort, 1872 @NonNull String languageTag, @NonNull String layoutType) { 1873 Objects.requireNonNull(inputPort); 1874 Objects.requireNonNull(languageTag); 1875 Objects.requireNonNull(layoutType); 1876 1877 synchronized (mAssociationsLock) { 1878 mKeyboardLayoutAssociations.put(inputPort, 1879 TextUtils.formatSimple("%s,%s", languageTag, layoutType)); 1880 } 1881 mNative.changeKeyboardLayoutAssociation(); 1882 } 1883 removeKeyboardLayoutAssociation(@onNull String inputPort)1884 private void removeKeyboardLayoutAssociation(@NonNull String inputPort) { 1885 Objects.requireNonNull(inputPort); 1886 synchronized (mAssociationsLock) { 1887 mKeyboardLayoutAssociations.remove(inputPort); 1888 } 1889 mNative.changeKeyboardLayoutAssociation(); 1890 } 1891 1892 @Override // Binder call getSensorList(int deviceId)1893 public InputSensorInfo[] getSensorList(int deviceId) { 1894 return mNative.getSensorList(deviceId); 1895 } 1896 1897 /** 1898 * Retrieves the hardware properties of the touchpad for the given device ID. 1899 * Returns null if the device has no touchpad hardware properties 1900 * or if the device ID is invalid. 1901 */ 1902 @Nullable getTouchpadHardwareProperties(int deviceId)1903 public TouchpadHardwareProperties getTouchpadHardwareProperties(int deviceId) { 1904 return mNative.getTouchpadHardwareProperties(deviceId); 1905 } 1906 1907 @Override // Binder call registerSensorListener(@onNull IInputSensorEventListener listener)1908 public boolean registerSensorListener(@NonNull IInputSensorEventListener listener) { 1909 if (DEBUG) { 1910 Slog.d(TAG, "registerSensorListener: listener=" + listener + " callingPid=" 1911 + Binder.getCallingPid()); 1912 } 1913 Objects.requireNonNull(listener, "listener must not be null"); 1914 1915 synchronized (mSensorEventLock) { 1916 int callingPid = Binder.getCallingPid(); 1917 if (mSensorEventListeners.get(callingPid) != null) { 1918 Slog.e(TAG, "The calling process " + callingPid + " has already " 1919 + "registered an InputSensorEventListener."); 1920 return false; 1921 } 1922 1923 SensorEventListenerRecord record = 1924 new SensorEventListenerRecord(callingPid, listener); 1925 try { 1926 IBinder binder = listener.asBinder(); 1927 binder.linkToDeath(record, 0); 1928 } catch (RemoteException ex) { 1929 // give up 1930 throw new RuntimeException(ex); 1931 } 1932 1933 mSensorEventListeners.put(callingPid, record); 1934 } 1935 return true; 1936 } 1937 1938 @Override // Binder call unregisterSensorListener(@onNull IInputSensorEventListener listener)1939 public void unregisterSensorListener(@NonNull IInputSensorEventListener listener) { 1940 if (DEBUG) { 1941 Slog.d(TAG, "unregisterSensorListener: listener=" + listener + " callingPid=" 1942 + Binder.getCallingPid()); 1943 } 1944 1945 Objects.requireNonNull(listener, "listener must not be null"); 1946 1947 synchronized (mSensorEventLock) { 1948 int callingPid = Binder.getCallingPid(); 1949 if (mSensorEventListeners.get(callingPid) != null) { 1950 SensorEventListenerRecord record = mSensorEventListeners.get(callingPid); 1951 if (record.getListener().asBinder() != listener.asBinder()) { 1952 throw new IllegalArgumentException("listener is not registered"); 1953 } 1954 mSensorEventListeners.remove(callingPid); 1955 } 1956 } 1957 } 1958 1959 @Override // Binder call flushSensor(int deviceId, int sensorType)1960 public boolean flushSensor(int deviceId, int sensorType) { 1961 synchronized (mSensorEventLock) { 1962 int callingPid = Binder.getCallingPid(); 1963 SensorEventListenerRecord listener = mSensorEventListeners.get(callingPid); 1964 if (listener != null) { 1965 return mNative.flushSensor(deviceId, sensorType); 1966 } 1967 return false; 1968 } 1969 } 1970 1971 @Override // Binder call enableSensor(int deviceId, int sensorType, int samplingPeriodUs, int maxBatchReportLatencyUs)1972 public boolean enableSensor(int deviceId, int sensorType, int samplingPeriodUs, 1973 int maxBatchReportLatencyUs) { 1974 synchronized (mInputDevicesLock) { 1975 return mNative.enableSensor(deviceId, sensorType, samplingPeriodUs, 1976 maxBatchReportLatencyUs); 1977 } 1978 } 1979 1980 @Override // Binder call disableSensor(int deviceId, int sensorType)1981 public void disableSensor(int deviceId, int sensorType) { 1982 synchronized (mInputDevicesLock) { 1983 mNative.disableSensor(deviceId, sensorType); 1984 } 1985 } 1986 1987 /** 1988 * LightSession represents a light session for lights manager. 1989 */ 1990 private final class LightSession implements DeathRecipient { 1991 private final int mDeviceId; 1992 private final IBinder mToken; 1993 private final String mOpPkg; 1994 // The light ids and states that are requested by the light seesion 1995 private int[] mLightIds; 1996 private LightState[] mLightStates; 1997 LightSession(int deviceId, String opPkg, IBinder token)1998 LightSession(int deviceId, String opPkg, IBinder token) { 1999 mDeviceId = deviceId; 2000 mOpPkg = opPkg; 2001 mToken = token; 2002 } 2003 2004 @Override binderDied()2005 public void binderDied() { 2006 if (DEBUG) { 2007 Slog.d(TAG, "Light token died."); 2008 } 2009 synchronized (mLightLock) { 2010 closeLightSession(mDeviceId, mToken); 2011 mLightSessions.remove(mToken); 2012 } 2013 } 2014 } 2015 2016 /** 2017 * Returns the lights available for apps to control on the specified input device. 2018 * Only lights that aren't reserved for system use are available to apps. 2019 */ 2020 @Override // Binder call getLights(int deviceId)2021 public List<Light> getLights(int deviceId) { 2022 return mNative.getLights(deviceId); 2023 } 2024 2025 /** 2026 * Set specified light state with for a specific input device. 2027 */ setLightStateInternal(int deviceId, @NonNull Light light, @NonNull LightState lightState)2028 private void setLightStateInternal(int deviceId, @NonNull Light light, 2029 @NonNull LightState lightState) { 2030 Objects.requireNonNull(light, "light does not exist"); 2031 if (DEBUG) { 2032 Slog.d(TAG, "setLightStateInternal device " + deviceId + " light " + light 2033 + "lightState " + lightState); 2034 } 2035 if (light.getType() == Light.LIGHT_TYPE_PLAYER_ID) { 2036 mNative.setLightPlayerId(deviceId, light.getId(), lightState.getPlayerId()); 2037 } else { 2038 // Set ARGB format color to input device light 2039 // Refer to https://developer.android.com/reference/kotlin/android/graphics/Color 2040 mNative.setLightColor(deviceId, light.getId(), lightState.getColor()); 2041 } 2042 } 2043 2044 /** 2045 * Set multiple light states with multiple light ids for a specific input device. 2046 */ setLightStatesInternal(int deviceId, int[] lightIds, LightState[] lightStates)2047 private void setLightStatesInternal(int deviceId, int[] lightIds, LightState[] lightStates) { 2048 final List<Light> lights = mNative.getLights(deviceId); 2049 SparseArray<Light> lightArray = new SparseArray<>(); 2050 for (int i = 0; i < lights.size(); i++) { 2051 lightArray.put(lights.get(i).getId(), lights.get(i)); 2052 } 2053 for (int i = 0; i < lightIds.length; i++) { 2054 if (lightArray.contains(lightIds[i])) { 2055 setLightStateInternal(deviceId, lightArray.get(lightIds[i]), lightStates[i]); 2056 } 2057 } 2058 } 2059 2060 /** 2061 * Set states for multiple lights for an opened light session. 2062 */ 2063 @Override setLightStates(int deviceId, int[] lightIds, LightState[] lightStates, IBinder token)2064 public void setLightStates(int deviceId, int[] lightIds, LightState[] lightStates, 2065 IBinder token) { 2066 Preconditions.checkArgument(lightIds.length == lightStates.length, 2067 "lights and light states are not same length"); 2068 synchronized (mLightLock) { 2069 LightSession lightSession = mLightSessions.get(token); 2070 Preconditions.checkArgument(lightSession != null, "not registered"); 2071 Preconditions.checkState(lightSession.mDeviceId == deviceId, "Incorrect device ID"); 2072 lightSession.mLightIds = lightIds.clone(); 2073 lightSession.mLightStates = lightStates.clone(); 2074 if (DEBUG) { 2075 Slog.d(TAG, "setLightStates for " + lightSession.mOpPkg + " device " + deviceId); 2076 } 2077 } 2078 setLightStatesInternal(deviceId, lightIds, lightStates); 2079 } 2080 2081 @Override getLightState(int deviceId, int lightId)2082 public @Nullable LightState getLightState(int deviceId, int lightId) { 2083 synchronized (mLightLock) { 2084 int color = mNative.getLightColor(deviceId, lightId); 2085 int playerId = mNative.getLightPlayerId(deviceId, lightId); 2086 2087 return new LightState(color, playerId); 2088 } 2089 } 2090 2091 @Override openLightSession(int deviceId, String opPkg, @NonNull IBinder token)2092 public void openLightSession(int deviceId, String opPkg, @NonNull IBinder token) { 2093 Objects.requireNonNull(token); 2094 synchronized (mLightLock) { 2095 Preconditions.checkState(mLightSessions.get(token) == null, "already registered"); 2096 LightSession lightSession = new LightSession(deviceId, opPkg, token); 2097 try { 2098 token.linkToDeath(lightSession, 0); 2099 } catch (RemoteException ex) { 2100 // give up 2101 ex.rethrowAsRuntimeException(); 2102 } 2103 mLightSessions.put(token, lightSession); 2104 if (DEBUG) { 2105 Slog.d(TAG, "Open light session for " + opPkg + " device " + deviceId); 2106 } 2107 } 2108 } 2109 2110 @Override closeLightSession(int deviceId, @NonNull IBinder token)2111 public void closeLightSession(int deviceId, @NonNull IBinder token) { 2112 Objects.requireNonNull(token); 2113 synchronized (mLightLock) { 2114 LightSession lightSession = mLightSessions.get(token); 2115 Preconditions.checkState(lightSession != null, "not registered"); 2116 // Turn off the lights that were previously requested by the session to be closed. 2117 Arrays.fill(lightSession.mLightStates, new LightState(0)); 2118 setLightStatesInternal(deviceId, lightSession.mLightIds, 2119 lightSession.mLightStates); 2120 mLightSessions.remove(token); 2121 // If any other session is still pending with light request, apply the first session's 2122 // request. 2123 if (!mLightSessions.isEmpty()) { 2124 LightSession nextSession = mLightSessions.valueAt(0); 2125 setLightStatesInternal(deviceId, nextSession.mLightIds, nextSession.mLightStates); 2126 } 2127 } 2128 } 2129 2130 @Override cancelCurrentTouch()2131 public void cancelCurrentTouch() { 2132 if (!checkCallingPermission(android.Manifest.permission.MONITOR_INPUT, 2133 "cancelCurrentTouch()")) { 2134 throw new SecurityException("Requires MONITOR_INPUT permission"); 2135 } 2136 2137 mNative.cancelCurrentTouch(); 2138 } 2139 2140 @Override registerBatteryListener(int deviceId, @NonNull IInputDeviceBatteryListener listener)2141 public void registerBatteryListener(int deviceId, 2142 @NonNull IInputDeviceBatteryListener listener) { 2143 Objects.requireNonNull(listener); 2144 mBatteryController.registerBatteryListener(deviceId, listener, Binder.getCallingPid()); 2145 } 2146 2147 @Override unregisterBatteryListener(int deviceId, @NonNull IInputDeviceBatteryListener listener)2148 public void unregisterBatteryListener(int deviceId, 2149 @NonNull IInputDeviceBatteryListener listener) { 2150 Objects.requireNonNull(listener); 2151 mBatteryController.unregisterBatteryListener(deviceId, listener, Binder.getCallingPid()); 2152 } 2153 2154 @EnforcePermission(Manifest.permission.BLUETOOTH) 2155 @Override getInputDeviceBluetoothAddress(int deviceId)2156 public String getInputDeviceBluetoothAddress(int deviceId) { 2157 super.getInputDeviceBluetoothAddress_enforcePermission(); 2158 2159 final String address = mNative.getBluetoothAddress(deviceId); 2160 if (address == null) return null; 2161 if (!BluetoothAdapter.checkBluetoothAddress(address)) { 2162 throw new IllegalStateException("The Bluetooth address of input device " + deviceId 2163 + " should not be invalid: address=" + address); 2164 } 2165 return address; 2166 } 2167 2168 @EnforcePermission(Manifest.permission.MONITOR_INPUT) 2169 @Override pilferPointers(@onNull IBinder inputChannelToken)2170 public void pilferPointers(@NonNull IBinder inputChannelToken) { 2171 super.pilferPointers_enforcePermission(); 2172 2173 Objects.requireNonNull(inputChannelToken); 2174 mNative.pilferPointers(inputChannelToken); 2175 } 2176 2177 @Override 2178 @EnforcePermission(Manifest.permission.MONITOR_KEYBOARD_BACKLIGHT) registerKeyboardBacklightListener(@onNull IKeyboardBacklightListener listener)2179 public void registerKeyboardBacklightListener(@NonNull IKeyboardBacklightListener listener) { 2180 super.registerKeyboardBacklightListener_enforcePermission(); 2181 Objects.requireNonNull(listener); 2182 mKeyboardBacklightController.registerKeyboardBacklightListener(listener, 2183 Binder.getCallingPid()); 2184 } 2185 2186 @Override 2187 @EnforcePermission(Manifest.permission.MONITOR_KEYBOARD_BACKLIGHT) unregisterKeyboardBacklightListener(@onNull IKeyboardBacklightListener listener)2188 public void unregisterKeyboardBacklightListener(@NonNull IKeyboardBacklightListener listener) { 2189 super.unregisterKeyboardBacklightListener_enforcePermission(); 2190 Objects.requireNonNull(listener); 2191 mKeyboardBacklightController.unregisterKeyboardBacklightListener(listener, 2192 Binder.getCallingPid()); 2193 } 2194 2195 @Override getHostUsiVersionFromDisplayConfig(int displayId)2196 public HostUsiVersion getHostUsiVersionFromDisplayConfig(int displayId) { 2197 return mDisplayManagerInternal.getHostUsiVersion(displayId); 2198 } 2199 2200 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)2201 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2202 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 2203 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 2204 2205 ipw.println("INPUT MANAGER (dumpsys input)\n"); 2206 String dumpStr = mNative.dump(); 2207 if (dumpStr != null) { 2208 pw.println(dumpStr); 2209 } 2210 2211 ipw.println("Input Manager Service (Java) State:"); 2212 ipw.increaseIndent(); 2213 dumpAssociations(ipw); 2214 dumpSpyWindowGestureMonitors(ipw); 2215 dumpDisplayInputPropertiesValues(ipw); 2216 mBatteryController.dump(ipw); 2217 mKeyboardBacklightController.dump(ipw); 2218 mKeyboardLedController.dump(ipw); 2219 mKeyboardGlyphManager.dump(ipw); 2220 mKeyGestureController.dump(ipw); 2221 } 2222 dumpAssociations(IndentingPrintWriter pw)2223 private void dumpAssociations(IndentingPrintWriter pw) { 2224 if (!mStaticAssociations.isEmpty()) { 2225 pw.println("Static Associations:"); 2226 mStaticAssociations.forEach((k, v) -> { 2227 pw.print(" port: " + k); 2228 pw.println(" display: " + v); 2229 }); 2230 } 2231 2232 synchronized (mAssociationsLock) { 2233 if (!mRuntimeAssociations.isEmpty()) { 2234 pw.println("Runtime Associations:"); 2235 mRuntimeAssociations.forEach((k, v) -> { 2236 pw.print(" port: " + k); 2237 pw.println(" display: " + v); 2238 }); 2239 } 2240 if (!mUniqueIdAssociationsByPort.isEmpty()) { 2241 pw.println("Unique Id Associations:"); 2242 mUniqueIdAssociationsByPort.forEach((k, v) -> { 2243 pw.print(" port: " + k); 2244 pw.println(" uniqueId: " + v); 2245 }); 2246 } 2247 if (!mUniqueIdAssociationsByDescriptor.isEmpty()) { 2248 pw.println("Unique Id Associations:"); 2249 mUniqueIdAssociationsByDescriptor.forEach((k, v) -> { 2250 pw.print(" descriptor: " + k); 2251 pw.println(" uniqueId: " + v); 2252 }); 2253 } 2254 if (!mDeviceTypeAssociations.isEmpty()) { 2255 pw.println("Type Associations:"); 2256 mDeviceTypeAssociations.forEach((k, v) -> { 2257 pw.print(" port: " + k); 2258 pw.println(" type: " + v); 2259 }); 2260 } 2261 } 2262 } 2263 dumpSpyWindowGestureMonitors(IndentingPrintWriter pw)2264 private void dumpSpyWindowGestureMonitors(IndentingPrintWriter pw) { 2265 synchronized (mInputMonitors) { 2266 if (mInputMonitors.isEmpty()) return; 2267 pw.println("Gesture Monitors (implemented as spy windows):"); 2268 int i = 0; 2269 for (final GestureMonitorSpyWindow monitor : mInputMonitors.values()) { 2270 pw.append(" " + i++ + ": ").println(monitor.dump()); 2271 } 2272 } 2273 } 2274 dumpDisplayInputPropertiesValues(IndentingPrintWriter pw)2275 private void dumpDisplayInputPropertiesValues(IndentingPrintWriter pw) { 2276 synchronized (mAdditionalDisplayInputPropertiesLock) { 2277 pw.println("mAdditionalDisplayInputProperties:"); 2278 pw.increaseIndent(); 2279 try { 2280 if (mAdditionalDisplayInputProperties.size() == 0) { 2281 pw.println("<none>"); 2282 return; 2283 } 2284 for (int i = 0; i < mAdditionalDisplayInputProperties.size(); i++) { 2285 pw.println("displayId: " + mAdditionalDisplayInputProperties.keyAt(i)); 2286 final AdditionalDisplayInputProperties properties = 2287 mAdditionalDisplayInputProperties.valueAt(i); 2288 pw.println("mouseScalingEnabled: " 2289 + properties.mouseScalingEnabled); 2290 pw.println("pointerIconVisible: " + properties.pointerIconVisible); 2291 } 2292 } finally { 2293 pw.decreaseIndent(); 2294 } 2295 } 2296 } checkCallingPermission(String permission, String func)2297 private boolean checkCallingPermission(String permission, String func) { 2298 return checkCallingPermission(permission, func, false /*checkInstrumentationSource*/); 2299 } 2300 checkCallingPermission(String permission, String func, boolean checkInstrumentationSource)2301 private boolean checkCallingPermission(String permission, String func, 2302 boolean checkInstrumentationSource) { 2303 // Quick check: if the calling permission is me, it's all okay. 2304 if (Binder.getCallingPid() == Process.myPid()) { 2305 return true; 2306 } 2307 2308 if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) { 2309 return true; 2310 } 2311 2312 if (checkInstrumentationSource) { 2313 final ActivityManagerInternal ami = 2314 LocalServices.getService(ActivityManagerInternal.class); 2315 Objects.requireNonNull(ami, "ActivityManagerInternal should not be null."); 2316 final int instrumentationUid = ami.getInstrumentationSourceUid(Binder.getCallingUid()); 2317 if (instrumentationUid != Process.INVALID_UID) { 2318 // Clear the calling identity when checking if the instrumentation source has 2319 // permission because PackageManager will deny all permissions to some callers, 2320 // such as instant apps. 2321 final long token = Binder.clearCallingIdentity(); 2322 try { 2323 if (mContext.checkPermission(permission, -1 /*pid*/, instrumentationUid) 2324 == PackageManager.PERMISSION_GRANTED) { 2325 return true; 2326 } 2327 } finally { 2328 Binder.restoreCallingIdentity(token); 2329 } 2330 } 2331 } 2332 2333 String msg = "Permission Denial: " + func + " from pid=" 2334 + Binder.getCallingPid() 2335 + ", uid=" + Binder.getCallingUid() 2336 + " requires " + permission; 2337 Slog.w(TAG, msg); 2338 return false; 2339 } 2340 2341 // Called by the heartbeat to ensure locks are not held indefinitely (for deadlock detection). 2342 @Override monitor()2343 public void monitor() { 2344 synchronized (mInputFilterLock) { } 2345 synchronized (mAssociationsLock) { /* Test if blocked by associations lock. */} 2346 synchronized (mLidSwitchLock) { /* Test if blocked by lid switch lock. */ } 2347 synchronized (mInputMonitors) { /* Test if blocked by input monitor lock. */ } 2348 synchronized (mAdditionalDisplayInputPropertiesLock) { /* Test if blocked by props lock */ } 2349 mBatteryController.monitor(); 2350 mPointerIconCache.monitor(); 2351 mNative.monitor(); 2352 } 2353 2354 // Native callback. 2355 @SuppressWarnings("unused") notifyInputDevicesChanged(InputDevice[] inputDevices)2356 private void notifyInputDevicesChanged(InputDevice[] inputDevices) { 2357 synchronized (mInputDevicesLock) { 2358 if (!mInputDevicesChangedPending) { 2359 mInputDevicesChangedPending = true; 2360 mHandler.obtainMessage(MSG_DELIVER_INPUT_DEVICES_CHANGED, 2361 mInputDevices).sendToTarget(); 2362 } 2363 2364 mInputDevices = inputDevices; 2365 } 2366 // Input device change can possibly change configuration, so notify window manager to update 2367 // its configuration. 2368 mWindowManagerCallbacks.notifyConfigurationChanged(); 2369 } 2370 2371 // Native callback. 2372 @SuppressWarnings("unused") notifyTouchpadHardwareState(TouchpadHardwareState hardwareStates, int deviceId)2373 private void notifyTouchpadHardwareState(TouchpadHardwareState hardwareStates, int deviceId) { 2374 if (mTouchpadDebugViewController != null) { 2375 mTouchpadDebugViewController.updateTouchpadHardwareState(hardwareStates, deviceId); 2376 } 2377 } 2378 2379 // Native callback. 2380 @SuppressWarnings("unused") notifyTouchpadGestureInfo(int type, int deviceId)2381 private void notifyTouchpadGestureInfo(int type, int deviceId) { 2382 if (mTouchpadDebugViewController != null) { 2383 mTouchpadDebugViewController.updateTouchpadGestureInfo(type, deviceId); 2384 } 2385 } 2386 2387 // Native callback. 2388 @SuppressWarnings("unused") notifyTouchpadThreeFingerTap()2389 private void notifyTouchpadThreeFingerTap() { 2390 mKeyGestureController.handleTouchpadGesture( 2391 InputGestureData.TOUCHPAD_GESTURE_TYPE_THREE_FINGER_TAP); 2392 } 2393 2394 // Native callback. 2395 @SuppressWarnings("unused") notifySwitch(long whenNanos, int switchValues, int switchMask)2396 private void notifySwitch(long whenNanos, int switchValues, int switchMask) { 2397 if (DEBUG) { 2398 Slog.d(TAG, "notifySwitch: values=" + Integer.toHexString(switchValues) 2399 + ", mask=" + Integer.toHexString(switchMask)); 2400 } 2401 2402 if ((switchMask & SW_LID_BIT) != 0) { 2403 final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0); 2404 synchronized (mLidSwitchLock) { 2405 if (mSystemReady) { 2406 for (int i = 0; i < mLidSwitchCallbacks.size(); i++) { 2407 LidSwitchCallback callbacks = mLidSwitchCallbacks.get(i); 2408 callbacks.notifyLidSwitchChanged(whenNanos, lidOpen); 2409 } 2410 } 2411 } 2412 } 2413 2414 if ((switchMask & SW_CAMERA_LENS_COVER_BIT) != 0) { 2415 final boolean lensCovered = ((switchValues & SW_CAMERA_LENS_COVER_BIT) != 0); 2416 mWindowManagerCallbacks.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered); 2417 // Use SW_CAMERA_LENS_COVER code for camera privacy toggles 2418 setSensorPrivacy(Sensors.CAMERA, lensCovered); 2419 } 2420 2421 if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) { 2422 mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues, 2423 switchMask); 2424 } 2425 2426 if ((switchMask & SW_TABLET_MODE_BIT) != 0) { 2427 SomeArgs args = SomeArgs.obtain(); 2428 args.argi1 = (int) (whenNanos & 0xFFFFFFFF); 2429 args.argi2 = (int) (whenNanos >> 32); 2430 args.arg1 = (switchValues & SW_TABLET_MODE_BIT) != 0; 2431 mHandler.obtainMessage(MSG_DELIVER_TABLET_MODE_CHANGED, 2432 args).sendToTarget(); 2433 } 2434 2435 if ((switchMask & SW_MUTE_DEVICE_BIT) != 0) { 2436 final boolean micMute = ((switchValues & SW_MUTE_DEVICE_BIT) != 0); 2437 AudioManager audioManager = mContext.getSystemService(AudioManager.class); 2438 audioManager.setMicrophoneMuteFromSwitch(micMute); 2439 2440 setSensorPrivacy(Sensors.MICROPHONE, micMute); 2441 } 2442 } 2443 2444 // Set the sensor privacy state based on the hardware toggles switch states setSensorPrivacy(@ensorPrivacyManager.Sensors.Sensor int sensor, boolean enablePrivacy)2445 private void setSensorPrivacy(@SensorPrivacyManager.Sensors.Sensor int sensor, 2446 boolean enablePrivacy) { 2447 final SensorPrivacyManagerInternal sensorPrivacyManagerInternal = 2448 LocalServices.getService(SensorPrivacyManagerInternal.class); 2449 sensorPrivacyManagerInternal.setPhysicalToggleSensorPrivacy(UserHandle.USER_CURRENT, sensor, 2450 enablePrivacy); 2451 } 2452 2453 // Native callback. 2454 @SuppressWarnings("unused") notifyInputChannelBroken(IBinder token)2455 private void notifyInputChannelBroken(IBinder token) { 2456 synchronized (mInputMonitors) { 2457 if (mInputMonitors.containsKey(token)) { 2458 removeSpyWindowGestureMonitor(token); 2459 } 2460 } 2461 mWindowManagerCallbacks.notifyInputChannelBroken(token); 2462 } 2463 2464 // Native callback 2465 @SuppressWarnings("unused") notifyFocusChanged(IBinder oldToken, IBinder newToken)2466 private void notifyFocusChanged(IBinder oldToken, IBinder newToken) { 2467 mWindowManagerCallbacks.notifyFocusChanged(oldToken, newToken); 2468 } 2469 2470 // Native callback 2471 @SuppressWarnings("unused") notifyDropWindow(IBinder token, float x, float y)2472 private void notifyDropWindow(IBinder token, float x, float y) { 2473 mWindowManagerCallbacks.notifyDropWindow(token, x, y); 2474 } 2475 2476 // Native callback. 2477 @SuppressWarnings("unused") notifyNoFocusedWindowAnr(InputApplicationHandle inputApplicationHandle)2478 private void notifyNoFocusedWindowAnr(InputApplicationHandle inputApplicationHandle) { 2479 mWindowManagerCallbacks.notifyNoFocusedWindowAnr(inputApplicationHandle); 2480 } 2481 2482 // Native callback 2483 @SuppressWarnings("unused") notifyWindowUnresponsive(IBinder token, int pid, boolean isPidValid, String reason)2484 private void notifyWindowUnresponsive(IBinder token, int pid, boolean isPidValid, 2485 String reason) { 2486 mWindowManagerCallbacks.notifyWindowUnresponsive(token, 2487 isPidValid ? OptionalInt.of(pid) : OptionalInt.empty(), reason); 2488 } 2489 2490 // Native callback 2491 @SuppressWarnings("unused") notifyWindowResponsive(IBinder token, int pid, boolean isPidValid)2492 private void notifyWindowResponsive(IBinder token, int pid, boolean isPidValid) { 2493 mWindowManagerCallbacks.notifyWindowResponsive(token, 2494 isPidValid ? OptionalInt.of(pid) : OptionalInt.empty()); 2495 } 2496 2497 // Native callback. 2498 @SuppressWarnings("unused") notifySensorEvent(int deviceId, int sensorType, int accuracy, long timestamp, float[] values)2499 private void notifySensorEvent(int deviceId, int sensorType, int accuracy, long timestamp, 2500 float[] values) { 2501 if (DEBUG) { 2502 Slog.d(TAG, "notifySensorEvent: deviceId=" + deviceId + " sensorType=" 2503 + sensorType + " values=" + Arrays.toString(values)); 2504 } 2505 mSensorEventListenersToNotify.clear(); 2506 final int numListeners; 2507 synchronized (mSensorEventLock) { 2508 numListeners = mSensorEventListeners.size(); 2509 for (int i = 0; i < numListeners; i++) { 2510 mSensorEventListenersToNotify.add( 2511 mSensorEventListeners.valueAt(i)); 2512 } 2513 } 2514 for (int i = 0; i < numListeners; i++) { 2515 mSensorEventListenersToNotify.get(i).notifySensorEvent(deviceId, sensorType, 2516 accuracy, timestamp, values); 2517 } 2518 mSensorEventListenersToNotify.clear(); 2519 } 2520 2521 // Native callback. 2522 @SuppressWarnings("unused") notifySensorAccuracy(int deviceId, int sensorType, int accuracy)2523 private void notifySensorAccuracy(int deviceId, int sensorType, int accuracy) { 2524 mSensorAccuracyListenersToNotify.clear(); 2525 final int numListeners; 2526 synchronized (mSensorEventLock) { 2527 numListeners = mSensorEventListeners.size(); 2528 for (int i = 0; i < numListeners; i++) { 2529 mSensorAccuracyListenersToNotify.add(mSensorEventListeners.valueAt(i)); 2530 } 2531 } 2532 for (int i = 0; i < numListeners; i++) { 2533 mSensorAccuracyListenersToNotify.get(i).notifySensorAccuracy( 2534 deviceId, sensorType, accuracy); 2535 } 2536 mSensorAccuracyListenersToNotify.clear(); 2537 } 2538 2539 // Native callback. 2540 @SuppressWarnings("unused") filterInputEvent(InputEvent event, int policyFlags)2541 final boolean filterInputEvent(InputEvent event, int policyFlags) { 2542 synchronized (mInputFilterLock) { 2543 if (mInputFilter != null) { 2544 try { 2545 mInputFilter.filterInputEvent(event, policyFlags); 2546 } catch (RemoteException e) { 2547 /* ignore */ 2548 } 2549 return false; 2550 } 2551 } 2552 event.recycle(); 2553 return true; 2554 } 2555 2556 @EnforcePermission(android.Manifest.permission.LISTEN_FOR_KEY_ACTIVITY) 2557 @Override // Binder Call registerKeyEventActivityListener(@onNull IKeyEventActivityListener listener)2558 public boolean registerKeyEventActivityListener(@NonNull IKeyEventActivityListener listener) { 2559 super.registerKeyEventActivityListener_enforcePermission(); 2560 Objects.requireNonNull(listener, "listener must not be null"); 2561 return InputManagerService.this.registerKeyEventActivityListenerInternal(listener); 2562 } 2563 2564 @EnforcePermission(android.Manifest.permission.LISTEN_FOR_KEY_ACTIVITY) 2565 @Override // Binder Call unregisterKeyEventActivityListener(@onNull IKeyEventActivityListener listener)2566 public boolean unregisterKeyEventActivityListener(@NonNull IKeyEventActivityListener listener) { 2567 super.unregisterKeyEventActivityListener_enforcePermission(); 2568 Objects.requireNonNull(listener, "listener must not be null"); 2569 return InputManagerService.this.unregisterKeyEventActivityListenerInternal(listener); 2570 } 2571 2572 /** 2573 * Registers a listener for updates to key event activeness 2574 */ registerKeyEventActivityListenerInternal(IKeyEventActivityListener listener)2575 private boolean registerKeyEventActivityListenerInternal(IKeyEventActivityListener listener) { 2576 synchronized (mKeyEventActivityLock) { 2577 if (!mKeyEventActivityListenersToNotify.contains(listener)) { 2578 mKeyEventActivityListenersToNotify.add(listener); 2579 return true; 2580 } 2581 } 2582 return false; 2583 } 2584 2585 /** 2586 * Unregisters a listener for updates to key event activeness 2587 */ unregisterKeyEventActivityListenerInternal(IKeyEventActivityListener listener)2588 private boolean unregisterKeyEventActivityListenerInternal(IKeyEventActivityListener listener) { 2589 synchronized (mKeyEventActivityLock) { 2590 return mKeyEventActivityListenersToNotify.removeIf(existingListener -> 2591 existingListener.asBinder() == listener.asBinder()); 2592 } 2593 } 2594 notifyKeyActivityListeners(KeyEvent event)2595 private void notifyKeyActivityListeners(KeyEvent event) { 2596 long currentTimeMs = SystemClock.uptimeMillis(); 2597 if (keyEventActivityDetection() 2598 && event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0 2599 && currentTimeMs - mLastKeyEventActivityTimeMs 2600 >= KEY_EVENT_ACTIVITY_RATE_LIMIT_INTERVAL_MS) { 2601 List<IKeyEventActivityListener> keyEventActivityListeners; 2602 synchronized (mKeyEventActivityLock) { 2603 keyEventActivityListeners = List.copyOf(mKeyEventActivityListenersToNotify); 2604 } 2605 for (IKeyEventActivityListener listener : keyEventActivityListeners) { 2606 try { 2607 listener.onKeyEventActivity(); 2608 } catch (RemoteException e) { 2609 Slog.i(TAG, 2610 "Could Not Notify Listener due to Remote Exception: " + e); 2611 unregisterKeyEventActivityListener(listener); 2612 } 2613 } 2614 mLastKeyEventActivityTimeMs = currentTimeMs; 2615 } 2616 } 2617 2618 // Native callback. 2619 @SuppressWarnings("unused") filterPointerMotion(float dx, float dy, float currentX, float currentY, int displayId)2620 final float[] filterPointerMotion(float dx, float dy, float currentX, float currentY, 2621 int displayId) { 2622 // This call happens on the input hot path and it is extremely performance sensitive. 2623 // This must not call back into native code. This is called while the 2624 // PointerChoreographer's lock is held. 2625 synchronized (mAccessibilityPointerMotionFilterLock) { 2626 if (mAccessibilityPointerMotionFilter == null) { 2627 throw new IllegalStateException( 2628 "filterCursor is invoked but no callback is registered."); 2629 } 2630 return mAccessibilityPointerMotionFilter.filterPointerMotionEvent(dx, dy, currentX, 2631 currentY, displayId); 2632 } 2633 } 2634 2635 // Native callback. 2636 @SuppressWarnings("unused") 2637 @VisibleForTesting interceptKeyBeforeQueueing(KeyEvent event, int policyFlags)2638 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { 2639 notifyKeyActivityListeners(event); 2640 synchronized (mFocusEventDebugViewLock) { 2641 if (mFocusEventDebugView != null) { 2642 mFocusEventDebugView.reportKeyEvent(event); 2643 } 2644 } 2645 if (useKeyGestureEventHandler() && mKeyGestureController.interceptKeyBeforeQueueing(event, 2646 policyFlags)) { 2647 // If key gesture gets triggered, we send the event to policy with KEY_GESTURE flag 2648 // indicating, the event is used in triggering a key gesture. We can't block event 2649 // like Power or volume keys since policy might still want to handle it to change 2650 // certain states. 2651 policyFlags |= WindowManagerPolicyConstants.FLAG_KEY_GESTURE_TRIGGERED; 2652 } 2653 return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags); 2654 } 2655 2656 // Native callback. 2657 @SuppressWarnings("unused") interceptMotionBeforeQueueingNonInteractive(int displayId, int source, int action, long whenNanos, int policyFlags)2658 private int interceptMotionBeforeQueueingNonInteractive(int displayId, 2659 int source, int action, long whenNanos, int policyFlags) { 2660 return mWindowManagerCallbacks.interceptMotionBeforeQueueingNonInteractive( 2661 displayId, source, action, whenNanos, policyFlags); 2662 } 2663 2664 // Native callback. 2665 @SuppressWarnings("unused") 2666 @VisibleForTesting interceptKeyBeforeDispatching(IBinder focus, KeyEvent event, int policyFlags)2667 long interceptKeyBeforeDispatching(IBinder focus, KeyEvent event, int policyFlags) { 2668 final long keyNotConsumedGoFallback = -2; 2669 final long keyConsumed = -1; 2670 final long keyNotConsumed = 0; 2671 long value = keyNotConsumed; 2672 // TODO(b/358569822) Remove below once we have nicer API for listening to shortcuts 2673 if ((event.isMetaPressed() || KeyEvent.isMetaKey(event.getKeyCode())) 2674 && shouldInterceptShortcuts(focus)) { 2675 return keyNotConsumed; 2676 } 2677 if (useKeyGestureEventHandler()) { 2678 value = mKeyGestureController.interceptKeyBeforeDispatching(focus, event, policyFlags); 2679 } 2680 if (value == keyNotConsumed) { 2681 value = mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, 2682 policyFlags); 2683 } 2684 if (fixSearchModifierFallbacks() && value == keyNotConsumed && event.isMetaPressed()) { 2685 // If the key has not been consumed and includes the meta key, do not send the event 2686 // to the app and attempt to generate a fallback. 2687 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 2688 final KeyCharacterMap.FallbackAction fallbackAction = 2689 kcm.getFallbackAction(event.getKeyCode(), event.getMetaState()); 2690 if (fallbackAction != null) { 2691 return keyNotConsumedGoFallback; 2692 } 2693 } 2694 return value; 2695 } 2696 shouldInterceptShortcuts(IBinder focusedToken)2697 private boolean shouldInterceptShortcuts(IBinder focusedToken) { 2698 KeyInterceptionInfo info = 2699 mWindowManagerInternal.getKeyInterceptionInfoFromToken(focusedToken); 2700 boolean hasInterceptWindowFlag = info != null && (info.layoutParamsPrivateFlags 2701 & WindowManager.LayoutParams.PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS) != 0; 2702 return hasInterceptWindowFlag && PermissionChecker.checkPermissionForDataDelivery(mContext, 2703 OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW, PID_UNKNOWN, info.windowOwnerUid, 2704 null, null, null) == PERMISSION_GRANTED; 2705 } 2706 2707 // Native callback. 2708 @SuppressWarnings("unused") dispatchUnhandledKey(IBinder focus, KeyEvent event, int policyFlags)2709 private KeyEvent dispatchUnhandledKey(IBinder focus, KeyEvent event, int policyFlags) { 2710 if (interceptUnhandledKey(event, focus)) { 2711 return null; 2712 } 2713 // TODO(b/358569822): Move fallback logic to KeyGestureController 2714 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) != 0) { 2715 return null; 2716 } 2717 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 2718 final int keyCode = event.getKeyCode(); 2719 final int metaState = event.getMetaState(); 2720 final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN 2721 && event.getRepeatCount() == 0; 2722 2723 // Check for fallback actions specified by the key character map. 2724 final KeyCharacterMap.FallbackAction fallbackAction; 2725 if (initialDown) { 2726 fallbackAction = kcm.getFallbackAction(keyCode, metaState); 2727 } else { 2728 fallbackAction = mFallbackActions.get(keyCode); 2729 } 2730 2731 if (fallbackAction == null) { 2732 return null; 2733 } 2734 KeyEvent fallbackEvent = null; 2735 final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK; 2736 fallbackEvent = KeyEvent.obtain( 2737 event.getDownTime(), event.getEventTime(), 2738 event.getAction(), fallbackAction.keyCode, 2739 event.getRepeatCount(), fallbackAction.metaState, 2740 event.getDeviceId(), event.getScanCode(), 2741 flags, event.getSource(), event.getDisplayId(), null); 2742 2743 if (!interceptFallback(focus, fallbackEvent, policyFlags)) { 2744 fallbackEvent.recycle(); 2745 fallbackEvent = null; 2746 } 2747 2748 if (initialDown) { 2749 mFallbackActions.put(keyCode, fallbackAction); 2750 } else if (event.getAction() == KeyEvent.ACTION_UP) { 2751 mFallbackActions.remove(keyCode); 2752 fallbackAction.recycle(); 2753 } 2754 return fallbackEvent; 2755 } 2756 interceptFallback(IBinder focusedToken, KeyEvent fallbackEvent, int policyFlags)2757 private boolean interceptFallback(IBinder focusedToken, KeyEvent fallbackEvent, 2758 int policyFlags) { 2759 int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags); 2760 if ((actions & ACTION_PASS_TO_USER) == 0) { 2761 return false; 2762 } 2763 long delayMillis = interceptKeyBeforeDispatching(focusedToken, fallbackEvent, policyFlags); 2764 return delayMillis == 0 && !interceptUnhandledKey(fallbackEvent, focusedToken); 2765 } 2766 interceptUnhandledKey(KeyEvent event, IBinder focus)2767 private boolean interceptUnhandledKey(KeyEvent event, IBinder focus) { 2768 if (useKeyGestureEventHandler() && mKeyGestureController.interceptUnhandledKey(event, 2769 focus)) { 2770 return true; 2771 } 2772 return mWindowManagerCallbacks.interceptUnhandledKey(event, focus); 2773 } 2774 2775 @SuppressLint("MissingPermission") initKeyGestures()2776 private void initKeyGestures() { 2777 InputManager im = Objects.requireNonNull(mContext.getSystemService(InputManager.class)); 2778 List<Integer> supportedGestures = List.of( 2779 KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP, 2780 KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN, 2781 KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE, 2782 KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK, 2783 KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS, 2784 KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS, 2785 KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS, 2786 KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS 2787 ); 2788 im.registerKeyGestureEventHandler(supportedGestures, 2789 (event, focusedToken) -> InputManagerService.this.handleKeyGestureEvent(event)); 2790 } 2791 2792 @SuppressLint("MissingPermission") 2793 @VisibleForTesting handleKeyGestureEvent(@onNull KeyGestureEvent event)2794 void handleKeyGestureEvent(@NonNull KeyGestureEvent event) { 2795 int deviceId = event.getDeviceId(); 2796 boolean complete = event.getAction() == KeyGestureEvent.ACTION_GESTURE_COMPLETE 2797 && !event.isCancelled(); 2798 switch (event.getKeyGestureType()) { 2799 case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP: 2800 if (complete) { 2801 mKeyboardBacklightController.incrementKeyboardBacklight(deviceId); 2802 } 2803 break; 2804 case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN: 2805 if (complete) { 2806 mKeyboardBacklightController.decrementKeyboardBacklight(deviceId); 2807 } 2808 break; 2809 case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE: 2810 // TODO(b/367748270): Add functionality to turn keyboard backlight on/off. 2811 break; 2812 case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK: 2813 if (complete) { 2814 mNative.toggleCapsLock(deviceId); 2815 } 2816 break; 2817 case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS: 2818 if (complete) { 2819 final boolean bounceKeysEnabled = 2820 InputSettings.isAccessibilityBounceKeysEnabled(mContext); 2821 InputSettings.setAccessibilityBounceKeysThreshold(mContext, 2822 bounceKeysEnabled ? 0 2823 : InputSettings.DEFAULT_BOUNCE_KEYS_THRESHOLD_MILLIS); 2824 } 2825 break; 2826 case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS: 2827 if (complete && InputSettings.isAccessibilityMouseKeysFeatureFlagEnabled()) { 2828 final boolean mouseKeysEnabled = InputSettings.isAccessibilityMouseKeysEnabled( 2829 mContext); 2830 InputSettings.setAccessibilityMouseKeysEnabled(mContext, !mouseKeysEnabled); 2831 } 2832 break; 2833 case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS: 2834 if (complete) { 2835 final boolean stickyKeysEnabled = 2836 InputSettings.isAccessibilityStickyKeysEnabled(mContext); 2837 InputSettings.setAccessibilityStickyKeysEnabled(mContext, !stickyKeysEnabled); 2838 } 2839 break; 2840 case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS: 2841 if (complete) { 2842 final boolean slowKeysEnabled = 2843 InputSettings.isAccessibilitySlowKeysEnabled(mContext); 2844 InputSettings.setAccessibilitySlowKeysThreshold(mContext, 2845 slowKeysEnabled ? 0 : InputSettings.DEFAULT_SLOW_KEYS_THRESHOLD_MILLIS); 2846 } 2847 break; 2848 default: 2849 Log.w(TAG, "Received a key gesture " + event 2850 + " that was not registered by this handler"); 2851 break; 2852 } 2853 } 2854 2855 // Native callback. 2856 @SuppressWarnings("unused") onPointerDownOutsideFocus(IBinder touchedToken)2857 private void onPointerDownOutsideFocus(IBinder touchedToken) { 2858 mWindowManagerCallbacks.onPointerDownOutsideFocus(touchedToken); 2859 } 2860 2861 // Native callback. 2862 @SuppressWarnings("unused") getVirtualKeyQuietTimeMillis()2863 private int getVirtualKeyQuietTimeMillis() { 2864 return mContext.getResources().getInteger( 2865 com.android.internal.R.integer.config_virtualKeyQuietTimeMillis); 2866 } 2867 2868 // Native callback. 2869 @SuppressWarnings("unused") getExcludedDeviceNames()2870 private static String[] getExcludedDeviceNames() { 2871 List<String> names = new ArrayList<>(); 2872 // Read partner-provided list of excluded input devices 2873 // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system". 2874 final File[] baseDirs = { 2875 Environment.getRootDirectory(), 2876 Environment.getVendorDirectory() 2877 }; 2878 for (File baseDir: baseDirs) { 2879 File confFile = new File(baseDir, EXCLUDED_DEVICES_PATH); 2880 try (InputStream stream = new FileInputStream(confFile)) { 2881 names.addAll(ConfigurationProcessor.processExcludedDeviceNames(stream)); 2882 } catch (FileNotFoundException e) { 2883 // It's ok if the file does not exist. 2884 } catch (Exception e) { 2885 Slog.e(TAG, "Could not parse '" + confFile.getAbsolutePath() + "'", e); 2886 } 2887 } 2888 return names.toArray(new String[0]); 2889 } 2890 2891 // Native callback. 2892 @SuppressWarnings("unused") isPerDisplayTouchModeEnabled()2893 private boolean isPerDisplayTouchModeEnabled() { 2894 return mContext.getResources().getBoolean( 2895 com.android.internal.R.bool.config_perDisplayFocusEnabled); 2896 } 2897 2898 // Native callback. 2899 @SuppressWarnings("unused") notifyStylusGestureStarted(int deviceId, long eventTime)2900 private void notifyStylusGestureStarted(int deviceId, long eventTime) { 2901 mBatteryController.notifyStylusGestureStarted(deviceId, eventTime); 2902 if (mDisplayManagerInternal != null) { 2903 mDisplayManagerInternal.stylusGestureStarted(eventTime); 2904 } 2905 } 2906 2907 /** 2908 * Flatten a map into a string list, with value positioned directly next to the 2909 * key. 2910 * @return Flattened list 2911 */ flatten(@onNull Map<String, T> map)2912 private static <T> String[] flatten(@NonNull Map<String, T> map) { 2913 final List<String> list = new ArrayList<>(map.size() * 2); 2914 map.forEach((k, v)-> { 2915 list.add(k); 2916 list.add(v.toString()); 2917 }); 2918 return list.toArray(new String[0]); 2919 } 2920 2921 /** 2922 * Ports are highly platform-specific, so allow these to be specified in the odm/vendor 2923 * directory. 2924 */ loadStaticInputPortAssociations()2925 private static Map<String, Integer> loadStaticInputPortAssociations() { 2926 File baseDir = Environment.getOdmDirectory(); 2927 File confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH); 2928 2929 if (!confFile.exists()) { 2930 baseDir = Environment.getVendorDirectory(); 2931 confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH); 2932 } 2933 2934 try (final InputStream stream = new FileInputStream(confFile)) { 2935 return ConfigurationProcessor.processInputPortAssociations(stream); 2936 } catch (FileNotFoundException e) { 2937 // Most of the time, file will not exist, which is expected. 2938 } catch (Exception e) { 2939 Slog.e(TAG, "Could not parse '" + confFile.getAbsolutePath() + "'", e); 2940 } 2941 2942 return new HashMap<>(); 2943 } 2944 2945 // Native callback 2946 @SuppressWarnings("unused") getInputPortAssociations()2947 private String[] getInputPortAssociations() { 2948 final Map<String, Integer> associations = new HashMap<>(mStaticAssociations); 2949 2950 // merge the runtime associations. 2951 synchronized (mAssociationsLock) { 2952 associations.putAll(mRuntimeAssociations); 2953 } 2954 2955 return flatten(associations); 2956 } 2957 2958 // Native callback 2959 @SuppressWarnings("unused") getInputUniqueIdAssociationsByPort()2960 private String[] getInputUniqueIdAssociationsByPort() { 2961 final Map<String, String> associations; 2962 synchronized (mAssociationsLock) { 2963 associations = new HashMap<>(mUniqueIdAssociationsByPort); 2964 } 2965 2966 return flatten(associations); 2967 } 2968 2969 // Native callback 2970 @SuppressWarnings("unused") getInputUniqueIdAssociationsByDescriptor()2971 private String[] getInputUniqueIdAssociationsByDescriptor() { 2972 final Map<String, String> associations; 2973 synchronized (mAssociationsLock) { 2974 associations = new HashMap<>(mUniqueIdAssociationsByDescriptor); 2975 } 2976 2977 return flatten(associations); 2978 } 2979 2980 // Native callback 2981 @SuppressWarnings("unused") 2982 @VisibleForTesting getDeviceTypeAssociations()2983 String[] getDeviceTypeAssociations() { 2984 final Map<String, String> associations; 2985 synchronized (mAssociationsLock) { 2986 associations = new HashMap<>(mDeviceTypeAssociations); 2987 } 2988 2989 return flatten(associations); 2990 } 2991 2992 // Native callback 2993 @SuppressWarnings("unused") 2994 @VisibleForTesting getKeyboardLayoutAssociations()2995 private String[] getKeyboardLayoutAssociations() { 2996 final Map<String, String> configs = new ArrayMap<>(); 2997 synchronized (mAssociationsLock) { 2998 configs.putAll(mKeyboardLayoutAssociations); 2999 } 3000 return flatten(configs); 3001 } 3002 3003 /** 3004 * Gets if an input device could dispatch to the given display". 3005 * @param deviceId The input device id. 3006 * @param displayId The specific display id. 3007 * @return True if the device could dispatch to the given display, false otherwise. 3008 */ canDispatchToDisplay(int deviceId, int displayId)3009 public boolean canDispatchToDisplay(int deviceId, int displayId) { 3010 return mNative.canDispatchToDisplay(deviceId, displayId); 3011 } 3012 3013 // Native callback. 3014 @SuppressWarnings("unused") getHoverTapTimeout()3015 private int getHoverTapTimeout() { 3016 return ViewConfiguration.getHoverTapTimeout(); 3017 } 3018 3019 // Native callback. 3020 @SuppressWarnings("unused") getHoverTapSlop()3021 private int getHoverTapSlop() { 3022 return ViewConfiguration.getHoverTapSlop(); 3023 } 3024 3025 // Native callback. 3026 @SuppressWarnings("unused") getDoubleTapTimeout()3027 private int getDoubleTapTimeout() { 3028 return ViewConfiguration.getDoubleTapTimeout(); 3029 } 3030 3031 // Native callback. 3032 @SuppressWarnings("unused") getLongPressTimeout()3033 private int getLongPressTimeout() { 3034 return ViewConfiguration.getLongPressTimeout(); 3035 } 3036 3037 // Native callback. 3038 @SuppressWarnings("unused") getPointerLayer()3039 private int getPointerLayer() { 3040 return mWindowManagerCallbacks.getPointerLayer(); 3041 } 3042 3043 // Native callback. 3044 @SuppressWarnings("unused") getLoadedPointerIcon(int displayId, int type)3045 private @NonNull PointerIcon getLoadedPointerIcon(int displayId, int type) { 3046 return mPointerIconCache.getLoadedPointerIcon(displayId, type); 3047 } 3048 3049 // Native callback. 3050 @SuppressWarnings("unused") getParentSurfaceForPointers(int displayId)3051 private long getParentSurfaceForPointers(int displayId) { 3052 final SurfaceControl sc = mWindowManagerCallbacks.getParentSurfaceForPointers(displayId); 3053 if (sc == null) { 3054 return 0; 3055 } 3056 return sc.mNativeObject; 3057 } 3058 3059 // Native callback. 3060 @SuppressWarnings("unused") getKeyboardLayoutOverlay(InputDeviceIdentifier identifier, String languageTag, String layoutType)3061 private String[] getKeyboardLayoutOverlay(InputDeviceIdentifier identifier, String languageTag, 3062 String layoutType) { 3063 if (!mSystemReady) { 3064 return null; 3065 } 3066 return mKeyboardLayoutManager.getKeyboardLayoutOverlay(identifier, languageTag, layoutType); 3067 } 3068 3069 @EnforcePermission(Manifest.permission.REMAP_MODIFIER_KEYS) 3070 @Override // Binder call remapModifierKey(int fromKey, int toKey)3071 public void remapModifierKey(int fromKey, int toKey) { 3072 super.remapModifierKey_enforcePermission(); 3073 mKeyRemapper.remapKey(fromKey, toKey); 3074 } 3075 3076 @EnforcePermission(Manifest.permission.REMAP_MODIFIER_KEYS) 3077 @Override // Binder call clearAllModifierKeyRemappings()3078 public void clearAllModifierKeyRemappings() { 3079 super.clearAllModifierKeyRemappings_enforcePermission(); 3080 mKeyRemapper.clearAllKeyRemappings(); 3081 } 3082 3083 @EnforcePermission(Manifest.permission.REMAP_MODIFIER_KEYS) 3084 @Override // Binder call getModifierKeyRemapping()3085 public Map<Integer, Integer> getModifierKeyRemapping() { 3086 super.getModifierKeyRemapping_enforcePermission(); 3087 return mKeyRemapper.getKeyRemapping(); 3088 } 3089 3090 // Native callback. 3091 @SuppressWarnings("unused") getDeviceAlias(String uniqueId)3092 private String getDeviceAlias(String uniqueId) { 3093 if (BluetoothAdapter.checkBluetoothAddress(uniqueId)) { 3094 // TODO(BT) mBluetoothService.getRemoteAlias(uniqueId) 3095 return null; 3096 } 3097 return null; 3098 } 3099 3100 @Override 3101 @EnforcePermission(Manifest.permission.MONITOR_STICKY_MODIFIER_STATE) registerStickyModifierStateListener( @onNull IStickyModifierStateListener listener)3102 public void registerStickyModifierStateListener( 3103 @NonNull IStickyModifierStateListener listener) { 3104 super.registerStickyModifierStateListener_enforcePermission(); 3105 Objects.requireNonNull(listener); 3106 mStickyModifierStateController.registerStickyModifierStateListener(listener, 3107 Binder.getCallingPid()); 3108 } 3109 3110 @Override 3111 @EnforcePermission(Manifest.permission.MONITOR_STICKY_MODIFIER_STATE) unregisterStickyModifierStateListener( @onNull IStickyModifierStateListener listener)3112 public void unregisterStickyModifierStateListener( 3113 @NonNull IStickyModifierStateListener listener) { 3114 super.unregisterStickyModifierStateListener_enforcePermission(); 3115 Objects.requireNonNull(listener); 3116 mStickyModifierStateController.unregisterStickyModifierStateListener(listener, 3117 Binder.getCallingPid()); 3118 } 3119 3120 // Native callback 3121 @SuppressWarnings("unused") notifyStickyModifierStateChanged(int modifierState, int lockedModifierState)3122 void notifyStickyModifierStateChanged(int modifierState, int lockedModifierState) { 3123 mStickyModifierStateController.notifyStickyModifierStateChanged(modifierState, 3124 lockedModifierState); 3125 } 3126 3127 /** 3128 * Enforces the caller contains the necessary permission to manage key gestures. 3129 */ 3130 @RequiresPermission(Manifest.permission.MANAGE_KEY_GESTURES) enforceManageKeyGesturePermission()3131 private void enforceManageKeyGesturePermission() { 3132 // TODO(b/361567988): Use @EnforcePermission to enforce permission once flag guarding the 3133 // permission is rolled out 3134 String systemUIPackage = mContext.getString(R.string.config_systemUi); 3135 PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class); 3136 if (pm != null) { 3137 int systemUIAppId = UserHandle.getAppId( 3138 pm.getPackageUid(systemUIPackage, PackageManager.MATCH_SYSTEM_ONLY, 3139 UserHandle.USER_SYSTEM)); 3140 if (UserHandle.getCallingAppId() == systemUIAppId) { 3141 return; 3142 } 3143 } 3144 if (mContext.checkCallingOrSelfPermission( 3145 Manifest.permission.MANAGE_KEY_GESTURES) == PackageManager.PERMISSION_GRANTED) { 3146 return; 3147 } 3148 3149 String message = "Managing Key Gestures requires the following permission: " 3150 + Manifest.permission.MANAGE_KEY_GESTURES; 3151 throw new SecurityException(message); 3152 } 3153 3154 3155 @Override 3156 @PermissionManuallyEnforced registerKeyGestureEventListener(@onNull IKeyGestureEventListener listener)3157 public void registerKeyGestureEventListener(@NonNull IKeyGestureEventListener listener) { 3158 enforceManageKeyGesturePermission(); 3159 3160 Objects.requireNonNull(listener); 3161 mKeyGestureController.registerKeyGestureEventListener(listener, Binder.getCallingPid()); 3162 } 3163 3164 @Override 3165 @PermissionManuallyEnforced unregisterKeyGestureEventListener(@onNull IKeyGestureEventListener listener)3166 public void unregisterKeyGestureEventListener(@NonNull IKeyGestureEventListener listener) { 3167 enforceManageKeyGesturePermission(); 3168 3169 Objects.requireNonNull(listener); 3170 mKeyGestureController.unregisterKeyGestureEventListener(listener, Binder.getCallingPid()); 3171 } 3172 3173 @Override 3174 @PermissionManuallyEnforced registerKeyGestureHandler(int[] keyGesturesToHandle, @NonNull IKeyGestureHandler handler)3175 public void registerKeyGestureHandler(int[] keyGesturesToHandle, 3176 @NonNull IKeyGestureHandler handler) { 3177 enforceManageKeyGesturePermission(); 3178 3179 Objects.requireNonNull(handler); 3180 Objects.requireNonNull(keyGesturesToHandle); 3181 mKeyGestureController.registerKeyGestureHandler(keyGesturesToHandle, handler, 3182 Binder.getCallingPid()); 3183 } 3184 3185 @Override 3186 @PermissionManuallyEnforced unregisterKeyGestureHandler(@onNull IKeyGestureHandler handler)3187 public void unregisterKeyGestureHandler(@NonNull IKeyGestureHandler handler) { 3188 enforceManageKeyGesturePermission(); 3189 3190 Objects.requireNonNull(handler); 3191 mKeyGestureController.unregisterKeyGestureHandler(handler, Binder.getCallingPid()); 3192 } 3193 3194 @Override 3195 @PermissionManuallyEnforced getInputGesture(@serIdInt int userId, @NonNull AidlInputGestureData.Trigger trigger)3196 public AidlInputGestureData getInputGesture(@UserIdInt int userId, 3197 @NonNull AidlInputGestureData.Trigger trigger) { 3198 enforceManageKeyGesturePermission(); 3199 3200 Objects.requireNonNull(trigger); 3201 return mKeyGestureController.getInputGesture(userId, trigger); 3202 } 3203 3204 @Override 3205 @PermissionManuallyEnforced addCustomInputGesture(@serIdInt int userId, @NonNull AidlInputGestureData inputGestureData)3206 public int addCustomInputGesture(@UserIdInt int userId, 3207 @NonNull AidlInputGestureData inputGestureData) { 3208 enforceManageKeyGesturePermission(); 3209 3210 Objects.requireNonNull(inputGestureData); 3211 return mKeyGestureController.addCustomInputGesture(userId, inputGestureData); 3212 } 3213 3214 @Override 3215 @PermissionManuallyEnforced removeCustomInputGesture(@serIdInt int userId, @NonNull AidlInputGestureData inputGestureData)3216 public int removeCustomInputGesture(@UserIdInt int userId, 3217 @NonNull AidlInputGestureData inputGestureData) { 3218 enforceManageKeyGesturePermission(); 3219 3220 Objects.requireNonNull(inputGestureData); 3221 return mKeyGestureController.removeCustomInputGesture(userId, inputGestureData); 3222 } 3223 3224 @Override 3225 @PermissionManuallyEnforced removeAllCustomInputGestures(@serIdInt int userId, int tag)3226 public void removeAllCustomInputGestures(@UserIdInt int userId, int tag) { 3227 enforceManageKeyGesturePermission(); 3228 3229 mKeyGestureController.removeAllCustomInputGestures(userId, InputGestureData.Filter.of(tag)); 3230 } 3231 3232 @Override getCustomInputGestures(@serIdInt int userId, int tag)3233 public AidlInputGestureData[] getCustomInputGestures(@UserIdInt int userId, int tag) { 3234 return mKeyGestureController.getCustomInputGestures(userId, 3235 InputGestureData.Filter.of(tag)); 3236 } 3237 3238 @Override getAppLaunchBookmarks()3239 public AidlInputGestureData[] getAppLaunchBookmarks() { 3240 return mKeyGestureController.getAppLaunchBookmarks(); 3241 } 3242 3243 @Override resetLockedModifierState()3244 public void resetLockedModifierState() { 3245 mNative.resetLockedModifierState(); 3246 } 3247 onUserSwitching(@onNull SystemService.TargetUser from, @NonNull SystemService.TargetUser to)3248 private void onUserSwitching(@NonNull SystemService.TargetUser from, 3249 @NonNull SystemService.TargetUser to) { 3250 if (DEBUG) { 3251 Slog.d(TAG, "onUserSwitching from=" + from + " to=" + to); 3252 } 3253 mHandler.obtainMessage(MSG_CURRENT_USER_CHANGED, to.getUserIdentifier()).sendToTarget(); 3254 } 3255 handleCurrentUserChanged(@serIdInt int userId)3256 private void handleCurrentUserChanged(@UserIdInt int userId) { 3257 mKeyGestureController.setCurrentUserId(userId); 3258 } 3259 3260 /** 3261 * Callback interface implemented by the Window Manager. 3262 */ 3263 public interface WindowManagerCallbacks extends LidSwitchCallback { 3264 /** 3265 * This callback is invoked when the configuration changes. 3266 */ notifyConfigurationChanged()3267 void notifyConfigurationChanged(); 3268 3269 /** 3270 * This callback is invoked when the pointer location changes. 3271 */ notifyPointerLocationChanged(boolean pointerLocationEnabled)3272 void notifyPointerLocationChanged(boolean pointerLocationEnabled); 3273 3274 /** 3275 * This callback is invoked when the camera lens cover switch changes state. 3276 * @param whenNanos the time when the change occurred 3277 * @param lensCovered true is the lens is covered 3278 */ notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered)3279 void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered); 3280 3281 /** 3282 * This callback is invoked when an input channel is closed unexpectedly. 3283 * @param token the connection token of the broken channel 3284 */ notifyInputChannelBroken(IBinder token)3285 void notifyInputChannelBroken(IBinder token); 3286 3287 /** 3288 * Notify the window manager about the focused application that does not have any focused 3289 * window and is unable to respond to focused input events. 3290 */ notifyNoFocusedWindowAnr(InputApplicationHandle applicationHandle)3291 void notifyNoFocusedWindowAnr(InputApplicationHandle applicationHandle); 3292 3293 /** 3294 * Notify the window manager about a window that is unresponsive. 3295 * 3296 * @param token the token that can be used to look up the window 3297 * @param pid the pid of the window owner, if known 3298 * @param reason the reason why this connection is unresponsive 3299 */ notifyWindowUnresponsive(@onNull IBinder token, @NonNull OptionalInt pid, @NonNull String reason)3300 void notifyWindowUnresponsive(@NonNull IBinder token, @NonNull OptionalInt pid, 3301 @NonNull String reason); 3302 3303 /** 3304 * Notify the window manager about a window that has become responsive. 3305 * 3306 * @param token the token that can be used to look up the window 3307 * @param pid the pid of the window owner, if known 3308 */ notifyWindowResponsive(@onNull IBinder token, @NonNull OptionalInt pid)3309 void notifyWindowResponsive(@NonNull IBinder token, @NonNull OptionalInt pid); 3310 3311 /** 3312 * This callback is invoked when an event first arrives to InputDispatcher and before it is 3313 * placed onto InputDispatcher's queue. If this event is intercepted, it will never be 3314 * processed by InputDispacher. 3315 * @param event The key event that's arriving to InputDispatcher 3316 * @param policyFlags The policy flags 3317 * @return the flags that tell InputDispatcher how to handle the event (for example, whether 3318 * to pass it to the user) 3319 */ interceptKeyBeforeQueueing(KeyEvent event, int policyFlags)3320 int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags); 3321 3322 /** 3323 * Provides an opportunity for the window manager policy to intercept early motion event 3324 * processing when the device is in a non-interactive state since these events are normally 3325 * dropped. 3326 */ interceptMotionBeforeQueueingNonInteractive(int displayId, int source, int action, long whenNanos, int policyFlags)3327 int interceptMotionBeforeQueueingNonInteractive(int displayId, int source, int action, 3328 long whenNanos, int policyFlags); 3329 3330 /** 3331 * This callback is invoked just before the key is about to be sent to an application. 3332 * This allows the policy to make some last minute decisions on whether to intercept this 3333 * key. 3334 * @param token the window token that's about to receive this event 3335 * @param event the key event that's being dispatched 3336 * @param policyFlags the policy flags 3337 * @return -1 if the key should be skipped (not sent to the app). -2 if the key should not 3338 * be sent to the app, but it should still generate a fallback. 3339 * 0 if the key should proceed getting dispatched to the app. positive value to indicate the 3340 * additional time delay, in nanoseconds, to wait before sending this key to the app. 3341 */ interceptKeyBeforeDispatching(IBinder token, KeyEvent event, int policyFlags)3342 long interceptKeyBeforeDispatching(IBinder token, KeyEvent event, int policyFlags); 3343 3344 /** 3345 * Intercept unhandled key 3346 */ interceptUnhandledKey(KeyEvent event, IBinder token)3347 boolean interceptUnhandledKey(KeyEvent event, IBinder token); 3348 getPointerLayer()3349 int getPointerLayer(); 3350 getPointerDisplayId()3351 int getPointerDisplayId(); 3352 3353 /** 3354 * Notifies window manager that a {@link android.view.MotionEvent#ACTION_DOWN} pointer event 3355 * occurred on a window that did not have focus. 3356 * 3357 * @param touchedToken The token for the window that received the input event. 3358 */ onPointerDownOutsideFocus(IBinder touchedToken)3359 void onPointerDownOutsideFocus(IBinder touchedToken); 3360 3361 /** 3362 * Called when the focused window has changed. 3363 */ notifyFocusChanged(IBinder oldToken, IBinder newToken)3364 void notifyFocusChanged(IBinder oldToken, IBinder newToken); 3365 3366 /** 3367 * Called when the drag over window has changed. 3368 */ notifyDropWindow(IBinder token, float x, float y)3369 void notifyDropWindow(IBinder token, float x, float y); 3370 3371 /** 3372 * Get the {@link SurfaceControl} that should be the parent for the surfaces created for 3373 * pointers such as the mouse cursor and touch spots for the given display. 3374 */ getParentSurfaceForPointers(int displayId)3375 SurfaceControl getParentSurfaceForPointers(int displayId); 3376 3377 /** 3378 * Create a {@link SurfaceControl} that can be configured to receive input over the entire 3379 * display to implement a gesture monitor. The surface will not have a graphical buffer. 3380 * @param name the name of the gesture monitor 3381 * @param displayId the display to create the window in 3382 * @return the SurfaceControl of the new layer container surface 3383 */ 3384 @Nullable createSurfaceForGestureMonitor(String name, int displayId)3385 SurfaceControl createSurfaceForGestureMonitor(String name, int displayId); 3386 3387 /** 3388 * Provide information on whether the keyguard is currently locked or not. 3389 */ isKeyguardLocked(int displayId)3390 boolean isKeyguardLocked(int displayId); 3391 } 3392 3393 /** 3394 * Callback interface implemented by WiredAccessoryObserver. 3395 */ 3396 public interface WiredAccessoryCallbacks { 3397 /** 3398 * Notifies WiredAccessoryObserver that input state for wired accessories has changed 3399 * @param whenNanos When the wired accessories changed 3400 * @param switchValues The state of the switches 3401 * @param switchMask The mask of switches that changed 3402 */ notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask)3403 void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask); 3404 3405 /** 3406 * Notifies WiredAccessoryObserver that the system is now ready. 3407 */ systemReady()3408 void systemReady(); 3409 } 3410 3411 /** 3412 * Private handler for the input manager. 3413 */ 3414 private final class InputManagerHandler extends Handler { InputManagerHandler(Looper looper)3415 public InputManagerHandler(Looper looper) { 3416 super(looper, null, true /*async*/); 3417 } 3418 3419 @Override handleMessage(Message msg)3420 public void handleMessage(Message msg) { 3421 switch (msg.what) { 3422 case MSG_DELIVER_INPUT_DEVICES_CHANGED: 3423 deliverInputDevicesChanged((InputDevice[])msg.obj); 3424 break; 3425 case MSG_RELOAD_DEVICE_ALIASES: 3426 reloadDeviceAliases(); 3427 break; 3428 case MSG_DELIVER_TABLET_MODE_CHANGED: 3429 SomeArgs args = (SomeArgs) msg.obj; 3430 long whenNanos = (args.argi1 & 0xFFFFFFFFL) | ((long) args.argi2 << 32); 3431 boolean inTabletMode = (boolean) args.arg1; 3432 deliverTabletModeChanged(whenNanos, inTabletMode); 3433 break; 3434 case MSG_CURRENT_USER_CHANGED: 3435 handleCurrentUserChanged((int) msg.obj); 3436 break; 3437 case MSG_SYSTEM_READY: 3438 systemRunning(); 3439 break; 3440 } 3441 } 3442 } 3443 3444 /** 3445 * Hosting interface for input filters to call back into the input manager. 3446 */ 3447 private final class InputFilterHost extends IInputFilterHost.Stub { 3448 @GuardedBy("mInputFilterLock") 3449 private boolean mDisconnected; 3450 3451 @GuardedBy("mInputFilterLock") disconnectLocked()3452 public void disconnectLocked() { 3453 mDisconnected = true; 3454 } 3455 3456 @Override sendInputEvent(@onNull InputEvent event, int policyFlags)3457 public void sendInputEvent(@NonNull InputEvent event, int policyFlags) { 3458 if (!checkCallingPermission(android.Manifest.permission.INJECT_EVENTS, 3459 "sendInputEvent()")) { 3460 throw new SecurityException( 3461 "The INJECT_EVENTS permission is required for injecting input events."); 3462 } 3463 Objects.requireNonNull(event, "event must not be null"); 3464 3465 synchronized (mInputFilterLock) { 3466 if (!mDisconnected) { 3467 mNative.injectInputEvent(event, false /* injectIntoUid */, -1 /* uid */, 3468 InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0 /* timeout */, 3469 policyFlags | WindowManagerPolicy.FLAG_FILTERED); 3470 } 3471 } 3472 } 3473 } 3474 3475 /** 3476 * Interface for the system to handle request from InputMonitors. 3477 */ 3478 private final class InputMonitorHost extends IInputMonitorHost.Stub { 3479 private final @NonNull IBinder mInputChannelToken; 3480 InputMonitorHost(@onNull IBinder inputChannelToken)3481 InputMonitorHost(@NonNull IBinder inputChannelToken) { 3482 mInputChannelToken = inputChannelToken; 3483 } 3484 3485 @Override pilferPointers()3486 public void pilferPointers() { 3487 mNative.pilferPointers(mInputChannelToken); 3488 } 3489 3490 @Override dispose()3491 public void dispose() { 3492 removeSpyWindowGestureMonitor(mInputChannelToken); 3493 } 3494 } 3495 3496 private final class InputDevicesChangedListenerRecord implements DeathRecipient { 3497 private final int mPid; 3498 private final IInputDevicesChangedListener mListener; 3499 InputDevicesChangedListenerRecord(int pid, IInputDevicesChangedListener listener)3500 public InputDevicesChangedListenerRecord(int pid, IInputDevicesChangedListener listener) { 3501 mPid = pid; 3502 mListener = listener; 3503 } 3504 3505 @Override binderDied()3506 public void binderDied() { 3507 if (DEBUG) { 3508 Slog.d(TAG, "Input devices changed listener for pid " + mPid + " died."); 3509 } 3510 onInputDevicesChangedListenerDied(mPid); 3511 } 3512 notifyInputDevicesChanged(int[] info)3513 public void notifyInputDevicesChanged(int[] info) { 3514 try { 3515 mListener.onInputDevicesChanged(info); 3516 } catch (RemoteException ex) { 3517 Slog.w(TAG, "Failed to notify process " 3518 + mPid + " that input devices changed, assuming it died.", ex); 3519 binderDied(); 3520 } 3521 } 3522 } 3523 3524 private final class TabletModeChangedListenerRecord implements DeathRecipient { 3525 private final int mPid; 3526 private final ITabletModeChangedListener mListener; 3527 TabletModeChangedListenerRecord(int pid, ITabletModeChangedListener listener)3528 public TabletModeChangedListenerRecord(int pid, ITabletModeChangedListener listener) { 3529 mPid = pid; 3530 mListener = listener; 3531 } 3532 3533 @Override binderDied()3534 public void binderDied() { 3535 if (DEBUG) { 3536 Slog.d(TAG, "Tablet mode changed listener for pid " + mPid + " died."); 3537 } 3538 onTabletModeChangedListenerDied(mPid); 3539 } 3540 notifyTabletModeChanged(long whenNanos, boolean inTabletMode)3541 public void notifyTabletModeChanged(long whenNanos, boolean inTabletMode) { 3542 try { 3543 mListener.onTabletModeChanged(whenNanos, inTabletMode); 3544 } catch (RemoteException ex) { 3545 Slog.w(TAG, "Failed to notify process " + mPid + 3546 " that tablet mode changed, assuming it died.", ex); 3547 binderDied(); 3548 } 3549 } 3550 } 3551 onSensorEventListenerDied(int pid)3552 private void onSensorEventListenerDied(int pid) { 3553 synchronized (mSensorEventLock) { 3554 mSensorEventListeners.remove(pid); 3555 } 3556 } 3557 3558 private final class SensorEventListenerRecord implements DeathRecipient { 3559 private final int mPid; 3560 private final IInputSensorEventListener mListener; 3561 SensorEventListenerRecord(int pid, IInputSensorEventListener listener)3562 SensorEventListenerRecord(int pid, IInputSensorEventListener listener) { 3563 mPid = pid; 3564 mListener = listener; 3565 } 3566 3567 @Override binderDied()3568 public void binderDied() { 3569 if (DEBUG) { 3570 Slog.d(TAG, "Sensor event listener for pid " + mPid + " died."); 3571 } 3572 onSensorEventListenerDied(mPid); 3573 } 3574 getListener()3575 public IInputSensorEventListener getListener() { 3576 return mListener; 3577 } 3578 notifySensorEvent(int deviceId, int sensorType, int accuracy, long timestamp, float[] values)3579 public void notifySensorEvent(int deviceId, int sensorType, int accuracy, long timestamp, 3580 float[] values) { 3581 try { 3582 mListener.onInputSensorChanged(deviceId, sensorType, accuracy, timestamp, 3583 values); 3584 } catch (RemoteException ex) { 3585 Slog.w(TAG, "Failed to notify process " + mPid 3586 + " that sensor event notified, assuming it died.", ex); 3587 binderDied(); 3588 } 3589 } 3590 notifySensorAccuracy(int deviceId, int sensorType, int accuracy)3591 public void notifySensorAccuracy(int deviceId, int sensorType, int accuracy) { 3592 try { 3593 mListener.onInputSensorAccuracyChanged(deviceId, sensorType, accuracy); 3594 } catch (RemoteException ex) { 3595 Slog.w(TAG, "Failed to notify process " + mPid 3596 + " that sensor accuracy notified, assuming it died.", ex); 3597 binderDied(); 3598 } 3599 } 3600 } 3601 3602 private final class VibratorToken implements DeathRecipient { 3603 public final int mDeviceId; 3604 public final IBinder mToken; 3605 public final int mTokenValue; 3606 3607 public boolean mVibrating; 3608 VibratorToken(int deviceId, IBinder token, int tokenValue)3609 public VibratorToken(int deviceId, IBinder token, int tokenValue) { 3610 mDeviceId = deviceId; 3611 mToken = token; 3612 mTokenValue = tokenValue; 3613 } 3614 3615 @Override binderDied()3616 public void binderDied() { 3617 if (DEBUG) { 3618 Slog.d(TAG, "Vibrator token died."); 3619 } 3620 onVibratorTokenDied(this); 3621 } 3622 } 3623 3624 /** 3625 * {@link SystemService} used to publish and manage the lifecycle of {@link InputManagerService} 3626 */ 3627 public static final class Lifecycle extends SystemService { 3628 3629 private final InputManagerService mService; 3630 Lifecycle(@onNull Context context)3631 public Lifecycle(@NonNull Context context) { 3632 super(context); 3633 mService = new InputManagerService(context); 3634 } 3635 3636 @Override onStart()3637 public void onStart() { 3638 publishBinderService(Context.INPUT_SERVICE, mService, 3639 /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL); 3640 } 3641 3642 @Override onBootPhase(int phase)3643 public void onBootPhase(int phase) { 3644 mService.onBootPhase(phase); 3645 } 3646 3647 @Override onUserSwitching(@ullable TargetUser from, @NonNull TargetUser to)3648 public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) { 3649 mService.onUserSwitching(from, to); 3650 } 3651 getService()3652 public InputManagerService getService() { 3653 return mService; 3654 } 3655 } 3656 3657 private final class LocalService extends InputManagerInternal { 3658 @Override setDisplayViewports(List<DisplayViewport> viewports)3659 public void setDisplayViewports(List<DisplayViewport> viewports) { 3660 setDisplayViewportsInternal(viewports); 3661 } 3662 3663 @Override setDisplayTopology(DisplayTopologyGraph topology)3664 public void setDisplayTopology(DisplayTopologyGraph topology) { 3665 setDisplayTopologyInternal(topology); 3666 } 3667 3668 @Override setDisplayInteractivities(SparseBooleanArray displayInteractivities)3669 public void setDisplayInteractivities(SparseBooleanArray displayInteractivities) { 3670 boolean globallyInteractive = false; 3671 ArraySet<Integer> nonInteractiveDisplays = new ArraySet<>(); 3672 for (int i = 0; i < displayInteractivities.size(); i++) { 3673 final int displayId = displayInteractivities.keyAt(i); 3674 final boolean displayInteractive = displayInteractivities.get(displayId); 3675 if (displayInteractive) { 3676 globallyInteractive = true; 3677 } else { 3678 nonInteractiveDisplays.add(displayId); 3679 } 3680 } 3681 mNative.setNonInteractiveDisplays( 3682 nonInteractiveDisplays.stream().mapToInt(Integer::intValue).toArray()); 3683 mBatteryController.onInteractiveChanged(globallyInteractive); 3684 mKeyboardBacklightController.onInteractiveChanged(globallyInteractive); 3685 } 3686 3687 // TODO(b/358569822): Remove this method from InputManagerInternal after key gesture 3688 // handler refactoring complete 3689 @Override toggleCapsLock(int deviceId)3690 public void toggleCapsLock(int deviceId) { 3691 mNative.toggleCapsLock(deviceId); 3692 } 3693 3694 @Override setPulseGestureEnabled(boolean enabled)3695 public void setPulseGestureEnabled(boolean enabled) { 3696 if (mDoubleTouchGestureEnableFile != null) { 3697 FileWriter writer = null; 3698 try { 3699 writer = new FileWriter(mDoubleTouchGestureEnableFile); 3700 writer.write(enabled ? "1" : "0"); 3701 } catch (IOException e) { 3702 Log.wtf(TAG, "Unable to setPulseGestureEnabled", e); 3703 } finally { 3704 IoUtils.closeQuietly(writer); 3705 } 3706 } 3707 } 3708 3709 @Override transferTouchGesture(@onNull IBinder fromChannelToken, @NonNull IBinder toChannelToken, boolean transferEntireGesture)3710 public boolean transferTouchGesture(@NonNull IBinder fromChannelToken, 3711 @NonNull IBinder toChannelToken, boolean transferEntireGesture) { 3712 return InputManagerService.this.transferTouchGesture( 3713 fromChannelToken, toChannelToken, transferEntireGesture); 3714 } 3715 3716 @Override getCursorPosition(int displayId)3717 public PointF getCursorPosition(int displayId) { 3718 final float[] p = mNative.getMouseCursorPosition(displayId); 3719 if (p == null || p.length != 2) { 3720 throw new IllegalStateException("Failed to get mouse cursor position"); 3721 } 3722 return new PointF(p[0], p[1]); 3723 } 3724 3725 @Override setMouseScalingEnabled(boolean enabled, int displayId)3726 public void setMouseScalingEnabled(boolean enabled, int displayId) { 3727 InputManagerService.this.setMouseScalingEnabled(enabled, displayId); 3728 } 3729 3730 @Override setDisplayEligibilityForPointerCapture(int displayId, boolean isEligible)3731 public void setDisplayEligibilityForPointerCapture(int displayId, boolean isEligible) { 3732 InputManagerService.this.setDisplayEligibilityForPointerCapture(displayId, isEligible); 3733 } 3734 3735 @Override setPointerIconVisible(boolean visible, int displayId)3736 public void setPointerIconVisible(boolean visible, int displayId) { 3737 InputManagerService.this.setPointerIconVisible(visible, displayId); 3738 } 3739 3740 @Override registerLidSwitchCallback(LidSwitchCallback callbacks)3741 public void registerLidSwitchCallback(LidSwitchCallback callbacks) { 3742 registerLidSwitchCallbackInternal(callbacks); 3743 } 3744 3745 @Override unregisterLidSwitchCallback(LidSwitchCallback callbacks)3746 public void unregisterLidSwitchCallback(LidSwitchCallback callbacks) { 3747 unregisterLidSwitchCallbackInternal(callbacks); 3748 } 3749 3750 @Override notifyInputMethodConnectionActive(boolean connectionIsActive)3751 public void notifyInputMethodConnectionActive(boolean connectionIsActive) { 3752 mNative.setInputMethodConnectionIsActive(connectionIsActive); 3753 } 3754 3755 @Override createInputChannel(String inputChannelName)3756 public InputChannel createInputChannel(String inputChannelName) { 3757 return InputManagerService.this.createInputChannel(inputChannelName); 3758 } 3759 3760 @Override pilferPointers(IBinder token)3761 public void pilferPointers(IBinder token) { 3762 mNative.pilferPointers(token); 3763 } 3764 3765 @Override onInputMethodSubtypeChangedForKeyboardLayoutMapping(@serIdInt int userId, @Nullable InputMethodSubtypeHandle subtypeHandle, @Nullable InputMethodSubtype subtype)3766 public void onInputMethodSubtypeChangedForKeyboardLayoutMapping(@UserIdInt int userId, 3767 @Nullable InputMethodSubtypeHandle subtypeHandle, 3768 @Nullable InputMethodSubtype subtype) { 3769 mKeyboardLayoutManager.onInputMethodSubtypeChanged(userId, subtypeHandle, subtype); 3770 } 3771 3772 @Override notifyUserActivity()3773 public void notifyUserActivity() { 3774 mKeyboardBacklightController.notifyUserActivity(); 3775 } 3776 3777 // TODO(b/358569822): Remove this method from InputManagerInternal after key gesture 3778 // handler refactoring complete 3779 @Override incrementKeyboardBacklight(int deviceId)3780 public void incrementKeyboardBacklight(int deviceId) { 3781 mKeyboardBacklightController.incrementKeyboardBacklight(deviceId); 3782 } 3783 3784 // TODO(b/358569822): Remove this method from InputManagerInternal after key gesture 3785 // handler refactoring complete 3786 @Override decrementKeyboardBacklight(int deviceId)3787 public void decrementKeyboardBacklight(int deviceId) { 3788 mKeyboardBacklightController.decrementKeyboardBacklight(deviceId); 3789 } 3790 3791 @Override setTypeAssociation(@onNull String inputPort, @NonNull String type)3792 public void setTypeAssociation(@NonNull String inputPort, @NonNull String type) { 3793 setTypeAssociationInternal(inputPort, type); 3794 } 3795 3796 @Override unsetTypeAssociation(@onNull String inputPort)3797 public void unsetTypeAssociation(@NonNull String inputPort) { 3798 unsetTypeAssociationInternal(inputPort); 3799 } 3800 3801 @Override addKeyboardLayoutAssociation(@onNull String inputPort, @NonNull String languageTag, @NonNull String layoutType)3802 public void addKeyboardLayoutAssociation(@NonNull String inputPort, 3803 @NonNull String languageTag, @NonNull String layoutType) { 3804 InputManagerService.this.addKeyboardLayoutAssociation(inputPort, 3805 languageTag, layoutType); 3806 } 3807 3808 @Override removeKeyboardLayoutAssociation(@onNull String inputPort)3809 public void removeKeyboardLayoutAssociation(@NonNull String inputPort) { 3810 InputManagerService.this.removeKeyboardLayoutAssociation(inputPort); 3811 } 3812 3813 @Override setStylusButtonMotionEventsEnabled(boolean enabled)3814 public void setStylusButtonMotionEventsEnabled(boolean enabled) { 3815 mNative.setStylusButtonMotionEventsEnabled(enabled); 3816 } 3817 3818 @Override getLastUsedInputDeviceId()3819 public int getLastUsedInputDeviceId() { 3820 return mNative.getLastUsedInputDeviceId(); 3821 } 3822 3823 @Override notifyKeyGestureCompleted(int deviceId, int[] keycodes, int modifierState, @KeyGestureEvent.KeyGestureType int gestureType)3824 public void notifyKeyGestureCompleted(int deviceId, int[] keycodes, int modifierState, 3825 @KeyGestureEvent.KeyGestureType int gestureType) { 3826 mKeyGestureController.notifyKeyGestureCompleted(deviceId, keycodes, modifierState, 3827 gestureType); 3828 } 3829 3830 @Override handleKeyGestureInKeyGestureController(int deviceId, int[] keycodes, int modifierState, @KeyGestureEvent.KeyGestureType int gestureType)3831 public void handleKeyGestureInKeyGestureController(int deviceId, int[] keycodes, 3832 int modifierState, @KeyGestureEvent.KeyGestureType int gestureType) { 3833 mKeyGestureController.handleKeyGesture(deviceId, keycodes, modifierState, gestureType); 3834 } 3835 3836 @Override setAccessibilityPointerIconScaleFactor(int displayId, float scaleFactor)3837 public void setAccessibilityPointerIconScaleFactor(int displayId, float scaleFactor) { 3838 InputManagerService.this.setAccessibilityPointerIconScaleFactor(displayId, scaleFactor); 3839 } 3840 3841 @Override setCurrentUser(@serIdInt int newUserId)3842 public void setCurrentUser(@UserIdInt int newUserId) { 3843 mHandler.obtainMessage(MSG_CURRENT_USER_CHANGED, newUserId).sendToTarget(); 3844 } 3845 3846 @Override registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)3847 public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver) 3848 throws RemoteException { 3849 mKeyGestureController.registerShortcutKey(shortcutCode, shortcutKeyReceiver); 3850 } 3851 3852 @Override setKernelWakeEnabled(int deviceId, boolean enabled)3853 public boolean setKernelWakeEnabled(int deviceId, boolean enabled) { 3854 return mNative.setKernelWakeEnabled(deviceId, enabled); 3855 } 3856 3857 @Override getBackupPayload(int userId)3858 public Map<Integer, byte[]> getBackupPayload(int userId) throws IOException { 3859 final Map<Integer, byte[]> payload = new HashMap<>(); 3860 if (enableCustomizableInputGestures()) { 3861 payload.put(BACKUP_CATEGORY_INPUT_GESTURES, 3862 mKeyGestureController.getInputGestureBackupPayload(userId)); 3863 } 3864 return payload; 3865 } 3866 3867 @Override applyBackupPayload(Map<Integer, byte[]> payload, int userId)3868 public void applyBackupPayload(Map<Integer, byte[]> payload, int userId) 3869 throws XmlPullParserException, IOException { 3870 if (enableCustomizableInputGestures() && payload.containsKey( 3871 BACKUP_CATEGORY_INPUT_GESTURES)) { 3872 mKeyGestureController.applyInputGesturesBackupPayload( 3873 payload.get(BACKUP_CATEGORY_INPUT_GESTURES), userId); 3874 } 3875 } 3876 3877 @Override registerAccessibilityPointerMotionFilter( AccessibilityPointerMotionFilter filter)3878 public void registerAccessibilityPointerMotionFilter( 3879 AccessibilityPointerMotionFilter filter) { 3880 InputManagerService.this.registerAccessibilityPointerMotionFilter(filter); 3881 } 3882 } 3883 3884 @Override onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)3885 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 3886 String[] args, ShellCallback callback, ResultReceiver resultReceiver) { 3887 new InputShellCommand().exec(this, in, out, err, args, callback, resultReceiver); 3888 } 3889 3890 private static class AdditionalDisplayInputProperties { 3891 3892 static final boolean DEFAULT_POINTER_ICON_VISIBLE = true; 3893 static final boolean DEFAULT_MOUSE_SCALING_ENABLED = true; 3894 3895 /** 3896 * Whether to enable mouse pointer scaling on this display. Note that this only affects 3897 * pointer movements from mice (that is, pointing devices which send relative motions, 3898 * including trackballs and pointing sticks), not from other pointer devices such as 3899 * touchpads and styluses. 3900 */ 3901 public boolean mouseScalingEnabled; 3902 3903 // Whether the pointer icon should be visible or hidden on this display. 3904 public boolean pointerIconVisible; 3905 AdditionalDisplayInputProperties()3906 AdditionalDisplayInputProperties() { 3907 reset(); 3908 } 3909 allDefaults()3910 public boolean allDefaults() { 3911 return mouseScalingEnabled == DEFAULT_MOUSE_SCALING_ENABLED 3912 && pointerIconVisible == DEFAULT_POINTER_ICON_VISIBLE; 3913 } 3914 reset()3915 public void reset() { 3916 mouseScalingEnabled = DEFAULT_MOUSE_SCALING_ENABLED; 3917 pointerIconVisible = DEFAULT_POINTER_ICON_VISIBLE; 3918 } 3919 } 3920 updateAdditionalDisplayInputProperties(int displayId, Consumer<AdditionalDisplayInputProperties> updater)3921 private void updateAdditionalDisplayInputProperties(int displayId, 3922 Consumer<AdditionalDisplayInputProperties> updater) { 3923 synchronized (mAdditionalDisplayInputPropertiesLock) { 3924 AdditionalDisplayInputProperties properties = 3925 mAdditionalDisplayInputProperties.get(displayId); 3926 if (properties == null) { 3927 properties = new AdditionalDisplayInputProperties(); 3928 mAdditionalDisplayInputProperties.put(displayId, properties); 3929 } 3930 final boolean oldPointerIconVisible = properties.pointerIconVisible; 3931 final boolean oldMouseScalingEnabled = properties.mouseScalingEnabled; 3932 updater.accept(properties); 3933 if (oldPointerIconVisible != properties.pointerIconVisible) { 3934 mNative.setPointerIconVisibility(displayId, properties.pointerIconVisible); 3935 } 3936 if (oldMouseScalingEnabled != properties.mouseScalingEnabled) { 3937 mNative.setMouseScalingEnabled(displayId, 3938 properties.mouseScalingEnabled); 3939 } 3940 if (properties.allDefaults()) { 3941 mAdditionalDisplayInputProperties.remove(displayId); 3942 } 3943 } 3944 } 3945 updateTouchpadVisualizerEnabled(boolean enabled)3946 void updateTouchpadVisualizerEnabled(boolean enabled) { 3947 mNative.setShouldNotifyTouchpadHardwareState(enabled); 3948 if (mTouchpadDebugViewController != null) { 3949 mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(enabled); 3950 } 3951 } 3952 updatePointerLocationEnabled(boolean enabled)3953 void updatePointerLocationEnabled(boolean enabled) { 3954 mWindowManagerCallbacks.notifyPointerLocationChanged(enabled); 3955 } 3956 updateShowKeyPresses(boolean enabled)3957 void updateShowKeyPresses(boolean enabled) { 3958 if (mShowKeyPresses == enabled) { 3959 return; 3960 } 3961 3962 mShowKeyPresses = enabled; 3963 updateFocusEventDebugViewEnabled(); 3964 3965 synchronized (mFocusEventDebugViewLock) { 3966 if (mFocusEventDebugView != null) { 3967 mFocusEventDebugView.updateShowKeyPresses(enabled); 3968 } 3969 } 3970 } 3971 updateShowRotaryInput(boolean enabled)3972 void updateShowRotaryInput(boolean enabled) { 3973 if (mShowRotaryInput == enabled) { 3974 return; 3975 } 3976 3977 mShowRotaryInput = enabled; 3978 updateFocusEventDebugViewEnabled(); 3979 3980 synchronized (mFocusEventDebugViewLock) { 3981 if (mFocusEventDebugView != null) { 3982 mFocusEventDebugView.updateShowRotaryInput(enabled); 3983 } 3984 } 3985 } 3986 updateFocusEventDebugViewEnabled()3987 private void updateFocusEventDebugViewEnabled() { 3988 boolean enabled = mShowKeyPresses || mShowRotaryInput; 3989 FocusEventDebugView view; 3990 synchronized (mFocusEventDebugViewLock) { 3991 if (enabled == (mFocusEventDebugView != null)) { 3992 return; 3993 } 3994 if (enabled) { 3995 mFocusEventDebugView = new FocusEventDebugView(mContext, this); 3996 view = mFocusEventDebugView; 3997 } else { 3998 view = mFocusEventDebugView; 3999 mFocusEventDebugView = null; 4000 } 4001 } 4002 Objects.requireNonNull(view); 4003 4004 // Interact with WM outside the lock, since the lock is part of the input hotpath. 4005 final WindowManager wm = 4006 Objects.requireNonNull(mContext.getSystemService(WindowManager.class)); 4007 if (!enabled) { 4008 wm.removeView(view); 4009 return; 4010 } 4011 4012 // TODO: Support multi display 4013 final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(); 4014 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY; 4015 lp.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE 4016 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 4017 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; 4018 lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; 4019 lp.setFitInsetsTypes(0); 4020 lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 4021 lp.format = PixelFormat.TRANSLUCENT; 4022 lp.setTitle("FocusEventDebugView - display " + mContext.getDisplayId()); 4023 lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; 4024 wm.addView(view, lp); 4025 } 4026 4027 /** 4028 * Sets Accessibility bounce keys threshold in milliseconds. 4029 */ setAccessibilityBounceKeysThreshold(int thresholdTimeMs)4030 public void setAccessibilityBounceKeysThreshold(int thresholdTimeMs) { 4031 mNative.setAccessibilityBounceKeysThreshold(thresholdTimeMs); 4032 } 4033 4034 /** 4035 * Sets Accessibility slow keys threshold in milliseconds. 4036 */ setAccessibilitySlowKeysThreshold(int thresholdTimeMs)4037 public void setAccessibilitySlowKeysThreshold(int thresholdTimeMs) { 4038 mNative.setAccessibilitySlowKeysThreshold(thresholdTimeMs); 4039 } 4040 4041 /** 4042 * Sets whether Accessibility sticky keys is enabled. 4043 */ setAccessibilityStickyKeysEnabled(boolean enabled)4044 public void setAccessibilityStickyKeysEnabled(boolean enabled) { 4045 mNative.setAccessibilityStickyKeysEnabled(enabled); 4046 } 4047 setUseLargePointerIcons(boolean useLargeIcons)4048 void setUseLargePointerIcons(boolean useLargeIcons) { 4049 mPointerIconCache.setUseLargePointerIcons(useLargeIcons); 4050 } 4051 setPointerFillStyle(@ointerIcon.PointerIconVectorStyleFill int fillStyle)4052 void setPointerFillStyle(@PointerIcon.PointerIconVectorStyleFill int fillStyle) { 4053 mPointerIconCache.setPointerFillStyle(fillStyle); 4054 } 4055 setPointerStrokeStyle(@ointerIcon.PointerIconVectorStyleStroke int strokeStyle)4056 void setPointerStrokeStyle(@PointerIcon.PointerIconVectorStyleStroke int strokeStyle) { 4057 mPointerIconCache.setPointerStrokeStyle(strokeStyle); 4058 } 4059 setPointerScale(float scale)4060 void setPointerScale(float scale) { 4061 mPointerIconCache.setPointerScale(scale); 4062 } 4063 setAccessibilityPointerIconScaleFactor(int displayId, float scaleFactor)4064 void setAccessibilityPointerIconScaleFactor(int displayId, float scaleFactor) { 4065 mPointerIconCache.setAccessibilityScaleFactor(displayId, scaleFactor); 4066 } 4067 registerAccessibilityPointerMotionFilter( InputManagerInternal.AccessibilityPointerMotionFilter filter)4068 void registerAccessibilityPointerMotionFilter( 4069 InputManagerInternal.AccessibilityPointerMotionFilter filter) { 4070 // `#filterPointerMotion` expects that when it's called, `mAccessibilityPointerMotionFilter` 4071 // is not null. 4072 // Also, to avoid potential lock contention, we shouldn't call native method while holding 4073 // the lock here. Native code calls `#filterPointerMotion` while PointerChoreographer's 4074 // lock is held. 4075 // Thus, we must set filter before we enable the filter in native, and reset the filter 4076 // after we disable the filter. 4077 // This also ensures the previously installed filter isn't called after the filter is 4078 // updated. 4079 mNative.setAccessibilityPointerMotionFilterEnabled(false); 4080 synchronized (mAccessibilityPointerMotionFilterLock) { 4081 mAccessibilityPointerMotionFilter = filter; 4082 } 4083 if (filter != null) { 4084 mNative.setAccessibilityPointerMotionFilterEnabled(true); 4085 } 4086 } 4087 4088 interface KeyboardBacklightControllerInterface { incrementKeyboardBacklight(int deviceId)4089 default void incrementKeyboardBacklight(int deviceId) {} decrementKeyboardBacklight(int deviceId)4090 default void decrementKeyboardBacklight(int deviceId) {} registerKeyboardBacklightListener(IKeyboardBacklightListener l, int pid)4091 default void registerKeyboardBacklightListener(IKeyboardBacklightListener l, int pid) {} unregisterKeyboardBacklightListener(IKeyboardBacklightListener l, int pid)4092 default void unregisterKeyboardBacklightListener(IKeyboardBacklightListener l, int pid) {} onInteractiveChanged(boolean isInteractive)4093 default void onInteractiveChanged(boolean isInteractive) {} notifyUserActivity()4094 default void notifyUserActivity() {} systemRunning()4095 default void systemRunning() {} dump(PrintWriter pw)4096 default void dump(PrintWriter pw) {} 4097 } 4098 } 4099