Support scaling haptic data in HapticGenerator

Move function of scaling haptic data from AudioMixer to vibrator
library. Scaling haptic data in HapticGenerator according to the haptic
intensity.

Bug: 136490803
Test: play audio-coupled-haptic files
Test: play audio with HapticGenerator effect
Change-Id: I6bac63c085332ea87cc6612a8f2f368ad7ef7826
diff --git a/media/libeffects/hapticgenerator/Android.bp b/media/libeffects/hapticgenerator/Android.bp
index ac40e33..f947339 100644
--- a/media/libeffects/hapticgenerator/Android.bp
+++ b/media/libeffects/hapticgenerator/Android.bp
@@ -36,8 +36,10 @@
 
     shared_libs: [
         "libaudioutils",
+        "libbinder",
         "liblog",
         "libutils",
+        "libvibrator",
     ],
 
     relative_install_path: "soundfx",
diff --git a/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp b/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp
index 2a41ed5..311e5ba 100644
--- a/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp
+++ b/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp
@@ -96,7 +96,10 @@
     context->config.outputCfg.bufferProvider.cookie = nullptr;
     context->config.outputCfg.mask = EFFECT_CONFIG_ALL;
 
-    memset(&context->param, 0, sizeof(struct HapticGeneratorParam));
+    memset(context->param.hapticChannelSource, 0, sizeof(context->param.hapticChannelSource));
+    context->param.hapticChannelCount = 0;
+    context->param.audioChannelCount = 0;
+    context->param.maxHapticIntensity = os::HapticScale::MUTE;
 
     context->state = HAPTICGENERATOR_STATE_INITIALIZED;
     return 0;
@@ -236,12 +239,36 @@
     return 0;
 }
 
-int HapticGenerator_SetParameter(struct HapticGeneratorContext *context __unused,
-                                 int32_t param __unused,
-                                 uint32_t size __unused,
-                                 void *value __unused) {
-    ALOGW("Setparameter is not implemented in HapticGenerator");
-    return -ENOSYS;
+int HapticGenerator_SetParameter(struct HapticGeneratorContext *context,
+                                 int32_t param,
+                                 uint32_t size,
+                                 void *value) {
+    switch (param) {
+    case HG_PARAM_HAPTIC_INTENSITY: {
+        if (value == nullptr || size != (uint32_t) (2 * sizeof(int))) {
+            return -EINVAL;
+        }
+        int id = *(int *) value;
+        os::HapticScale hapticIntensity = static_cast<os::HapticScale>(*((int *) value + 1));
+        if (hapticIntensity == os::HapticScale::MUTE) {
+            context->param.id2Intensity.erase(id);
+        } else {
+            context->param.id2Intensity.emplace(id, hapticIntensity);
+        }
+        context->param.maxHapticIntensity = hapticIntensity;
+        for (const auto&[id, intensity] : context->param.id2Intensity) {
+            context->param.maxHapticIntensity = std::max(
+                    context->param.maxHapticIntensity, intensity);
+        }
+        break;
+    }
+
+    default:
+        ALOGW("Unknown param: %d", param);
+        return -EINVAL;
+    }
+
+    return 0;
 }
 
 /**
@@ -346,6 +373,11 @@
         return -ENODATA;
     }
 
+    if (context->param.maxHapticIntensity == os::HapticScale::MUTE) {
+        // Haptic channels are muted, not need to generate haptic data.
+        return 0;
+    }
+
     // Resize buffer if the haptic sample count is greater than buffer size.
     size_t hapticSampleCount = inBuffer->frameCount * context->param.hapticChannelCount;
     if (hapticSampleCount > context->inputBuffer.size()) {
@@ -367,6 +399,7 @@
     float* hapticOutBuffer = HapticGenerator_runProcessingChain(
             context->processingChain, context->inputBuffer.data(),
             context->outputBuffer.data(), inBuffer->frameCount);
+    os::scaleHapticData(hapticOutBuffer, hapticSampleCount, context->param.maxHapticIntensity);
 
     // For haptic data, the haptic playback thread will copy the data from effect input buffer,
     // which contains haptic data at the end of the buffer, directly to sink buffer.
diff --git a/media/libeffects/hapticgenerator/EffectHapticGenerator.h b/media/libeffects/hapticgenerator/EffectHapticGenerator.h
index 4a2308b..a5688de 100644
--- a/media/libeffects/hapticgenerator/EffectHapticGenerator.h
+++ b/media/libeffects/hapticgenerator/EffectHapticGenerator.h
@@ -19,9 +19,11 @@
 
 #include <functional>
 #include <vector>
+#include <map>
 
 #include <hardware/audio_effect.h>
 #include <system/audio_effect.h>
+#include <vibrator/ExternalVibrationUtils.h>
 
 #include "Processors.h"
 
@@ -45,6 +47,10 @@
                                      // The value will be offset of audio channel
     uint32_t audioChannelCount;
     uint32_t hapticChannelCount;
+
+    // A map from track id to haptic intensity.
+    std::map<int, os::HapticScale> id2Intensity;
+    os::HapticScale maxHapticIntensity; // max intensity will be used to scale haptic data.
 };
 
 // A structure to keep all shared pointers for all processors in HapticGenerator.