summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/hardware/input/IInputManager.aidl3
-rw-r--r--core/java/android/hardware/input/InputDeviceVibrator.java93
-rw-r--r--core/java/android/hardware/input/InputManager.java27
3 files changed, 116 insertions, 7 deletions
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index c69c47f80d01..eaa38f3e862c 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -26,6 +26,7 @@ import android.os.CombinedVibrationEffect;
import android.hardware.input.IInputSensorEventListener;
import android.hardware.input.InputSensorInfo;
import android.os.IBinder;
+import android.os.IVibratorStateListener;
import android.os.VibrationEffect;
import android.view.InputDevice;
import android.view.InputEvent;
@@ -92,6 +93,8 @@ interface IInputManager {
void cancelVibrate(int deviceId, IBinder token);
int[] getVibratorIds(int deviceId);
boolean isVibrating(int deviceId);
+ boolean registerVibratorStateListener(int deviceId, in IVibratorStateListener listener);
+ boolean unregisterVibratorStateListener(int deviceId, in IVibratorStateListener listener);
// Input device battery query.
int getBatteryStatus(int deviceId);
diff --git a/core/java/android/hardware/input/InputDeviceVibrator.java b/core/java/android/hardware/input/InputDeviceVibrator.java
index c60d6ce46fdb..f4d8a65d54c6 100644
--- a/core/java/android/hardware/input/InputDeviceVibrator.java
+++ b/core/java/android/hardware/input/InputDeviceVibrator.java
@@ -18,10 +18,18 @@ package android.hardware.input;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
+import android.app.ActivityThread;
+import android.content.Context;
import android.os.Binder;
+import android.os.IVibratorStateListener;
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.os.Vibrator;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
import java.util.concurrent.Executor;
@@ -29,12 +37,18 @@ import java.util.concurrent.Executor;
* Vibrator implementation that communicates with the input device vibrators.
*/
final class InputDeviceVibrator extends Vibrator {
+ private static final String TAG = "InputDeviceVibrator";
+
// mDeviceId represents InputDevice ID the vibrator belongs to
private final int mDeviceId;
private final int mVibratorId;
private final Binder mToken;
private final InputManager mInputManager;
+ @GuardedBy("mDelegates")
+ private final ArrayMap<OnVibratorStateChangedListener,
+ OnVibratorStateChangedListenerDelegate> mDelegates = new ArrayMap<>();
+
InputDeviceVibrator(InputManager inputManager, int deviceId, int vibratorId) {
mInputManager = inputManager;
mDeviceId = deviceId;
@@ -42,6 +56,23 @@ final class InputDeviceVibrator extends Vibrator {
mToken = new Binder();
}
+ private class OnVibratorStateChangedListenerDelegate extends
+ IVibratorStateListener.Stub {
+ private final Executor mExecutor;
+ private final OnVibratorStateChangedListener mListener;
+
+ OnVibratorStateChangedListenerDelegate(@NonNull OnVibratorStateChangedListener listener,
+ @NonNull Executor executor) {
+ mExecutor = executor;
+ mListener = listener;
+ }
+
+ @Override
+ public void onVibrating(boolean isVibrating) {
+ mExecutor.execute(() -> mListener.onVibratorStateChanged(isVibrating));
+ }
+ }
+
@Override
public boolean hasVibrator() {
return true;
@@ -52,25 +83,73 @@ final class InputDeviceVibrator extends Vibrator {
return mInputManager.isVibrating(mDeviceId);
}
- /* TODO: b/161634264 Support Vibrator listener API in input devices */
+ /**
+ * Adds a listener for vibrator state changes. Callbacks will be executed on the main thread.
+ * If the listener was previously added and not removed, this call will be ignored.
+ *
+ * @param listener listener to be added
+ */
@Override
public void addVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
- throw new UnsupportedOperationException(
- "addVibratorStateListener not supported in InputDeviceVibrator");
+ Preconditions.checkNotNull(listener);
+ Context context = ActivityThread.currentApplication();
+ addVibratorStateListener(context.getMainExecutor(), listener);
}
+ /**
+ * Adds a listener for vibrator state change. If the listener was previously added and not
+ * removed, this call will be ignored.
+ *
+ * @param listener Listener to be added.
+ * @param executor The {@link Executor} on which the listener's callbacks will be executed on.
+ */
@Override
public void addVibratorStateListener(
@NonNull @CallbackExecutor Executor executor,
@NonNull OnVibratorStateChangedListener listener) {
- throw new UnsupportedOperationException(
- "addVibratorStateListener not supported in InputDeviceVibrator");
+ Preconditions.checkNotNull(listener);
+ Preconditions.checkNotNull(executor);
+
+ synchronized (mDelegates) {
+ // If listener is already registered, reject and return.
+ if (mDelegates.containsKey(listener)) {
+ Log.w(TAG, "Listener already registered.");
+ return;
+ }
+
+ final OnVibratorStateChangedListenerDelegate delegate =
+ new OnVibratorStateChangedListenerDelegate(listener, executor);
+ if (!mInputManager.registerVibratorStateListener(mDeviceId, delegate)) {
+ Log.w(TAG, "Failed to register vibrate state listener");
+ return;
+ }
+ mDelegates.put(listener, delegate);
+
+ }
}
+ /**
+ * Removes the listener for vibrator state changes. If the listener was not previously
+ * registered, this call will do nothing.
+ *
+ * @param listener Listener to be removed.
+ */
@Override
public void removeVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
- throw new UnsupportedOperationException(
- "removeVibratorStateListener not supported in InputDeviceVibrator");
+ Preconditions.checkNotNull(listener);
+
+ synchronized (mDelegates) {
+ // Check if the listener is registered, otherwise will return.
+ if (mDelegates.containsKey(listener)) {
+ final OnVibratorStateChangedListenerDelegate delegate = mDelegates.get(listener);
+
+ if (!mInputManager.unregisterVibratorStateListener(mDeviceId, delegate)) {
+ Log.w(TAG, "Failed to unregister vibrate state listener");
+ return;
+ }
+ mDelegates.remove(listener);
+ }
+ }
}
@Override
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 185c59d8ccfc..8a01c660ebd0 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -35,6 +35,7 @@ import android.os.Build;
import android.os.CombinedVibrationEffect;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IVibratorStateListener;
import android.os.InputEventInjectionSync;
import android.os.Looper;
import android.os.Message;
@@ -1484,6 +1485,32 @@ public final class InputManager {
}
/**
+ * Register input device vibrator state listener
+ *
+ * @hide
+ */
+ public boolean registerVibratorStateListener(int deviceId, IVibratorStateListener listener) {
+ try {
+ return mIm.registerVibratorStateListener(deviceId, listener);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Unregister input device vibrator state listener
+ *
+ * @hide
+ */
+ public boolean unregisterVibratorStateListener(int deviceId, IVibratorStateListener listener) {
+ try {
+ return mIm.unregisterVibratorStateListener(deviceId, listener);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Gets a sensor manager service associated with an input device, always create a new instance.
* @return The sensor manager, never null.
* @hide