diff options
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/hardware/input/IInputManager.aidl | 3 | ||||
| -rw-r--r-- | core/java/android/hardware/input/InputDeviceVibrator.java | 93 | ||||
| -rw-r--r-- | core/java/android/hardware/input/InputManager.java | 27 |
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 |
