1 /* 2 * Copyright (C) 2023 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 android.hardware.input; 18 19 import android.Manifest; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.RequiresPermission; 23 import android.content.Context; 24 import android.hardware.BatteryState; 25 import android.hardware.SensorManager; 26 import android.hardware.input.InputManager.InputDeviceBatteryListener; 27 import android.hardware.input.InputManager.InputDeviceListener; 28 import android.hardware.input.InputManager.KeyEventActivityListener; 29 import android.hardware.input.InputManager.KeyGestureEventHandler; 30 import android.hardware.input.InputManager.KeyGestureEventListener; 31 import android.hardware.input.InputManager.KeyboardBacklightListener; 32 import android.hardware.input.InputManager.OnTabletModeChangedListener; 33 import android.hardware.input.InputManager.StickyModifierStateListener; 34 import android.hardware.lights.Light; 35 import android.hardware.lights.LightState; 36 import android.hardware.lights.LightsManager; 37 import android.hardware.lights.LightsRequest; 38 import android.os.Binder; 39 import android.os.CombinedVibration; 40 import android.os.Handler; 41 import android.os.IBinder; 42 import android.os.IVibratorStateListener; 43 import android.os.InputEventInjectionSync; 44 import android.os.Looper; 45 import android.os.Message; 46 import android.os.Process; 47 import android.os.RemoteException; 48 import android.os.ServiceManager; 49 import android.os.VibrationEffect; 50 import android.os.Vibrator; 51 import android.os.VibratorManager; 52 import android.util.IntArray; 53 import android.util.Log; 54 import android.util.SparseArray; 55 import android.view.Display; 56 import android.view.InputDevice; 57 import android.view.InputEvent; 58 import android.view.InputMonitor; 59 import android.view.KeyCharacterMap; 60 import android.view.KeyEvent; 61 import android.view.PointerIcon; 62 import android.view.inputmethod.InputMethodInfo; 63 import android.view.inputmethod.InputMethodSubtype; 64 65 import com.android.internal.annotations.GuardedBy; 66 import com.android.internal.annotations.VisibleForTesting; 67 import com.android.internal.os.SomeArgs; 68 69 import java.util.ArrayList; 70 import java.util.Arrays; 71 import java.util.List; 72 import java.util.Objects; 73 import java.util.concurrent.Executor; 74 75 /** 76 * Manages communication with the input manager service on behalf of 77 * an application process. You're probably looking for {@link InputManager}. 78 * 79 * @hide 80 */ 81 public final class InputManagerGlobal { 82 private static final String TAG = "InputManagerGlobal"; 83 // To enable these logs, run: 'adb shell setprop log.tag.InputManagerGlobal DEBUG' debug()84 private boolean debug() { 85 return Log.isLoggable(TAG, Log.DEBUG); 86 } 87 88 @GuardedBy("mInputDeviceListeners") 89 @Nullable private SparseArray<InputDevice> mInputDevices; 90 @GuardedBy("mInputDeviceListeners") 91 @Nullable private InputDevicesChangedListener mInputDevicesChangedListener; 92 @GuardedBy("mInputDeviceListeners") 93 private final ArrayList<InputDeviceListenerDelegate> mInputDeviceListeners = new ArrayList<>(); 94 95 @GuardedBy("mOnTabletModeChangedListeners") 96 private final ArrayList<OnTabletModeChangedListenerDelegate> mOnTabletModeChangedListeners = 97 new ArrayList<>(); 98 99 private final Object mBatteryListenersLock = new Object(); 100 // Maps a deviceId whose battery is currently being monitored to an entry containing the 101 // registered listeners for that device. 102 @GuardedBy("mBatteryListenersLock") 103 @Nullable private SparseArray<RegisteredBatteryListeners> mBatteryListeners; 104 @GuardedBy("mBatteryListenersLock") 105 @Nullable private IInputDeviceBatteryListener mInputDeviceBatteryListener; 106 107 private final Object mKeyboardBacklightListenerLock = new Object(); 108 @GuardedBy("mKeyboardBacklightListenerLock") 109 @Nullable private ArrayList<KeyboardBacklightListenerDelegate> mKeyboardBacklightListeners; 110 @GuardedBy("mKeyboardBacklightListenerLock") 111 @Nullable private IKeyboardBacklightListener mKeyboardBacklightListener; 112 113 private final Object mStickyModifierStateListenerLock = new Object(); 114 @GuardedBy("mStickyModifierStateListenerLock") 115 @Nullable 116 private ArrayList<StickyModifierStateListenerDelegate> mStickyModifierStateListeners; 117 @GuardedBy("mStickyModifierStateListenerLock") 118 @Nullable 119 private IStickyModifierStateListener mStickyModifierStateListener; 120 121 private final Object mKeyGestureEventListenerLock = new Object(); 122 @GuardedBy("mKeyGestureEventListenerLock") 123 @Nullable 124 private ArrayList<KeyGestureEventListenerDelegate> mKeyGestureEventListeners; 125 @GuardedBy("mKeyGestureEventListenerLock") 126 @Nullable 127 private IKeyGestureEventListener mKeyGestureEventListener; 128 129 private final Object mKeyEventActivityLock = new Object(); 130 @GuardedBy("mKeyEventActivityLock") 131 private ArrayList<KeyEventActivityListener> mKeyEventActivityListeners; 132 @GuardedBy("mKeyEventActivityLock") 133 @Nullable 134 private IKeyEventActivityListener mKeyEventActivityListener; 135 136 @GuardedBy("mKeyGesturesToHandlerMap") 137 @Nullable 138 private IKeyGestureHandler mKeyGestureHandler; 139 @GuardedBy("mKeyGesturesToHandlerMap") 140 private final SparseArray<KeyGestureEventHandler> mKeyGesturesToHandlerMap = 141 new SparseArray<>(); 142 143 144 // InputDeviceSensorManager gets notified synchronously from the binder thread when input 145 // devices change, so it must be synchronized with the input device listeners. 146 @GuardedBy("mInputDeviceListeners") 147 @Nullable private InputDeviceSensorManager mInputDeviceSensorManager; 148 149 private static InputManagerGlobal sInstance; 150 151 private final String mVelocityTrackerStrategy; 152 153 private final IInputManager mIm; 154 InputManagerGlobal(IInputManager im)155 public InputManagerGlobal(IInputManager im) { 156 mIm = im; 157 String strategy = null; 158 try { 159 strategy = mIm.getVelocityTrackerStrategy(); 160 } catch (RemoteException ex) { 161 Log.w(TAG, "Could not get VelocityTracker strategy: " + ex); 162 } 163 mVelocityTrackerStrategy = strategy; 164 } 165 166 /** 167 * Gets an instance of the input manager global singleton. 168 * 169 * @return The input manager instance, may be null early in system startup 170 * before the input manager has been fully initialized. 171 */ getInstance()172 public static InputManagerGlobal getInstance() { 173 synchronized (InputManagerGlobal.class) { 174 if (sInstance == null) { 175 IBinder b = ServiceManager.getService(Context.INPUT_SERVICE); 176 if (b != null) { 177 sInstance = new InputManagerGlobal(IInputManager.Stub.asInterface(b)); 178 } 179 } 180 return sInstance; 181 } 182 } 183 getInputManagerService()184 public IInputManager getInputManagerService() { 185 return mIm; 186 } 187 188 /** 189 * A test session tracker for InputManagerGlobal. 190 * @see #createTestSession(IInputManager) 191 */ 192 @VisibleForTesting 193 public interface TestSession extends AutoCloseable { 194 @Override close()195 void close(); 196 } 197 198 /** 199 * Create and set a test instance of InputManagerGlobal. 200 * 201 * @return The test session. The session must be {@link TestSession#close()}-ed at the end 202 * of the test. 203 */ 204 @VisibleForTesting createTestSession(IInputManager inputManagerService)205 public static TestSession createTestSession(IInputManager inputManagerService) { 206 synchronized (InputManagerGlobal.class) { 207 final var oldInstance = sInstance; 208 sInstance = new InputManagerGlobal(inputManagerService); 209 return () -> sInstance = oldInstance; 210 } 211 } 212 213 /** 214 * Get the current VelocityTracker strategy. 215 * Only works when the system has fully booted up. 216 */ getVelocityTrackerStrategy()217 public String getVelocityTrackerStrategy() { 218 return mVelocityTrackerStrategy; 219 } 220 221 /** 222 * @see InputManager#getInputDevice(int) 223 */ 224 @Nullable getInputDevice(int id)225 public InputDevice getInputDevice(int id) { 226 synchronized (mInputDeviceListeners) { 227 populateInputDevicesLocked(); 228 229 int index = mInputDevices.indexOfKey(id); 230 if (index < 0) { 231 return null; 232 } 233 234 InputDevice inputDevice = mInputDevices.valueAt(index); 235 if (inputDevice == null) { 236 try { 237 inputDevice = mIm.getInputDevice(id); 238 } catch (RemoteException ex) { 239 throw ex.rethrowFromSystemServer(); 240 } 241 if (inputDevice != null) { 242 mInputDevices.setValueAt(index, inputDevice); 243 } 244 } 245 return inputDevice; 246 } 247 } 248 249 @GuardedBy("mInputDeviceListeners") populateInputDevicesLocked()250 private void populateInputDevicesLocked() { 251 if (mInputDevicesChangedListener == null) { 252 final InputDevicesChangedListener 253 listener = new InputDevicesChangedListener(); 254 try { 255 mIm.registerInputDevicesChangedListener(listener); 256 } catch (RemoteException ex) { 257 throw ex.rethrowFromSystemServer(); 258 } 259 mInputDevicesChangedListener = listener; 260 } 261 262 if (mInputDevices == null) { 263 final int[] ids; 264 try { 265 ids = mIm.getInputDeviceIds(); 266 } catch (RemoteException ex) { 267 throw ex.rethrowFromSystemServer(); 268 } 269 270 mInputDevices = new SparseArray<>(); 271 for (int id : ids) { 272 mInputDevices.put(id, null); 273 } 274 } 275 } 276 277 private final class InputDevicesChangedListener extends IInputDevicesChangedListener.Stub { 278 @Override onInputDevicesChanged(int[] deviceIdAndGeneration)279 public void onInputDevicesChanged(int[] deviceIdAndGeneration) throws RemoteException { 280 InputManagerGlobal.this.onInputDevicesChanged(deviceIdAndGeneration); 281 } 282 } 283 onInputDevicesChanged(int[] deviceIdAndGeneration)284 private void onInputDevicesChanged(int[] deviceIdAndGeneration) { 285 final boolean enableDebugLogs = debug(); 286 if (enableDebugLogs) { 287 Log.d(TAG, "Received input devices changed: " + Arrays.toString(deviceIdAndGeneration)); 288 } 289 290 synchronized (mInputDeviceListeners) { 291 for (int i = mInputDevices.size(); --i > 0; ) { 292 final int deviceId = mInputDevices.keyAt(i); 293 if (!containsDeviceId(deviceIdAndGeneration, deviceId)) { 294 if (enableDebugLogs) { 295 final InputDevice device = mInputDevices.valueAt(i); 296 final String name = device != null ? device.getName() : "<null>"; 297 Log.d(TAG, "Device removed: " + deviceId + " (" + name + ")"); 298 } 299 mInputDevices.removeAt(i); 300 if (mInputDeviceSensorManager != null) { 301 mInputDeviceSensorManager.onInputDeviceRemoved(deviceId); 302 } 303 sendMessageToInputDeviceListenersLocked( 304 InputDeviceListenerDelegate.MSG_DEVICE_REMOVED, deviceId); 305 } 306 } 307 308 for (int i = 0; i < deviceIdAndGeneration.length; i += 2) { 309 final int deviceId = deviceIdAndGeneration[i]; 310 int index = mInputDevices.indexOfKey(deviceId); 311 if (index >= 0) { 312 final InputDevice device = mInputDevices.valueAt(index); 313 if (device != null) { 314 final int generation = deviceIdAndGeneration[i + 1]; 315 if (device.getGeneration() != generation) { 316 if (enableDebugLogs) { 317 Log.d(TAG, "Device changed: " + deviceId + " (" 318 + device.getName() + ")"); 319 } 320 mInputDevices.setValueAt(index, null); 321 if (mInputDeviceSensorManager != null) { 322 mInputDeviceSensorManager.onInputDeviceChanged(deviceId); 323 } 324 sendMessageToInputDeviceListenersLocked( 325 InputDeviceListenerDelegate.MSG_DEVICE_CHANGED, deviceId); 326 } 327 } 328 } else { 329 if (enableDebugLogs) { 330 Log.d(TAG, "Device added: " + deviceId); 331 } 332 mInputDevices.put(deviceId, null); 333 if (mInputDeviceSensorManager != null) { 334 mInputDeviceSensorManager.onInputDeviceAdded(deviceId); 335 } 336 sendMessageToInputDeviceListenersLocked( 337 InputDeviceListenerDelegate.MSG_DEVICE_ADDED, deviceId); 338 } 339 } 340 } 341 } 342 343 private static final class InputDeviceListenerDelegate extends Handler { 344 public final InputDeviceListener mListener; 345 static final int MSG_DEVICE_ADDED = 1; 346 static final int MSG_DEVICE_REMOVED = 2; 347 static final int MSG_DEVICE_CHANGED = 3; 348 InputDeviceListenerDelegate(InputDeviceListener listener, Handler handler)349 InputDeviceListenerDelegate(InputDeviceListener listener, Handler handler) { 350 super(handler != null ? handler.getLooper() : Looper.myLooper()); 351 mListener = listener; 352 } 353 354 @Override handleMessage(Message msg)355 public void handleMessage(Message msg) { 356 switch (msg.what) { 357 case MSG_DEVICE_ADDED: 358 mListener.onInputDeviceAdded(msg.arg1); 359 break; 360 case MSG_DEVICE_REMOVED: 361 mListener.onInputDeviceRemoved(msg.arg1); 362 break; 363 case MSG_DEVICE_CHANGED: 364 mListener.onInputDeviceChanged(msg.arg1); 365 break; 366 } 367 } 368 } 369 containsDeviceId(int[] deviceIdAndGeneration, int deviceId)370 private static boolean containsDeviceId(int[] deviceIdAndGeneration, int deviceId) { 371 for (int i = 0; i < deviceIdAndGeneration.length; i += 2) { 372 if (deviceIdAndGeneration[i] == deviceId) { 373 return true; 374 } 375 } 376 return false; 377 } 378 379 @GuardedBy("mInputDeviceListeners") sendMessageToInputDeviceListenersLocked(int what, int deviceId)380 private void sendMessageToInputDeviceListenersLocked(int what, int deviceId) { 381 final int numListeners = mInputDeviceListeners.size(); 382 for (int i = 0; i < numListeners; i++) { 383 InputDeviceListenerDelegate listener = mInputDeviceListeners.get(i); 384 listener.sendMessage(listener.obtainMessage(what, deviceId, 0)); 385 } 386 } 387 388 /** 389 * @see InputManager#registerInputDeviceListener 390 */ registerInputDeviceListener(InputDeviceListener listener, Handler handler)391 public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) { 392 Objects.requireNonNull(listener, "listener must not be null"); 393 394 synchronized (mInputDeviceListeners) { 395 populateInputDevicesLocked(); 396 int index = findInputDeviceListenerLocked(listener); 397 if (index < 0) { 398 mInputDeviceListeners.add(new InputDeviceListenerDelegate(listener, handler)); 399 } 400 } 401 } 402 403 /** 404 * @see InputManager#unregisterInputDeviceListener 405 */ unregisterInputDeviceListener(InputDeviceListener listener)406 public void unregisterInputDeviceListener(InputDeviceListener listener) { 407 if (listener == null) { 408 throw new IllegalArgumentException("listener must not be null"); 409 } 410 411 synchronized (mInputDeviceListeners) { 412 int index = findInputDeviceListenerLocked(listener); 413 if (index >= 0) { 414 InputDeviceListenerDelegate d = mInputDeviceListeners.get(index); 415 d.removeCallbacksAndMessages(null); 416 mInputDeviceListeners.remove(index); 417 } 418 } 419 } 420 421 @GuardedBy("mInputDeviceListeners") findInputDeviceListenerLocked(InputDeviceListener listener)422 private int findInputDeviceListenerLocked(InputDeviceListener listener) { 423 final int numListeners = mInputDeviceListeners.size(); 424 for (int i = 0; i < numListeners; i++) { 425 if (mInputDeviceListeners.get(i).mListener == listener) { 426 return i; 427 } 428 } 429 return -1; 430 } 431 432 /** 433 * @see InputManager#getInputDeviceIds 434 */ getInputDeviceIds()435 public int[] getInputDeviceIds() { 436 synchronized (mInputDeviceListeners) { 437 populateInputDevicesLocked(); 438 439 final int count = mInputDevices.size(); 440 final int[] ids = new int[count]; 441 for (int i = 0; i < count; i++) { 442 ids[i] = mInputDevices.keyAt(i); 443 } 444 return ids; 445 } 446 } 447 448 /** 449 * @see InputManager#enableInputDevice(int) 450 */ enableInputDevice(int id)451 public void enableInputDevice(int id) { 452 try { 453 mIm.enableInputDevice(id); 454 } catch (RemoteException ex) { 455 Log.w(TAG, "Could not enable input device with id = " + id); 456 throw ex.rethrowFromSystemServer(); 457 } 458 } 459 460 /** 461 * @see InputManager#disableInputDevice(int) 462 */ disableInputDevice(int id)463 public void disableInputDevice(int id) { 464 try { 465 mIm.disableInputDevice(id); 466 } catch (RemoteException ex) { 467 Log.w(TAG, "Could not disable input device with id = " + id); 468 throw ex.rethrowFromSystemServer(); 469 } 470 } 471 472 /** 473 * @see InputManager#getInputDeviceByDescriptor 474 */ getInputDeviceByDescriptor(String descriptor)475 InputDevice getInputDeviceByDescriptor(String descriptor) { 476 Objects.requireNonNull(descriptor, "descriptor must not be null."); 477 478 synchronized (mInputDeviceListeners) { 479 populateInputDevicesLocked(); 480 481 int numDevices = mInputDevices.size(); 482 for (int i = 0; i < numDevices; i++) { 483 InputDevice inputDevice = mInputDevices.valueAt(i); 484 if (inputDevice == null) { 485 int id = mInputDevices.keyAt(i); 486 try { 487 inputDevice = mIm.getInputDevice(id); 488 } catch (RemoteException ex) { 489 throw ex.rethrowFromSystemServer(); 490 } 491 if (inputDevice == null) { 492 continue; 493 } 494 mInputDevices.setValueAt(i, inputDevice); 495 } 496 if (descriptor.equals(inputDevice.getDescriptor())) { 497 return inputDevice; 498 } 499 } 500 return null; 501 } 502 } 503 504 /** 505 * @see InputManager#getHostUsiVersion 506 */ 507 @Nullable getHostUsiVersion(@onNull Display display)508 HostUsiVersion getHostUsiVersion(@NonNull Display display) { 509 Objects.requireNonNull(display, "display should not be null"); 510 511 // Return the first valid USI version reported by any input device associated with 512 // the display. 513 synchronized (mInputDeviceListeners) { 514 populateInputDevicesLocked(); 515 516 for (int i = 0; i < mInputDevices.size(); i++) { 517 final InputDevice device = getInputDevice(mInputDevices.keyAt(i)); 518 if (device != null && device.getAssociatedDisplayId() == display.getDisplayId()) { 519 if (device.getHostUsiVersion() != null) { 520 return device.getHostUsiVersion(); 521 } 522 } 523 } 524 } 525 526 // If there are no input devices that report a valid USI version, see if there is a config 527 // that specifies the USI version for the display. This is to handle cases where the USI 528 // input device is not registered by the kernel/driver all the time. 529 try { 530 return mIm.getHostUsiVersionFromDisplayConfig(display.getDisplayId()); 531 } catch (RemoteException e) { 532 throw e.rethrowFromSystemServer(); 533 } 534 } 535 onTabletModeChanged(long whenNanos, boolean inTabletMode)536 private void onTabletModeChanged(long whenNanos, boolean inTabletMode) { 537 if (debug()) { 538 Log.d(TAG, "Received tablet mode changed: " 539 + "whenNanos=" + whenNanos + ", inTabletMode=" + inTabletMode); 540 } 541 synchronized (mOnTabletModeChangedListeners) { 542 final int numListeners = mOnTabletModeChangedListeners.size(); 543 for (int i = 0; i < numListeners; i++) { 544 OnTabletModeChangedListenerDelegate listener = 545 mOnTabletModeChangedListeners.get(i); 546 listener.sendTabletModeChanged(whenNanos, inTabletMode); 547 } 548 } 549 } 550 551 private final class TabletModeChangedListener extends ITabletModeChangedListener.Stub { 552 @Override onTabletModeChanged(long whenNanos, boolean inTabletMode)553 public void onTabletModeChanged(long whenNanos, boolean inTabletMode) { 554 InputManagerGlobal.this.onTabletModeChanged(whenNanos, inTabletMode); 555 } 556 } 557 558 private static final class OnTabletModeChangedListenerDelegate extends Handler { 559 private static final int MSG_TABLET_MODE_CHANGED = 0; 560 561 public final OnTabletModeChangedListener mListener; 562 OnTabletModeChangedListenerDelegate( OnTabletModeChangedListener listener, Handler handler)563 OnTabletModeChangedListenerDelegate( 564 OnTabletModeChangedListener listener, Handler handler) { 565 super(handler != null ? handler.getLooper() : Looper.myLooper()); 566 mListener = listener; 567 } 568 sendTabletModeChanged(long whenNanos, boolean inTabletMode)569 public void sendTabletModeChanged(long whenNanos, boolean inTabletMode) { 570 SomeArgs args = SomeArgs.obtain(); 571 args.argi1 = (int) whenNanos; 572 args.argi2 = (int) (whenNanos >> 32); 573 args.arg1 = inTabletMode; 574 obtainMessage(MSG_TABLET_MODE_CHANGED, args).sendToTarget(); 575 } 576 577 @Override handleMessage(Message msg)578 public void handleMessage(Message msg) { 579 if (msg.what == MSG_TABLET_MODE_CHANGED) { 580 SomeArgs args = (SomeArgs) msg.obj; 581 long whenNanos = (args.argi1 & 0xFFFFFFFFL) | ((long) args.argi2 << 32); 582 boolean inTabletMode = (boolean) args.arg1; 583 mListener.onTabletModeChanged(whenNanos, inTabletMode); 584 } 585 } 586 } 587 588 /** 589 * @see InputManager#registerInputDeviceListener(InputDeviceListener, Handler) 590 */ registerOnTabletModeChangedListener( OnTabletModeChangedListener listener, Handler handler)591 void registerOnTabletModeChangedListener( 592 OnTabletModeChangedListener listener, Handler handler) { 593 Objects.requireNonNull(listener, "listener must not be null"); 594 595 synchronized (mOnTabletModeChangedListeners) { 596 if (mOnTabletModeChangedListeners.isEmpty()) { 597 initializeTabletModeListenerLocked(); 598 } 599 int idx = findOnTabletModeChangedListenerLocked(listener); 600 if (idx < 0) { 601 OnTabletModeChangedListenerDelegate d = 602 new OnTabletModeChangedListenerDelegate(listener, handler); 603 mOnTabletModeChangedListeners.add(d); 604 } 605 } 606 } 607 608 /** 609 * @see InputManager#unregisterOnTabletModeChangedListener(OnTabletModeChangedListener) 610 */ unregisterOnTabletModeChangedListener(OnTabletModeChangedListener listener)611 void unregisterOnTabletModeChangedListener(OnTabletModeChangedListener listener) { 612 Objects.requireNonNull(listener, "listener must not be null"); 613 614 synchronized (mOnTabletModeChangedListeners) { 615 int idx = findOnTabletModeChangedListenerLocked(listener); 616 if (idx >= 0) { 617 OnTabletModeChangedListenerDelegate d = mOnTabletModeChangedListeners.remove(idx); 618 d.removeCallbacksAndMessages(null); 619 } 620 } 621 } 622 623 @GuardedBy("mOnTabletModeChangedListeners") initializeTabletModeListenerLocked()624 private void initializeTabletModeListenerLocked() { 625 final TabletModeChangedListener listener = new TabletModeChangedListener(); 626 try { 627 mIm.registerTabletModeChangedListener(listener); 628 } catch (RemoteException ex) { 629 throw ex.rethrowFromSystemServer(); 630 } 631 } 632 633 @GuardedBy("mOnTabletModeChangedListeners") findOnTabletModeChangedListenerLocked(OnTabletModeChangedListener listener)634 private int findOnTabletModeChangedListenerLocked(OnTabletModeChangedListener listener) { 635 final int n = mOnTabletModeChangedListeners.size(); 636 for (int i = 0; i < n; i++) { 637 if (mOnTabletModeChangedListeners.get(i).mListener == listener) { 638 return i; 639 } 640 } 641 return -1; 642 } 643 644 private static final class RegisteredBatteryListeners { 645 final List<InputDeviceBatteryListenerDelegate> mDelegates = new ArrayList<>(); 646 IInputDeviceBatteryState mInputDeviceBatteryState; 647 } 648 649 private static final class InputDeviceBatteryListenerDelegate { 650 final InputDeviceBatteryListener mListener; 651 final Executor mExecutor; 652 InputDeviceBatteryListenerDelegate(InputDeviceBatteryListener listener, Executor executor)653 InputDeviceBatteryListenerDelegate(InputDeviceBatteryListener listener, Executor executor) { 654 mListener = listener; 655 mExecutor = executor; 656 } 657 notifyBatteryStateChanged(IInputDeviceBatteryState state)658 void notifyBatteryStateChanged(IInputDeviceBatteryState state) { 659 mExecutor.execute(() -> 660 mListener.onBatteryStateChanged(state.deviceId, state.updateTime, 661 new LocalBatteryState(state.isPresent, state.status, state.capacity))); 662 } 663 } 664 665 /** 666 * @see InputManager#addInputDeviceBatteryListener(int, Executor, InputDeviceBatteryListener) 667 */ addInputDeviceBatteryListener(int deviceId, @NonNull Executor executor, @NonNull InputDeviceBatteryListener listener)668 public void addInputDeviceBatteryListener(int deviceId, @NonNull Executor executor, 669 @NonNull InputDeviceBatteryListener listener) { 670 Objects.requireNonNull(executor, "executor should not be null"); 671 Objects.requireNonNull(listener, "listener should not be null"); 672 673 synchronized (mBatteryListenersLock) { 674 if (mBatteryListeners == null) { 675 mBatteryListeners = new SparseArray<>(); 676 mInputDeviceBatteryListener = new LocalInputDeviceBatteryListener(); 677 } 678 RegisteredBatteryListeners listenersForDevice = mBatteryListeners.get(deviceId); 679 if (listenersForDevice == null) { 680 // The deviceId is currently not being monitored for battery changes. 681 // Start monitoring the device. 682 listenersForDevice = new RegisteredBatteryListeners(); 683 mBatteryListeners.put(deviceId, listenersForDevice); 684 try { 685 mIm.registerBatteryListener(deviceId, mInputDeviceBatteryListener); 686 } catch (RemoteException e) { 687 throw e.rethrowFromSystemServer(); 688 } 689 } else { 690 // The deviceId is already being monitored for battery changes. 691 // Ensure that the listener is not already registered. 692 final int numDelegates = listenersForDevice.mDelegates.size(); 693 for (int i = 0; i < numDelegates; i++) { 694 InputDeviceBatteryListener registeredListener = 695 listenersForDevice.mDelegates.get(i).mListener; 696 if (Objects.equals(listener, registeredListener)) { 697 throw new IllegalArgumentException( 698 "Attempting to register an InputDeviceBatteryListener that has " 699 + "already been registered for deviceId: " 700 + deviceId); 701 } 702 } 703 } 704 final InputDeviceBatteryListenerDelegate delegate = 705 new InputDeviceBatteryListenerDelegate(listener, executor); 706 listenersForDevice.mDelegates.add(delegate); 707 708 // Notify the listener immediately if we already have the latest battery state. 709 if (listenersForDevice.mInputDeviceBatteryState != null) { 710 delegate.notifyBatteryStateChanged(listenersForDevice.mInputDeviceBatteryState); 711 } 712 } 713 } 714 715 /** 716 * @see InputManager#removeInputDeviceBatteryListener(int, InputDeviceBatteryListener) 717 */ removeInputDeviceBatteryListener(int deviceId, @NonNull InputDeviceBatteryListener listener)718 void removeInputDeviceBatteryListener(int deviceId, 719 @NonNull InputDeviceBatteryListener listener) { 720 Objects.requireNonNull(listener, "listener should not be null"); 721 722 synchronized (mBatteryListenersLock) { 723 if (mBatteryListeners == null) { 724 return; 725 } 726 RegisteredBatteryListeners listenersForDevice = mBatteryListeners.get(deviceId); 727 if (listenersForDevice == null) { 728 // The deviceId is not currently being monitored. 729 return; 730 } 731 final List<InputDeviceBatteryListenerDelegate> delegates = 732 listenersForDevice.mDelegates; 733 for (int i = 0; i < delegates.size();) { 734 if (Objects.equals(listener, delegates.get(i).mListener)) { 735 delegates.remove(i); 736 continue; 737 } 738 i++; 739 } 740 if (!delegates.isEmpty()) { 741 return; 742 } 743 744 // There are no more battery listeners for this deviceId. Stop monitoring this device. 745 mBatteryListeners.remove(deviceId); 746 try { 747 mIm.unregisterBatteryListener(deviceId, mInputDeviceBatteryListener); 748 } catch (RemoteException e) { 749 throw e.rethrowFromSystemServer(); 750 } 751 if (mBatteryListeners.size() == 0) { 752 // There are no more devices being monitored, so the registered 753 // IInputDeviceBatteryListener will be automatically dropped by the server. 754 mBatteryListeners = null; 755 mInputDeviceBatteryListener = null; 756 } 757 } 758 } 759 760 private class LocalInputDeviceBatteryListener extends IInputDeviceBatteryListener.Stub { 761 @Override onBatteryStateChanged(IInputDeviceBatteryState state)762 public void onBatteryStateChanged(IInputDeviceBatteryState state) { 763 synchronized (mBatteryListenersLock) { 764 if (mBatteryListeners == null) return; 765 final RegisteredBatteryListeners entry = mBatteryListeners.get(state.deviceId); 766 if (entry == null) return; 767 768 entry.mInputDeviceBatteryState = state; 769 final int numDelegates = entry.mDelegates.size(); 770 for (int i = 0; i < numDelegates; i++) { 771 entry.mDelegates.get(i) 772 .notifyBatteryStateChanged(entry.mInputDeviceBatteryState); 773 } 774 } 775 } 776 } 777 778 /** 779 * @see #getInputDeviceBatteryState(int, boolean) 780 */ 781 @NonNull getInputDeviceBatteryState(int deviceId, boolean hasBattery)782 public BatteryState getInputDeviceBatteryState(int deviceId, boolean hasBattery) { 783 if (!hasBattery) { 784 return new LocalBatteryState(); 785 } 786 try { 787 final IInputDeviceBatteryState state = mIm.getBatteryState(deviceId); 788 return new LocalBatteryState(state.isPresent, state.status, state.capacity); 789 } catch (RemoteException ex) { 790 throw ex.rethrowFromSystemServer(); 791 } 792 } 793 794 // Implementation of the android.hardware.BatteryState interface used to report the battery 795 // state via the InputDevice#getBatteryState() and InputDeviceBatteryListener interfaces. 796 private static final class LocalBatteryState extends BatteryState { 797 private final boolean mIsPresent; 798 private final int mStatus; 799 private final float mCapacity; 800 LocalBatteryState()801 LocalBatteryState() { 802 this(false /*isPresent*/, BatteryState.STATUS_UNKNOWN, Float.NaN /*capacity*/); 803 } 804 LocalBatteryState(boolean isPresent, int status, float capacity)805 LocalBatteryState(boolean isPresent, int status, float capacity) { 806 mIsPresent = isPresent; 807 mStatus = status; 808 mCapacity = capacity; 809 } 810 811 @Override isPresent()812 public boolean isPresent() { 813 return mIsPresent; 814 } 815 816 @Override getStatus()817 public int getStatus() { 818 return mStatus; 819 } 820 821 @Override getCapacity()822 public float getCapacity() { 823 return mCapacity; 824 } 825 } 826 827 private static final class KeyboardBacklightListenerDelegate { 828 final InputManager.KeyboardBacklightListener mListener; 829 final Executor mExecutor; 830 KeyboardBacklightListenerDelegate(KeyboardBacklightListener listener, Executor executor)831 KeyboardBacklightListenerDelegate(KeyboardBacklightListener listener, Executor executor) { 832 mListener = listener; 833 mExecutor = executor; 834 } 835 notifyKeyboardBacklightChange(int deviceId, IKeyboardBacklightState state, boolean isTriggeredByKeyPress)836 void notifyKeyboardBacklightChange(int deviceId, IKeyboardBacklightState state, 837 boolean isTriggeredByKeyPress) { 838 mExecutor.execute(() -> 839 mListener.onKeyboardBacklightChanged(deviceId, 840 new LocalKeyboardBacklightState(state.brightnessLevel, 841 state.maxBrightnessLevel), isTriggeredByKeyPress)); 842 } 843 } 844 845 private class LocalKeyboardBacklightListener extends IKeyboardBacklightListener.Stub { 846 847 @Override onBrightnessChanged(int deviceId, IKeyboardBacklightState state, boolean isTriggeredByKeyPress)848 public void onBrightnessChanged(int deviceId, IKeyboardBacklightState state, 849 boolean isTriggeredByKeyPress) { 850 synchronized (mKeyboardBacklightListenerLock) { 851 if (mKeyboardBacklightListeners == null) return; 852 final int numListeners = mKeyboardBacklightListeners.size(); 853 for (int i = 0; i < numListeners; i++) { 854 mKeyboardBacklightListeners.get(i) 855 .notifyKeyboardBacklightChange(deviceId, state, isTriggeredByKeyPress); 856 } 857 } 858 } 859 } 860 861 // Implementation of the android.hardware.input.KeyboardBacklightState interface used to report 862 // the keyboard backlight state via the KeyboardBacklightListener interfaces. 863 private static final class LocalKeyboardBacklightState extends KeyboardBacklightState { 864 865 private final int mBrightnessLevel; 866 private final int mMaxBrightnessLevel; 867 LocalKeyboardBacklightState(int brightnessLevel, int maxBrightnessLevel)868 LocalKeyboardBacklightState(int brightnessLevel, int maxBrightnessLevel) { 869 mBrightnessLevel = brightnessLevel; 870 mMaxBrightnessLevel = maxBrightnessLevel; 871 } 872 873 @Override getBrightnessLevel()874 public int getBrightnessLevel() { 875 return mBrightnessLevel; 876 } 877 878 @Override getMaxBrightnessLevel()879 public int getMaxBrightnessLevel() { 880 return mMaxBrightnessLevel; 881 } 882 } 883 884 /** 885 * @see InputManager#registerKeyboardBacklightListener(Executor, KeyboardBacklightListener) 886 */ 887 @RequiresPermission(Manifest.permission.MONITOR_KEYBOARD_BACKLIGHT) registerKeyboardBacklightListener(@onNull Executor executor, @NonNull KeyboardBacklightListener listener)888 void registerKeyboardBacklightListener(@NonNull Executor executor, 889 @NonNull KeyboardBacklightListener listener) throws IllegalArgumentException { 890 Objects.requireNonNull(executor, "executor should not be null"); 891 Objects.requireNonNull(listener, "listener should not be null"); 892 893 synchronized (mKeyboardBacklightListenerLock) { 894 if (mKeyboardBacklightListener == null) { 895 mKeyboardBacklightListeners = new ArrayList<>(); 896 mKeyboardBacklightListener = new LocalKeyboardBacklightListener(); 897 898 try { 899 mIm.registerKeyboardBacklightListener(mKeyboardBacklightListener); 900 } catch (RemoteException e) { 901 throw e.rethrowFromSystemServer(); 902 } 903 } 904 final int numListeners = mKeyboardBacklightListeners.size(); 905 for (int i = 0; i < numListeners; i++) { 906 if (mKeyboardBacklightListeners.get(i).mListener == listener) { 907 throw new IllegalArgumentException("Listener has already been registered!"); 908 } 909 } 910 KeyboardBacklightListenerDelegate delegate = 911 new KeyboardBacklightListenerDelegate(listener, executor); 912 mKeyboardBacklightListeners.add(delegate); 913 } 914 } 915 916 /** 917 * @see InputManager#unregisterKeyboardBacklightListener(KeyboardBacklightListener) 918 */ 919 @RequiresPermission(Manifest.permission.MONITOR_KEYBOARD_BACKLIGHT) unregisterKeyboardBacklightListener( @onNull KeyboardBacklightListener listener)920 void unregisterKeyboardBacklightListener( 921 @NonNull KeyboardBacklightListener listener) { 922 Objects.requireNonNull(listener, "listener should not be null"); 923 924 synchronized (mKeyboardBacklightListenerLock) { 925 if (mKeyboardBacklightListeners == null) { 926 return; 927 } 928 mKeyboardBacklightListeners.removeIf((delegate) -> delegate.mListener == listener); 929 if (mKeyboardBacklightListeners.isEmpty()) { 930 try { 931 mIm.unregisterKeyboardBacklightListener(mKeyboardBacklightListener); 932 } catch (RemoteException e) { 933 throw e.rethrowFromSystemServer(); 934 } 935 mKeyboardBacklightListeners = null; 936 mKeyboardBacklightListener = null; 937 } 938 } 939 } 940 941 private static final class StickyModifierStateListenerDelegate { 942 final InputManager.StickyModifierStateListener mListener; 943 final Executor mExecutor; 944 StickyModifierStateListenerDelegate(StickyModifierStateListener listener, Executor executor)945 StickyModifierStateListenerDelegate(StickyModifierStateListener listener, 946 Executor executor) { 947 mListener = listener; 948 mExecutor = executor; 949 } 950 notifyStickyModifierStateChange(int modifierState, int lockedModifierState)951 void notifyStickyModifierStateChange(int modifierState, int lockedModifierState) { 952 mExecutor.execute(() -> 953 mListener.onStickyModifierStateChanged( 954 new LocalStickyModifierState(modifierState, lockedModifierState))); 955 } 956 } 957 958 private class LocalStickyModifierStateListener extends IStickyModifierStateListener.Stub { 959 960 @Override onStickyModifierStateChanged(int modifierState, int lockedModifierState)961 public void onStickyModifierStateChanged(int modifierState, int lockedModifierState) { 962 synchronized (mStickyModifierStateListenerLock) { 963 if (mStickyModifierStateListeners == null) return; 964 final int numListeners = mStickyModifierStateListeners.size(); 965 for (int i = 0; i < numListeners; i++) { 966 mStickyModifierStateListeners.get(i) 967 .notifyStickyModifierStateChange(modifierState, lockedModifierState); 968 } 969 } 970 } 971 } 972 973 // Implementation of the android.hardware.input.StickyModifierState interface used to report 974 // the sticky modifier state via the StickyModifierStateListener interfaces. 975 private static final class LocalStickyModifierState extends StickyModifierState { 976 977 private final int mModifierState; 978 private final int mLockedModifierState; 979 LocalStickyModifierState(int modifierState, int lockedModifierState)980 LocalStickyModifierState(int modifierState, int lockedModifierState) { 981 mModifierState = modifierState; 982 mLockedModifierState = lockedModifierState; 983 } 984 985 @Override isShiftModifierOn()986 public boolean isShiftModifierOn() { 987 return (mModifierState & KeyEvent.META_SHIFT_ON) != 0; 988 } 989 990 @Override isShiftModifierLocked()991 public boolean isShiftModifierLocked() { 992 return (mLockedModifierState & KeyEvent.META_SHIFT_ON) != 0; 993 } 994 995 @Override isCtrlModifierOn()996 public boolean isCtrlModifierOn() { 997 return (mModifierState & KeyEvent.META_CTRL_ON) != 0; 998 } 999 1000 @Override isCtrlModifierLocked()1001 public boolean isCtrlModifierLocked() { 1002 return (mLockedModifierState & KeyEvent.META_CTRL_ON) != 0; 1003 } 1004 1005 @Override isMetaModifierOn()1006 public boolean isMetaModifierOn() { 1007 return (mModifierState & KeyEvent.META_META_ON) != 0; 1008 } 1009 1010 @Override isMetaModifierLocked()1011 public boolean isMetaModifierLocked() { 1012 return (mLockedModifierState & KeyEvent.META_META_ON) != 0; 1013 } 1014 1015 @Override isAltModifierOn()1016 public boolean isAltModifierOn() { 1017 return (mModifierState & KeyEvent.META_ALT_LEFT_ON) != 0; 1018 } 1019 1020 @Override isAltModifierLocked()1021 public boolean isAltModifierLocked() { 1022 return (mLockedModifierState & KeyEvent.META_ALT_LEFT_ON) != 0; 1023 } 1024 1025 @Override isAltGrModifierOn()1026 public boolean isAltGrModifierOn() { 1027 return (mModifierState & KeyEvent.META_ALT_RIGHT_ON) != 0; 1028 } 1029 1030 @Override isAltGrModifierLocked()1031 public boolean isAltGrModifierLocked() { 1032 return (mLockedModifierState & KeyEvent.META_ALT_RIGHT_ON) != 0; 1033 } 1034 } 1035 1036 /** 1037 * @see InputManager#registerStickyModifierStateListener(Executor, StickyModifierStateListener) 1038 */ 1039 @RequiresPermission(Manifest.permission.MONITOR_STICKY_MODIFIER_STATE) registerStickyModifierStateListener(@onNull Executor executor, @NonNull StickyModifierStateListener listener)1040 void registerStickyModifierStateListener(@NonNull Executor executor, 1041 @NonNull StickyModifierStateListener listener) throws IllegalArgumentException { 1042 Objects.requireNonNull(executor, "executor should not be null"); 1043 Objects.requireNonNull(listener, "listener should not be null"); 1044 1045 synchronized (mStickyModifierStateListenerLock) { 1046 if (mStickyModifierStateListener == null) { 1047 mStickyModifierStateListeners = new ArrayList<>(); 1048 mStickyModifierStateListener = new LocalStickyModifierStateListener(); 1049 1050 try { 1051 mIm.registerStickyModifierStateListener(mStickyModifierStateListener); 1052 } catch (RemoteException e) { 1053 throw e.rethrowFromSystemServer(); 1054 } 1055 } 1056 final int numListeners = mStickyModifierStateListeners.size(); 1057 for (int i = 0; i < numListeners; i++) { 1058 if (mStickyModifierStateListeners.get(i).mListener == listener) { 1059 throw new IllegalArgumentException("Listener has already been registered!"); 1060 } 1061 } 1062 StickyModifierStateListenerDelegate delegate = 1063 new StickyModifierStateListenerDelegate(listener, executor); 1064 mStickyModifierStateListeners.add(delegate); 1065 } 1066 } 1067 1068 /** 1069 * @see InputManager#unregisterStickyModifierStateListener(StickyModifierStateListener) 1070 */ 1071 @RequiresPermission(Manifest.permission.MONITOR_STICKY_MODIFIER_STATE) unregisterStickyModifierStateListener( @onNull StickyModifierStateListener listener)1072 void unregisterStickyModifierStateListener( 1073 @NonNull StickyModifierStateListener listener) { 1074 Objects.requireNonNull(listener, "listener should not be null"); 1075 1076 synchronized (mStickyModifierStateListenerLock) { 1077 if (mStickyModifierStateListeners == null) { 1078 return; 1079 } 1080 mStickyModifierStateListeners.removeIf((delegate) -> delegate.mListener == listener); 1081 if (mStickyModifierStateListeners.isEmpty()) { 1082 try { 1083 mIm.unregisterStickyModifierStateListener(mStickyModifierStateListener); 1084 } catch (RemoteException e) { 1085 throw e.rethrowFromSystemServer(); 1086 } 1087 mStickyModifierStateListeners = null; 1088 mStickyModifierStateListener = null; 1089 } 1090 } 1091 } 1092 1093 private static final class KeyGestureEventListenerDelegate { 1094 final KeyGestureEventListener mListener; 1095 final Executor mExecutor; 1096 KeyGestureEventListenerDelegate(KeyGestureEventListener listener, Executor executor)1097 KeyGestureEventListenerDelegate(KeyGestureEventListener listener, 1098 Executor executor) { 1099 mListener = listener; 1100 mExecutor = executor; 1101 } 1102 onKeyGestureEvent(KeyGestureEvent event)1103 void onKeyGestureEvent(KeyGestureEvent event) { 1104 mExecutor.execute(() -> mListener.onKeyGestureEvent(event)); 1105 } 1106 } 1107 1108 private class LocalKeyGestureEventListener extends IKeyGestureEventListener.Stub { 1109 @Override onKeyGestureEvent(@onNull AidlKeyGestureEvent ev)1110 public void onKeyGestureEvent(@NonNull AidlKeyGestureEvent ev) { 1111 synchronized (mKeyGestureEventListenerLock) { 1112 if (mKeyGestureEventListeners == null) return; 1113 final int numListeners = mKeyGestureEventListeners.size(); 1114 final KeyGestureEvent event = new KeyGestureEvent(ev); 1115 for (int i = 0; i < numListeners; i++) { 1116 mKeyGestureEventListeners.get(i).onKeyGestureEvent(event); 1117 } 1118 } 1119 } 1120 } 1121 1122 /** 1123 * @see InputManager#registerKeyGestureEventListener(Executor, 1124 * KeyGestureEventListener) 1125 */ 1126 @RequiresPermission(Manifest.permission.MANAGE_KEY_GESTURES) registerKeyGestureEventListener(@onNull Executor executor, @NonNull KeyGestureEventListener listener)1127 void registerKeyGestureEventListener(@NonNull Executor executor, 1128 @NonNull KeyGestureEventListener listener) throws IllegalArgumentException { 1129 Objects.requireNonNull(executor, "executor should not be null"); 1130 Objects.requireNonNull(listener, "listener should not be null"); 1131 1132 synchronized (mKeyGestureEventListenerLock) { 1133 if (mKeyGestureEventListener == null) { 1134 mKeyGestureEventListeners = new ArrayList<>(); 1135 mKeyGestureEventListener = new LocalKeyGestureEventListener(); 1136 1137 try { 1138 mIm.registerKeyGestureEventListener(mKeyGestureEventListener); 1139 } catch (RemoteException e) { 1140 throw e.rethrowFromSystemServer(); 1141 } 1142 } 1143 final int numListeners = mKeyGestureEventListeners.size(); 1144 for (int i = 0; i < numListeners; i++) { 1145 if (mKeyGestureEventListeners.get(i).mListener == listener) { 1146 throw new IllegalArgumentException("Listener has already been registered!"); 1147 } 1148 } 1149 KeyGestureEventListenerDelegate delegate = 1150 new KeyGestureEventListenerDelegate(listener, executor); 1151 mKeyGestureEventListeners.add(delegate); 1152 } 1153 } 1154 1155 /** 1156 * @see InputManager#unregisterKeyGestureEventListener(KeyGestureEventListener) 1157 */ 1158 @RequiresPermission(Manifest.permission.MANAGE_KEY_GESTURES) unregisterKeyGestureEventListener(@onNull KeyGestureEventListener listener)1159 void unregisterKeyGestureEventListener(@NonNull KeyGestureEventListener listener) { 1160 Objects.requireNonNull(listener, "listener should not be null"); 1161 1162 synchronized (mKeyGestureEventListenerLock) { 1163 if (mKeyGestureEventListeners == null) { 1164 return; 1165 } 1166 mKeyGestureEventListeners.removeIf((delegate) -> delegate.mListener == listener); 1167 if (mKeyGestureEventListeners.isEmpty()) { 1168 try { 1169 mIm.unregisterKeyGestureEventListener(mKeyGestureEventListener); 1170 } catch (RemoteException e) { 1171 throw e.rethrowFromSystemServer(); 1172 } 1173 mKeyGestureEventListeners = null; 1174 mKeyGestureEventListener = null; 1175 } 1176 } 1177 } 1178 1179 private class LocalKeyGestureHandler extends IKeyGestureHandler.Stub { 1180 @Override handleKeyGesture(@onNull AidlKeyGestureEvent ev, IBinder focusedToken)1181 public void handleKeyGesture(@NonNull AidlKeyGestureEvent ev, IBinder focusedToken) { 1182 synchronized (mKeyGesturesToHandlerMap) { 1183 KeyGestureEventHandler handler = mKeyGesturesToHandlerMap.get(ev.gestureType); 1184 if (handler == null) { 1185 Log.w(TAG, "Key gesture event " + ev.gestureType 1186 + " occurred without a registered handler!"); 1187 return; 1188 } 1189 handler.handleKeyGestureEvent(new KeyGestureEvent(ev), focusedToken); 1190 } 1191 } 1192 } 1193 1194 /** 1195 * @see InputManager#registerKeyGestureEventHandler(List, KeyGestureEventHandler) 1196 */ 1197 @RequiresPermission(Manifest.permission.MANAGE_KEY_GESTURES) registerKeyGestureEventHandler(List<Integer> keyGesturesToHandle, @NonNull KeyGestureEventHandler handler)1198 void registerKeyGestureEventHandler(List<Integer> keyGesturesToHandle, 1199 @NonNull KeyGestureEventHandler handler) throws IllegalArgumentException { 1200 Objects.requireNonNull(keyGesturesToHandle, "List of gestures should not be null"); 1201 Objects.requireNonNull(handler, "handler should not be null"); 1202 1203 if (keyGesturesToHandle.isEmpty()) { 1204 throw new IllegalArgumentException("No key gestures provided!"); 1205 } 1206 1207 synchronized (mKeyGesturesToHandlerMap) { 1208 IntArray newKeyGestures = new IntArray( 1209 keyGesturesToHandle.size() + mKeyGesturesToHandlerMap.size()); 1210 1211 // Check if the handler already exists 1212 for (int i = 0; i < mKeyGesturesToHandlerMap.size(); i++) { 1213 KeyGestureEventHandler h = mKeyGesturesToHandlerMap.valueAt(i); 1214 if (h == handler) { 1215 throw new IllegalArgumentException("Handler has already been registered!"); 1216 } 1217 newKeyGestures.add(mKeyGesturesToHandlerMap.keyAt(i)); 1218 } 1219 1220 // Check if any of the key gestures are already handled by existing handlers 1221 for (int gesture : keyGesturesToHandle) { 1222 if (mKeyGesturesToHandlerMap.contains(gesture)) { 1223 throw new IllegalArgumentException("Key gesture " + gesture 1224 + " is already registered by another handler!"); 1225 } 1226 newKeyGestures.add(gesture); 1227 } 1228 1229 try { 1230 // If handler was already registered for this process, we need to unregister and 1231 // re-register it for the new set of gestures 1232 if (mKeyGestureHandler != null) { 1233 mIm.unregisterKeyGestureHandler(mKeyGestureHandler); 1234 } else { 1235 mKeyGestureHandler = new LocalKeyGestureHandler(); 1236 } 1237 mIm.registerKeyGestureHandler(newKeyGestures.toArray(), mKeyGestureHandler); 1238 for (int gesture : keyGesturesToHandle) { 1239 mKeyGesturesToHandlerMap.put(gesture, handler); 1240 } 1241 } catch (RemoteException e) { 1242 throw e.rethrowFromSystemServer(); 1243 } 1244 } 1245 } 1246 1247 /** 1248 * @see InputManager#unregisterKeyGestureEventHandler(KeyGestureEventHandler) 1249 */ 1250 @RequiresPermission(Manifest.permission.MANAGE_KEY_GESTURES) unregisterKeyGestureEventHandler(@onNull KeyGestureEventHandler handler)1251 void unregisterKeyGestureEventHandler(@NonNull KeyGestureEventHandler handler) { 1252 Objects.requireNonNull(handler, "handler should not be null"); 1253 1254 synchronized (mKeyGesturesToHandlerMap) { 1255 if (mKeyGestureHandler == null) { 1256 return; 1257 } 1258 for (int i = mKeyGesturesToHandlerMap.size() - 1; i >= 0; i--) { 1259 if (mKeyGesturesToHandlerMap.valueAt(i) == handler) { 1260 mKeyGesturesToHandlerMap.removeAt(i); 1261 } 1262 } 1263 if (mKeyGesturesToHandlerMap.size() == 0) { 1264 try { 1265 mIm.unregisterKeyGestureHandler(mKeyGestureHandler); 1266 } catch (RemoteException e) { 1267 throw e.rethrowFromSystemServer(); 1268 } 1269 mKeyGestureHandler = null; 1270 } 1271 } 1272 } 1273 1274 private class LocalKeyEventActivityListener extends IKeyEventActivityListener.Stub { 1275 @Override onKeyEventActivity()1276 public void onKeyEventActivity() { 1277 synchronized (mKeyEventActivityLock) { 1278 final int numListeners = mKeyEventActivityListeners.size(); 1279 for (int i = 0; i < numListeners; i++) { 1280 KeyEventActivityListener listener = mKeyEventActivityListeners.get(i); 1281 listener.onKeyEventActivity(); 1282 } 1283 } 1284 } 1285 } 1286 registerKeyEventActivityListener(@onNull KeyEventActivityListener listener)1287 boolean registerKeyEventActivityListener(@NonNull KeyEventActivityListener listener) { 1288 Objects.requireNonNull(listener, "listener should not be null"); 1289 boolean success = false; 1290 synchronized (mKeyEventActivityLock) { 1291 if (mKeyEventActivityListener == null) { 1292 mKeyEventActivityListeners = new ArrayList<>(); 1293 mKeyEventActivityListener = new LocalKeyEventActivityListener(); 1294 1295 try { 1296 success = mIm.registerKeyEventActivityListener(mKeyEventActivityListener); 1297 } catch (RemoteException e) { 1298 throw e.rethrowFromSystemServer(); 1299 } 1300 } 1301 if (mKeyEventActivityListeners.contains(listener)) { 1302 throw new IllegalArgumentException("Listener has already been registered!"); 1303 } 1304 mKeyEventActivityListeners.add(listener); 1305 return success; 1306 } 1307 } 1308 unregisterKeyEventActivityListener(@onNull KeyEventActivityListener listener)1309 boolean unregisterKeyEventActivityListener(@NonNull KeyEventActivityListener listener) { 1310 Objects.requireNonNull(listener, "listener should not be null"); 1311 1312 boolean success = true; 1313 synchronized (mKeyEventActivityLock) { 1314 if (mKeyEventActivityListeners == null) { 1315 return success; 1316 } 1317 mKeyEventActivityListeners.remove(listener); 1318 if (mKeyEventActivityListeners.isEmpty()) { 1319 try { 1320 success = mIm.unregisterKeyEventActivityListener(mKeyEventActivityListener); 1321 } catch (RemoteException e) { 1322 throw e.rethrowFromSystemServer(); 1323 } 1324 mKeyEventActivityListeners = null; 1325 mKeyEventActivityListener = null; 1326 } 1327 } 1328 return success; 1329 } 1330 1331 /** 1332 * Sets the keyboard layout override for the specified input device. This will set the 1333 * keyboard layout as the default for the input device irrespective of the underlying IME 1334 * configuration. 1335 * 1336 * <p> 1337 * Prefer using {@link InputManager#setKeyboardLayoutForInputDevice(InputDeviceIdentifier, int, 1338 * InputMethodInfo, InputMethodSubtype, String)} for normal use cases. 1339 * </p><p> 1340 * This method is to be used only for special cases where we knowingly want to set a 1341 * particular keyboard layout for a keyboard, ignoring the IME configuration. e.g. Setting a 1342 * default layout for an Android Emulator where we know the preferred H/W keyboard layout. 1343 * </p><p> 1344 * NOTE: This may affect the typing experience if the layout isn't compatible with the IME 1345 * configuration. 1346 * </p><p> 1347 * NOTE: User can still change the keyboard layout configuration from the settings page. 1348 * </p> 1349 * 1350 * @param identifier The identifier for the input device. 1351 * @param keyboardLayoutDescriptor The keyboard layout descriptor to use. 1352 * 1353 * @hide 1354 */ 1355 @RequiresPermission(Manifest.permission.SET_KEYBOARD_LAYOUT) setKeyboardLayoutOverrideForInputDevice(@onNull InputDeviceIdentifier identifier, @NonNull String keyboardLayoutDescriptor)1356 public void setKeyboardLayoutOverrideForInputDevice(@NonNull InputDeviceIdentifier identifier, 1357 @NonNull String keyboardLayoutDescriptor) { 1358 Objects.requireNonNull(identifier, "identifier should not be null"); 1359 Objects.requireNonNull(keyboardLayoutDescriptor, 1360 "keyboardLayoutDescriptor should not be null"); 1361 try { 1362 mIm.setKeyboardLayoutOverrideForInputDevice(identifier, keyboardLayoutDescriptor); 1363 } catch (RemoteException e) { 1364 throw e.rethrowFromSystemServer(); 1365 } 1366 } 1367 1368 /** 1369 * TODO(b/330517633): Cleanup the unsupported API 1370 */ 1371 @NonNull getKeyboardLayoutsForInputDevice( @onNull InputDeviceIdentifier identifier)1372 public KeyboardLayout[] getKeyboardLayoutsForInputDevice( 1373 @NonNull InputDeviceIdentifier identifier) { 1374 return new KeyboardLayout[0]; 1375 } 1376 1377 /** 1378 * TODO(b/330517633): Cleanup the unsupported API 1379 */ setCurrentKeyboardLayoutForInputDevice( @onNull InputDeviceIdentifier identifier, @NonNull String keyboardLayoutDescriptor)1380 public void setCurrentKeyboardLayoutForInputDevice( 1381 @NonNull InputDeviceIdentifier identifier, 1382 @NonNull String keyboardLayoutDescriptor) {} 1383 1384 1385 /** 1386 * @see InputDevice#getSensorManager() 1387 */ 1388 @NonNull getInputDeviceSensorManager(int deviceId)1389 public SensorManager getInputDeviceSensorManager(int deviceId) { 1390 synchronized (mInputDeviceListeners) { 1391 if (mInputDeviceSensorManager == null) { 1392 mInputDeviceSensorManager = new InputDeviceSensorManager(this); 1393 } 1394 return mInputDeviceSensorManager.getSensorManager(deviceId); 1395 } 1396 } 1397 1398 /** 1399 * Get information about all of the sensors supported by an input device 1400 * @see InputDeviceSensorManager 1401 */ getSensorList(int deviceId)1402 InputSensorInfo[] getSensorList(int deviceId) { 1403 try { 1404 return mIm.getSensorList(deviceId); 1405 } catch (RemoteException ex) { 1406 throw ex.rethrowFromSystemServer(); 1407 } 1408 } 1409 1410 /** 1411 * @see InputDeviceSensorManager 1412 */ enableSensor(int deviceId, int sensorType, int samplingPeriodUs, int maxBatchReportLatencyUs)1413 boolean enableSensor(int deviceId, int sensorType, int samplingPeriodUs, 1414 int maxBatchReportLatencyUs) { 1415 try { 1416 return mIm.enableSensor(deviceId, sensorType, samplingPeriodUs, 1417 maxBatchReportLatencyUs); 1418 } catch (RemoteException ex) { 1419 throw ex.rethrowFromSystemServer(); 1420 } 1421 } 1422 1423 /** 1424 * @see InputDeviceSensorManager 1425 */ disableSensor(int deviceId, int sensorType)1426 void disableSensor(int deviceId, int sensorType) { 1427 try { 1428 mIm.disableSensor(deviceId, sensorType); 1429 } catch (RemoteException ex) { 1430 throw ex.rethrowFromSystemServer(); 1431 } 1432 } 1433 1434 /** 1435 * @see InputDeviceSensorManager 1436 */ flushSensor(int deviceId, int sensorType)1437 boolean flushSensor(int deviceId, int sensorType) { 1438 try { 1439 return mIm.flushSensor(deviceId, sensorType); 1440 } catch (RemoteException ex) { 1441 throw ex.rethrowFromSystemServer(); 1442 } 1443 } 1444 1445 /** 1446 * @see InputDeviceSensorManager 1447 */ registerSensorListener(IInputSensorEventListener listener)1448 boolean registerSensorListener(IInputSensorEventListener listener) { 1449 try { 1450 return mIm.registerSensorListener(listener); 1451 } catch (RemoteException ex) { 1452 throw ex.rethrowFromSystemServer(); 1453 } 1454 } 1455 1456 /** 1457 * @see InputDeviceSensorManager 1458 */ unregisterSensorListener(IInputSensorEventListener listener)1459 void unregisterSensorListener(IInputSensorEventListener listener) { 1460 try { 1461 mIm.unregisterSensorListener(listener); 1462 } catch (RemoteException ex) { 1463 throw ex.rethrowFromSystemServer(); 1464 } 1465 } 1466 1467 /** 1468 * @see InputDevice#getLightsManager() 1469 */ 1470 @NonNull getInputDeviceLightsManager(int deviceId)1471 public LightsManager getInputDeviceLightsManager(int deviceId) { 1472 return new InputDeviceLightsManager(deviceId); 1473 } 1474 1475 /** 1476 * Gets a list of light objects associated with an input device. 1477 * @return The list of lights, never null. 1478 */ getLights(int deviceId)1479 @NonNull List<Light> getLights(int deviceId) { 1480 try { 1481 return mIm.getLights(deviceId); 1482 } catch (RemoteException e) { 1483 throw e.rethrowFromSystemServer(); 1484 } 1485 } 1486 1487 /** 1488 * Returns the state of an input device light. 1489 * @return the light state 1490 */ getLightState(int deviceId, @NonNull Light light)1491 @NonNull LightState getLightState(int deviceId, @NonNull Light light) { 1492 try { 1493 return mIm.getLightState(deviceId, light.getId()); 1494 } catch (RemoteException e) { 1495 throw e.rethrowFromSystemServer(); 1496 } 1497 } 1498 1499 /** 1500 * Request to modify the states of multiple lights. 1501 * 1502 * @param request the settings for lights that should change 1503 */ requestLights(int deviceId, @NonNull LightsRequest request, IBinder token)1504 void requestLights(int deviceId, @NonNull LightsRequest request, IBinder token) { 1505 try { 1506 List<Integer> lightIdList = request.getLights(); 1507 int[] lightIds = new int[lightIdList.size()]; 1508 for (int i = 0; i < lightIds.length; i++) { 1509 lightIds[i] = lightIdList.get(i); 1510 } 1511 List<LightState> lightStateList = request.getLightStates(); 1512 mIm.setLightStates(deviceId, lightIds, 1513 lightStateList.toArray(new LightState[0]), 1514 token); 1515 } catch (RemoteException e) { 1516 throw e.rethrowFromSystemServer(); 1517 } 1518 } 1519 1520 /** 1521 * Open light session for input device manager 1522 * 1523 * @param token The token for the light session 1524 */ openLightSession(int deviceId, String opPkg, @NonNull IBinder token)1525 void openLightSession(int deviceId, String opPkg, @NonNull IBinder token) { 1526 try { 1527 mIm.openLightSession(deviceId, opPkg, token); 1528 } catch (RemoteException e) { 1529 throw e.rethrowFromSystemServer(); 1530 } 1531 } 1532 1533 /** 1534 * Close light session 1535 * 1536 */ closeLightSession(int deviceId, @NonNull IBinder token)1537 void closeLightSession(int deviceId, @NonNull IBinder token) { 1538 try { 1539 mIm.closeLightSession(deviceId, token); 1540 } catch (RemoteException e) { 1541 throw e.rethrowFromSystemServer(); 1542 } 1543 } 1544 1545 /** 1546 * @see InputManager#getInputDeviceVibrator(int, int) 1547 */ getInputDeviceVibrator(int deviceId, int vibratorId)1548 public Vibrator getInputDeviceVibrator(int deviceId, int vibratorId) { 1549 return new InputDeviceVibrator(deviceId, vibratorId); 1550 } 1551 1552 /** 1553 * @see InputDevice#getVibratorManager() 1554 */ 1555 @NonNull getInputDeviceVibratorManager(int deviceId)1556 public VibratorManager getInputDeviceVibratorManager(int deviceId) { 1557 return new InputDeviceVibratorManager(deviceId); 1558 } 1559 1560 /* 1561 * Get the list of device vibrators 1562 * @return The list of vibrators IDs 1563 */ getVibratorIds(int deviceId)1564 int[] getVibratorIds(int deviceId) { 1565 try { 1566 return mIm.getVibratorIds(deviceId); 1567 } catch (RemoteException ex) { 1568 throw ex.rethrowFromSystemServer(); 1569 } 1570 } 1571 1572 /* 1573 * Perform vibration effect 1574 */ vibrate(int deviceId, VibrationEffect effect, IBinder token)1575 void vibrate(int deviceId, VibrationEffect effect, IBinder token) { 1576 try { 1577 mIm.vibrate(deviceId, effect, token); 1578 } catch (RemoteException ex) { 1579 throw ex.rethrowFromSystemServer(); 1580 } 1581 } 1582 1583 /* 1584 * Perform combined vibration effect 1585 */ vibrate(int deviceId, CombinedVibration effect, IBinder token)1586 void vibrate(int deviceId, CombinedVibration effect, IBinder token) { 1587 try { 1588 mIm.vibrateCombined(deviceId, effect, token); 1589 } catch (RemoteException ex) { 1590 throw ex.rethrowFromSystemServer(); 1591 } 1592 } 1593 1594 /* 1595 * Cancel an ongoing vibration 1596 */ cancelVibrate(int deviceId, IBinder token)1597 void cancelVibrate(int deviceId, IBinder token) { 1598 try { 1599 mIm.cancelVibrate(deviceId, token); 1600 } catch (RemoteException ex) { 1601 throw ex.rethrowFromSystemServer(); 1602 } 1603 } 1604 1605 /* 1606 * Check if input device is vibrating 1607 */ isVibrating(int deviceId)1608 boolean isVibrating(int deviceId) { 1609 try { 1610 return mIm.isVibrating(deviceId); 1611 } catch (RemoteException ex) { 1612 throw ex.rethrowFromSystemServer(); 1613 } 1614 } 1615 1616 /** 1617 * Register input device vibrator state listener 1618 */ registerVibratorStateListener(int deviceId, IVibratorStateListener listener)1619 boolean registerVibratorStateListener(int deviceId, IVibratorStateListener listener) { 1620 try { 1621 return mIm.registerVibratorStateListener(deviceId, listener); 1622 } catch (RemoteException ex) { 1623 throw ex.rethrowFromSystemServer(); 1624 } 1625 } 1626 1627 /** 1628 * Unregister input device vibrator state listener 1629 */ unregisterVibratorStateListener(int deviceId, IVibratorStateListener listener)1630 boolean unregisterVibratorStateListener(int deviceId, IVibratorStateListener listener) { 1631 try { 1632 return mIm.unregisterVibratorStateListener(deviceId, listener); 1633 } catch (RemoteException ex) { 1634 throw ex.rethrowFromSystemServer(); 1635 } 1636 } 1637 1638 /** 1639 * @see InputManager#deviceHasKeys(int[]) 1640 */ deviceHasKeys(int[] keyCodes)1641 public boolean[] deviceHasKeys(int[] keyCodes) { 1642 return deviceHasKeys(-1, keyCodes); 1643 } 1644 1645 /** 1646 * @see InputManager#deviceHasKeys(int, int[]) 1647 */ deviceHasKeys(int id, int[] keyCodes)1648 public boolean[] deviceHasKeys(int id, int[] keyCodes) { 1649 boolean[] ret = new boolean[keyCodes.length]; 1650 try { 1651 mIm.hasKeys(id, InputDevice.SOURCE_ANY, keyCodes, ret); 1652 } catch (RemoteException e) { 1653 throw e.rethrowFromSystemServer(); 1654 } 1655 return ret; 1656 } 1657 1658 /** 1659 * @see InputManager#getKeyCodeForKeyLocation(int, int) 1660 */ getKeyCodeForKeyLocation(int deviceId, int locationKeyCode)1661 public int getKeyCodeForKeyLocation(int deviceId, int locationKeyCode) { 1662 try { 1663 return mIm.getKeyCodeForKeyLocation(deviceId, locationKeyCode); 1664 } catch (RemoteException e) { 1665 throw e.rethrowFromSystemServer(); 1666 } 1667 } 1668 1669 /** 1670 * Returns KeyCharacterMap for the provided Keyboard layout. If provided layout is null it will 1671 * return KeyCharacter map for the default layout {@code Generic.kl}. 1672 */ getKeyCharacterMap(@ullable KeyboardLayout keyboardLayout)1673 public KeyCharacterMap getKeyCharacterMap(@Nullable KeyboardLayout keyboardLayout) { 1674 if (keyboardLayout == null) { 1675 return KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); 1676 } 1677 try { 1678 return mIm.getKeyCharacterMap(keyboardLayout.getDescriptor()); 1679 } catch (RemoteException e) { 1680 throw e.rethrowFromSystemServer(); 1681 } 1682 } 1683 1684 /** 1685 * @see InputManager#injectInputEvent(InputEvent, int, int) 1686 */ 1687 injectInputEvent(InputEvent event, int mode, int targetUid)1688 public boolean injectInputEvent(InputEvent event, int mode, int targetUid) { 1689 Objects.requireNonNull(event , "event must not be null"); 1690 1691 if (mode != InputEventInjectionSync.NONE 1692 && mode != InputEventInjectionSync.WAIT_FOR_FINISHED 1693 && mode != InputEventInjectionSync.WAIT_FOR_RESULT) { 1694 throw new IllegalArgumentException("mode is invalid"); 1695 } 1696 1697 try { 1698 return mIm.injectInputEventToTarget(event, mode, targetUid); 1699 } catch (RemoteException ex) { 1700 throw ex.rethrowFromSystemServer(); 1701 } 1702 } 1703 1704 /** 1705 * @see InputManager#injectInputEvent(InputEvent, int) 1706 */ injectInputEvent(InputEvent event, int mode)1707 public boolean injectInputEvent(InputEvent event, int mode) { 1708 return injectInputEvent(event, mode, Process.INVALID_UID); 1709 } 1710 1711 /** 1712 * @see InputManager#setPointerIcon(PointerIcon, int, int, int, IBinder) 1713 */ setPointerIcon(PointerIcon icon, int displayId, int deviceId, int pointerId, IBinder inputToken)1714 public boolean setPointerIcon(PointerIcon icon, int displayId, int deviceId, int pointerId, 1715 IBinder inputToken) { 1716 try { 1717 return mIm.setPointerIcon(icon, displayId, deviceId, pointerId, inputToken); 1718 } catch (RemoteException ex) { 1719 throw ex.rethrowFromSystemServer(); 1720 } 1721 } 1722 1723 /** 1724 * @see InputManager#requestPointerCapture(IBinder, boolean) 1725 */ requestPointerCapture(IBinder windowToken, boolean enable)1726 public void requestPointerCapture(IBinder windowToken, boolean enable) { 1727 try { 1728 mIm.requestPointerCapture(windowToken, enable); 1729 } catch (RemoteException ex) { 1730 throw ex.rethrowFromSystemServer(); 1731 } 1732 } 1733 1734 /** 1735 * @see InputManager#monitorGestureInput(String, int) 1736 */ monitorGestureInput(String name, int displayId)1737 public InputMonitor monitorGestureInput(String name, int displayId) { 1738 try { 1739 return mIm.monitorGestureInput(new Binder(), name, displayId); 1740 } catch (RemoteException ex) { 1741 throw ex.rethrowFromSystemServer(); 1742 } 1743 } 1744 1745 /** 1746 * @see InputManager#addUniqueIdAssociationByPort(String, String) 1747 */ addUniqueIdAssociationByPort(@onNull String inputPort, @NonNull String displayUniqueId)1748 public void addUniqueIdAssociationByPort(@NonNull String inputPort, 1749 @NonNull String displayUniqueId) { 1750 try { 1751 mIm.addUniqueIdAssociationByPort(inputPort, displayUniqueId); 1752 } catch (RemoteException e) { 1753 throw e.rethrowFromSystemServer(); 1754 } 1755 } 1756 1757 /** 1758 * @see InputManager#removeUniqueIdAssociationByPort(String) 1759 */ removeUniqueIdAssociationByPort(@onNull String inputPort)1760 public void removeUniqueIdAssociationByPort(@NonNull String inputPort) { 1761 try { 1762 mIm.removeUniqueIdAssociationByPort(inputPort); 1763 } catch (RemoteException e) { 1764 throw e.rethrowFromSystemServer(); 1765 } 1766 } 1767 1768 /** 1769 * @see InputManager#addUniqueIdAssociationByDescriptor(String, String) 1770 */ addUniqueIdAssociationByDescriptor(@onNull String inputDeviceDescriptor, @NonNull String displayUniqueId)1771 public void addUniqueIdAssociationByDescriptor(@NonNull String inputDeviceDescriptor, 1772 @NonNull String displayUniqueId) { 1773 try { 1774 mIm.addUniqueIdAssociationByDescriptor(inputDeviceDescriptor, displayUniqueId); 1775 } catch (RemoteException e) { 1776 throw e.rethrowFromSystemServer(); 1777 } 1778 } 1779 1780 /** 1781 * @see InputManager#removeUniqueIdAssociationByDescriptor(String) 1782 */ removeUniqueIdAssociationByDescriptor(@onNull String inputDeviceDescriptor)1783 public void removeUniqueIdAssociationByDescriptor(@NonNull String inputDeviceDescriptor) { 1784 try { 1785 mIm.removeUniqueIdAssociationByDescriptor(inputDeviceDescriptor); 1786 } catch (RemoteException e) { 1787 throw e.rethrowFromSystemServer(); 1788 } 1789 } 1790 1791 /** 1792 * @see InputManager#getInputDeviceBluetoothAddress(int) 1793 */ 1794 @RequiresPermission(Manifest.permission.BLUETOOTH) 1795 @Nullable getInputDeviceBluetoothAddress(int deviceId)1796 public String getInputDeviceBluetoothAddress(int deviceId) { 1797 try { 1798 return mIm.getInputDeviceBluetoothAddress(deviceId); 1799 } catch (RemoteException e) { 1800 throw e.rethrowFromSystemServer(); 1801 } 1802 } 1803 1804 /** 1805 * @see InputManager#cancelCurrentTouch() 1806 */ cancelCurrentTouch()1807 public void cancelCurrentTouch() { 1808 try { 1809 mIm.cancelCurrentTouch(); 1810 } catch (RemoteException e) { 1811 throw e.rethrowFromSystemServer(); 1812 } 1813 } 1814 1815 /** 1816 * @see InputManager#pilferPointers(IBinder) 1817 */ 1818 @RequiresPermission(Manifest.permission.MONITOR_INPUT) pilferPointers(IBinder inputChannelToken)1819 public void pilferPointers(IBinder inputChannelToken) { 1820 try { 1821 mIm.pilferPointers(inputChannelToken); 1822 } catch (RemoteException e) { 1823 throw e.rethrowFromSystemServer(); 1824 } 1825 } 1826 } 1827