Send effect device/mode/source update if indicator was set in descriptor

Bug: 271500140
Test: Enable AIDL and test with YTM
Test: atest EffectsFactoryHalInterfaceTest
Change-Id: Ie85c2101eb37f2835d6e9e91a0ecc9273a250a0e
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index 9cf0cb8..4e34fca 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -25,6 +25,7 @@
 #include <media/AidlConversionCppNdk.h>
 #include <media/AidlConversionNdk.h>
 #include <media/AidlConversionEffect.h>
+#include <media/AudioContainers.h>
 #include <system/audio_effects/effect_visualizer.h>
 
 #include <utils/Log.h>
@@ -61,6 +62,7 @@
                 {EFFECT_CMD_RESET, &EffectConversionHelperAidl::handleReset},
                 {EFFECT_CMD_ENABLE, &EffectConversionHelperAidl::handleEnable},
                 {EFFECT_CMD_DISABLE, &EffectConversionHelperAidl::handleDisable},
+                {EFFECT_CMD_SET_AUDIO_MODE, &EffectConversionHelperAidl::handleSetAudioMode},
                 {EFFECT_CMD_SET_AUDIO_SOURCE, &EffectConversionHelperAidl::handleSetAudioSource},
                 {EFFECT_CMD_SET_DEVICE, &EffectConversionHelperAidl::handleSetDevice},
                 {EFFECT_CMD_SET_INPUT_DEVICE, &EffectConversionHelperAidl::handleSetDevice},
@@ -279,6 +281,10 @@
               pReplyData);
         return BAD_VALUE;
     }
+    if (!getDescriptor().common.flags.audioSourceIndication) {
+        ALOGW("%s parameter no audioSourceIndication, skipping", __func__);
+        return OK;
+    }
 
     audio_source_t source = *(audio_source_t*)pCmdData;
     AudioSource aidlSource =
@@ -295,6 +301,10 @@
               pReplyData);
         return BAD_VALUE;
     }
+    if (!getDescriptor().common.flags.audioModeIndication) {
+        ALOGW("%s parameter no audioModeIndication, skipping", __func__);
+        return OK;
+    }
     audio_mode_t mode = *(audio_mode_t *)pCmdData;
     AudioMode aidlMode =
             VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
@@ -310,9 +320,26 @@
               pReplyData);
         return BAD_VALUE;
     }
-    // TODO: convert from audio_devices_t to std::vector<AudioDeviceDescription>
-    // const auto& legacyDevice = *(uint32_t*)(pCmdData);
+    if (!getDescriptor().common.flags.deviceIndication) {
+        ALOGW("%s parameter no deviceIndication, skipping", __func__);
+        return OK;
+    }
+    // convert from bitmask of audio_devices_t to std::vector<AudioDeviceDescription>
+    auto legacyDevices = *(uint32_t*)(pCmdData);
+    // extract the input bit and remove it from bitmasks
+    const auto inputBit = legacyDevices & AUDIO_DEVICE_BIT_IN;
+    legacyDevices &= ~AUDIO_DEVICE_BIT_IN;
     std::vector<AudioDeviceDescription> aidlDevices;
+    while (legacyDevices) {
+        // get audio_devices_t represented by the last true bit and convert to AIDL
+        const auto lowestBitDevice = legacyDevices & -legacyDevices;
+        AudioDeviceDescription deviceDesc = VALUE_OR_RETURN_STATUS(
+                ::aidl::android::legacy2aidl_audio_devices_t_AudioDeviceDescription(
+                        static_cast<audio_devices_t>(lowestBitDevice | inputBit)));
+        aidlDevices.emplace_back(deviceDesc);
+        legacyDevices -= lowestBitDevice;
+    }
+
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
             mEffect->setParameter(Parameter::make<Parameter::deviceDescription>(aidlDevices))));
     return *static_cast<int32_t*>(pReplyData) = OK;
@@ -435,5 +462,19 @@
             (mIsProxyEffect && std::static_pointer_cast<EffectProxy>(mEffect)->isBypassing()));
 }
 
+Descriptor EffectConversionHelperAidl::getDescriptor() const {
+    if (!mIsProxyEffect) {
+        return mDesc;
+    }
+
+    Descriptor desc;
+    if (const auto status = mEffect->getDescriptor(&desc); !status.isOk()) {
+        ALOGE("%s failed to get proxy descriptor (%d:%s), using default", __func__,
+              status.getStatus(), status.getMessage());
+        return mDesc;
+    }
+    return desc;
+}
+
 }  // namespace effect
 }  // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 7c8f11b..85e877e 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -43,6 +43,8 @@
     std::shared_ptr<android::hardware::EventFlag> getEventFlagGroup() { return mEfGroup; }
     bool isBypassing() const;
 
+    ::aidl::android::hardware::audio::effect::Descriptor getDescriptor() const;
+
   protected:
     const int32_t mSessionId;
     const int32_t mIoId;
@@ -134,7 +136,6 @@
     virtual status_t visualizerMeasure(uint32_t* replySize __unused, void* pReplyData __unused) {
         return BAD_VALUE;
     }
