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