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