InputFlinger: Support amplitude control for InputDeviceVibrator
Add support for sending multi-channel rumble amplitudes to input
devices supporting FF_RUMBLE.
Bug: 38511270
Bug: 136215622
Test: Connect a gamepad whose driver supports FF_RUMBLE, find it
with the android input framework, and do something like this:
// waveform where rumble magnitude doubles every 2 seconds
VibrationEffect effect = VibrationEffect.createWaveform(
new long[] { 2000L, 2000L, 2000L, 2000L, 2000L },
new int[] { 16, 32, 64, 128, 255 },
-1);
inputDevice.getVibrator().vibrate(effect);
Change-Id: I2f059e085c106cbca2372c72d09a9f579d35e4c7
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index fe428f1..cef2b4c 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -702,7 +702,7 @@
identifier.descriptor.c_str());
}
-void EventHub::vibrate(int32_t deviceId, nsecs_t duration) {
+void EventHub::vibrate(int32_t deviceId, const VibrationElement& element) {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
if (device != nullptr && device->hasValidFd()) {
@@ -710,9 +710,10 @@
memset(&effect, 0, sizeof(effect));
effect.type = FF_RUMBLE;
effect.id = device->ffEffectId;
- effect.u.rumble.strong_magnitude = 0xc000;
- effect.u.rumble.weak_magnitude = 0xc000;
- effect.replay.length = (duration + 999999LL) / 1000000LL;
+ // evdev FF_RUMBLE effect only supports two channels of vibration.
+ effect.u.rumble.strong_magnitude = element.getChannel(0);
+ effect.u.rumble.weak_magnitude = element.getChannel(1);
+ effect.replay.length = element.duration.count();
effect.replay.delay = 0;
if (ioctl(device->fd, EVIOCSFF, &effect)) {
ALOGW("Could not upload force feedback effect to device %s due to error %d.",