-
 };
 
 }  // namespace effect
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index b8e62ae..642d352 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -69,7 +69,6 @@
       mEffect(effect),
       mSessionId(sessionId),
       mIoId(ioId),
-      mDesc(desc),
       mIsProxyEffect(isProxyEffect) {
     createAidlConversion(effect, sessionId, ioId, desc);
 }
@@ -169,7 +168,8 @@
     State state = State::INIT;
     if (mConversion->isBypassing() || !mEffect->getState(&state).isOk() ||
         state != State::PROCESSING) {
-        ALOGI("%s skipping %s process because it's %s", __func__, mDesc.common.name.c_str(),
+        ALOGI("%s skipping %s process because it's %s", __func__,
+              mConversion->getDescriptor().common.name.c_str(),
               mConversion->isBypassing()
                       ? "bypassing"
                       : aidl::android::hardware::audio::effect::toString(state).c_str());
@@ -225,8 +225,8 @@
         return INVALID_OPERATION;
     }
 
-    ALOGD("%s %s consumed %zu produced %zu", __func__, mDesc.common.name.c_str(), floatsToWrite,
-          floatsToRead);
+    ALOGD("%s %s consumed %zu produced %zu", __func__,
+          mConversion->getDescriptor().common.name.c_str(), floatsToWrite, floatsToRead);
     return OK;
 }
 
diff --git a/media/libaudiohal/impl/EffectHalAidl.h b/media/libaudiohal/impl/EffectHalAidl.h
index 1b7a3d6..bbcb7e2 100644
--- a/media/libaudiohal/impl/EffectHalAidl.h
+++ b/media/libaudiohal/impl/EffectHalAidl.h
@@ -72,7 +72,6 @@
     const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> mEffect;
     const int32_t mSessionId;
     const int32_t mIoId;
-    const ::aidl::android::hardware::audio::effect::Descriptor mDesc;
     const bool mIsProxyEffect;
 
     std::unique_ptr<EffectConversionHelperAidl> mConversion;
diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp
index 5e465d9..88ac5b7 100644
--- a/media/libaudiohal/impl/EffectProxy.cpp
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -169,12 +169,6 @@
             common.flags.hwAcceleratorMode = Flags::HardwareAccelerator::TUNNEL;
         }
 
-        // initial flag values before we know which sub-effect to active (with setOffloadParam)
-        // same as HIDL EffectProxy flags
-        common.flags.type = Flags::Type::INSERT;
-        common.flags.insert = Flags::Insert::LAST;
-        common.flags.volume = Flags::Volume::NONE;
-
         // set indication if any sub-effect indication was set
         common.flags.offloadIndication |= desc.common.flags.offloadIndication;
         common.flags.deviceIndication |= desc.common.flags.deviceIndication;
diff --git a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
index 2854496..0cb654c 100644
--- a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
+++ b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
@@ -347,6 +347,45 @@
     }
 }
 
+TEST_P(libAudioHalEffectParamTest, deviceIndicationUpdate) {
+    for (auto& interface : mHalInterfaces) {
+        EXPECT_NO_FATAL_FAILURE(initEffect(interface));
+
+        // output device
+        uint32_t deviceTypes = AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_BLE_SPEAKER;
+        status_t cmdStatus;
+        uint32_t replySize = sizeof(cmdStatus);
+        EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_DEVICE, sizeof(uint32_t), &deviceTypes,
+                                         &replySize, &cmdStatus));
+        // input device
+        deviceTypes = AUDIO_DEVICE_IN_WIRED_HEADSET | AUDIO_DEVICE_IN_BLUETOOTH_BLE;
+        EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_DEVICE, sizeof(uint32_t), &deviceTypes,
+                                         &replySize, &cmdStatus));
+    }
+}
+
+TEST_P(libAudioHalEffectParamTest, audioModeIndicationUpdate) {
+    for (auto& interface : mHalInterfaces) {
+        EXPECT_NO_FATAL_FAILURE(initEffect(interface));
+        uint32_t mode = AUDIO_MODE_IN_CALL;
+        status_t cmdStatus;
+        uint32_t replySize = sizeof(cmdStatus);
+        EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_AUDIO_MODE, sizeof(uint32_t), &mode,
+                                         &replySize, &cmdStatus));
+    }
+}
+
+TEST_P(libAudioHalEffectParamTest, audioSourceIndicationUpdate) {
+    for (auto& interface : mHalInterfaces) {
+        EXPECT_NO_FATAL_FAILURE(initEffect(interface));
+        uint32_t source = AUDIO_SOURCE_MIC;
+        status_t cmdStatus;
+        uint32_t replySize = sizeof(cmdStatus);
+        EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_AUDIO_SOURCE, sizeof(uint32_t), &source,
+                                         &replySize, &cmdStatus));
+    }
+}
+
 INSTANTIATE_TEST_SUITE_P(
         libAudioHalEffectParamTest, libAudioHalEffectParamTest, ::testing::ValuesIn(testPairs),
         [](const testing::TestParamInfo<libAudioHalEffectParamTest::ParamType>& info) {