Refactor input device rumble support.

Change VibrationElement to fixed size array of uint8_t.
Move default amplitude handling to Java.
Address previous code review comments.

Bug: 136215622
Test: Connect game controller with rumble support and play game for
force feedback effect.

Change-Id: Ife7294bd829a2ca88354ffa09f523e43a1bc26dc
diff --git a/services/inputflinger/VibrationElement.cpp b/services/inputflinger/VibrationElement.cpp
index a69f5d0..aaf5834 100644
--- a/services/inputflinger/VibrationElement.cpp
+++ b/services/inputflinger/VibrationElement.cpp
@@ -25,38 +25,27 @@
 
 namespace android {
 
-// The sentinel to use the default amplitude
-static const int DEFAULT_AMPLITUDE = -1;
-
-// The vibration magnitude for the "DEFAULT_AMPLITUDE" magnitude constant.
-static const uint16_t DEFAULT_MAGNITUDE = 0xc000;
-
-void VibrationElement::dump(std::string& dump) const {
+const std::string VibrationElement::toString() const {
+    std::string dump;
     dump += StringPrintf("[duration=%lldms, channels=[", duration.count());
 
-    if (channels.size()) {
-        dump += std::to_string(channels[0]);
-        std::for_each(channels.begin() + 1, channels.end(), [&dump](int channel) {
+    for (auto it = channels.begin(); it != channels.end(); ++it) {
+        dump += std::to_string(*it);
+        if (std::next(it) != channels.end()) {
             dump += ", ";
-            dump += std::to_string(channel);
-        });
+        }
     }
+
     dump += "]]";
+    return dump;
 }
 
-uint16_t VibrationElement::getChannel(int id) const {
-    if (id >= (int)channels.size()) {
+uint16_t VibrationElement::getMagnitude(size_t channelIdx) const {
+    if (channelIdx >= channels.size()) {
         return 0;
     }
-
-    // android framework uses DEFAULT_AMPLITUDE to signal that the vibration
-    // should use some built-in default value, denoted here as DEFAULT_MAGNITUDE
-    if (channels[id] == DEFAULT_AMPLITUDE) {
-        return DEFAULT_MAGNITUDE;
-    }
-
     // convert range [0,255] to [0,65535] (android framework to linux ff ranges)
-    return ((uint16_t)channels[id]) << 8;
+    return static_cast<uint16_t>(channels[channelIdx]) << 8;
 }
 
 bool VibrationElement::isOn() const {
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index 5a832e7..a24b293 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -39,11 +39,6 @@
 // Must be at least 2.
 #define MAX_VIBRATE_PATTERN_SIZE 100
 
-// Maximum allowable delay value in a vibration pattern before
-// which the delay will be truncated.
-#define MAX_VIBRATE_PATTERN_DELAY_NSECS (1000000 * 1000000000LL)
-#define MAX_VIBRATE_PATTERN_DELAY_MSECS (1000000 * 1000LL)
-
 namespace android {
 
 // --- InputReaderInterface ---
diff --git a/services/inputflinger/include/VibrationElement.h b/services/inputflinger/include/VibrationElement.h
index 8a134ee..b60ffac 100644
--- a/services/inputflinger/include/VibrationElement.h
+++ b/services/inputflinger/include/VibrationElement.h
@@ -17,22 +17,25 @@
 #ifndef _VIBRATION_ELEMENT_H
 #define _VIBRATION_ELEMENT_H
 
+#include <array>
 #include <chrono>
 #include <cstdint>
 #include <string>
-#include <vector>
 
 namespace android {
 
+// evdev FF_RUMBLE effect only supports two channels of vibration.
+constexpr size_t CHANNEL_SIZE = 2;
 /*
  * Describes a rumble effect
  */
 struct VibrationElement {
     std::chrono::milliseconds duration;
-    std::vector<int> channels;
+    // Channel amplitude range 0-255.
+    std::array<uint8_t, CHANNEL_SIZE> channels = {0, 0};
 
-    void dump(std::string& dump) const;
-    uint16_t getChannel(int id) const;
+    const std::string toString() const;
+    uint16_t getMagnitude(size_t channelIndex) const;
     bool isOn() const;
 };
 
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index 8f34e8a..cde977f 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -61,6 +61,9 @@
 // v4l2 devices go directly into /dev
 static const char* VIDEO_DEVICE_PATH = "/dev";
 
+static constexpr size_t FF_STRONG_MAGNITUDE_CHANNEL_IDX = 0;
+static constexpr size_t FF_WEAK_MAGNITUDE_CHANNEL_IDX = 1;
+
 static inline const char* toString(bool value) {
     return value ? "true" : "false";
 }
@@ -834,8 +837,8 @@
         effect.type = FF_RUMBLE;
         effect.id = device->ffEffectId;
         // 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.u.rumble.strong_magnitude = element.getMagnitude(FF_STRONG_MAGNITUDE_CHANNEL_IDX);
+        effect.u.rumble.weak_magnitude = element.getMagnitude(FF_WEAK_MAGNITUDE_CHANNEL_IDX);
         effect.replay.length = element.duration.count();
         effect.replay.delay = 0;
         if (ioctl(device->fd, EVIOCSFF, &effect)) {
diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
index 8c1e224..ac7c266 100644
--- a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
@@ -91,8 +91,7 @@
     const VibrationElement& element = mPattern[mIndex];
     if (element.isOn()) {
 #if DEBUG_VIBRATOR
-        std::string description;
-        element.dump(description);
+        std::string description = element.toString();
         ALOGD("nextStep: sending vibrate deviceId=%d, element=%s", getDeviceId(),
               description.c_str());
 #endif
@@ -135,13 +134,13 @@
 void VibratorInputMapper::dumpPattern(std::string& dump) const {
     dump += "[";
 
-    if (mPattern.size() > 0) {
-        mPattern[0].dump(dump);
-        std::for_each(mPattern.begin() + 1, mPattern.end(), [&dump](const auto& element) {
+    for (auto it = mPattern.begin(); it != mPattern.end(); ++it) {
+        dump += it->toString();
+        if (std::next(it) != mPattern.end()) {
             dump += ", ";
-            element.dump(dump);
-        });
+        }
     }
+
     dump += "]";
 }