[AudioPolicyService] Add creation of DeviceEffects

Todo: use new AudioEffect systemAPI

Bug: 136294538
Test: build

Change-Id: I249d9ef112a8a8c7947a099e5937bf0a8b05014c
Merged-In: I249d9ef112a8a8c7947a099e5937bf0a8b05014c
Signed-off-by: François Gaffie <francois.gaffie@renault.com>
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index 60caa31..738a279 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -42,7 +42,10 @@
 AudioPolicyEffects::AudioPolicyEffects()
 {
     status_t loadResult = loadAudioEffectXmlConfig();
-    if (loadResult < 0) {
+    if (loadResult == NO_ERROR) {
+        mDefaultDeviceEffectFuture = std::async(
+                    std::launch::async, &AudioPolicyEffects::initDefaultDeviceEffects, this);
+    } else if (loadResult < 0) {
         ALOGW("Failed to load XML effect configuration, fallback to .conf");
         // load automatic audio effect modules
         if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
@@ -908,8 +911,24 @@
             streams.add(stream.type, effectDescs.release());
         }
     };
+
+    auto loadDeviceProcessingChain = [](auto &processingChain, auto& devicesEffects) {
+        for (auto& deviceProcess : processingChain) {
+
+            auto effectDescs = std::make_unique<EffectDescVector>();
+            for (auto& effect : deviceProcess.effects) {
+                effectDescs->mEffects.add(
+                        new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
+            }
+            auto deviceEffects = std::make_unique<DeviceEffects>(
+                        std::move(effectDescs), deviceProcess.type, deviceProcess.address);
+            devicesEffects.emplace(deviceProcess.address, std::move(deviceEffects));
+        }
+    };
+
     loadProcessingChain(result.parsedConfig->preprocess, mInputSources);
     loadProcessingChain(result.parsedConfig->postprocess, mOutputStreams);
+    loadDeviceProcessingChain(result.parsedConfig->deviceprocess, mDeviceEffects);
     // Casting from ssize_t to status_t is probably safe, there should not be more than 2^31 errors
     return result.nbSkippedElement;
 }
@@ -942,5 +961,32 @@
     return NO_ERROR;
 }
 
+void AudioPolicyEffects::initDefaultDeviceEffects()
+{
+    Mutex::Autolock _l(mLock);
+    for (const auto& deviceEffectsIter : mDeviceEffects) {
+        const auto& deviceEffects =  deviceEffectsIter.second;
+        for (const auto& effectDesc : deviceEffects->mEffectDescriptors->mEffects) {
+            auto fx = std::make_unique<AudioEffect>(
+                        EFFECT_UUID_NULL, String16("android"), &effectDesc->mUuid, 0, nullptr,
+                        nullptr, AUDIO_SESSION_DEVICE, AUDIO_IO_HANDLE_NONE,
+                        AudioDeviceTypeAddr{deviceEffects->getDeviceType(),
+                                            deviceEffects->getDeviceAddress()});
+            status_t status = fx->initCheck();
+            if (status != NO_ERROR && status != ALREADY_EXISTS) {
+                ALOGE("%s(): failed to create Fx %s on port type=%d address=%s", __func__,
+                      effectDesc->mName, deviceEffects->getDeviceType(),
+                      deviceEffects->getDeviceAddress().c_str());
+                // fx goes out of scope and strong ref on AudioEffect is released
+                continue;
+            }
+            fx->setEnabled(true);
+            ALOGV("%s(): create Fx %s added on port type=%d address=%s", __func__,
+                  effectDesc->mName, deviceEffects->getDeviceType(),
+                  deviceEffects->getDeviceAddress().c_str());
+            deviceEffects->mEffects.push_back(std::move(fx));
+        }
+    }
+}
 
 } // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index dcf093b..88be1ad 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -25,6 +25,9 @@
 #include <system/audio.h>
 #include <utils/Vector.h>
 #include <utils/SortedVector.h>
+#include <android-base/thread_annotations.h>
+
+#include <future>
 
 namespace android {
 
@@ -104,6 +107,7 @@
     status_t removeStreamDefaultEffect(audio_unique_id_t id);
 
 private:
+    void initDefaultDeviceEffects();
 
     // class to store the description of an effects and its parameters
     // as defined in audio_effects.conf
@@ -192,6 +196,28 @@
         Vector< sp<AudioEffect> >mEffects;
     };
 
+    /**
+     * @brief The DeviceEffects class stores the effects associated to a given Device Port.
+     */
+    class DeviceEffects {
+    public:
+        explicit DeviceEffects(std::unique_ptr<EffectDescVector> effectDescriptors,
+                               audio_devices_t device, const std::string& address) :
+            mEffectDescriptors(std::move(effectDescriptors)),
+            mDeviceType(device), mDeviceAddress(address) {}
+        /*virtual*/ ~DeviceEffects() = default;
+
+        std::vector<std::unique_ptr<AudioEffect>> mEffects;
+        audio_devices_t getDeviceType() const { return mDeviceType; }
+        std::string getDeviceAddress() const { return mDeviceAddress; }
+        const std::unique_ptr<EffectDescVector> mEffectDescriptors;
+
+    private:
+        const audio_devices_t mDeviceType;
+        const std::string mDeviceAddress;
+
+    };
+
 
     static const char * const kInputSourceNames[AUDIO_SOURCE_CNT -1];
     static audio_source_t inputSourceNameToEnum(const char *name);
@@ -237,6 +263,19 @@
     KeyedVector< audio_stream_type_t, EffectDescVector* > mOutputStreams;
     // Automatic output effects are unique for audiosession ID
     KeyedVector< audio_session_t, EffectVector* > mOutputSessions;
+
+    /**
+     * @brief mDeviceEffects map of device effects indexed by the device address
+     */
+    std::map<std::string, std::unique_ptr<DeviceEffects>> mDeviceEffects GUARDED_BY(mLock);
+
+    /**
+     * Device Effect initialization must be asynchronous: the audio_policy service parses and init
+     * effect on first reference. AudioFlinger will handle effect creation and register these
+     * effect on audio_policy service.
+     * We must store the reference of the furture garantee real asynchronous operation.
+     */
+    std::future<void> mDefaultDeviceEffectFuture;
 };
 
 } // namespace android